casaconfig 1.3.1__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- casaconfig/__init__.py +7 -0
- casaconfig/config.py +34 -21
- casaconfig/private/config_defaults.py +4 -2
- casaconfig/private/config_defaults_static.py +22 -0
- casaconfig/private/data_available.py +17 -37
- casaconfig/private/data_update.py +22 -26
- casaconfig/private/do_auto_updates.py +4 -3
- casaconfig/private/do_pull_data.py +7 -27
- casaconfig/private/do_untar_url.py +94 -0
- casaconfig/private/get_available_files.py +94 -0
- casaconfig/private/get_data_info.py +35 -20
- casaconfig/private/measures_available.py +205 -54
- casaconfig/private/measures_update.py +138 -84
- casaconfig/private/print_log_messages.py +7 -3
- casaconfig/private/pull_data.py +11 -6
- casaconfig/private/read_readme.py +57 -13
- casaconfig/private/set_casacore_path.py +2 -2
- casaconfig/private/summary.py +3 -0
- casaconfig/private/update_all.py +6 -5
- casaconfig-1.4.0.dist-info/METADATA +92 -0
- casaconfig-1.4.0.dist-info/RECORD +34 -0
- {casaconfig-1.3.1.dist-info → casaconfig-1.4.0.dist-info}/WHEEL +1 -1
- tests/test_casaconfig.py +190 -17
- casaconfig-1.3.1.dist-info/METADATA +0 -293
- casaconfig-1.3.1.dist-info/RECORD +0 -32
- {casaconfig-1.3.1.dist-info → casaconfig-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {casaconfig-1.3.1.dist-info → casaconfig-1.4.0.dist-info}/top_level.txt +0 -0
@@ -15,11 +15,12 @@
|
|
15
15
|
this module will be included in the api
|
16
16
|
"""
|
17
17
|
|
18
|
-
def measures_update(path=None, version=None, force=False, logger=None, auto_update_rules=False, use_astron_obs_table=False, verbose=None):
|
18
|
+
def measures_update(path=None, version=None, force=False, measures_site=None, logger=None, auto_update_rules=False, use_astron_obs_table=False, verbose=None):
|
19
19
|
"""
|
20
|
-
Update or install the IERS data used for measures calculations from
|
20
|
+
Update or install the IERS data used for measures calculations from measures_site into path.
|
21
21
|
|
22
|
-
Original data source used by
|
22
|
+
Original IERS data source used by each of the recommended measures sites
|
23
|
+
is here: https://www.iers.org/IERS/EN/DataProducts/data.html
|
23
24
|
|
24
25
|
If no update is necessary then this function will silently return.
|
25
26
|
|
@@ -27,16 +28,16 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
27
28
|
are unchanged for expected reasons. A level of 0 outputs nothing. A
|
28
29
|
value of 1 sends any output to the logger and a value of 2 logs and prints the information.
|
29
30
|
The default value of the verbose argument is taken from the casaconfig_verbose config
|
30
|
-
value (defaults to 1).
|
31
|
+
value (defaults to 1). Error messages are always logged and printed.
|
31
32
|
|
32
33
|
CASA maintains a separate Observatories table which is available in the casarundata
|
33
|
-
collection through pull_data and data_update. The Observatories table found at
|
34
|
+
collection through pull_data and data_update. The Observatories table found at measures_site
|
34
35
|
is not installed by measures_update and any Observatories file at path will not be changed
|
35
36
|
by using this function. This behavior can be changed by setting force and use_astron_obs_table
|
36
37
|
both to True (use_astron_obs_table is ignored when force is False).
|
37
38
|
|
38
|
-
A text file (readme.txt in the geodetic directory in path) records the measures version string
|
39
|
-
and the date when that version was installed in path.
|
39
|
+
A text file (readme.txt in the geodetic directory in path) records the measures version string,
|
40
|
+
the measures site that was used and the date when that version was installed in path.
|
40
41
|
|
41
42
|
If path is None then config.measurespath is used.
|
42
43
|
|
@@ -44,12 +45,26 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
44
45
|
nothing unless force is True.
|
45
46
|
|
46
47
|
If a specific version is not requested (the default) and the modification time of that text
|
47
|
-
file is less than
|
48
|
-
function checks for a more recent version and finds
|
49
|
-
|
50
|
-
changed
|
51
|
-
|
52
|
-
|
48
|
+
file is less than the measures_update_interval config value (days) before now then this function
|
49
|
+
does nothing unless force is True. When this function checks for a more recent version and finds
|
50
|
+
that the installed version is the most recent one then the modification time of that text file
|
51
|
+
is changed to the current time even though nothing has changed in path. This limits the
|
52
|
+
number of attempts to update the measures data (including checking
|
53
|
+
for more recent data) to once every measures_update_interval days. When the force argument
|
54
|
+
is True and a specific version is not requested then this function always checks for the
|
55
|
+
latest version. The measures_update_interval is always used as an int type (including
|
56
|
+
any truncation of the actual value in config if not an integer).
|
57
|
+
|
58
|
+
The measures_site is a single URL or a list of URLs to use to find the measures tar file
|
59
|
+
to use in the update. See measures_available for more details on how that parameter
|
60
|
+
is used.
|
61
|
+
|
62
|
+
If a specific version is requested then that must match a file in the list returned
|
63
|
+
by measures_available. The version is usually unique at each measures_site and so care
|
64
|
+
may need to be taken when requesting a specific version to ensure that it's available at
|
65
|
+
measures_site. If measures_site is a list and a specific version is requested then
|
66
|
+
measures_update will try and find that version in each measures_site in that list, using
|
67
|
+
the first site that has that version.
|
53
68
|
|
54
69
|
When auto_update_rules is True then path must exist and contain the expected readme.txt file.
|
55
70
|
Path must be owned by the user, force must be False, and the version must be None. This
|
@@ -107,12 +122,13 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
107
122
|
|
108
123
|
Parameters
|
109
124
|
- path (str=None) - Folder path to place updated measures data. Must contain a valid geodetic/readme.txt. If not set then config.measurespath is used.
|
110
|
-
- version (str=None) - Version of measures data to retrieve (usually in the form of WSRT_Measures_yyyymmdd-160001.ztar, see measures_available
|
125
|
+
- version (str=None) - Version of measures data to retrieve (usually in the form of WSRT_Measures_yyyymmdd-160001.ztar, see measures_available). Default None retrieves the latest.
|
111
126
|
- force (bool=False) - If True, always re-download the measures data. Default False will not download measures data if updated within the past day unless the version parameter is specified and different from what was last downloaded.
|
127
|
+
- measures_site(str or list of str = None) - Each value is a URL where measures tar files are found. If measures_site is a list then the elements are used in order until a list can be assembled. Default None uses config.measures_site.
|
112
128
|
- logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal
|
113
129
|
- auto_update_rules (bool=False) - If True then the user must be the owner of path, version must be None, and force must be False.
|
114
130
|
- use_astron_obs_table (bool=False) - If True and force is also True then keep the Observatories table found in the Measures tar tarball (possibly overwriting the Observatories table from casarundata).
|
115
|
-
- verbose (int=None) - Level of output, 0 is none, 1 is to logger, 2 is to logger and terminal, defaults to
|
131
|
+
- verbose (int=None) - Level of output, 0 is none, 1 is to logger, 2 is to logger and terminal, defaults to config.casaconfig_verbose.
|
116
132
|
|
117
133
|
Returns
|
118
134
|
None
|
@@ -130,16 +146,11 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
130
146
|
|
131
147
|
"""
|
132
148
|
import os
|
133
|
-
import pkg_resources
|
134
149
|
from datetime import datetime
|
135
150
|
import sys
|
136
151
|
|
137
152
|
import tarfile
|
138
153
|
import re
|
139
|
-
import ssl
|
140
|
-
import urllib.request
|
141
|
-
import certifi
|
142
|
-
import shutil
|
143
154
|
|
144
155
|
from casaconfig import measures_available
|
145
156
|
from casaconfig import AutoUpdatesNotAllowed, UnsetMeasurespath, RemoteError, NotWritable, BadReadme, BadLock, NoReadme, NoNetwork
|
@@ -148,16 +159,20 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
148
159
|
from .get_data_lock import get_data_lock
|
149
160
|
from .get_data_info import get_data_info
|
150
161
|
from .measures_available import measures_available
|
151
|
-
|
162
|
+
from .do_untar_url import do_untar_url
|
163
|
+
|
164
|
+
from .. import config as _config
|
165
|
+
|
152
166
|
if path is None:
|
153
|
-
from .. import config as _config
|
154
167
|
path = _config.measurespath
|
155
168
|
|
156
169
|
if path is None:
|
157
170
|
raise UnsetMeasurespath('measures_update: path is None and has not been set in config.measurespath. Provide a valid path and retry.')
|
158
171
|
|
172
|
+
if measures_site is None:
|
173
|
+
measures_site = _config.measures_site
|
174
|
+
|
159
175
|
if verbose is None:
|
160
|
-
from .. import config as _config
|
161
176
|
verbose = _config.casaconfig_verbose
|
162
177
|
|
163
178
|
path = os.path.expanduser(path)
|
@@ -176,42 +191,52 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
176
191
|
# make dirs all the way down, if possible
|
177
192
|
os.makedirs(path)
|
178
193
|
|
179
|
-
|
194
|
+
currentVersion = None
|
180
195
|
ageRecent = False
|
196
|
+
currentSite = None
|
181
197
|
|
182
198
|
# first, does this look like it needs to be updated
|
183
199
|
|
184
200
|
# get any existing measures readme information
|
185
201
|
readmeInfo = get_data_info(path, logger, type='measures')
|
186
202
|
if readmeInfo is not None:
|
187
|
-
|
203
|
+
currentVersion = readmeInfo['version']
|
204
|
+
currentSite = readmeInfo['site']
|
188
205
|
if readmeInfo['age'] is not None:
|
189
|
-
ageRecent = readmeInfo['age'] <
|
206
|
+
ageRecent = readmeInfo['age'] < int(_config.measures_update_interval)
|
190
207
|
|
191
208
|
if not force:
|
192
|
-
# don't check for new version if the age is less than
|
209
|
+
# don't check for new version if the age is less than measures_update_interval days
|
193
210
|
if version is None and ageRecent:
|
194
|
-
|
195
|
-
print_log_messages('measures_update: version installed or checked less than 1 day ago, nothing updated or checked', logger, verbose=verbose)
|
211
|
+
print_log_messages('measures_update: version installed or checked less than %s day(s) ago, nothing updated or checked' % int(_config.measures_update_interval), logger, verbose=verbose)
|
196
212
|
return
|
197
213
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
214
|
+
if currentVersion is not None:
|
215
|
+
# don't overwrite something that looks bad unless forced to do so
|
216
|
+
if 'invalid' in currentVersion:
|
217
|
+
raise NoReadme('measures_update: no measures readme.txt file found at %s. Nothing updated or checked.' % path)
|
218
|
+
|
219
|
+
if 'error' in currentVersion:
|
220
|
+
msg = "measures_update: the measures readme.txt file at %s could not be read as expected, an update can not proceed unless force is True" % path
|
221
|
+
# add any additional error message, anything after the first ":" if is found
|
222
|
+
colonIndex = currentVersion.find(":")
|
223
|
+
if colonIndex != -1:
|
224
|
+
msg += "; " + currentVersion[colonIndex+1:]
|
225
|
+
raise BadReadme(msg)
|
226
|
+
|
227
|
+
# don't overwrite something that looks like valid measures data unless forced to do so
|
228
|
+
if 'unknown' in currentVersion:
|
229
|
+
print_log_messages('measures_update: the measures data at %s is not maintained by casaconfig and so it can not be updated unless force is True' % path, logger, True)
|
230
|
+
return
|
209
231
|
|
210
232
|
checkVersion = version
|
211
233
|
if checkVersion is None:
|
212
234
|
# get the current most recent version
|
213
235
|
try:
|
214
|
-
|
236
|
+
# if measures_site is a list, measures_available will return the list from the appropriate site in that list
|
237
|
+
# that might not be the same site recorded with currentVersion, but that's OK for this update step
|
238
|
+
# the currentVersion is already old enough to trigger this check for a more recent version
|
239
|
+
checkVersion = measures_available(measures_site=measures_site)[-1]
|
215
240
|
except NoNetwork as exc:
|
216
241
|
# no network, no point in continuing, just reraise
|
217
242
|
raise exc
|
@@ -220,12 +245,14 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
220
245
|
raise exc
|
221
246
|
except:
|
222
247
|
# unsure what happened, leave it at none, which will trigger an update attempt, which might work
|
248
|
+
print("unexpected excption in measuress_available")
|
249
|
+
import traceback
|
250
|
+
traceback.print_exc()
|
223
251
|
pass
|
224
252
|
|
225
253
|
# don't re-download the same data
|
226
|
-
if (checkVersion is not None) and (checkVersion ==
|
227
|
-
|
228
|
-
print_log_messages('measures_update: requested version already installed in %s' % path, logger, verbose=verbose)
|
254
|
+
if (checkVersion is not None) and (checkVersion == currentVersion):
|
255
|
+
print_log_messages('measures_update: requested version already installed in %s' % path, logger, verbose=verbose)
|
229
256
|
# update the age of the readme to now
|
230
257
|
readme_path = os.path.join(path,'geodetic/readme.txt')
|
231
258
|
# readme_path should already exist if it's here
|
@@ -239,7 +266,7 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
239
266
|
msgs = []
|
240
267
|
msgs.append("Error: the Observatories table was not found as expected in %s" % path)
|
241
268
|
msgs.append("Either install casarundata first or set use_astron_obs_table and force to be True when using measures_update.")
|
242
|
-
msgs.append("Note that the Observatories table provided in the
|
269
|
+
msgs.append("Note that the Observatories table provided in the measures tarfile is not the same as that maintained by CASA")
|
243
270
|
print_log_messages(msgs, logger, True)
|
244
271
|
return
|
245
272
|
|
@@ -253,7 +280,7 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
253
280
|
lock_fd = None
|
254
281
|
clean_lock = True # set to false if the contents are actively being update and the lock file should not be cleaned one exception
|
255
282
|
try:
|
256
|
-
print_log_messages('measures_update ... acquiring the lock ... ', logger)
|
283
|
+
print_log_messages('measures_update ... acquiring the lock ... ', logger, verbose=verbose)
|
257
284
|
|
258
285
|
# the BadLock exception that may happen here is caught below
|
259
286
|
lock_fd = get_data_lock(path, 'measures_update')
|
@@ -262,21 +289,19 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
262
289
|
|
263
290
|
if not do_update:
|
264
291
|
# recheck the readme file, another update may have already happened before the lock was obtained
|
265
|
-
|
292
|
+
currentVersion = None
|
266
293
|
ageRecent = False
|
267
294
|
|
268
295
|
readmeInfo = get_data_info(path, logger, type='measures')
|
269
296
|
if readmeInfo is not None:
|
270
|
-
|
297
|
+
currentVersion = readmeInfo['version']
|
271
298
|
if readmeInfo['age'] is not None:
|
272
|
-
ageRecent = readmeInfo['age'] <
|
299
|
+
ageRecent = readmeInfo['age'] < int(_config.measures_update_interval)
|
273
300
|
|
274
|
-
if (version is not None) and (version ==
|
275
|
-
|
276
|
-
print_log_messages('The requested measures version is already installed in %s, using version %s' % (path, current), logger)
|
301
|
+
if (version is not None) and (version == currentVersion):
|
302
|
+
print_log_messages('The requested measures version is already installed in %s, using version %s' % (path, currentVersion), logger, verbose=verbose)
|
277
303
|
elif (version is None) and ageRecent:
|
278
|
-
|
279
|
-
print_log_messages('The latest measures version was checked recently in %s, using version %s' % (path, current), logger)
|
304
|
+
print_log_messages('The latest measures version was checked recently in %s, using version %s' % (path, currentVersion), logger, verbose=verbose)
|
280
305
|
else:
|
281
306
|
# final check for problems before updating
|
282
307
|
if not force and readmeInfo is not None and (version=='invalid' or version=='unknown'):
|
@@ -291,39 +316,62 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
291
316
|
|
292
317
|
if do_update:
|
293
318
|
if force:
|
294
|
-
print_log_messages('A measures update has been requested by the force argument', logger)
|
295
|
-
|
296
|
-
print_log_messages(' ... finding available measures
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
#
|
302
|
-
#
|
303
|
-
|
304
|
-
if
|
305
|
-
|
306
|
-
|
319
|
+
print_log_messages('A measures update has been requested by the force argument', logger, verbose=verbose)
|
320
|
+
|
321
|
+
print_log_messages(' ... finding available measures ...', logger, verbose=verbose)
|
322
|
+
|
323
|
+
target = None
|
324
|
+
site = None
|
325
|
+
|
326
|
+
# if a specific version has been request AND measures_site is a list with more than one value
|
327
|
+
# then find the site with that version in it. Turn off logging in measures_available calls
|
328
|
+
# here as the age of the site doesn't matter
|
329
|
+
if version is not None and isinstance(measures_site, list) and len(measures_site) > 1:
|
330
|
+
target = version
|
331
|
+
for this_site in measures_site:
|
332
|
+
files = measures_available(measures_site=this_site, logger=None)
|
333
|
+
# make sure that site is excluded from files before target is checked
|
334
|
+
files = files[1:]
|
335
|
+
if target in files:
|
336
|
+
site = this_site
|
337
|
+
break
|
338
|
+
if site is None:
|
339
|
+
print_log_messages("measures_update can't find specfied version %s at any of the sites in the measures_site list" % target, logger, True)
|
340
|
+
# else site and target are set
|
307
341
|
else:
|
342
|
+
# if measure_available sorts out what site to use if it's a list with more than one element
|
343
|
+
# a specific version probably needs to use a specific site to make it work
|
344
|
+
# if a specific version has been requested then the age of the site isn't an issue, turn logging off
|
345
|
+
this_logger = logger if version is None else None
|
346
|
+
files = measures_available(measures_site=measures_site, logger=this_logger)
|
347
|
+
site = files[0]
|
348
|
+
# this makes sure that the site is exclude from files before target is checked.
|
349
|
+
files = files[1:]
|
350
|
+
|
351
|
+
# target filename to download
|
352
|
+
# for the non-force unspecified version case this can only get here if the age is > 1 day so there should be a newer version
|
353
|
+
# but that isn't checked - this could install a version that's already installed
|
354
|
+
target = files[-1] if version is None else version
|
355
|
+
if target not in files:
|
356
|
+
print_log_messages("measures_update can't find specified version %s at site %s" % (target,site), logger, True)
|
357
|
+
# unset site here to signal nothing to extract
|
358
|
+
site = None
|
359
|
+
|
360
|
+
if site is not None:
|
308
361
|
# there are files to extract
|
309
|
-
print_log_messages(' ... downloading %s from
|
362
|
+
print_log_messages(' ... downloading %s from %s to %s ...' % (target, site, path), logger, verbose=verbose)
|
310
363
|
|
311
|
-
astronURL = 'https://www.astron.nl/iers'
|
312
|
-
context = ssl.create_default_context(cafile=certifi.where())
|
313
|
-
# just in case there's a redirect at astron the way there is for the go.nrao.edu site and casarundata
|
314
|
-
measuresURLroot = urllib.request.urlopen(astronURL, context=context).url
|
315
|
-
measuresURL = os.path.join(measuresURLroot, target)
|
316
|
-
|
317
364
|
# it's at this point that this code starts modifying what's there so the lock file should
|
318
|
-
# not be removed on failure
|
365
|
+
# not be removed on failure from here on (until it succeeds)
|
319
366
|
clean_lock = False
|
367
|
+
|
320
368
|
# remove any existing measures readme.txt now in case something goes wrong during extraction
|
321
369
|
readme_path = os.path.join(path,'geodetic/readme.txt')
|
322
370
|
if os.path.exists(readme_path):
|
323
371
|
os.remove(readme_path)
|
324
372
|
|
325
|
-
# custom filter that incorporates data_filter to watch for dangerous members of the tar file
|
326
|
-
#
|
373
|
+
# custom filter that incorporates 'data_filter' to watch for dangerous members of the tar file
|
374
|
+
# this adds filtering to remove the Observatories table (unless use_astron_obs_table is True) and
|
327
375
|
# the *.old tables that may be in the geodetic tree
|
328
376
|
def custom_filter(member, extractionPath):
|
329
377
|
# member is a TarInfo instance and extractionPath is the destination path
|
@@ -337,18 +385,16 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
337
385
|
member = None
|
338
386
|
return member
|
339
387
|
|
340
|
-
|
341
|
-
|
342
|
-
tar.extraction_filter = custom_filter
|
343
|
-
tar.extractall(path=path)
|
344
|
-
tar.close()
|
388
|
+
# untar the target at site to path using the custom filter, do not be verbose
|
389
|
+
do_untar_url(site, target, path, custom_filter)
|
345
390
|
|
346
391
|
# create a new readme.txt file
|
347
392
|
with open(readme_path,'w') as fid:
|
348
|
-
|
393
|
+
# site added last to not break past readers of the measures readme
|
394
|
+
fid.write("# measures data populated by casaconfig\nversion : %s\ndate : %s\nsite : %s" % (target, datetime.today().strftime('%Y-%m-%d'),site))
|
349
395
|
|
350
396
|
clean_lock = True
|
351
|
-
print_log_messages(' ... measures data updated at %s' % path, logger)
|
397
|
+
print_log_messages(' ... measures data updated at %s' % path, logger, verbose=verbose)
|
352
398
|
|
353
399
|
# closing out the do_update
|
354
400
|
|
@@ -372,6 +418,14 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
|
|
372
418
|
msgs.append('Check for other updates in progress or choose a different path or clear out this path and reinstall the casarundata as well as the measures data')
|
373
419
|
print_log_messages(msgs, logger, True)
|
374
420
|
raise
|
421
|
+
|
422
|
+
except RemoteError as exc:
|
423
|
+
# probably an empty site
|
424
|
+
msgs = [str(exc)]
|
425
|
+
msgs.append('There was a remote error while attempting to update measures at %s' % path)
|
426
|
+
msgs.append('Check the value of measures_site and try again')
|
427
|
+
print_log_messages(msgs, logger, True)
|
428
|
+
raise
|
375
429
|
|
376
430
|
except Exception as exc:
|
377
431
|
msgs = []
|
@@ -30,13 +30,17 @@ def print_log_messages(msg, logger, is_err=False, verbose=2):
|
|
30
30
|
- msg (str) - The message to print and optionally log.
|
31
31
|
- logger (casatools.logsink) - Instance of the casalogger to use. Not used if None.
|
32
32
|
- is_err (bool=False) - When False, output goes to sys.stdout and logged as INFO level. When True, output goes to sys.stderr and logged as SEVERE
|
33
|
-
- verbose (int=2) -
|
33
|
+
- verbose (int=2) - 0 - do nothing, 1 log unless there is no logger, then print, 2 log and print
|
34
34
|
|
35
35
|
Returns
|
36
36
|
None
|
37
37
|
|
38
38
|
"""
|
39
39
|
|
40
|
+
if verbose == 0:
|
41
|
+
# do nothing
|
42
|
+
return
|
43
|
+
|
40
44
|
import sys
|
41
45
|
fileout = sys.stdout
|
42
46
|
loglevel = 'INFO'
|
@@ -48,8 +52,8 @@ def print_log_messages(msg, logger, is_err=False, verbose=2):
|
|
48
52
|
if type(msg) is not list:
|
49
53
|
msg = [msg]
|
50
54
|
|
51
|
-
#
|
52
|
-
if (logger is None) or (
|
55
|
+
# print if there is no logger or verbose >= 2
|
56
|
+
if (logger is None) or (verbose >= 2):
|
53
57
|
for m_msg in msg:
|
54
58
|
print(m_msg,file=fileout)
|
55
59
|
|
casaconfig/private/pull_data.py
CHANGED
@@ -22,6 +22,7 @@ def pull_data(path=None, version=None, force=False, logger=None, verbose=None):
|
|
22
22
|
The verbose argument controls the level of information provided when this function when the data
|
23
23
|
are unchanged for expected reasons. A level of 0 prints and logs nothing. A
|
24
24
|
value of 1 logs the information and a value of 2 logs and prints the information.
|
25
|
+
Error messages are always logged and printed.
|
25
26
|
|
26
27
|
The path must either contain a previously installed version of casarundata
|
27
28
|
or it must not exist or be empty.
|
@@ -107,19 +108,23 @@ def pull_data(path=None, version=None, force=False, logger=None, verbose=None):
|
|
107
108
|
|
108
109
|
from casaconfig import data_available
|
109
110
|
from casaconfig import get_data_info
|
110
|
-
from casaconfig import UnsetMeasurespath, BadLock, BadReadme, NotWritable
|
111
|
+
from casaconfig import UnsetMeasurespath, BadLock, BadReadme, NoNetwork, NotWritable, RemoteError
|
111
112
|
|
112
113
|
from .print_log_messages import print_log_messages
|
113
114
|
from .get_data_lock import get_data_lock
|
114
115
|
from .do_pull_data import do_pull_data
|
115
116
|
|
117
|
+
from .. import config as _config
|
118
|
+
|
116
119
|
if path is None:
|
117
|
-
from .. import config as _config
|
118
120
|
path = _config.measurespath
|
119
121
|
|
120
122
|
if path is None:
|
121
123
|
raise UnsetMeasurespath('path is None and has not been set in config.measurespath. Provide a valid path and retry.')
|
122
124
|
|
125
|
+
if verbose is None:
|
126
|
+
verbose = _config.casaconfig_verbose
|
127
|
+
|
123
128
|
# when a specific version is requested then the measures readme.txt that is part of that version
|
124
129
|
# will get a timestamp of now so that default measures updates won't happen for a day unless the
|
125
130
|
# force argument is used for measures_update
|
@@ -223,7 +228,7 @@ def pull_data(path=None, version=None, force=False, logger=None, verbose=None):
|
|
223
228
|
lock_fd = None
|
224
229
|
clean_lock = True # set to False if the contents are actively being update and the lock file should not be cleaned on exception
|
225
230
|
try:
|
226
|
-
print_log_messages('pull_data using version %s, acquiring the lock ... ' % version, logger)
|
231
|
+
print_log_messages('pull_data using version %s, acquiring the lock ... ' % version, logger, verbose=verbose)
|
227
232
|
|
228
233
|
# attempting to get the lock will raise NoNetwork if there is no network and the lock will not be set, catch and reemit that in this try block
|
229
234
|
lock_fd = get_data_lock(path, 'pull_data')
|
@@ -248,13 +253,13 @@ def pull_data(path=None, version=None, force=False, logger=None, verbose=None):
|
|
248
253
|
if measuresVersion == expectedMeasuresVersion:
|
249
254
|
# no pull is necessary
|
250
255
|
do_pull = False
|
251
|
-
print_log_messages('pull_data requested "release" versions of casarundata and measures are already installed.', logger)
|
256
|
+
print_log_messages('pull_data requested "release" versions of casarundata and measures are already installed.', logger, verbose=verbose)
|
252
257
|
# otherwise this is a release pull and even if the measuresVersion is 'unknown' or 'invalid' we should proceed with a pull at this point
|
253
258
|
# problems with casarundata path will have been caught before
|
254
259
|
else:
|
255
260
|
# nothing to do here, already at the expected casarundata version and a pull is not being forced and this is not a release pull
|
256
261
|
do_pull = False
|
257
|
-
print_log_messages('pull_data requested version is already installed.', logger)
|
262
|
+
print_log_messages('pull_data requested version is already installed.', logger, verbose=verbose)
|
258
263
|
|
259
264
|
# a version of 'invalid', 'error', or 'unknown' is a surprise here, likely caused by something else doing something
|
260
265
|
# incompatible with this attempt
|
@@ -274,7 +279,7 @@ def pull_data(path=None, version=None, force=False, logger=None, verbose=None):
|
|
274
279
|
if do_pull:
|
275
280
|
# do not clean the lock file contents at this point unless do_pull_data returns normally
|
276
281
|
clean_lock = False
|
277
|
-
do_pull_data(path, version, installed_files, currentVersion, currentDate, logger)
|
282
|
+
do_pull_data(path, version, installed_files, currentVersion, currentDate, logger, verbose)
|
278
283
|
clean_lock = True
|
279
284
|
if namedVersion:
|
280
285
|
# a specific version has been requested, set the times on the measures readme.txt to now to avoid
|
@@ -16,45 +16,89 @@ def read_readme(path):
|
|
16
16
|
"""
|
17
17
|
Read and parse the contents of a readme.txt file used by casaconfig.
|
18
18
|
|
19
|
-
A dictionary containing the 'version', 'date', and 'extra' (containing
|
19
|
+
A dictionary containing the 'version', 'date', 'site', and 'extra' (containing
|
20
20
|
a list of optional extra lines found). On error, the return values is None.
|
21
21
|
|
22
22
|
The extra lines are stripped and do not include lines begining with '#'
|
23
23
|
|
24
24
|
The format is assumed to be:
|
25
25
|
a line begining with #, which is ignored.
|
26
|
+
a line "site: the site url string"
|
26
27
|
a line "version : the versions string"
|
27
28
|
a line "date : the date"
|
28
29
|
optional extra lines (the manifest of installed files for the main readme)
|
29
30
|
|
30
|
-
The version
|
31
|
+
The version, site and date strings are stripped of leading and trailing whitespace.
|
32
|
+
|
33
|
+
The site string only appears in measures data and is missing is early readme
|
34
|
+
files for measures data. If no site string is seen the value in the dictionary
|
35
|
+
is None.
|
36
|
+
|
37
|
+
The version and date strings are required. If they are not found a BadReadme
|
38
|
+
exception is raised.
|
31
39
|
|
32
40
|
Parameters
|
33
41
|
- path (str) - the path to the file to be read
|
34
42
|
|
35
43
|
Returns
|
36
|
-
Dictionary of '
|
37
|
-
'extra' (a list of any extra lines found).
|
44
|
+
Dictionary of 'site' ( the site URL or None), 'version' (the version string),
|
45
|
+
'date' (the date string), 'extra' (a list of any extra lines found).
|
46
|
+
The return value is None on error except that format errors raise
|
47
|
+
a BadReadme exception.
|
48
|
+
|
49
|
+
Raises
|
50
|
+
- casaconfig.BadReadme - raised when there is a format error in the file at path
|
38
51
|
"""
|
39
52
|
|
40
53
|
import os
|
54
|
+
from casaconfig import BadReadme
|
41
55
|
|
56
|
+
site = None
|
42
57
|
version = ""
|
43
58
|
date = ""
|
44
59
|
extra = []
|
45
60
|
result = None
|
46
|
-
|
61
|
+
|
47
62
|
try:
|
48
63
|
with open(path, 'r') as fid:
|
49
64
|
readmeLines = fid.readlines()
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
65
|
+
# order is unimportant except the first line must start with
|
66
|
+
# an "#" and the second line starting with "#" indicates the
|
67
|
+
# start of the "extra" lines
|
68
|
+
# duplicate instances of the same key in key : value lines are accepted
|
69
|
+
# the last value associated with key is used, that should never happen.
|
70
|
+
inExtraLines = False
|
71
|
+
if readmeLines[0][0] != '#':
|
72
|
+
raise BadReadme('Readme file missing required "#" at start of first line, %s' % path)
|
73
|
+
for line in readmeLines[1:]:
|
74
|
+
if inExtraLines and not (line[0] == '#'):
|
75
|
+
extra.append(line.strip())
|
76
|
+
elif line[0] == '#':
|
77
|
+
inExtraLines = True
|
78
|
+
else:
|
79
|
+
splitLine = line.split(':')
|
80
|
+
if len(splitLine) < 2:
|
81
|
+
raise BadReadme('A line did not have an expected ":" separating into at least two parts, %s' % path)
|
82
|
+
key = splitLine[0].strip()
|
83
|
+
if key == 'site':
|
84
|
+
# the URL likely also has a ":" so rejoin the second part and then strip that
|
85
|
+
siteURL = ":".join(splitLine[1:])
|
86
|
+
site = siteURL.strip()
|
87
|
+
elif key == 'version':
|
88
|
+
version = splitLine[1].strip()
|
89
|
+
elif key == 'date':
|
90
|
+
date = splitLine[1].strip()
|
91
|
+
# anything else is OK and silently ignored
|
92
|
+
result = {'site':site, 'version':version, 'date':date, 'extra':extra}
|
93
|
+
except BadReadme as exc:
|
94
|
+
# reraise it
|
95
|
+
raise
|
96
|
+
except Exception as exc:
|
97
|
+
# silently return None, handled elsewhere
|
58
98
|
result = None
|
59
99
|
|
100
|
+
# require that date and version are now set in result
|
101
|
+
if result is not None and ((len(result['version'])==0) or (len(result['date'])==0)):
|
102
|
+
raise BadReadme('Readme file missing required version or date fields, %s' % path)
|
103
|
+
|
60
104
|
return result
|
@@ -32,12 +32,12 @@ def set_casacore_path(path=None):
|
|
32
32
|
None
|
33
33
|
|
34
34
|
"""
|
35
|
-
import
|
35
|
+
import importlib.resources
|
36
36
|
import os
|
37
37
|
import re
|
38
38
|
import sys
|
39
39
|
|
40
|
-
if path is None: path =
|
40
|
+
if path is None: path = str(importlib.resources.files('casaconfig').joinpath('data/'))
|
41
41
|
path = os.path.abspath(os.path.expanduser(path))
|
42
42
|
|
43
43
|
rctext = 'measures.directory: %s\n' % path
|
casaconfig/private/summary.py
CHANGED
@@ -80,6 +80,9 @@ def summary(configDict = None):
|
|
80
80
|
msg += "; legacy data not maintained by casaconfig"
|
81
81
|
elif measVers == "error":
|
82
82
|
msg += "; unexpected readme.txt file, measures should be reinstalled"
|
83
|
+
measSite = dataInfo['measures']['site']
|
84
|
+
if measSite is not None and len(measSite) > 0:
|
85
|
+
msg = msg + " site : " + measSite
|
83
86
|
print(msg)
|
84
87
|
|
85
88
|
if (dataInfo['release'] is None):
|