casaconfig 0.0.79__tar.gz → 0.0.81__tar.gz

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.
Files changed (34) hide show
  1. {casaconfig-0.0.79/casaconfig.egg-info → casaconfig-0.0.81}/PKG-INFO +1 -1
  2. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/__main__.py +10 -5
  3. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/config.py +3 -8
  4. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/data_available.py +2 -2
  5. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/data_update.py +91 -37
  6. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/do_auto_updates.py +10 -7
  7. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/do_pull_data.py +1 -1
  8. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/get_data_info.py +58 -46
  9. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/measures_update.py +118 -49
  10. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/print_log_messages.py +11 -2
  11. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/pull_data.py +62 -29
  12. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/update_all.py +9 -4
  13. {casaconfig-0.0.79 → casaconfig-0.0.81/casaconfig.egg-info}/PKG-INFO +1 -1
  14. {casaconfig-0.0.79 → casaconfig-0.0.81}/setup.py +1 -1
  15. {casaconfig-0.0.79 → casaconfig-0.0.81}/LICENSE +0 -0
  16. {casaconfig-0.0.79 → casaconfig-0.0.81}/MANIFEST.in +0 -0
  17. {casaconfig-0.0.79 → casaconfig-0.0.81}/README.md +0 -0
  18. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/__init__.py +0 -0
  19. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/__init__.py +0 -0
  20. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/casasiteconfig.py +0 -0
  21. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/config_defaults.py +0 -0
  22. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/config_defaults_static.py +0 -0
  23. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/get_argparser.py +0 -0
  24. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/get_config.py +0 -0
  25. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/get_data_lock.py +0 -0
  26. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/io_redirect.py +0 -0
  27. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/measures_available.py +0 -0
  28. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/read_readme.py +0 -0
  29. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig/private/set_casacore_path.py +0 -0
  30. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig.egg-info/SOURCES.txt +0 -0
  31. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig.egg-info/dependency_links.txt +0 -0
  32. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig.egg-info/requires.txt +0 -0
  33. {casaconfig-0.0.79 → casaconfig-0.0.81}/casaconfig.egg-info/top_level.txt +0 -0
  34. {casaconfig-0.0.79 → casaconfig-0.0.81}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: casaconfig
3
- Version: 0.0.79
3
+ Version: 0.0.81
4
4
  Summary: CASA Operational Configuration Package
5
5
  Home-page: https://github.com/casangi/casaconfig
6
6
  Author: National Radio Astronomy Observatory
@@ -7,6 +7,8 @@ parser = get_argparser(add_help=True)
7
7
  # get_argparser supplies configfile, noconfig, nositeconfig
8
8
  # add measurespath, pull-data, data-update, measures-update, update-all, reference-testing, current-data
9
9
 
10
+ parser.prog = "casaconfig"
11
+
10
12
  # measurespath will default to the value in config if not set here
11
13
  parser.add_argument( "--measurespath", dest='measurespath', default=None,
12
14
  help="location of casarundata")
@@ -23,6 +25,8 @@ parser.add_argument( "--reference-testing", action='store_const', const=True, de
23
25
  help="set measurespath to the casarundata when this version was produced, used for testing purposes")
24
26
  parser.add_argument( "--current-data", dest='currentdata', action='store_const', const=True, default=False,
25
27
  help="print out a summary of the current casarundata and measures data installed in measurespath and then exit")
28
+ parser.add_argument("--force", dest='force', action='store_const', const=True, default=False,
29
+ help="force an update using the force=True option to update_all, data_update, and measures_update")
26
30
 
27
31
  # initialize the configuration to be used
28
32
  flags,args = parser.parse_known_args(sys.argv)
@@ -65,8 +69,8 @@ if flags.currentdata:
65
69
 
66
70
  # measures
67
71
  measuresInfo = dataInfo['measures']
68
- if measuresInfo is None or casarunInfo['version'] == "invalid":
69
- print("No measures data found (missing or unexpected readme.txt, not obviously legaca measures data).")
72
+ if measuresInfo is None or measuresInfo['version'] == "invalid":
73
+ print("No measures data found (missing or unexpected readme.txt, not obviously legacy measures data).")
70
74
  elif measuresInfo['version'] == "unknown":
71
75
  print("measures version is unknown (probably legacy measures data not maintained by casaconfig).")
72
76
  else:
@@ -83,17 +87,18 @@ else:
83
87
  # ignore all other options
84
88
  else:
85
89
  # the update options, update all does everything, no need to invoke anything else
90
+ print("Checking for updates into %s" % measurespath)
86
91
  if flags.updateall:
87
- casaconfig.update_all(measurespath)
92
+ casaconfig.update_all(measurespath,force=flags.force)
88
93
  else:
89
94
  # do any pull_update first
90
95
  if flags.pulldata:
91
96
  casaconfig.pull_data(measurespath)
92
97
  # then data_update, not necessary if pull_data just happened
93
98
  if flags.dataupdate and not flags.pulldata:
94
- casaconfig.data_update(measurespath)
99
+ casaconfig.data_update(measurespath, force=flags.force)
95
100
  # then measures_update
96
101
  if flags.measuresupdate:
97
- casaconfig.measures_update(measurespath)
102
+ casaconfig.measures_update(measurespath, force=flags.force)
98
103
 
99
104
  sys.exit(0)
@@ -124,14 +124,9 @@ for __v in __defaults:
124
124
  if globals()[__v] is not None:
125
125
  globals()[__v] = __os.path.abspath(__os.path.expanduser(globals()[__v]))
126
126
  else:
127
- # debugging for now
128
- print("None value seen while expanding path-like fields for config parameter %s" % __v)
129
- print("__loaded_config_files : ")
130
- for __f in __loaded_config_files:
131
- print(" %s" % __f)
132
- print("__config_files : ")
133
- for __f in __config_files:
134
- print(" %s" % __f)
127
+ pass
128
+ # debugging
129
+ # print("None value seen while expanding path-like fields for config parameter %s" % __v)
135
130
 
136
131
  def load_success( ):
137
132
  return __loaded_config_files
@@ -51,8 +51,8 @@ def data_available():
51
51
  if tag == 'a':
52
52
  for (name, value) in attrs:
53
53
  # only care if this is an href and the value starts with
54
- # casarundata and has '.tar.' somewhere later
55
- if name == 'href' and (value.startswith('casarundata') and (value.rfind('.tar')>11)):
54
+ # casarundata and has '.tar.' somewhere later and does not end in .md5
55
+ if name == 'href' and (value.startswith('casarundata') and (value.rfind('.tar')>11) and (value[-4:] != '.md5')):
56
56
  # only add it to the list if it's not already there
57
57
  if (value not in self.rundataList):
58
58
  self.rundataList.append(value)
@@ -20,6 +20,8 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
20
20
  Check for updates to the installed casarundata and install the update or change to
21
21
  the requested version when appropriate.
22
22
 
23
+ If no update is necessary then this function will silently return.
24
+
23
25
  The path must contain a previously installed version of casarundata.
24
26
  Use pull_data to install casarundata into a new path (empty or does not exist).
25
27
 
@@ -34,13 +36,14 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
34
36
  and nothing is updated. Release version information is only available in
35
37
  monolithic CASA installations.
36
38
 
37
- If a specific version is not requested (the default) **and** the version currently
38
- at path was installed today then this function does nothing even if there is a more
39
- recent version available from the CASA server.
39
+ If a specific version is not requested (the default) and a check for the
40
+ versions available for installation at path has been done within the past
41
+ 24 hours then this function does nothing even if there is a more
42
+ recent version available from the CASA server unless force is True.
40
43
 
41
- If force is True then the requested version is installed even if that version
42
- is already installed or a version was previously installed today (there may be a
43
- newer version available).
44
+ If force is True then the requested version (or the latest version available
45
+ now) is installed even if that version is already installed or a check for the
46
+ latest version has been done within the past 24 hours.
44
47
 
45
48
  A text file (readme.txt at path) records the version string, the date
46
49
  when that version was installed in path, and the files installed into path. That file
@@ -92,7 +95,7 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
92
95
  Parameters
93
96
  - path (str=None) - Folder path to update. Must contain a valid readme.txt. If not set then config.measurespath is used.
94
97
  - version (str=None) - Version of casarundata to retrieve (usually in the form of casarundata-x.y.z.tar.gz, see data_available()). Default None retrieves the latest.
95
- - force (bool=False) - If True, always re-download the casarundata. Default False will not download casarundata if already updated today unless the version parameter is specified and different from what was last downloaded.
98
+ - force (bool=False) - If True, always re-download the casarundata. Default False will not download casarundata if updated within the past day unless the version parameter is specified and different from what was last downloaded.
96
99
  - logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal.
97
100
  - 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.
98
101
 
@@ -107,6 +110,7 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
107
110
  from .data_available import data_available
108
111
  from .print_log_messages import print_log_messages
109
112
  from .get_data_lock import get_data_lock
113
+ from .pull_data import pull_data
110
114
  from .do_pull_data import do_pull_data
111
115
  from .get_data_info import get_data_info
112
116
 
@@ -119,6 +123,11 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
119
123
  print_log_messages('path is None and has not been set in config.measurespath (probably casasiteconfig.py). Provide a valid path and retry.', logger, True)
120
124
  return
121
125
 
126
+ # when a specific version is requested then the measures readme.txt that is part of that version
127
+ # will get a timestamp of now so that default measures updates won't happen for a day unless the
128
+ # force argument is used for measures_update
129
+ namedVersion = version is not None
130
+
122
131
  path = os.path.expanduser(path)
123
132
  readme_path = os.path.join(path, 'readme.txt')
124
133
 
@@ -130,12 +139,19 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
130
139
  print_log_messages('force must be False when auto_update_rules is True', logger, True)
131
140
  return
132
141
  if (not os.path.isdir(path)) or (os.stat(path).st_uid != os.getuid()):
133
- print_log_messages('path must exist as a directory and it must be owned by the user when auto_update_rules is True', logger, True)
142
+ msgs = []
143
+ msgs.append("Warning: path must exist as a directory and it must be owned by the user, path = %s" % path)
144
+ msgs.append("Warning: no data updates are possible on this path by this user.")
145
+ print_log_messages(msgs, logger, False)
134
146
  return
135
147
 
136
148
  if not os.path.exists(readme_path):
137
- print_log_messages('No readme.txt file found at path. Nothing updated or checked.', logger, True);
138
- return
149
+ # path must exist and it must be empty in order to continue
150
+ if not os.path.exists(path) or (len(os.listdir(path)) > 0):
151
+ print_log_messages('No readme.txt file found at path. Nothing updated or checked.', logger, True);
152
+ return
153
+ # ok to install a fresh copy, use pull_data directly
154
+ return pull_data(path,version,force,logger)
139
155
 
140
156
  # path must be writable with execute bit set
141
157
  if (not os.access(path, os.W_OK | os.X_OK)) :
@@ -147,42 +163,53 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
147
163
  installed_files = []
148
164
  currentVersion = []
149
165
  currentDate = []
166
+ ageRecent = False
150
167
 
151
168
  dataReadmeInfo = get_data_info(path, logger, type='casarundata')
152
169
 
153
170
  if dataReadmeInfo is None or dataReadmeInfo['version'] == 'invalid':
154
- print_log_messages('The readme.txt file at path could not be read as expected', logger, True)
155
- print_log_messages('choose a different path or empty this path and try again using pull_data', logger, True)
171
+ msgs = []
172
+ msgs.append('The readme.txt file at path could not be read as expected')
173
+ msgs.append('choose a different path or empty this path and try again using pull_data')
174
+ print_log_messages(msgs, logger, True)
156
175
  # no lock has been set yet, safe to simply return here
157
176
  return
158
177
 
159
178
  currentVersion = dataReadmeInfo['version']
160
179
  currentDate = dataReadmeInfo['date']
161
180
  installed_files = dataReadmeInfo['manifest']
181
+ if dataReadmeInfo['age'] is not None:
182
+ ageRecent = dataReadmeInfo['age'] < 1.0
162
183
 
163
184
  if currentVersion is 'unknown':
164
- print_log_messages('The data update path appears to be casarundata but no readme.txt file was found', logger, False)
165
- print_log_messages('A data update is not possible but CASA use of this data may be OK.', logger, False)
166
- print_log_messages('casaconfig must first install the casarundata in path for data_update to run as expected on that path', logger, False)
185
+ msgs = []
186
+ msgs.append('The data update path appears to be casarundata but no readme.txt file was found')
187
+ msgs.append('A data update is not possible but CASA use of this data may be OK.')
188
+ msgs.append('casaconfig must first install the casarundata in path for data_update to run as expected on that path')
189
+ print_log_messages(msgs, logger, True)
167
190
 
168
191
  if (len(installed_files) == 0):
169
192
  # this shouldn't happen
170
- print_log_messages('The readme.txt file at path did not contain the expected list of installed files', logger, True)
171
- print_log_messages('choose a different path or empty this path and try again using pull_data', logger, True)
193
+ msgs = []
194
+ msgs.append('The readme.txt file at path did not contain the expected list of installed files')
195
+ msgs.append('choose a different path or empty this path and try again using pull_data')
196
+ print_log_messages(msgs, logger, True)
172
197
  # no lock has been set yet, safe to simply return here
173
198
  return
174
199
 
175
- today_string = datetime.today().strftime('%Y-%m-%d')
176
- if version is None and force is False and currentDate == today_string:
177
- # if version is None, currentDate is today and force is False then return without checking for any newer versions
178
- print_log_messages('data_update current casarundata detected in %s, using version %s' % (path, currentVersion), logger)
200
+ if version is None and force is False and ageRecent:
201
+ # if version is None, the readme is less than 1 day old and force is False then return without checking for any newer versions
202
+ # normal use is silent, this line is useful during debugging
203
+ # print_log_messages('data_update latest version checked recently in %s, using version %s' % (path, currentVersion), logger)
179
204
  # no lock has been set yet, safe to simply return here
180
205
  return
181
206
 
182
207
  available_data = data_available()
183
208
  requestedVersion = version
209
+ latestVersion = False
184
210
 
185
211
  if requestedVersion is None:
212
+ latestVersion = True
186
213
  requestedVersion = available_data[-1]
187
214
 
188
215
  expectedMeasuresVersion = None
@@ -190,7 +217,7 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
190
217
  # use the release version from get_data_info
191
218
  releaseInfo = get_data_info()['release']
192
219
  if releaseInfo is None:
193
- print_log_messages('No release info found, pull_data can not continue', logger, True)
220
+ print_log_messages('No release info found, data_update can not continue', logger, True)
194
221
  return
195
222
  requestedVersion = releaseInfo['casarundata']
196
223
  expectedMeasuresVersion = releaseInfo['measures']
@@ -213,12 +240,20 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
213
240
  force = False
214
241
  # if measuresReadmeInfo is None then that's a problem and force remains True, this also catches 'invalid' and 'unknown' measures versions, which should not happen here
215
242
  if not force:
216
- print_log_messages('data_update requested "release" version of casarundata and measures are already installed.', logger)
243
+ # normal use is silent, this line is useful during debugging
244
+ # print_log_messages('data_update requested "release" version of casarundata and measures are already installed.', logger)
217
245
  # no lock has been set yet, safe to simply return here
218
246
  return
219
247
  else:
220
248
  # normal usage, ok to return now
221
- print_log_messages('Requested casarundata is installed in %s, using version %s' % (path, currentVersion), logger)
249
+ # normal use is silent, commented out lines are useful during debugging
250
+ if latestVersion:
251
+ # print_log_messages('The latest version is already installed in %s, using version %s' % (path, currentVersion), logger)
252
+ # touch the dates of the readme to prevent a future check on available data for the next 24 hours
253
+ os.utime(readme_path)
254
+ #else:
255
+ # print_log_messages('Requested casarundata is installed in %s, using version %s' % (path, currentVersion), logger)
256
+
222
257
  # no lock has been set yet, safe to simply return here
223
258
  return
224
259
 
@@ -231,10 +266,12 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
231
266
  lock_fd = get_data_lock(path, 'data_update')
232
267
  # if lock_fd is None it means the lock file was not empty - because we know that path exists at this point
233
268
  if lock_fd is None:
234
- print_log_messages('The lock file at %s is not empty.' % path, logger, True)
235
- print_log_messages('A previous attempt to update path may have failed or exited prematurely.', logger, True)
236
- print_log_messages('Remove the lock file and set force to True with the desired version (default to most recent).', logger, True)
237
- print_log_messages('It may be best to completely repopulate path using pull_data and measures_update.', logger, True)
269
+ msgs = []
270
+ msgs.append('The lock file at %s is not empty.' % path)
271
+ msgs.append('A previous attempt to update path may have failed or exited prematurely.')
272
+ msgs.append('Remove the lock file and set force to True with the desired version (default to most recent).')
273
+ msgs.append('It may be best to completely repopulate path using pull_data and measures_update.')
274
+ print_log_messages(msgs, logger, True)
238
275
  return
239
276
 
240
277
  do_update = True
@@ -244,6 +281,7 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
244
281
  currentVersion = dataReadmeInfo['version']
245
282
  currentDate = dataReadmeInfo['date']
246
283
  installedFiles = dataReadmeInfo['manifest']
284
+ ageRecent = dataReadmeInfo['age'] < 1.0
247
285
  if ((currentVersion == requestedVersion) and (not force)):
248
286
  if expectedMeasuresVersion is not None:
249
287
  # this is a 'release' update request, need to check that the measures version is also now OK
@@ -257,33 +295,49 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
257
295
  print_log_messages('data update requested "release" version of casarundata and measures are already installed.', logger)
258
296
  else:
259
297
  # nothing to do here, already at the expected version and an update is not being forced
298
+ if latestVersion:
299
+ print_log_messages('The latest version is already installed, using version %s' % currentVersion, logger)
300
+ # touch the dates of the readme to prevent a future check on available data for the next 24 hours
301
+ os.utime(readme_path)
302
+ else:
303
+ print_log_messages('requested version is already installed.', logger)
260
304
  do_update = False
261
- print_log_messages('data_update requested version is already installed.', logger)
262
305
 
263
306
  if do_update:
264
307
  # update is still on, check the manifest
265
308
  if len(installed_files) == 0:
266
309
  # this shouldn't happen, do not do an update
267
310
  do_update = False
268
- print_log_messages('The readme.txt file read at path did not contain the expected list of installed files', logger, True)
269
- print_log_messages('This should not happen unless multiple sessions are trying to update data at the same time and one experienced problems or was done out of sequence', logger, True)
270
- print_log_messages('Check for other updates in process or choose a different path or clear out this path and try again using pull_data or update_all', logger, True)
311
+ msgs = []
312
+ msgs.append('The readme.txt file read at path did not contain the expected list of installed files')
313
+ msgs.append('This should not happen unless multiple sessions are trying to update data at the same time and one experienced problems or was done out of sequence')
314
+ msgs.append('Check for other updates in process or choose a different path or clear out this path and try again using pull_data or update_all')
315
+ print_log_messages(msgs, logger, True)
271
316
  else:
272
317
  # this shouldn't happen, do not do an update
273
318
  do_update = False
274
- print_log_messages('Unexpected problem reading readme.txt file during data_update, can not safely update to the requested version', logger, True)
275
- print_log_messages('This should not happen unless multiple sessions are trying to update at the same time and one experienced problems or was done out of sequence', logger, True)
276
- print_log_messages('Check for other updates in process or choose a different path or clear out this path and try again using pull_data or update_all', logger, True)
319
+ msgs = []
320
+ msgs.append('Unexpected problem reading readme.txt file during data_update, can not safely update to the requested version')
321
+ msgs.append('This should not happen unless multiple sessions are trying to update at the same time and one experienced problems or was done out of sequence')
322
+ msgs.append('Check for other updates in process or choose a different path or clear out this path and try again using pull_data or update_all')
323
+ print_log_messages(msgs, logger, True)
277
324
 
278
325
  if do_update:
279
326
  do_pull_data(path, requestedVersion, installed_files, currentVersion, currentDate, logger)
327
+ if namedVersion is not None:
328
+ # a specific version has been requested, set the times on the measures readme.txt to now to avoid
329
+ # a default update of the measures data without using the force argument
330
+ measuresReadmePath = os.path.join(path,'geodetic/readme.txt')
331
+ os.utime(measuresReadmePath)
280
332
 
281
333
  # truncate the lock file
282
334
  lock_fd.truncate(0)
283
335
 
284
336
  except Exception as exc:
285
- print_log_messages('ERROR! : Unexpected exception while populating casarundata version %s to %s' % (requestedVersion, path), logger, True)
286
- print_log_messages('ERROR! : %s' % exc, logger, True)
337
+ msgs = []
338
+ msgs.append('ERROR! : Unexpected exception while populating casarundata version %s to %s' % (requestedVersion, path))
339
+ msgs.append('ERROR! : %s' % exc)
340
+ print_log_messages(msgs, logger, True)
287
341
  # leave the contents of the lock file as is to aid in debugging
288
342
  # import traceback
289
343
  # traceback.print_exc()
@@ -45,20 +45,23 @@ def do_auto_updates(configDict, logger=None):
45
45
  from .print_log_messages import print_log_messages
46
46
  from .data_update import data_update
47
47
  from .measures_update import measures_update
48
-
48
+
49
49
  if configDict.measurespath is None:
50
50
  # likely still unset in casasiteconfig.py, suggest setting it in ~/.casa/config.py
51
51
  # or ask the site administrator (which may be the user) to edit casasiteconfig.py
52
52
  # point at the documentation
53
53
  # continue, because things still might work if there are measures in datapath
54
- print_log_messages('measurespath is None in config', logger, True)
55
- print_log_messages('this likely means a casasiteconfig.py was used and measurespath remains unset there.', logger, True)
56
- print_log_messages('Either set measurespath in your config file at ~/.casa/config.py', logger, True)
57
- print_log_messages('or ask the site manager to set that in casasiteconfig.py', logger, True)
58
- print_log_messages('visit https://casadocs.readthedocs.io/en/stable/notebooks/external-data.html for more information', logger, True)
54
+ msgs = []
55
+ msgs.append('measurespath is None in config')
56
+ msgs.append('this likely means a casasiteconfig.py was used and measurespath remains unset there.')
57
+ msgs.append('Either set measurespath in your config file at ~/.casa/config.py')
58
+ msgs.append('or ask the site manager to set that in casasiteconfig.py')
59
+ msgs.append('visit https://casadocs.readthedocs.io/en/stable/notebooks/external-data.html for more information')
59
60
 
60
61
  if (configDict.measures_auto_update or configDict.data_auto_update):
61
- print('\nAuto updates of measures path are not possible because measurespath is not set, skipping auto updates', logger, True)
62
+ msgs.append('Auto updates of measures path are not possible because measurespath is not set, skipping auto updates')
63
+
64
+ print_log_messages(msgs, logger, True)
62
65
 
63
66
  return
64
67
 
@@ -49,7 +49,7 @@ def do_pull_data(path, version, installed_files, currentVersion, currentDate, lo
49
49
 
50
50
  readme_path = os.path.join(path, 'readme.txt')
51
51
 
52
- if (len(installed_files) > 0):
52
+ if (installed_files is not None and len(installed_files) > 0):
53
53
  # remove the previously installed files
54
54
  # remove this readme file so it's not confusing if something goes wrong after this
55
55
  os.remove(readme_path)
@@ -51,9 +51,9 @@ def get_data_info(path=None, logger=None, type=None):
51
51
  expected for casarundata then the version returned for 'casarundata' is 'unknown' and
52
52
  the date is an empty string. In that case the path may contain casarundata from a legacy
53
53
  installation of CASA data. CASA will be able to use the files at this location but they
54
- can not be maintained by casaconfig. If the path is not empty but does not appear to
55
- contain legacy casarundata or the readme.txt file found there can not be read as expected
56
- then the version is 'invalid'.
54
+ can not be maintained by casaconfig. If the path is not empty (except for a possible lock
55
+ file while it's in use but does not appear to contain legacy casarundata or the readme.txt
56
+ file found there can not be read as expected then the version is 'invalid'.
57
57
 
58
58
  If no readme.txt file can be found for the measures at path/geodetic but both the geodetic
59
59
  and ephemeris directories are present in path then the version returned for 'measures' is
@@ -83,10 +83,14 @@ def get_data_info(path=None, logger=None, type=None):
83
83
  result = None
84
84
 
85
85
  import os
86
+ import time
86
87
  import importlib.resources
87
88
  from .print_log_messages import print_log_messages
88
89
  from .read_readme import read_readme
89
90
 
91
+ currentTime = time.time()
92
+ secondsPerDay = 24. * 60. * 60.
93
+
90
94
  if path is None:
91
95
  from .. import config as _config
92
96
  path = _config.measurespath
@@ -106,51 +110,59 @@ def get_data_info(path=None, logger=None, type=None):
106
110
  # casarundata and measures
107
111
 
108
112
  if os.path.isdir(path) and (len(os.listdir(path))>0):
109
- # there's something at path, look for the casarundata readme
110
- if type is None or type=='casarundata':
111
- datareadme_path = os.path.join(path,'readme.txt')
112
- if os.path.exists(datareadme_path):
113
- # the readme exists, get the info
114
- result['casarundata'] = {'version':'error', 'date':'', 'manifest':[]}
115
- readmeContents = read_readme(datareadme_path)
116
- if readmeContents is not None:
117
- currentVersion = readmeContents['version']
118
- currentDate = readmeContents['date']
119
- # the manifest ('extra') must exist with at least 1 entry, otherwise this is no a valid readme file and the version should be 'error'
120
- if len(readmeContents['extra']) > 0:
121
- result['casarundata'] = {'version':currentVersion, 'date':currentDate, 'manifest':readmeContents['extra']}
122
- else:
123
- # does it look like it's probably casarundata?
124
- expected_dirs = ['alma','catalogs','demo','ephemerides','geodetic','gui','nrao']
125
- ok = True
126
- for d in expected_dirs:
127
- if not os.path.isdir(os.path.join(path,d)): ok = False
128
- if ok:
129
- # probably casarundata
130
- result['casarundata'] = {'version':'unknown', 'date':''}
113
+ # if the only thing at path is the lock file then proceed as if path is empty - skip this section
114
+ pathfiles = os.listdir(path)
115
+ if len(pathfiles) == 1 and pathfiles[0] == "data_update.lock":
116
+ pass
117
+ else:
118
+ # there's something at path, look for the casarundata readme
119
+ if type is None or type=='casarundata':
120
+ datareadme_path = os.path.join(path,'readme.txt')
121
+ if os.path.exists(datareadme_path):
122
+ # the readme exists, get the info
123
+ result['casarundata'] = {'version':'error', 'date':'', 'manifest':[], 'age':None}
124
+ readmeContents = read_readme(datareadme_path)
125
+ if readmeContents is not None:
126
+ currentAge = (currentTime - os.path.getmtime(datareadme_path)) / secondsPerDay
127
+ currentVersion = readmeContents['version']
128
+ currentDate = readmeContents['date']
129
+ # the manifest ('extra') must exist with at least 1 entry, otherwise this is no a valid readme file and the version should be 'error'
130
+ if len(readmeContents['extra']) > 0:
131
+ result['casarundata'] = {'version':currentVersion, 'date':currentDate, 'manifest':readmeContents['extra'], 'age':currentAge}
131
132
  else:
132
- # probably not casarundata
133
- result['casarundata'] = {'version':'invalid', 'date':''}
134
-
135
- if type is None or type=='measures':
136
- # look for the measures readme
137
- measuresreadme_path = os.path.join(path,'geodetic/readme.txt')
138
- if os.path.exists(measuresreadme_path):
139
- # the readme exists, get the info
140
- result['measures'] = {'version':'error', 'date':''}
141
- readmeContents = read_readme(measuresreadme_path)
142
- if readmeContents is not None:
143
- currentVersion = readmeContents['version']
144
- currentDate = readmeContents['date']
145
- result['measures'] = {'version':currentVersion,'date':currentDate}
146
- else:
147
- # does it look like it's probably measuresdata?
148
- # path should have ephemerides and geodetic directories
149
- if os.path.isdir(os.path.join(path,'ephemerides')) and os.path.isdir(os.path.join(path,'geodetic')):
150
- result['measures'] = {'version':'unknown', 'date':''}
133
+ # does it look like it's probably casarundata?
134
+ expected_dirs = ['alma','catalogs','demo','ephemerides','geodetic','gui','nrao']
135
+ ok = True
136
+ for d in expected_dirs:
137
+ if not os.path.isdir(os.path.join(path,d)): ok = False
138
+ if ok:
139
+ # probably casarundata
140
+ result['casarundata'] = {'version':'unknown', 'date':'', 'manifest': None,'age':None}
141
+ else:
142
+ # probably not casarundata
143
+ # this is invalid, unexpected things are happening there
144
+ result['casarundata'] = {'version':'invalid', 'date':'', 'manifest': None, 'age':None}
145
+
146
+ if type is None or type=='measures':
147
+ # look for the measures readme
148
+ measuresreadme_path = os.path.join(path,'geodetic/readme.txt')
149
+ if os.path.exists(measuresreadme_path):
150
+ # the readme exists, get the info
151
+ result['measures'] = {'version':'error', 'date':'', 'age':None}
152
+ readmeContents = read_readme(measuresreadme_path)
153
+ if readmeContents is not None:
154
+ currentVersion = readmeContents['version']
155
+ currentDate = readmeContents['date']
156
+ currentAge = (currentTime - os.path.getmtime(measuresreadme_path)) / secondsPerDay
157
+ result['measures'] = {'version':currentVersion,'date':currentDate,'age':currentAge}
151
158
  else:
152
- # probably not measuresdata
153
- result['measures'] = {'version':'invalid', 'date':''}
159
+ # does it look like it's probably measuresdata?
160
+ # path should have ephemerides and geodetic directories
161
+ if os.path.isdir(os.path.join(path,'ephemerides')) and os.path.isdir(os.path.join(path,'geodetic')):
162
+ result['measures'] = {'version':'unknown', 'date':'', 'age':None}
163
+ else:
164
+ # probably not measuresdata
165
+ result['measures'] = {'version':'invalid', 'date':'', 'age':None}
154
166
 
155
167
  if type is None or type=='release':
156
168
  # release data versions
@@ -15,12 +15,14 @@
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):
18
+ def measures_update(path=None, version=None, force=False, logger=None, auto_update_rules=False, use_astron_obs_table=False):
19
19
  """
20
- Retrieve IERS data used for measures calculations from the ASTRON server
20
+ Update or install the IERS data used for measures calculations from the ASTRON server at path.
21
21
 
22
22
  Original data source used by ASTRON is here: https://www.iers.org/IERS/EN/DataProducts/data.html
23
23
 
24
+ If no update is necessary then this function will silently return.
25
+
24
26
  CASA maintains a separate Observatories table which is available in the casarundata
25
27
  collection through pull_data and data_update. The Observatories table found at ASTRON
26
28
  is not installed by measures_update and any Observatories file at path will not be changed
@@ -34,9 +36,13 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
34
36
  If the version requested matches the one in that text file then this function does
35
37
  nothing unless force is True.
36
38
 
37
- If a specific version is not requested (the default) and the date in that text file
38
- is today, then this function does nothing unless force is True even if there is a more
39
- recent version available from the ASTRON server.
39
+ If a specific version is not requested (the default) and the modification time of that text
40
+ file is less than 24 hrs before now then this function does nothing unless force is True. When this
41
+ function checks for a more recent version and finds that the installed version is the most recent
42
+ then modification time of that text file is checked to the current time even though nothing has
43
+ changed in path. This limits the number of attempts to update the measures data (including checking f\
44
+ or more recent data) to once per day. When the force argument is True and a specific version is
45
+ not requested then this function always checks for the latest version.
40
46
 
41
47
  When auto_update_rules is True then path must exist and contain the expected readme.txt file.
42
48
  Path must be owned by the user, force must be False, and the version must be None. This
@@ -96,7 +102,7 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
96
102
  Parameters
97
103
  - 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.
98
104
  - version (str=None) - Version of measures data to retrieve (usually in the form of yyyymmdd-160001.ztar, see measures_available()). Default None retrieves the latest.
99
- - force (bool=False) - If True, always re-download the measures data. Default False will not download measures data if already updated today unless the version parameter is specified and different from what was last downloaded.
105
+ - 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.
100
106
  - logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal
101
107
  - 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.
102
108
 
@@ -120,6 +126,7 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
120
126
  from .print_log_messages import print_log_messages
121
127
  from .get_data_lock import get_data_lock
122
128
  from .get_data_info import get_data_info
129
+ from .measures_available import measures_available
123
130
 
124
131
  if path is None:
125
132
  from .. import config as _config
@@ -140,7 +147,10 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
140
147
  print_log_messages('force must be False when auto_update_rules is True', logger, True)
141
148
  return
142
149
  if (not os.path.isdir(path)) or (os.stat(path).st_uid != os.getuid()):
143
- print_log_messages('path must exist as a directory and it must be owned by the user when auto_update_rules is True', logger, True)
150
+ msgs = []
151
+ msgs.append("Warning: path must exist as a directory and it must be owned by the user, path = %s" % path)
152
+ msgs.append("Warning: no measures auto update is possible on this path by this user.")
153
+ print_log_messages(msgs, logger, False)
144
154
  return
145
155
 
146
156
  if not os.path.exists(path):
@@ -148,8 +158,7 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
148
158
  os.makedirs(path)
149
159
 
150
160
  current = None
151
- updated = None
152
- today_string = datetime.today().strftime('%Y-%m-%d')
161
+ ageRecent = False
153
162
 
154
163
  # first, does this look like it needs to be updated
155
164
 
@@ -157,17 +166,19 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
157
166
  readmeInfo = get_data_info(path, logger, type='measures')
158
167
  if readmeInfo is not None:
159
168
  current = readmeInfo['version']
160
- updated = readmeInfo['date']
169
+ if readmeInfo['age'] is not None:
170
+ ageRecent = readmeInfo['age'] < 1.0
161
171
 
162
172
  if not force:
163
- # don't re-download the same data
164
- if ((version is not None) and (version == current)) or ((version is None) and (updated == today_string)):
165
- print_log_messages('measures_update current measures detected in %s, using version %s' % (path, current), logger)
173
+ # don't check for new version if the age is less than 1 day
174
+ if version is None and ageRecent:
175
+ # normal use is silent, this line is useful during debugging
176
+ # print_log_messages('measures_update latest version checked recently in %s, using version %s' % (path, current), logger)
166
177
  return
167
178
 
168
179
  # don't overwrite something that looks bad unless forced to do so
169
180
  if current == 'invalid':
170
- print_log_messages('the measures readme.txt file could not be read as expected, an update can not proceed unless force is True', logger, True)
181
+ print_log_messages('The measures readme.txt file could not be read as expected, an update can not proceed unless force is True', logger, True)
171
182
  return
172
183
 
173
184
  # don't overwrite something that looks like valid measures data unless forced to do so
@@ -175,6 +186,38 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
175
186
  print_log_messages('The measures data at %s is not maintained by casaconfig and so it can not be updated unless force is True' % path, logger, True)
176
187
  return
177
188
 
189
+ checkVersion = version
190
+ if checkVersion is None:
191
+ # get the current most recent version
192
+ try:
193
+ checkVersion = measures_available()[-1]
194
+ except:
195
+ # unsure what happened, leave it at none, which will trigger an update attempt, which might work
196
+ pass
197
+
198
+ # don't re-download the same data
199
+ if (checkVersion is not None) and (checkVersion == current):
200
+ # normal use is silent, this line is useful during debugging
201
+ # print_log_messages('measures_update requested version already installed in %s' % path, logger)
202
+ # update the age of the readme to now
203
+ try:
204
+ readme_path = os.path.join(path,'geodetic/readme.txt')
205
+ # readme_path should already exist if it's here
206
+ os.utime(readme_path)
207
+ except:
208
+ # unsure what happened, everything otherwise is fine if we got here, ignore this error
209
+ pass
210
+
211
+ return
212
+
213
+ # don't do anything unless the Observatories table is already installed as expected
214
+ obsTabPath = os.path.join(path,'geodetic/Observatories')
215
+ if not os.path.isdir(obsTabPath):
216
+ print("Error: the Observatories table was not found as expected in %s" % path, logger, True)
217
+ print("Either install casarundata first or set use_astron_obs_table and force to be True when using measures_update.", logger, True)
218
+ print("Note that the Observatories table provided in the Astron measures tarfile is not the same as that maintained by CASA", logger, True)
219
+ return
220
+
178
221
  # path must be writable with execute bit set
179
222
  if (not os.access(path, os.W_OK | os.X_OK)) :
180
223
  print_log_messages('No permission to write to the measures path, cannot update : %s' % path, logger, True)
@@ -185,15 +228,18 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
185
228
  # lock the measures_update.lock file
186
229
  lock_fd = None
187
230
  try:
188
- print_log_messages('measures_update measures need to be updated, acquiring the lock ... ', logger)
231
+ print_log_messages('measures_update ... acquiring the lock ... ', logger)
189
232
 
190
233
  lock_fd = get_data_lock(path, 'measures_update')
191
234
  # if lock_fd is None it means the lock file was not empty - because we know that path exists at this point
192
235
  if lock_fd is None:
193
- print_log_messages('The lock file at %s is not empty.' % path, logger, True)
194
- print_log_messages('A previous attempt to update path may have failed or exited prematurely.', logger, True)
195
- print_log_messages('Remove the lock file and set force to True with the desired version (default to most recent).', logger, True)
196
- print_log_messages('It may be best to completely repopulate path using pull_data and measures_update.', logger, True)
236
+ # using a list of messages results in a better printing if the logger is redirected to the terminal
237
+ msgs = []
238
+ msgs.append('The lock file at %s is not empty.' % path)
239
+ msgs.append('A previous attempt to update path may have failed or exited prematurely.')
240
+ msgs.append('Remove the lock file and set force to True with the desired version (default to most recent).')
241
+ msgs.append('It may be best to completely repopulate path using pull_data and measures_update.')
242
+ print_log_messages(msgs, logger, True)
197
243
  return
198
244
 
199
245
  do_update = force
@@ -201,31 +247,40 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
201
247
  if not do_update:
202
248
  # recheck the readme file, another update may have already happened before the lock was obtained
203
249
  current = None
204
- updated = None
250
+ ageRecent = False
251
+
205
252
  readmeInfo = get_data_info(path, logger, type='measures')
206
253
  if readmeInfo is not None:
207
254
  current = readmeInfo['version']
208
- updated = readmeInfo['date']
209
-
210
- if ((version is not None) and (version == current)) or ((version is None) and (updated == today_string)):
211
- # no update will be done, version is as requested or it's already been updated today
212
- print_log_messages('measures_update current measures detected in %s, using version %s' % (path, current), logger)
255
+ if readmeInfo['age'] is not None:
256
+ ageRecent = readmeInfo['age'] < 1.0
257
+
258
+ if (version is not None) and (version == current):
259
+ # no update will be done, version is as requested - not silent here because the lock is in use
260
+ print_log_messages('The requested measures version is already installed in %s, using version %s' % (path, current), logger)
261
+ elif (version is None) and ageRecent:
262
+ # no update will be done, it's already been checked or updated recently - not silent here because the lock is in use
263
+ print_log_messages('The latest measures version was checked recently in %s, using version %s' % (path, current), logger)
213
264
  else:
265
+ # final check for problems before updating
214
266
  if not force and readmeInfo is not None and (version=='invalid' or version=='unknown'):
215
267
  # at this point, this indicates something is unexpectedly wrong, do not continue
216
- print_log_messages('Something unexpected has changed in the measures path location, and measures_update can not continue', logger, True)
217
- print_log_messages('a previous measures_update may have exited unexpectedly', logger, True)
218
- print_log_messages('It may be necessary to reinstall the casarundata as well as the measures data if %s is the correct path' % path, logger, True)
268
+ # using a list of messages results in a better printing if the logger is redirected to the terminal
269
+ msgs = []
270
+ msgs.append('Something unexpected has changed in the measures path location, and measures_update can not continue')
271
+ msgs.append('A previous measures_update may have exited unexpectedly')
272
+ msgs.append('It may be necessary to reinstall the casarundata as well as the measures data if %s is the correct path' % path)
273
+ print_log_messages(msgs, logger, True)
219
274
  # update is already turned off, the lock file will be cleaned up on exit
220
-
221
- # an update is needed
222
- do_update = True
275
+ else:
276
+ # an update is needed
277
+ do_update = True
223
278
 
224
279
  if do_update:
225
280
  if force:
226
- print_log_messages('meaures_update a measures update has been requested by the force argument', logger)
281
+ print_log_messages('A measures update has been requested by the force argument', logger)
227
282
 
228
- print_log_messages('measures_update connecting to ftp.astron.nl ...', logger)
283
+ print_log_messages(' ... connecting to ftp.astron.nl ...', logger)
229
284
 
230
285
  ftp = FTP('ftp.astron.nl')
231
286
  rc = ftp.login()
@@ -233,43 +288,55 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
233
288
  files = sorted([ff for ff in ftp.nlst() if (len(ff) > 0) and (not ff.endswith('.dat')) and (ftp.size(ff) > 0)])
234
289
 
235
290
  # target filename to download
291
+ # 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
292
+ # but that isn't checked - this could install a version that's already installed
236
293
  target = files[-1] if version is None else version
237
294
  if target not in files:
238
295
  print_log_messages('measures_update cant find specified version %s' % target, logger, True)
239
296
 
240
297
  else:
241
- # there are files to extract, remove the readme.txt file in case this dies unexpectedly
242
- readme_path = os.path.join(path,'geodetic/readme.txt')
243
- if os.path.exists(readme_path):
244
- os.remove(readme_path)
298
+ # there are files to extract, make sure there's no past measures.ztar from a failed previous install
299
+ ztarPath = os.path.join(path,'measures.ztar')
300
+ if os.path.exists(ztarPath):
301
+ os.remove(ztarPath)
245
302
 
246
- with open(os.path.join(path,'measures.ztar'), 'wb') as fid:
247
- print_log_messages('measures_update downloading %s from ASTRON server to %s ...' % (target, path), logger)
303
+ with open(ztarPath, 'wb') as fid:
304
+ print_log_messages(' ... downloading %s from ASTRON server to %s ...' % (target, path), logger)
248
305
  ftp.retrbinary('RETR ' + target, fid.write)
249
306
 
250
307
  ftp.close()
251
-
308
+
309
+ # remove any existing measures readme.txt now in case something goes wrong during extraction
310
+ readme_path = os.path.join(path,'geodetic/readme.txt')
311
+ if os.path.exists(readme_path):
312
+ os.remove(readme_path)
313
+
252
314
  # extract from the fetched tarfile
253
- with tarfile.open(os.path.join(path,'measures.ztar'),mode='r:gz') as ztar:
315
+ with tarfile.open(ztarPath, mode='r:gz') as ztar:
254
316
  # the list of members to extract
255
317
  x_list = []
256
318
  for m in ztar.getmembers() :
257
- # always exclude the Observatories table and *.old names in geodetic
258
- if not((re.search('geodetic',m.name) and re.search('.old',m.name)) or re.search('Observatories',m.name)):
259
- x_list.append(m)
319
+ if force and use_astron_obs_table:
320
+ # exclude the *.old names in geodetic
321
+ if not(re.search('geodetic',m.name) and re.search('.old',m.name)):
322
+ x_list.append(m)
323
+ else:
324
+ # exclude the Observatories table and *.old names in geodetic
325
+ if not((re.search('geodetic',m.name) and re.search('.old',m.name)) or re.search('Observatories',m.name)):
326
+ x_list.append(m)
260
327
 
261
328
  # use the 'data' filter if available, revert to previous 'fully_trusted' behavior of not available
262
329
  ztar.extraction_filter = getattr(tarfile, 'data_filter', (lambda member, path: member))
263
330
  ztar.extractall(path=path,members=x_list)
264
331
  ztar.close()
265
332
 
266
- os.system("rm %s" % os.path.join(path, 'measures.ztar'))
333
+ os.remove(ztarPath)
267
334
 
268
- # update the readme.txt file
335
+ # create a new readme.txt file
269
336
  with open(readme_path,'w') as fid:
270
337
  fid.write("# measures data populated by casaconfig\nversion : %s\ndate : %s" % (target, datetime.today().strftime('%Y-%m-%d')))
271
338
 
272
- print_log_messages('measures_update updated measures data at %s' % path, logger)
339
+ print_log_messages(' ... measures data update at %s' % path, logger)
273
340
 
274
341
  # closing out the do_update
275
342
 
@@ -278,8 +345,10 @@ def measures_update(path=None, version=None, force=False, logger=None, auto_upda
278
345
  lock_fd.truncate(0)
279
346
 
280
347
  except Exception as exc:
281
- print_log_messages("ERROR! : Unexpected exception while updating measures at %s" % path, logger, True)
282
- print_log_messages("ERROR! : %s" % exc, logger, True)
348
+ msgs = []
349
+ msgs.append("ERROR! : Unexpected exception while updating measures at %s" % path)
350
+ msgs.append("ERROR! : %s" % exc)
351
+ print_log_messages(msgs, logger, True)
283
352
  # leave the contents of the lock file as is to aid in debugging
284
353
 
285
354
  # if the lock file is not closed, do that now to release the lock
@@ -16,6 +16,8 @@ def print_log_messages(msg, logger, is_err=False):
16
16
  """
17
17
  Print msg and optionally write it to an instance of the casalogger.
18
18
 
19
+ If msg is a list then the elements are each printed first followed by logging each element.
20
+
19
21
  Messages are normally printed to sys.stdout and logged as INFO to the casalogger.
20
22
 
21
23
  When is_err is True the message is printed sys.stderr and logged as SEVERE
@@ -39,5 +41,12 @@ def print_log_messages(msg, logger, is_err=False):
39
41
  fileout = sys.stderr
40
42
  loglevel = 'SEVERE'
41
43
 
42
- print(msg,file=fileout)
43
- if logger is not None: logger.post(msg, loglevel)
44
+ # this is rarely called and this should be a fast operation, it makes the code simpler
45
+ if type(msg) is not list:
46
+ msg = [msg]
47
+
48
+ for m_msg in msg:
49
+ print(m_msg,file=fileout)
50
+
51
+ for m_msg in msg:
52
+ if logger is not None: logger.post(m_msg, loglevel)
@@ -75,6 +75,10 @@ def pull_data(path=None, version=None, force=False, logger=None):
75
75
  pull_data should typically be followed by a restart of CASA so that
76
76
  any changes are seen by the tools and tasks that use this data.
77
77
 
78
+ **Note:** When version is None (the default), data_available is always used to find out
79
+ what versions are available. There is no check on when the data were last updated before
80
+ calling data_available (as there is in the two update functions).
81
+
78
82
  Parameters
79
83
  - path (str) - Folder path to place casarundata contents. It must be empty or not exist or contain a valid, previously installed version. If not set then config.measurespath is used.
80
84
  - version (str=None) - casadata version to retrieve. Default None gets the most recent version.
@@ -103,6 +107,11 @@ def pull_data(path=None, version=None, force=False, logger=None):
103
107
  print_log_messages('path is None and has not been set in config.measurespath (probably casasiteconfig.py). Provide a valid path and retry.', logger, True)
104
108
  return
105
109
 
110
+ # when a specific version is requested then the measures readme.txt that is part of that version
111
+ # will get a timestamp of now so that default measures updates won't happen for a day unless the
112
+ # force argument is used for measures_update
113
+ namedVersion = version is not None
114
+
106
115
  path = os.path.expanduser(path)
107
116
  readme_path = os.path.join(path, 'readme.txt')
108
117
 
@@ -111,35 +120,40 @@ def pull_data(path=None, version=None, force=False, logger=None):
111
120
  currentVersion = None
112
121
  currentDate = None
113
122
 
114
- # attempt a pull if path does not exist or is empty:
115
- do_pull = (not os.path.exists(path)) or (len(os.listdir(path))==0)
123
+ # attempt a pull if path does not exist or is empty (except for any lock file, handled later)
124
+ readmeInfo = get_data_info(path, logger, type='casarundata')
125
+ do_pull = readmeInfo is None
116
126
  if not do_pull:
117
127
  # find the current version, install date, and installed files
118
- readmeInfo = get_data_info(path, logger, type='casarundata')
119
- # the only way readmeInfo is None is if path does not exist or is empty, which we already know is not the case
120
128
  currentVersion = readmeInfo['version']
121
129
  currentDate = readmeInfo['date']
122
130
  installed_files = readmeInfo['manifest']
123
131
 
124
132
  if currentVersion == 'invalid':
125
- print_log_messages('destination path is not empty and this does not appear to be casarundata OR the readme.txt file found there could not be read as expected', logger, True)
126
- print_log_messages('choose a different path or empty this path and try again', logger, True)
133
+ msgs = []
134
+ msgs.append('destination path is not empty and this does not appear to be casarundata OR the readme.txt file found there could not be read as expected')
135
+ msgs.append('choose a different path or empty this path and try again')
136
+ print_log_messages(msgs, logger, True)
127
137
  # no lock has been set yet, safe to simply return here
128
138
  return
129
139
 
130
140
  if currentVersion == 'unknown':
131
- print_log_messages('destination path appears to be casarundata but no readme.txt file was found', logger, False)
132
- print_log_messages('no data will be installed but CASA use of this data may be OK. Choose a different path or delete this path to install new casarundata.', logger, False)
141
+ msgs = []
142
+ msgs.append('destination path appears to be casarundata but no readme.txt file was found')
143
+ msgs.append('no data will be installed but CASA use of this data may be OK. Choose a different path or delete this path to install new casarundata.')
133
144
  if force:
134
- print_log_messages('force is True but there is no readme.txt found and the location is not empty, no data will be installed', logger, True);
135
- print_log_messages('Choose a different path or empty this path to install new casarundata', logger, True)
145
+ msgs.append('force is True but there is no readme.txt found and the location is not empty, no data will be installed')
146
+ msgs.append('Choose a different path or empty this path to install new casarundata')
147
+ print_log_messages(msgs, logger, True)
136
148
  # no lock as been set yet, safe to simply return here
137
149
  return
138
150
 
139
- if (len(installed_files) == 0):
151
+ if (installed_files is None or len(installed_files) == 0):
140
152
  # this shouldn't happen
141
- print_log_messages('destination path is not empty and the readme.txt file found there did not contain the expected list of installed files', logger, True)
142
- print_log_messages('choose a different path or empty this path and try again', logger, True)
153
+ msgs = []
154
+ msgs.append('destination path is not empty and the readme.txt file found there did not contain the expected list of installed files')
155
+ msgs.append('choose a different path or empty this path and try again')
156
+ print_log_messages(msgs, logger, True)
143
157
  # no lock as been set yet, safe to simply return here
144
158
  return
145
159
 
@@ -191,10 +205,12 @@ def pull_data(path=None, version=None, force=False, logger=None):
191
205
  lock_fd = get_data_lock(path, 'pull_data')
192
206
  # if lock_fd is None it means the lock file was not empty - because we know that path exists at this point
193
207
  if lock_fd is None:
194
- print_log_messages('The lock file at %s is not empty.' % path, logger, True)
195
- print_log_messages('A previous attempt to update path may have failed or exited prematurely.', logger, True)
196
- print_log_messages('It may be best to do a fresh pull_data on that location.', logger, True)
197
- print_log_messages('Remove the lock file and set force to True with the desired version (default to the most recent).', logger, True)
208
+ msgs = []
209
+ msgs.append('The lock file at %s is not empty.' % path)
210
+ msgs.append('A previous attempt to update path may have failed or exited prematurely.')
211
+ msgs.append('Remove the lock file and set force to True with the desired version (default to the most recent).')
212
+ msgs.append('It may be best to clean out that location and do a fresh pull_data.')
213
+ print_log_messages(msgs, logger, True)
198
214
  return
199
215
 
200
216
  do_pull = True
@@ -205,6 +221,9 @@ def pull_data(path=None, version=None, force=False, logger=None):
205
221
  if readmeInfo is not None:
206
222
  currentVersion = readmeInfo['version']
207
223
  currentDate = readmeInfo['date']
224
+ print('readmeInfo is not None')
225
+ print('currentVersion : %s' % currentVersion)
226
+ print('currentDate : %s' % currentDate)
208
227
  if ((currentVersion == version) and (not force)):
209
228
  if expectedMeasuresVersion is not None:
210
229
  # this is a release pull and the measures version must also match
@@ -224,30 +243,44 @@ def pull_data(path=None, version=None, force=False, logger=None):
224
243
  do_pull = False
225
244
  print_log_messages('pull_data requested version is already installed.', logger)
226
245
 
246
+ # a version of 'invalid', 'error', or 'unknown' is a surprise here, likely caused by something else doing something
247
+ # incompatible with this attempt
248
+ if version in ['invalid','error','unknown']:
249
+ do_pull = False
250
+ msgs = []
251
+ msgs.append('Unexpected version or problem found in readme.txt file during pull_data, can not safely pull the requested version')
252
+ msgs.append('This should not happen unless multiple sessions are trying to pull_data at the same time and one experienced problems or was done out of sequence')
253
+ print_log_messages(msgs, logger, True)
254
+
255
+
227
256
  if do_pull:
228
257
  # make sure the copy of installed_files is the correct one
229
258
  installed_files = readmeInfo['manifest']
230
259
  if len(installed_files) == 0:
231
260
  # this shoudn't happen, do not do a pull
232
261
  do_pull = False
233
- print_log_messages('destination path is not empty and the readme.txt file found there did not contain the expected list of installed files', logger, True)
234
- print_log_messages('This should not happen unless multiple sessions are trying to pull_data at the same time and one experienced problems or was done out of sequence', logger, True)
235
- print_log_messages('Check for other updates in process or choose a different path or clear out this path and try again', logger, True)
236
- else:
237
- # this shouldn't happen, do not do a pull
238
- do_pull = False
239
- print_log_messages('Unexpected error reading readme.txt file during pull_data, can not safely pull the requested version', logger, True)
240
- print_log_messages('This should not happen unless multiple sessions are trying to pull_data at the same time and one experienced problems or was done out of sequence', logger, True)
241
-
262
+ msgs = []
263
+ msgs.append('destination path is not empty and the readme.txt file found there did not contain the expected list of installed files')
264
+ msgs.append('This should not happen unless multiple sessions are trying to pull_data at the same time and one experienced problems or was done out of sequence')
265
+ msgs.append('Check for other updates in process or choose a different path or clear out this path and try again')
266
+ print_log_messages(msgs, logger, True)
267
+
242
268
  if do_pull:
243
269
  do_pull_data(path, version, installed_files, currentVersion, currentDate, logger)
270
+ if namedVersion:
271
+ # a specific version has been requested, set the times on the measures readme.txt to now to avoid
272
+ # a default update of the measures data without using the force argument
273
+ measuresReadmePath = os.path.join(path,'geodetic/readme.txt')
274
+ os.utime(measuresReadmePath)
244
275
 
245
- # truncate the lock file
276
+ # truncate the lock filed
246
277
  lock_fd.truncate(0)
247
278
 
248
279
  except Exception as exc:
249
- print_log_messages('ERROR! : Unexpected exception while populating casarundata version %s to %s' % (version, path), logger, True)
250
- print_log_messages('ERROR! : %s' % exc, logger, True)
280
+ msgs = []
281
+ msgs.append('ERROR! : Unexpected exception while populating casarundata version %s to %s' % (version, path))
282
+ msgs.append('ERROR! : %s' % exc)
283
+ print_log_messages(msgs, logger, True)
251
284
  # leave the contents of the lock file as is to aid in debugging
252
285
  # import traceback
253
286
  # traceback.print_exc()
@@ -15,7 +15,7 @@
15
15
  this module will be included in the api
16
16
  """
17
17
 
18
- def update_all(path=None, logger=None):
18
+ def update_all(path=None, logger=None, force=False):
19
19
  """
20
20
  Update the data contants at path to the most recently released versions
21
21
  of casarundata and measures data.
@@ -33,6 +33,8 @@ def update_all(path=None, logger=None):
33
33
  If path already contains the most recent versions of casarundata and
34
34
  measurespath then nothing will change at path.
35
35
 
36
+ The force argument is passed to data_update and measures_update
37
+
36
38
  This uses pull_data, data_update and measures_update. See the
37
39
  documentation for those functions for additional details.
38
40
 
@@ -76,7 +78,10 @@ def update_all(path=None, logger=None):
76
78
  # path must be a directory and it must be owned by the user
77
79
 
78
80
  if (not os.path.isdir(path)) or (os.stat(path).st_uid != os.getuid()):
79
- print_log_messages("path must exist as a directory and it must be owned by the user, path = %s" % path, logger, True)
81
+ msgs = []
82
+ msgs.append("Warning: path must exist as a directory and it must be owned by the user, path = %s" % path)
83
+ msgs.append("Warning: no updates are possible on this path by this user.")
84
+ print_log_messages(msgs, logger, False)
80
85
  return
81
86
 
82
87
  # if path is empty, first use pull_data
@@ -106,7 +111,7 @@ def update_all(path=None, logger=None):
106
111
  return
107
112
 
108
113
  # the updates should work now
109
- data_update(path, logger)
110
- measures_update(path, logger)
114
+ data_update(path, logger, force=force)
115
+ measures_update(path, logger, force=force)
111
116
 
112
117
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: casaconfig
3
- Version: 0.0.79
3
+ Version: 0.0.81
4
4
  Summary: CASA Operational Configuration Package
5
5
  Home-page: https://github.com/casangi/casaconfig
6
6
  Author: National Radio Astronomy Observatory
@@ -6,7 +6,7 @@ with open('README.md', "r") as fid: #encoding='utf-8'
6
6
 
7
7
  setup(
8
8
  name='casaconfig',
9
- version='0.0.79',
9
+ version='0.0.81',
10
10
  description='CASA Operational Configuration Package',
11
11
  long_description=long_description,
12
12
  long_description_content_type="text/markdown",
File without changes
File without changes
File without changes
File without changes