22
33import re
44import datetime
5+ from collections .abc import Iterator
56
67from adif_file .__version__ import __version__ as __version_str__
78
@@ -116,6 +117,25 @@ def loads_adi(adi: str) -> dict:
116117 return doc
117118
118119
120+ def load_adi (file_name : str ):
121+ """Turn ADI formated string to dictionary
122+ The parameters are converted to uppercase
123+
124+ {
125+ 'HEADER': None,
126+ 'RECORDS': [list of records]
127+ }
128+
129+ :param file_name: the file name where the ADI data is stored
130+ :return: the ADI as a dict
131+ """
132+
133+ with open (file_name , encoding = 'ascii' ) as af :
134+ data = af .read ()
135+
136+ return loads_adi (data )
137+
138+
119139def pack (param : str , value : str , dtype : str = None ) -> str :
120140 """Generates ADI tag if value is not empty
121141 Does not generate tags for *_INTL types as required by specification.
@@ -143,7 +163,7 @@ def pack(param: str, value: str, dtype: str = None) -> str:
143163 return ''
144164
145165
146- def dumps_adi (data_dict : dict , comment : str = 'ADIF export by ' + __proj_name__ ) -> str :
166+ def dumpi_adi (data_dict : dict , comment : str = 'ADIF export by ' + __proj_name__ ) -> Iterator [ str ] :
147167 """Takes a dictionary and converts it to ADI format
148168 Parameters can be in upper or lower case. The output is upper case. The user must take care
149169 that parameters are not doubled!
@@ -155,16 +175,15 @@ def dumps_adi(data_dict: dict, comment: str = 'ADIF export by ' + __proj_name__)
155175 with datatype as "dtype" and field definition as "userdef" instead of a string value.
156176
157177 :param data_dict: the dictionary with header and records
158- :param comment: the comment to induce the header"""
178+ :param comment: the comment to induce the header
179+ :return: an iterator of chunks of the ADI:"""
159180
160181 default = {'ADIF_VER' : '3.1.4' ,
161182 'PROGRAMID' : __proj_name__ ,
162183 'PROGRAMVERSION' : __version__ ,
163184 'CREATED_TIMESTAMP' : datetime .datetime .utcnow ().strftime ('%Y%m%d %H%M%S' )
164185 }
165186
166- data = ''
167-
168187 if 'HEADER' in data_dict :
169188 data = comment + ' \n '
170189
@@ -177,10 +196,12 @@ def dumps_adi(data_dict: dict, comment: str = 'ADIF export by ' + __proj_name__)
177196 data += pack (f'USERDEF{ i } ' , u ['userdef' ], u ['dtype' ]) + '\n '
178197 for p in default .items ():
179198 data += pack (p , default [p ]) + '\n '
180- data += '<EOH>\n \n '
199+ data += '<EOH>'
200+ yield data
181201
182202 if 'RECORDS' in data_dict :
183203 for r in data_dict ['RECORDS' ]:
204+ data = ''
184205 empty = True
185206 for i , pv in enumerate (zip (r .keys (), r .values ()), 1 ):
186207 tag = pack (pv [0 ].upper (), pv [1 ])
@@ -191,6 +212,50 @@ def dumps_adi(data_dict: dict, comment: str = 'ADIF export by ' + __proj_name__)
191212 data += '\n '
192213
193214 if not empty :
194- data += '<EOR>\n \n '
215+ data += '<EOR>'
216+ yield data
217+
218+
219+ def dumps_adi (data_dict : dict , comment : str = 'ADIF export by ' + __proj_name__ ) -> str :
220+ """Takes a dictionary and converts it to ADI format
221+ Parameters can be in upper or lower case. The output is upper case. The user must take care
222+ that parameters are not doubled!
223+ *_INTL parameters are ignored as they are not allowed in ADI.
224+ Empty records are skipped.
195225
196- return data .strip ()
226+ If 'HEADER' is present the comment is added and missing header fields are filled with defaults.
227+ The header can contain a list of user definitions as USERDEFS. Each user definition is expected as a dictionary
228+ with datatype as "dtype" and field definition as "userdef" instead of a string value.
229+
230+ :param data_dict: the dictionary with header and records
231+ :param comment: the comment to induce the header
232+ :return: the complete ADI as a string"""
233+
234+ return '\n \n ' .join (list (dumpi_adi (data_dict , comment )))
235+
236+
237+ def dump_adi (file_name : str , data_dict : dict , comment : str = 'ADIF export by ' + __proj_name__ ):
238+ """Takes a dictionary and stores it to filename in ADI format
239+ Parameters can be in upper or lower case. The output is upper case. The user must take care
240+ that parameters are not doubled!
241+ *_INTL parameters are ignored as they are not allowed in ADI.
242+ Empty records are skipped.
243+
244+ If 'HEADER' is present the comment is added and missing header fields are filled with defaults.
245+ The header can contain a list of user definitions as USERDEFS. Each user definition is expected as a dictionary
246+ with datatype as "dtype" and field definition as "userdef" instead of a string value.
247+
248+ :param file_name: the filename to store the ADI data to
249+ :param data_dict: the dictionary with header and records
250+ :param comment: the comment to induce the header
251+ :return: the complete ADI as a string"""
252+
253+ with open (file_name , 'w' , encoding = 'ascii' ) as af :
254+ first = True
255+ for chunk in dumpi_adi (data_dict , comment ):
256+ if first :
257+ first = False
258+ else :
259+ af .write ('\n \n ' )
260+
261+ af .write (chunk )
0 commit comments