casaconfig 0.0.84__tar.gz → 0.0.86__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.
- {casaconfig-0.0.84/casaconfig.egg-info → casaconfig-0.0.86}/PKG-INFO +1 -1
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/__init__.py +1 -0
- casaconfig-0.0.86/casaconfig/__main__.py +143 -0
- casaconfig-0.0.86/casaconfig/private/CasaconfigErrors.py +42 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/config_defaults_static.py +3 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/data_available.py +13 -3
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/data_update.py +82 -65
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/do_auto_updates.py +18 -14
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/get_config.py +2 -2
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/get_data_info.py +10 -4
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/get_data_lock.py +16 -7
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/measures_available.py +24 -9
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/measures_update.py +82 -54
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/print_log_messages.py +8 -3
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/pull_data.py +64 -44
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/read_readme.py +2 -2
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/summary.py +19 -1
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/update_all.py +13 -7
- {casaconfig-0.0.84 → casaconfig-0.0.86/casaconfig.egg-info}/PKG-INFO +1 -1
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig.egg-info/SOURCES.txt +1 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/setup.py +1 -1
- casaconfig-0.0.84/casaconfig/__main__.py +0 -111
- {casaconfig-0.0.84 → casaconfig-0.0.86}/LICENSE +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/MANIFEST.in +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/README.md +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/config.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/__init__.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/casasiteconfig_example.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/config_defaults.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/do_pull_data.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/get_argparser.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/io_redirect.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig/private/set_casacore_path.py +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig.egg-info/dependency_links.txt +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig.egg-info/requires.txt +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/casaconfig.egg-info/top_level.txt +0 -0
- {casaconfig-0.0.84 → casaconfig-0.0.86}/setup.cfg +0 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
import sys
|
2
|
+
import os
|
3
|
+
from casaconfig.private.get_argparser import get_argparser
|
4
|
+
|
5
|
+
parser = get_argparser(add_help=True)
|
6
|
+
|
7
|
+
# get_argparser supplies configfile, noconfig, nositeconfig
|
8
|
+
# add measurespath, pull-data, data-update, measures-update, update-all, reference-testing, current-data
|
9
|
+
|
10
|
+
parser.prog = "casaconfig"
|
11
|
+
|
12
|
+
# measurespath will default to the value in config if not set here
|
13
|
+
parser.add_argument( "--measurespath", dest='measurespath', default=None,
|
14
|
+
help="location of casarundata")
|
15
|
+
|
16
|
+
parser.add_argument( "--pull-data", dest='pulldata', action='store_const', const=True, default=False,
|
17
|
+
help="invoke pull_data() to populate measurespath with latest casarundata")
|
18
|
+
parser.add_argument( "--data-update", dest='dataupdate', action='store_const', const=True, default=False,
|
19
|
+
help="invoke data_update() to update measurespath to the latest casarundata")
|
20
|
+
parser.add_argument( "--measures-update", dest='measuresupdate', action='store_const', const=True, default=False,
|
21
|
+
help="invoke measures_update() to update measurespath to the latest measures data")
|
22
|
+
parser.add_argument( "--update-all", dest='updateall', action='store_const', const=True, default=False,
|
23
|
+
help="invoke update_all() to populate (update) measurespath with the latest casarundata and measures data")
|
24
|
+
parser.add_argument( "--reference-testing", action='store_const', const=True, dest='referencetesting', default=False,
|
25
|
+
help="set measurespath to the casarundata when this version was produced, used for testing purposes")
|
26
|
+
parser.add_argument( "--current-data", dest='currentdata', action='store_const', const=True, default=False,
|
27
|
+
help="print out a summary of the current casarundata and measures data installed in measurespath and then exit")
|
28
|
+
parser.add_argument( "--summary", dest='summary', action='store_const', const=True, default=False,
|
29
|
+
help="print out a summary of casaconfig data handling and the exit")
|
30
|
+
parser.add_argument("--force", dest='force', action='store_const', const=True, default=False,
|
31
|
+
help="force an update using the force=True option to update_all, data_update, and measures_update")
|
32
|
+
|
33
|
+
# initialize the configuration to be used
|
34
|
+
flags,args = parser.parse_known_args(sys.argv)
|
35
|
+
from casaconfig import config
|
36
|
+
|
37
|
+
# import the casaconfig module
|
38
|
+
import casaconfig
|
39
|
+
|
40
|
+
# make sure measurespath reflects any command line value
|
41
|
+
if flags.measurespath is None:
|
42
|
+
flags.measurespath = config.measurespath
|
43
|
+
else:
|
44
|
+
config.measurespath = flags.measurespath
|
45
|
+
|
46
|
+
# watch for measurespath of None, that likely means that casasiteconfig.py is in use and this has not been set. It can't be used then.
|
47
|
+
try:
|
48
|
+
if flags.measurespath is None:
|
49
|
+
print("measurespath has been set to None in the user or site config file.")
|
50
|
+
print("Either provide a measurespath on the casaconfig command line or edit the user or site config file to set measurespath to a location.")
|
51
|
+
sys.exit(1)
|
52
|
+
|
53
|
+
# do any expanduser and abspath - this is what should be used
|
54
|
+
measurespath = os.path.abspath(os.path.expanduser(flags.measurespath))
|
55
|
+
|
56
|
+
if flags.currentdata:
|
57
|
+
if not os.path.exists(measurespath) or not os.path.isdir(measurespath):
|
58
|
+
print("No data installed at %s. The measurespath does not exist or is not a directory." % measurespath)
|
59
|
+
else:
|
60
|
+
print("current data installed at %s" % measurespath)
|
61
|
+
dataInfo = casaconfig.get_data_info(measurespath)
|
62
|
+
|
63
|
+
# casarundata
|
64
|
+
casarunInfo = dataInfo['casarundata']
|
65
|
+
if casarunInfo is None or casarunInfo['version'] == "invalid":
|
66
|
+
print("No casarundata found (missing readme.txt and not obviously legacy casa data).")
|
67
|
+
if casarunInfo['version'] == "error":
|
68
|
+
print("Unexpected casarundata readme.txt content; casarundata should be reinstalled.")
|
69
|
+
elif casarunInfo['version'] == "unknown":
|
70
|
+
print("casarundata version is unknown (probably legacy casa data not maintained by casaconfig).")
|
71
|
+
else:
|
72
|
+
currentVersion = casarunInfo['version']
|
73
|
+
currentDate = casarunInfo['date']
|
74
|
+
print('casarundata version %s installed on %s' % (currentVersion, currentDate))
|
75
|
+
|
76
|
+
# measures
|
77
|
+
measuresInfo = dataInfo['measures']
|
78
|
+
if measuresInfo is None or measuresInfo['version'] == "invalid":
|
79
|
+
print("No measures data found (missing readme.txt and not obviously legacy measures data).")
|
80
|
+
if measuresInfo['version'] == "error":
|
81
|
+
print("Unexpected measures readme.txt content; measures should be reinstalled.")
|
82
|
+
elif measuresInfo['version'] == "unknown":
|
83
|
+
print("measures version is unknown (probably legacy measures data not maintained by casaconfig).")
|
84
|
+
else:
|
85
|
+
currentVersion = measuresInfo['version']
|
86
|
+
currentDate = measuresInfo['date']
|
87
|
+
print('measures version %s installed on %s' % (currentVersion, currentDate))
|
88
|
+
|
89
|
+
# ignore any other arguments
|
90
|
+
elif flags.summary:
|
91
|
+
from casaconfig.private.summary import summary
|
92
|
+
summary(config)
|
93
|
+
# ignore any other arguments
|
94
|
+
else:
|
95
|
+
if flags.referencetesting:
|
96
|
+
print("reference testing using pull_data and 'release' version into %s" % measurespath)
|
97
|
+
casaconfig.pull_data(measurespath,'release')
|
98
|
+
# ignore all other options
|
99
|
+
else:
|
100
|
+
# watch for nothing actually set
|
101
|
+
if not flags.updateall and not flags.pulldata and not flags.dataupdate and not flags.measuresupdate:
|
102
|
+
parser.print_help()
|
103
|
+
sys.exit(1)
|
104
|
+
# the update options, update all does everything, no need to invoke anything else
|
105
|
+
print("Checking for updates into %s" % measurespath)
|
106
|
+
if flags.updateall:
|
107
|
+
casaconfig.update_all(measurespath,force=flags.force)
|
108
|
+
else:
|
109
|
+
# do any pull_update first
|
110
|
+
if flags.pulldata:
|
111
|
+
casaconfig.pull_data(measurespath)
|
112
|
+
# then data_update, not necessary if pull_data just happened
|
113
|
+
if flags.dataupdate and not flags.pulldata:
|
114
|
+
casaconfig.data_update(measurespath, force=flags.force)
|
115
|
+
# then measures_update
|
116
|
+
if flags.measuresupdate:
|
117
|
+
casaconfig.measures_update(measurespath, force=flags.force)
|
118
|
+
|
119
|
+
except casaconfig.UnsetMeasurespath as exc:
|
120
|
+
# UnsetMeasurespath should not happen because measurespath is checked to not be None above, but just in case
|
121
|
+
print(str(exc))
|
122
|
+
print("This exception should not happen, check the previous messages for additional information and try a different path")
|
123
|
+
sys.exit(1)
|
124
|
+
|
125
|
+
except casaconfig.BadReadme as exc:
|
126
|
+
print(str(exc))
|
127
|
+
sys.exit(1)
|
128
|
+
|
129
|
+
except casaconfig.RemoteError as exc:
|
130
|
+
print(str(exc))
|
131
|
+
print("This is likely due to no network connection or bad connectivity to a remote site, wait and try again")
|
132
|
+
sys.exit(1)
|
133
|
+
|
134
|
+
except casaconfig.BadLock as exc:
|
135
|
+
# the output produced by the update functions is sufficient, just re-echo the exception text itself
|
136
|
+
print(str(exc))
|
137
|
+
sys.exit(1)
|
138
|
+
|
139
|
+
except casaconfig.NotWritable as exc:
|
140
|
+
print(str(exc))
|
141
|
+
sys.exit(1)
|
142
|
+
|
143
|
+
sys.exit(0)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Copyright 2024 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
|
+
class AutoUpdatesNotAllowed(Exception):
|
19
|
+
"""Raised when a path does not exist or is not owned by the user"""
|
20
|
+
pass
|
21
|
+
|
22
|
+
class BadLock(Exception):
|
23
|
+
"""Raised when the lock file is not empty and a lock attempt was made"""
|
24
|
+
pass
|
25
|
+
|
26
|
+
class BadReadme(Exception):
|
27
|
+
"""Raised when a readme.txt file does not contain the expected contents"""
|
28
|
+
pass
|
29
|
+
|
30
|
+
class NoReadme(Exception):
|
31
|
+
"""Raised when the readme.txt file is not found at path (path also may not exist)"""
|
32
|
+
|
33
|
+
class RemoteError(Exception):
|
34
|
+
"""Raised when there is an error fetching some remote content"""
|
35
|
+
pass
|
36
|
+
|
37
|
+
class NotWritable(Exception):
|
38
|
+
"""Raised when the path is not writable by the user"""
|
39
|
+
|
40
|
+
class UnsetMeasurespath(Exception):
|
41
|
+
"""Raised when a path argument is None"""
|
42
|
+
pass
|
@@ -51,3 +51,6 @@ iplogfile='ipython-%s.log' % _time.strftime("%Y%m%d-%H%M%S", _time.gmtime())
|
|
51
51
|
|
52
52
|
# include the user's local site-packages in the python path if True. May conflict with CASA modules
|
53
53
|
user_site = False
|
54
|
+
|
55
|
+
# verbosity level for casaconfig
|
56
|
+
casaconfig_verbose = 1
|
@@ -35,12 +35,19 @@ def data_available():
|
|
35
35
|
Returns
|
36
36
|
list - version names returned as list of strings
|
37
37
|
|
38
|
+
Raises
|
39
|
+
- casaconfig.RemoteError - Raised when there is an error fetching some remote content
|
40
|
+
- Exception - Unexpected exception while getting list of available casarundata versions
|
41
|
+
|
38
42
|
"""
|
39
43
|
|
40
44
|
import html.parser
|
41
45
|
import urllib.request
|
46
|
+
import urllib.error
|
42
47
|
import ssl
|
43
48
|
import certifi
|
49
|
+
|
50
|
+
from casaconfig import RemoteError
|
44
51
|
|
45
52
|
class LinkParser(html.parser.HTMLParser):
|
46
53
|
def reset(self):
|
@@ -67,10 +74,13 @@ def data_available():
|
|
67
74
|
|
68
75
|
# return the sorted list, earliest versions are first, newest is last
|
69
76
|
return sorted(parser.rundataList)
|
70
|
-
|
77
|
+
|
78
|
+
except urllib.error.URLError as urlerr:
|
79
|
+
raise RemoteError("Unable to retrieve list of available casarundata versions : " + str(urlerr)) from None
|
80
|
+
|
71
81
|
except Exception as exc:
|
72
|
-
|
73
|
-
|
82
|
+
msg = "Unexpected exception while getting list of available casarundata versions : " + str(exc)
|
83
|
+
raise Exception(msg)
|
74
84
|
|
75
85
|
# nothing to return if it got here, must have been an exception
|
76
86
|
return []
|
@@ -15,12 +15,14 @@
|
|
15
15
|
this module will be included in the api
|
16
16
|
"""
|
17
17
|
|
18
|
-
def data_update(path=None, version=None, force=False, logger=None, auto_update_rules=False):
|
18
|
+
def data_update(path=None, version=None, force=False, logger=None, auto_update_rules=False, verbose=None):
|
19
19
|
"""
|
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
|
-
|
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.
|
24
26
|
|
25
27
|
The path must contain a previously installed version of casarundata.
|
26
28
|
Use pull_data to install casarundata into a new path (empty or does not exist).
|
@@ -98,29 +100,45 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
|
|
98
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.
|
99
101
|
- logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal.
|
100
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.
|
101
104
|
|
102
105
|
Returns
|
103
106
|
None
|
104
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
|
+
|
105
118
|
"""
|
106
119
|
|
107
120
|
import os
|
108
121
|
|
109
|
-
from
|
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
|
110
126
|
from .print_log_messages import print_log_messages
|
111
127
|
from .get_data_lock import get_data_lock
|
112
|
-
from .pull_data import pull_data
|
113
128
|
from .do_pull_data import do_pull_data
|
114
|
-
from .get_data_info import get_data_info
|
115
129
|
|
116
130
|
if path is None:
|
117
131
|
from .. import config as _config
|
118
132
|
path = _config.measurespath
|
119
133
|
|
120
134
|
if path is None:
|
121
|
-
|
135
|
+
raise UnsetMeasurespath('data_update: path is None and has not been set in config.measurespath. Provide a valid path and retry.')
|
122
136
|
return
|
123
137
|
|
138
|
+
if verbose is None:
|
139
|
+
from .. import config as _config
|
140
|
+
verbose = _config.casaconfig_verbose
|
141
|
+
|
124
142
|
# when a specific version is requested then the measures readme.txt that is part of that version
|
125
143
|
# will get a timestamp of now so that default measures updates won't happen for a day unless the
|
126
144
|
# force argument is used for measures_update
|
@@ -131,30 +149,24 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
|
|
131
149
|
|
132
150
|
if auto_update_rules:
|
133
151
|
if version is not None:
|
134
|
-
print_log_messages('auto_update_rules requires that version be None', logger, True)
|
152
|
+
print_log_messages('data_update: auto_update_rules requires that version be None', logger, True)
|
135
153
|
return
|
136
154
|
if force:
|
137
|
-
print_log_messages('force must be False when auto_update_rules is True', logger, True)
|
155
|
+
print_log_messages('data_update: force must be False when auto_update_rules is True', logger, True)
|
138
156
|
return
|
139
157
|
if (not os.path.isdir(path)) or (os.stat(path).st_uid != os.getuid()):
|
140
|
-
|
141
|
-
msgs.append("Warning: path must exist as a directory and it must be owned by the user, path = %s" % path)
|
142
|
-
msgs.append("Warning: no data updates are possible on this path by this user.")
|
143
|
-
print_log_messages(msgs, logger, False)
|
144
|
-
return
|
158
|
+
raise AutoUpdatesNotAllowed("data_update: path must exist as a directory and it must be owned by the user, path = %s" % path)
|
145
159
|
|
146
160
|
if not os.path.exists(readme_path):
|
147
161
|
# path must exist and it must be empty in order to continue
|
148
162
|
if not os.path.exists(path) or (len(os.listdir(path)) > 0):
|
149
|
-
|
150
|
-
return
|
163
|
+
raise NoReadme('data_update: no casarundata readme.txt file found at %s. Nothing updated or checked.' % path);
|
151
164
|
# ok to install a fresh copy, use pull_data directly
|
152
|
-
return pull_data(path,version,force,logger)
|
165
|
+
return pull_data(path,version,force,logger,verbose)
|
153
166
|
|
154
167
|
# path must be writable with execute bit set
|
155
168
|
if (not os.access(path, os.W_OK | os.X_OK)) :
|
156
|
-
|
157
|
-
return
|
169
|
+
raise NotWritable('data_update: No permission to write to %s, cannot update.' % path)
|
158
170
|
|
159
171
|
# try and digest the readme file
|
160
172
|
|
@@ -162,7 +174,8 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
|
|
162
174
|
currentVersion = []
|
163
175
|
currentDate = []
|
164
176
|
ageRecent = False
|
165
|
-
|
177
|
+
|
178
|
+
# already checked that path is OK, type is OK here, no need to trap for exceptions here
|
166
179
|
dataReadmeInfo = get_data_info(path, logger, type='casarundata')
|
167
180
|
|
168
181
|
if dataReadmeInfo is None or dataReadmeInfo['version'] == 'invalid':
|
@@ -188,20 +201,17 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
|
|
188
201
|
|
189
202
|
if (len(installed_files) == 0):
|
190
203
|
# this shouldn't happen
|
191
|
-
|
192
|
-
|
193
|
-
msgs.append('choose a different path or empty this path and try again using pull_data')
|
194
|
-
print_log_messages(msgs, logger, True)
|
195
|
-
# no lock has been set yet, safe to simply return here
|
196
|
-
return
|
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')
|
197
206
|
|
198
207
|
if version is None and force is False and ageRecent:
|
199
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
|
200
|
-
|
201
|
-
|
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)
|
202
211
|
# no lock has been set yet, safe to simply return here
|
203
212
|
return
|
204
213
|
|
214
|
+
# this may raise a RemoteError, no need to catch that here but it may need to be caught upstream
|
205
215
|
available_data = data_available()
|
206
216
|
requestedVersion = version
|
207
217
|
latestVersion = False
|
@@ -238,19 +248,20 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
|
|
238
248
|
force = False
|
239
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
|
240
250
|
if not force:
|
241
|
-
|
242
|
-
|
251
|
+
if verbose > 0:
|
252
|
+
print_log_messages('data_update: requested "release" version of casarundata and measures are already installed.', logger, verbose=verbose)
|
243
253
|
# no lock has been set yet, safe to simply return here
|
244
254
|
return
|
245
255
|
else:
|
246
256
|
# normal usage, ok to return now
|
247
|
-
# normal use is silent, commented out lines are useful during debugging
|
248
257
|
if latestVersion:
|
249
|
-
|
258
|
+
if verbose > 0:
|
259
|
+
print_log_messages('The latest version is already installed in %s' % path, logger, verbose=verbose)
|
250
260
|
# touch the dates of the readme to prevent a future check on available data for the next 24 hours
|
251
261
|
os.utime(readme_path)
|
252
|
-
|
253
|
-
|
262
|
+
else:
|
263
|
+
if verbose > 0:
|
264
|
+
print_log_messages('Requested casarundata version is already installed in %s, %s' % (path, currentVersion), logger, verbose=verbose)
|
254
265
|
|
255
266
|
# no lock has been set yet, safe to simply return here
|
256
267
|
return
|
@@ -258,19 +269,12 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
|
|
258
269
|
# an update appears necessary
|
259
270
|
|
260
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
|
261
273
|
try:
|
262
274
|
print_log_messages('data_update using version %s, acquiring the lock ... ' % requestedVersion, logger)
|
263
275
|
|
264
276
|
lock_fd = get_data_lock(path, 'data_update')
|
265
|
-
#
|
266
|
-
if lock_fd is None:
|
267
|
-
msgs = []
|
268
|
-
msgs.append('The lock file at %s is not empty.' % path)
|
269
|
-
msgs.append('A previous attempt to update path may have failed or exited prematurely.')
|
270
|
-
msgs.append('Remove the lock file and set force to True with the desired version (default to most recent).')
|
271
|
-
msgs.append('It may be best to completely repopulate path using pull_data and measures_update.')
|
272
|
-
print_log_messages(msgs, logger, True)
|
273
|
-
return
|
277
|
+
# the BadLock exception that may happen here is caught below
|
274
278
|
|
275
279
|
do_update = True
|
276
280
|
# it's possible that another process had path locked and updated the readme with new information, re-read it
|
@@ -290,58 +294,71 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
|
|
290
294
|
do_update = False
|
291
295
|
# if measuresReadmeInfo is None there was a problem which requires a full update so do_update remains True
|
292
296
|
if not do_update:
|
297
|
+
# always verbose here because the lock file is in use
|
293
298
|
print_log_messages('data update requested "release" version of casarundata and measures are already installed.', logger)
|
294
299
|
else:
|
295
300
|
# nothing to do here, already at the expected version and an update is not being forced
|
296
301
|
if latestVersion:
|
302
|
+
# always verbose here because the lock file is in use
|
297
303
|
print_log_messages('The latest version is already installed, using version %s' % currentVersion, logger)
|
298
304
|
# touch the dates of the readme to prevent a future check on available data for the next 24 hours
|
299
305
|
os.utime(readme_path)
|
300
306
|
else:
|
307
|
+
# always verbose here because the lock file is in use
|
301
308
|
print_log_messages('requested version is already installed.', logger)
|
302
309
|
do_update = False
|
303
310
|
|
304
311
|
if do_update:
|
305
312
|
# update is still on, check the manifest
|
306
313
|
if len(installed_files) == 0:
|
307
|
-
# this shouldn't happen, do not do an update
|
308
|
-
|
309
|
-
msgs = []
|
310
|
-
msgs.append('The readme.txt file read at path did not contain the expected list of installed files')
|
311
|
-
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')
|
312
|
-
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')
|
313
|
-
print_log_messages(msgs, logger, True)
|
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')
|
314
316
|
else:
|
315
|
-
# this shouldn't happen
|
316
|
-
|
317
|
-
msgs = []
|
318
|
-
msgs.append('Unexpected problem reading readme.txt file during data_update, can not safely update to the requested version')
|
319
|
-
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')
|
320
|
-
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')
|
321
|
-
print_log_messages(msgs, logger, True)
|
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')
|
322
319
|
|
323
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
|
324
323
|
do_pull_data(path, requestedVersion, installed_files, currentVersion, currentDate, logger)
|
324
|
+
clean_lock = True
|
325
325
|
if namedVersion:
|
326
326
|
# a specific version has been requested, set the times on the measures readme.txt to now to avoid
|
327
327
|
# a default update of the measures data without using the force argument
|
328
328
|
measuresReadmePath = os.path.join(path,'geodetic/readme.txt')
|
329
329
|
os.utime(measuresReadmePath)
|
330
330
|
|
331
|
-
|
332
|
-
|
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
|
333
349
|
|
334
350
|
except Exception as exc:
|
335
351
|
msgs = []
|
336
352
|
msgs.append('ERROR! : Unexpected exception while populating casarundata version %s to %s' % (requestedVersion, path))
|
337
353
|
msgs.append('ERROR! : %s' % exc)
|
338
354
|
print_log_messages(msgs, logger, True)
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
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()
|
346
363
|
|
347
364
|
return
|
@@ -15,7 +15,7 @@
|
|
15
15
|
this module will be included in the api
|
16
16
|
"""
|
17
17
|
|
18
|
-
def do_auto_updates(configDict, logger=None):
|
18
|
+
def do_auto_updates(configDict, logger=None, verbose=None):
|
19
19
|
"""
|
20
20
|
Use measurespath, data_auto_update, and measures_auto_update from configDict to
|
21
21
|
do any auto updates as necessary.
|
@@ -33,41 +33,45 @@ def do_auto_updates(configDict, logger=None):
|
|
33
33
|
See the documentation for data_update and measures_update for additional details
|
34
34
|
about the auto update rules.
|
35
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
|
+
|
36
42
|
Paramters
|
37
43
|
- configDict (dict) - A config dictionary previously set.
|
38
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.
|
39
46
|
|
40
47
|
Returns
|
41
48
|
None
|
42
49
|
|
50
|
+
Raises
|
51
|
+
- casaconfig.UnsetMeasurespath - raised when measurespath is None in config
|
52
|
+
|
43
53
|
"""
|
44
54
|
|
45
55
|
from .print_log_messages import print_log_messages
|
46
56
|
from .data_update import data_update
|
47
57
|
from .measures_update import measures_update
|
48
58
|
|
59
|
+
from casaconfig import UnsetMeasurespath
|
60
|
+
|
49
61
|
if configDict.measurespath is None:
|
50
62
|
# continue, because things still might work if there are measures in datapath
|
51
|
-
|
52
|
-
msgs.append('measurespath is None in config')
|
53
|
-
msgs.append('set measurespath in your config file at ~/.casa/config.py')
|
54
|
-
msgs.append('or ask the site manager to set that in a casasiteconfig.py')
|
55
|
-
msgs.append('visit https://casadocs.readthedocs.io/en/stable/notebooks/external-data.html for more information')
|
56
|
-
|
57
|
-
if (configDict.measures_auto_update or configDict.data_auto_update):
|
58
|
-
msgs.append('Auto updates of measures path are not possible because measurespath is not set, skipping auto updates')
|
59
|
-
|
60
|
-
print_log_messages(msgs, logger, True)
|
63
|
+
raise UnsetMeasurespath('do_auto_updates: measurespath is None in configDict. Provide a valid path and retry.')
|
61
64
|
|
62
|
-
|
65
|
+
if verbose is None:
|
66
|
+
verbose = configDict.casaconfig_verbose
|
63
67
|
|
64
68
|
if (configDict.measures_auto_update or configDict.data_auto_update):
|
65
69
|
if (configDict.data_auto_update and (not configDict.measures_auto_update)):
|
66
70
|
print_log_messages('measures_auto_update must be True when data_auto_update is True, skipping auto updates', logger, True)
|
67
71
|
else:
|
68
72
|
if configDict.data_auto_update:
|
69
|
-
data_update(configDict.measurespath, logger=logger, auto_update_rules=True)
|
73
|
+
data_update(configDict.measurespath, logger=logger, auto_update_rules=True, verbose=verbose)
|
70
74
|
if configDict.data_auto_update or configDict.measures_auto_update:
|
71
|
-
measures_update(configDict.measurespath, logger=logger, auto_update_rules=True)
|
75
|
+
measures_update(configDict.measurespath, logger=logger, auto_update_rules=True, verbose=verbose)
|
72
76
|
|
73
77
|
return
|
@@ -23,10 +23,10 @@ def get_config( default=False ):
|
|
23
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
24
|
|
25
25
|
Parameters
|
26
|
-
default (bool=False) - If True, return the default values.
|
26
|
+
- default (bool=False) - If True, return the default values.
|
27
27
|
|
28
28
|
Returns
|
29
|
-
list[str] - list of configuration strings
|
29
|
+
- list[str] - list of configuration strings
|
30
30
|
"""
|
31
31
|
|
32
32
|
from .. import config as _config
|
@@ -76,10 +76,14 @@ def get_data_info(path=None, logger=None, type=None):
|
|
76
76
|
- type (str) - the specific type of data info to return (None, 'casarundata', 'measures', 'release'; None returns a dictionary of all types)
|
77
77
|
|
78
78
|
Returns
|
79
|
-
|
79
|
+
- a dictionary by type, 'casarundata', 'measures', 'release' where each type is a dictionary containing 'version' and 'date'. A return value of None indicates path is unset. A value of None for that type means no information could be found about that type. If a specific type is requested then only the dictionary for that type is returned (or None if that type can not be found).
|
80
|
+
|
81
|
+
Raises
|
82
|
+
- casaconfig.UnsetMeasurespath - path is None and has not been set in config
|
83
|
+
- ValueError - raised when type has an invalid value
|
84
|
+
|
80
85
|
"""
|
81
86
|
|
82
|
-
# when None is returned, path wasn't set
|
83
87
|
result = None
|
84
88
|
|
85
89
|
import os
|
@@ -87,6 +91,9 @@ def get_data_info(path=None, logger=None, type=None):
|
|
87
91
|
import importlib.resources
|
88
92
|
from .print_log_messages import print_log_messages
|
89
93
|
from .read_readme import read_readme
|
94
|
+
|
95
|
+
from casaconfig import UnsetMeasurespath
|
96
|
+
|
90
97
|
|
91
98
|
currentTime = time.time()
|
92
99
|
secondsPerDay = 24. * 60. * 60.
|
@@ -96,8 +103,7 @@ def get_data_info(path=None, logger=None, type=None):
|
|
96
103
|
path = _config.measurespath
|
97
104
|
|
98
105
|
if path is None:
|
99
|
-
|
100
|
-
return None
|
106
|
+
raise UnsetMeasurespath('get_data_info: path is None and has not been set in config.measurespath. Provide a valid path and retry.')
|
101
107
|
|
102
108
|
path = os.path.abspath(os.path.expanduser(path))
|
103
109
|
|