casaconfig 1.0.2__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.
@@ -0,0 +1,364 @@
1
+ # Copyright 2023 AUI, Inc. Washington DC, USA
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ this module will be included in the api
16
+ """
17
+
18
+ def data_update(path=None, version=None, force=False, logger=None, auto_update_rules=False, verbose=None):
19
+ """
20
+ Check for updates to the installed casarundata and install the update or change to
21
+ the requested version when appropriate.
22
+
23
+ The verbose argument controls the level of information provided when this function when the data
24
+ are unchanged for expected reasons. A level of 0 prints and logs nothing. A
25
+ value of 1 logs the information and a value of 2 logs and prints the information.
26
+
27
+ The path must contain a previously installed version of casarundata.
28
+ Use pull_data to install casarundata into a new path (empty or does not exist).
29
+
30
+ If path is None then config.measurespath is used.
31
+
32
+ If the version is None (the default) then the most recent version returned by
33
+ data_available is used.
34
+
35
+ If version is "release" then the version associated with the release in
36
+ the dictionary returned by get_data_info is used. If there is no release
37
+ version information available to casaconfig then an error message is printed
38
+ and nothing is updated. Release version information is only available in
39
+ monolithic CASA installations.
40
+
41
+ If a specific version is not requested (the default) and a check for the
42
+ versions available for installation at path has been done within the past
43
+ 24 hours then this function does nothing even if there is a more
44
+ recent version available from the CASA server unless force is True.
45
+
46
+ If force is True then the requested version (or the latest version available
47
+ now) is installed even if that version is already installed or a check for the
48
+ latest version has been done within the past 24 hours.
49
+
50
+ A text file (readme.txt at path) records the version string, the date
51
+ when that version was installed in path, and the files installed into path. That file
52
+ must already exist in path in order to use this function. Use pull_data to install
53
+ casarundata into a new location.
54
+
55
+ When auto_update_rules is True then path must be owned by the user, force must be
56
+ False and the version must be None. This is used during casatools initialization when
57
+ data_auto_update is True. Automatic updating happens during casatools initialization
58
+ so that the updated casarundata and measures are in place before any tool needs to use them.
59
+
60
+ If an update is to be installed the previously installed files, as listed in the
61
+ readme.txt file at path, are removed before the contents of the version
62
+ being installed are unpacked. If the measures contents of path have been updated since
63
+ the previously installed version of casarundata then those updates will also be removed
64
+ by this data update while preparing to install the requested version of casarundata (which
65
+ includes a copy of the measures data that is likely older than today). A data update is
66
+ typically followed by a measures_update to ensure that the most recent measures data
67
+ are installed.
68
+
69
+ A file lock is used to prevent more that one data update (pull_data, measures_update,
70
+ or data_update) from updating any files in path at the same time. When locked, the
71
+ lock file (data_update.lock in path) contains information about the process that
72
+ has the lock. When data_update gets the lock it checks the readme.txt file in path
73
+ to make sure that an update is still necessary (if force is True then an update
74
+ always happens). If the lock file is not empty then a previous update of path (pull_data,
75
+ data_update, or measures_update) did not exit as expected or is still in process (via a
76
+ separate instance of CASA) and the contents of path may be suspect. In that case,
77
+ an error will be reported and nothing will be updated. The lock file can be checked to
78
+ see the details of when that file was locked. The lock file can be removed and data_update
79
+ can be tried again. It may be safest in that case to remove path completely or use a
80
+ different path and use pull_data to install a fresh copy of the desired version.
81
+
82
+ Some of the tables installed by data_update are only read when casatools starts. Use of
83
+ data_update except during CASA startup by the auto update proess should typically be
84
+ followed by a restart of CASA so that any changes are seen by the tools and tasks that
85
+ use this data.
86
+
87
+ **Note:** data_update requires that the expected readme.txt file already exists at the top-level
88
+ directory at path. If the file does not exist or can not be interpreted as expected then
89
+ data_update will return without updating any data.
90
+
91
+ **Note:** if auto_update_rules is True the user must own path (in addition to having read and
92
+ write permissions there). The version must then also be None and the force option must be False.
93
+
94
+ **Note:** the most recent casarundata may not include the most recent measures data. A data_update
95
+ is typically followed by a measures_update.
96
+
97
+ Parameters
98
+ - path (str=None) - Folder path to update. Must contain a valid readme.txt. If not set then config.measurespath is used.
99
+ - 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.
100
+ - 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.
101
+ - logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal.
102
+ - 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.
103
+ - verbose (int) - Level of output, 0 is none, 1 is to logger, 2 is to logger and terminal, defaults to casaconfig_verbose in the config dictionary.
104
+
105
+ Returns
106
+ None
107
+
108
+ Raises
109
+ - casaconfig.AutoUpdatesNotAllowed - raised when path does not exist as a directory or is not owned by the user
110
+ - casaconfig.BadLock - raised when the lock file was not empty when an attempt was made to obtain the lock
111
+ - casaconfig.BadReadme - raised when the readme.txt file at path did not contain the expected list of installed files or was incorrectly formatted
112
+ - casaconfig.NoReadme - raised when the readme.txt file is not found at path (path also may not exist)
113
+ - casaconfig.NotWritable - raised when the user does not have permission to write to path
114
+ - casaconfig.RemoteError - raised by data_available when the list of available data versions could not be fetched
115
+ - casaconfig.UnsetMeasurespath - raised when path is None and measurespath has not been set in config.
116
+ - Exception - raised when there was an unexpected exception while populating path
117
+
118
+ """
119
+
120
+ import os
121
+
122
+ from casaconfig import data_available
123
+ from casaconfig import pull_data
124
+ from casaconfig import get_data_info
125
+ from casaconfig import AutoUpdatesNotAllowed, BadReadme, BadLock, NoReadme, RemoteError, UnsetMeasurespath, NotWritable
126
+ from .print_log_messages import print_log_messages
127
+ from .get_data_lock import get_data_lock
128
+ from .do_pull_data import do_pull_data
129
+
130
+ if path is None:
131
+ from .. import config as _config
132
+ path = _config.measurespath
133
+
134
+ if path is None:
135
+ raise UnsetMeasurespath('data_update: path is None and has not been set in config.measurespath. Provide a valid path and retry.')
136
+ return
137
+
138
+ if verbose is None:
139
+ from .. import config as _config
140
+ verbose = _config.casaconfig_verbose
141
+
142
+ # when a specific version is requested then the measures readme.txt that is part of that version
143
+ # will get a timestamp of now so that default measures updates won't happen for a day unless the
144
+ # force argument is used for measures_update
145
+ namedVersion = version is not None
146
+
147
+ path = os.path.expanduser(path)
148
+ readme_path = os.path.join(path, 'readme.txt')
149
+
150
+ if auto_update_rules:
151
+ if version is not None:
152
+ print_log_messages('data_update: auto_update_rules requires that version be None', logger, True)
153
+ return
154
+ if force:
155
+ print_log_messages('data_update: force must be False when auto_update_rules is True', logger, True)
156
+ return
157
+ if (not os.path.isdir(path)) or (os.stat(path).st_uid != os.getuid()):
158
+ raise AutoUpdatesNotAllowed("data_update: path must exist as a directory and it must be owned by the user, path = %s" % path)
159
+
160
+ if not os.path.exists(readme_path):
161
+ # path must exist and it must be empty in order to continue
162
+ if not os.path.exists(path) or (len(os.listdir(path)) > 0):
163
+ raise NoReadme('data_update: no casarundata readme.txt file found at %s. Nothing updated or checked.' % path);
164
+ # ok to install a fresh copy, use pull_data directly
165
+ return pull_data(path,version,force,logger,verbose)
166
+
167
+ # path must be writable with execute bit set
168
+ if (not os.access(path, os.W_OK | os.X_OK)) :
169
+ raise NotWritable('data_update: No permission to write to %s, cannot update.' % path)
170
+
171
+ # try and digest the readme file
172
+
173
+ installed_files = []
174
+ currentVersion = []
175
+ currentDate = []
176
+ ageRecent = False
177
+
178
+ # already checked that path is OK, type is OK here, no need to trap for exceptions here
179
+ dataReadmeInfo = get_data_info(path, logger, type='casarundata')
180
+
181
+ if dataReadmeInfo is None or dataReadmeInfo['version'] == 'invalid':
182
+ msgs = []
183
+ msgs.append('The readme.txt file at path could not be read as expected')
184
+ msgs.append('choose a different path or empty this path and try again using pull_data')
185
+ print_log_messages(msgs, logger, True)
186
+ # no lock has been set yet, safe to simply return here
187
+ return
188
+
189
+ currentVersion = dataReadmeInfo['version']
190
+ currentDate = dataReadmeInfo['date']
191
+ installed_files = dataReadmeInfo['manifest']
192
+ if dataReadmeInfo['age'] is not None:
193
+ ageRecent = dataReadmeInfo['age'] < 1.0
194
+
195
+ if currentVersion == 'unknown':
196
+ msgs = []
197
+ msgs.append('The data update path appears to be casarundata but no readme.txt file was found')
198
+ msgs.append('A data update is not possible but CASA use of this data may be OK.')
199
+ msgs.append('casaconfig must first install the casarundata in path for data_update to run as expected on that path')
200
+ print_log_messages(msgs, logger, True)
201
+
202
+ if (len(installed_files) == 0):
203
+ # this shouldn't happen
204
+ # no lock has been set yet, safe to raise this exception without worrying about the lock
205
+ raise BadReadme('data_update: the readme.txt file at path did not contain the expected list of installed files')
206
+
207
+ if version is None and force is False and ageRecent:
208
+ # if version is None, the readme is less than 1 day old and force is False then return without checking for any newer versions
209
+ if verbose > 0:
210
+ print_log_messages('data_update: version installed or checked less than 1 day ago, nothing updated or checked', logger, verbose=verbose)
211
+ # no lock has been set yet, safe to simply return here
212
+ return
213
+
214
+ # this may raise a RemoteError, no need to catch that here but it may need to be caught upstream
215
+ available_data = data_available()
216
+ requestedVersion = version
217
+ latestVersion = False
218
+
219
+ if requestedVersion is None:
220
+ latestVersion = True
221
+ requestedVersion = available_data[-1]
222
+
223
+ expectedMeasuresVersion = None
224
+ if requestedVersion == 'release':
225
+ # use the release version from get_data_info
226
+ releaseInfo = get_data_info()['release']
227
+ if releaseInfo is None:
228
+ print_log_messages('No release info found, data_update can not continue', logger, True)
229
+ return
230
+ requestedVersion = releaseInfo['casarundata']
231
+ expectedMeasuresVersion = releaseInfo['measures']
232
+
233
+ if requestedVersion not in available_data:
234
+ print_log_messages('Requested casarundata version %s was not found. See available_data for a list of available casarundata versions.' % requestedVersion)
235
+ # no lock has been set yet, safe to simply return here
236
+ return
237
+
238
+ # don't update if force is false and the requested version is already installed
239
+ if force is False and (currentVersion == requestedVersion):
240
+ if expectedMeasuresVersion is not None:
241
+ # the 'release' version has been requested, need to check the measures version
242
+ # assume a force is necessary until the measures version is known to be OK
243
+ measuresReadmeInfo = get_data_info(path, logger, type='measures')
244
+ if measuresReadmeInfo is not None:
245
+ measuresVersion = measuresReadmeInfo['version']
246
+ if measuresVersion == expectedMeasuresVersion:
247
+ # it's OK, do not force
248
+ force = False
249
+ # 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
250
+ if not force:
251
+ if verbose > 0:
252
+ print_log_messages('data_update: requested "release" version of casarundata and measures are already installed.', logger, verbose=verbose)
253
+ # no lock has been set yet, safe to simply return here
254
+ return
255
+ else:
256
+ # normal usage, ok to return now
257
+ if latestVersion:
258
+ if verbose > 0:
259
+ print_log_messages('The latest version is already installed in %s' % path, logger, verbose=verbose)
260
+ # touch the dates of the readme to prevent a future check on available data for the next 24 hours
261
+ os.utime(readme_path)
262
+ else:
263
+ if verbose > 0:
264
+ print_log_messages('Requested casarundata version is already installed in %s, %s' % (path, currentVersion), logger, verbose=verbose)
265
+
266
+ # no lock has been set yet, safe to simply return here
267
+ return
268
+
269
+ # an update appears necessary
270
+
271
+ lock_fd = None
272
+ clean_lock = True # set to False if the contents are actively being update and the lock file should not be cleaned on exception
273
+ try:
274
+ print_log_messages('data_update using version %s, acquiring the lock ... ' % requestedVersion, logger)
275
+
276
+ lock_fd = get_data_lock(path, 'data_update')
277
+ # the BadLock exception that may happen here is caught below
278
+
279
+ do_update = True
280
+ # it's possible that another process had path locked and updated the readme with new information, re-read it
281
+ dataReadmeInfo = get_data_info(path, logger, type='casarundata')
282
+ if dataReadmeInfo is not None:
283
+ currentVersion = dataReadmeInfo['version']
284
+ currentDate = dataReadmeInfo['date']
285
+ installedFiles = dataReadmeInfo['manifest']
286
+ ageRecent = dataReadmeInfo['age'] < 1.0
287
+ if ((currentVersion == requestedVersion) and (not force)):
288
+ if expectedMeasuresVersion is not None:
289
+ # this is a 'release' update request, need to check that the measures version is also now OK
290
+ measuresReadmeInfo = get_data_info(path, logger, type='measures')
291
+ if measuresReadmeInfo is not None:
292
+ measuresVersion = measuresReadmeInfo['version']
293
+ if measuresVersion == expectedMeasuresVersion:
294
+ do_update = False
295
+ # if measuresReadmeInfo is None there was a problem which requires a full update so do_update remains True
296
+ if not do_update:
297
+ # always verbose here because the lock file is in use
298
+ print_log_messages('data update requested "release" version of casarundata and measures are already installed.', logger)
299
+ else:
300
+ # nothing to do here, already at the expected version and an update is not being forced
301
+ if latestVersion:
302
+ # always verbose here because the lock file is in use
303
+ print_log_messages('The latest version is already installed, using version %s' % currentVersion, logger)
304
+ # touch the dates of the readme to prevent a future check on available data for the next 24 hours
305
+ os.utime(readme_path)
306
+ else:
307
+ # always verbose here because the lock file is in use
308
+ print_log_messages('requested version is already installed.', logger)
309
+ do_update = False
310
+
311
+ if do_update:
312
+ # update is still on, check the manifest
313
+ if len(installed_files) == 0:
314
+ # this shouldn't happen, do not do an update, raise the BadReadme exception, caught below and the lock cleaned up then
315
+ raise BadReadme('data_update: the readme.txt file at path did not contain the expected list of installed files')
316
+ else:
317
+ # this shouldn't happen
318
+ raise BadReadme('data_update: unexpected problem reading readme.txt file during data update, can not safely update to the requested version')
319
+
320
+ if do_update:
321
+ # do not clean the lock file contents at this point unless do_pull_data returns normally
322
+ clean_lock = False
323
+ do_pull_data(path, requestedVersion, installed_files, currentVersion, currentDate, logger)
324
+ clean_lock = True
325
+ if namedVersion:
326
+ # a specific version has been requested, set the times on the measures readme.txt to now to avoid
327
+ # a default update of the measures data without using the force argument
328
+ measuresReadmePath = os.path.join(path,'geodetic/readme.txt')
329
+ os.utime(measuresReadmePath)
330
+
331
+ except BadLock as exc:
332
+ # the path is known to exist so this means that the lock file was not empty and it's not locked
333
+ msgs = str(exc)
334
+ msgs.append('data_update: the lock file at %s is not empty.' % path)
335
+ msgs.append('A previous attempt to update path may have failed or exited prematurely.')
336
+ msgs.append('Remove the lock file and set force to True with the desired version (default to most recent).')
337
+ msgs.append('It may be best to completely re-populate path using pull_data and measures_update.')
338
+ print_log_messages(msgs, logger, True)
339
+ # reraise this
340
+ raise
341
+
342
+ except BadReadme as exc:
343
+ # something is wrong in the readme after an update was triggered, this shouldn't happen, print more context reraise this
344
+ msgs = str(exc)
345
+ 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')
346
+ msgs.append('Check for other updates in progress or choose a different path or clear out this path and try again using pull_data or update_all')
347
+ print_log_messages(msgs, logger, True)
348
+ raise
349
+
350
+ except Exception as exc:
351
+ msgs = []
352
+ msgs.append('ERROR! : Unexpected exception while populating casarundata version %s to %s' % (requestedVersion, path))
353
+ msgs.append('ERROR! : %s' % exc)
354
+ print_log_messages(msgs, logger, True)
355
+ raise
356
+
357
+ finally:
358
+ # make sure the lock file is closed and also clean the lock file if safe to do so, this is always executed
359
+ if lock_fd is not None and not lock_fd.closed:
360
+ if clean_lock:
361
+ lock_fd.truncate(0)
362
+ lock_fd.close()
363
+
364
+ return
@@ -0,0 +1,77 @@
1
+ # Copyright 2023 AUI, Inc. Washington DC, USA
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ this module will be included in the api
16
+ """
17
+
18
+ def do_auto_updates(configDict, logger=None, verbose=None):
19
+ """
20
+ Use measurespath, data_auto_update, and measures_auto_update from configDict to
21
+ do any auto updates as necessary.
22
+
23
+ This is intended for use during casatools init but may be useful in other cases.
24
+
25
+ Note that the IERS measures data is usually read when casatools starts and so
26
+ changes made to that table may not be seen until a new session if this function
27
+ is used outside of casatools initialization.
28
+
29
+ measurespath must be set (not None).
30
+
31
+ measures_auto_update must be True when data_auto_update is True.
32
+
33
+ See the documentation for data_update and measures_update for additional details
34
+ about the auto update rules.
35
+
36
+ The verbose argument controls the level of information provided when this function when the data
37
+ are unchanged for expected reasons. A level of 0 prints and logs nothing. A
38
+ value of 1 logs the information and a value of 2 logs and prints the information.
39
+
40
+ See data_update and measures_update for additional details about exceptions
41
+
42
+ Paramters
43
+ - configDict (dict) - A config dictionary previously set.
44
+ - logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal.
45
+ - verbose (int) - Level of output, 0 is none, 1 is to logger, 2 is to logger and terminal, defaults to casaconfig_verbose in the config dictionary.
46
+
47
+ Returns
48
+ None
49
+
50
+ Raises
51
+ - casaconfig.UnsetMeasurespath - raised when measurespath is None in config
52
+
53
+ """
54
+
55
+ from .print_log_messages import print_log_messages
56
+ from .data_update import data_update
57
+ from .measures_update import measures_update
58
+
59
+ from casaconfig import UnsetMeasurespath
60
+
61
+ if configDict.measurespath is None:
62
+ # continue, because things still might work if there are measures in datapath
63
+ raise UnsetMeasurespath('do_auto_updates: measurespath is None in configDict. Provide a valid path and retry.')
64
+
65
+ if verbose is None:
66
+ verbose = configDict.casaconfig_verbose
67
+
68
+ if (configDict.measures_auto_update or configDict.data_auto_update):
69
+ if (configDict.data_auto_update and (not configDict.measures_auto_update)):
70
+ print_log_messages('measures_auto_update must be True when data_auto_update is True, skipping auto updates', logger, True)
71
+ else:
72
+ if configDict.data_auto_update:
73
+ data_update(configDict.measurespath, logger=logger, auto_update_rules=True, verbose=verbose)
74
+ if configDict.data_auto_update or configDict.measures_auto_update:
75
+ measures_update(configDict.measurespath, logger=logger, auto_update_rules=True, verbose=verbose)
76
+
77
+ return
@@ -0,0 +1,136 @@
1
+ # Copyright 2023 AUI, Inc. Washington DC, USA
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ def do_pull_data(path, version, installed_files, currentVersion, currentDate, logger):
16
+ """
17
+ Pull the casarundata for the given version and install it in path, removing
18
+ the installed files and updating the readme.txt file when done.
19
+
20
+ This function is used by both pull_data and data_update when each has
21
+ determind that the desired version should be installed. The calling function
22
+ has already obtained the lock. No additional checking happens here. The
23
+ calling function has already examined any existing readme file and used that
24
+ to set the installed_files list as appropriate.
25
+
26
+ Parameters
27
+ - path (str) - Folder path to place casadata contents.
28
+ - version (str) - casadata version to retrieve.
29
+ - installed_files (str list) - list of installed files from the version already installed. Set to an empty list if there is no previously installed version.
30
+ - currentVersion (str) - from the readme file if it already exists, or an empty string if there is no previously installed version.
31
+ - currentDate (str) - from the readme file if it already exists, or an empty string if there is no previously installed version.
32
+ - logger (casatools.logsink) - Instance of the casalogger to use for writing messages. Messages are always written to the terminal. Set to None to skip writing messages to a logger.
33
+
34
+ Returns
35
+ None
36
+
37
+ """
38
+
39
+ import os
40
+ import sys
41
+ from datetime import datetime
42
+ import ssl
43
+ import urllib.request
44
+ import certifi
45
+ import tarfile
46
+ import shutil
47
+
48
+ from .print_log_messages import print_log_messages
49
+
50
+ readme_path = os.path.join(path, 'readme.txt')
51
+
52
+ if (installed_files is not None and len(installed_files) > 0):
53
+ # remove the previously installed files
54
+ # remove this readme file so it's not confusing if something goes wrong after this
55
+ os.remove(readme_path)
56
+ print_log_messages('Removing files using manifest from previous install of %s on %s' % (currentVersion, currentDate), logger)
57
+ for relpath in installed_files:
58
+ filepath = os.path.join(path,relpath)
59
+ # don't say anything if filepath isn't found, remove it if it is found
60
+ if os.path.exists(filepath) and os.path.isfile(filepath):
61
+ os.remove(filepath)
62
+
63
+ # remove any empty directories in path - this is recursive
64
+ def remove_empty_dirs(dirpath):
65
+ # look at all of the files in dirpath, for dirs, go down that recursively
66
+ # if there's nothing there after the dirs have all been handled, remove it
67
+ files = os.listdir(dirpath)
68
+ not_dirs = []
69
+ for f in os.listdir(dirpath):
70
+ fpath = os.path.join(dirpath, f)
71
+ if os.path.isdir(fpath):
72
+ remove_empty_dirs(fpath)
73
+ else:
74
+ not_dirs.append(f)
75
+ if len(not_dirs) == 0:
76
+ if len(os.listdir(dirpath)) == 0:
77
+ os.rmdir(dirpath)
78
+
79
+ remove_empty_dirs(path)
80
+
81
+ # okay, safe to install the requested version
82
+
83
+ goURL = 'https://go.nrao.edu/casarundata'
84
+ context = ssl.create_default_context(cafile=certifi.where())
85
+
86
+ # need to first resolve the go.nrao.edu URL to find the actual data URL
87
+ dataURLroot = urllib.request.urlopen(goURL, context=context).url
88
+ dataURL = os.path.join(dataURLroot, version)
89
+
90
+ with urllib.request.urlopen(dataURL, context=context, timeout=400) as tstream, tarfile.open(fileobj=tstream, mode='r|*') as tar :
91
+ l = int(tstream.headers.get('content-length', 0))
92
+ sizeString = "unknown size"
93
+ if (l>0): sizeString = ("%.0fM" % (l/(1024*1024)))
94
+ # use print directly to make use of the end argument
95
+ print('downloading casarundata contents to %s (%s) ... ' % (path,sizeString), file = sys.stdout, end="" )
96
+ sys.stdout.flush()
97
+ # also log it
98
+ if logger is not None: logger.post('downloading casarundata contents to %s ...' % path, 'INFO')
99
+ # use the 'data' filter if available, revert to previous 'fully_trusted' behavior of not available
100
+ tar.extraction_filter = getattr(tarfile, 'data_filter', (lambda member, path: member))
101
+ tar.extractall(path=path)
102
+
103
+ print("done", file=sys.stdout)
104
+
105
+ # the tarball has been extracted to path/version
106
+ # get the instaled files of files to be written to the readme file
107
+ versdir = os.path.join(path,version[:version.index('.tar')])
108
+ installed_files = []
109
+ wgen = os.walk(versdir)
110
+ for (dirpath, dirnames, filenames) in wgen:
111
+ for f in filenames:
112
+ installed_files.append(os.path.relpath(os.path.join(dirpath,f),versdir))
113
+
114
+ # move everything in version up a level to path
115
+ for f in os.listdir(versdir):
116
+ srcPath = os.path.join(versdir,f)
117
+ if os.path.isdir(srcPath):
118
+ # directories are first copied, then removed
119
+ # existing directories are reused, existing files are overwritten
120
+ # things in path that do not exist in srcPath are not changed
121
+ shutil.copytree(srcPath,os.path.join(path,f),dirs_exist_ok=True)
122
+ shutil.rmtree(srcPath)
123
+ else:
124
+ # assume it's a simple file, these can be moved directly, overwriting anything already there
125
+ os.rename(srcPath,os.path.join(path,f))
126
+
127
+ # safe to remove versdir, it would be a surprise if it's not empty
128
+ os.rmdir(versdir)
129
+ # update the readme.txt file
130
+ with open(readme_path,'w') as fid:
131
+ fid.write("# casarundata populated by casaconfig.pull_data\nversion : %s\ndate : %s" % (version, datetime.today().strftime('%Y-%m-%d')))
132
+ fid.write("\n#\n# manifest")
133
+ for f in installed_files:
134
+ fid.write("\n%s" % f)
135
+
136
+ print_log_messages('casarundata installed %s at %s' % (version, path), logger)
@@ -0,0 +1,31 @@
1
+ # Copyright 2022 AUI, Inc. Washington DC, USA
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ ## get an argparse.ArgumentParser suitable for parsing the configurable
16
+ ## parameters known to casa, help is turned off here but can be turned on in the returned parser
17
+ ## this parser includes the arguments used by casaconfig, additional arguments can be added
18
+ ## this is known to be used by the casaconfig command line as well as by casashell
19
+
20
+ def get_argparser(add_help=False):
21
+ import argparse as __argparse
22
+
23
+ ## look for arguments affecting the configuration
24
+ parser = __argparse.ArgumentParser(add_help=add_help)
25
+ parser.add_argument( "--configfile",dest='configfile', default='~/.casa/config.py',
26
+ help='path to the user configuration file')
27
+ parser.add_argument( "--noconfig", dest='noconfig', action='store_const', const=True, default=False,
28
+ help='do not load user configuration file' )
29
+ parser.add_argument( "--nositeconfig", dest='nositeconfig', action='store_const', const=True, default=False,
30
+ help='do not load site configuration file')
31
+ return parser
@@ -0,0 +1,38 @@
1
+
2
+ # Copyright 2020 AUI, Inc. Washington DC, USA
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """
16
+ this module will be included in the api
17
+ """
18
+
19
+ def get_config( default=False ):
20
+ """
21
+ Get configuration values as a list of strings which can be logged, stored, or evaluated.
22
+
23
+ The default values (returned when default is True) are the configuration values after all config files have been evaluated but before the path values have been expanded using os.path.expanduser and os.path.abspath. Modules that use the command line to change config values may also not update the default values. User actions in a CASA session will also typically not change the default values.
24
+
25
+ Parameters
26
+ - default (bool=False) - If True, return the default values.
27
+
28
+ Returns
29
+ - list[str] - list of configuration strings
30
+ """
31
+
32
+ from .. import config as _config
33
+ if not default :
34
+ valsObj = _config
35
+ else:
36
+ valsObj = _config._config_defaults
37
+
38
+ return list( map( lambda name: f'{name} = {repr(getattr(valsObj,name))}', _config.__defaults ) )