casaconfig 0.0.84__tar.gz → 0.0.85__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 (37) hide show
  1. {casaconfig-0.0.84/casaconfig.egg-info → casaconfig-0.0.85}/PKG-INFO +1 -1
  2. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/__init__.py +1 -0
  3. casaconfig-0.0.85/casaconfig/__main__.py +139 -0
  4. casaconfig-0.0.85/casaconfig/private/CasaconfigErrors.py +42 -0
  5. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/config_defaults_static.py +3 -0
  6. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/data_available.py +16 -6
  7. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/data_update.py +89 -72
  8. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/do_auto_updates.py +22 -18
  9. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/do_pull_data.py +8 -8
  10. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/get_config.py +4 -4
  11. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/get_data_info.py +15 -9
  12. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/get_data_lock.py +19 -10
  13. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/measures_available.py +26 -11
  14. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/measures_update.py +89 -61
  15. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/print_log_messages.py +11 -6
  16. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/pull_data.py +70 -50
  17. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/read_readme.py +6 -6
  18. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/set_casacore_path.py +3 -3
  19. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/summary.py +19 -1
  20. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/update_all.py +17 -11
  21. {casaconfig-0.0.84 → casaconfig-0.0.85/casaconfig.egg-info}/PKG-INFO +1 -1
  22. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig.egg-info/SOURCES.txt +1 -0
  23. {casaconfig-0.0.84 → casaconfig-0.0.85}/setup.py +1 -1
  24. casaconfig-0.0.84/casaconfig/__main__.py +0 -111
  25. {casaconfig-0.0.84 → casaconfig-0.0.85}/LICENSE +0 -0
  26. {casaconfig-0.0.84 → casaconfig-0.0.85}/MANIFEST.in +0 -0
  27. {casaconfig-0.0.84 → casaconfig-0.0.85}/README.md +0 -0
  28. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/config.py +0 -0
  29. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/__init__.py +0 -0
  30. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/casasiteconfig_example.py +0 -0
  31. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/config_defaults.py +0 -0
  32. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/get_argparser.py +0 -0
  33. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig/private/io_redirect.py +0 -0
  34. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig.egg-info/dependency_links.txt +0 -0
  35. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig.egg-info/requires.txt +0 -0
  36. {casaconfig-0.0.84 → casaconfig-0.0.85}/casaconfig.egg-info/top_level.txt +0 -0
  37. {casaconfig-0.0.84 → casaconfig-0.0.85}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: casaconfig
3
- Version: 0.0.84
3
+ Version: 0.0.85
4
4
  Summary: CASA Operational Configuration Package
5
5
  Home-page: https://github.com/casangi/casaconfig
6
6
  Author: National Radio Astronomy Observatory
@@ -12,3 +12,4 @@ from .private.update_all import update_all
12
12
  from .private.set_casacore_path import set_casacore_path
13
13
  from .private.get_config import get_config
14
14
  from .private.get_data_info import get_data_info
15
+ from .private.CasaconfigErrors import *
@@ -0,0 +1,139 @@
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
+ # the update options, update all does everything, no need to invoke anything else
101
+ print("Checking for updates into %s" % measurespath)
102
+ if flags.updateall:
103
+ casaconfig.update_all(measurespath,force=flags.force)
104
+ else:
105
+ # do any pull_update first
106
+ if flags.pulldata:
107
+ casaconfig.pull_data(measurespath)
108
+ # then data_update, not necessary if pull_data just happened
109
+ if flags.dataupdate and not flags.pulldata:
110
+ casaconfig.data_update(measurespath, force=flags.force)
111
+ # then measures_update
112
+ if flags.measuresupdate:
113
+ casaconfig.measures_update(measurespath, force=flags.force)
114
+
115
+ except casaconfig.UnsetMeasurespath as exc:
116
+ # UnsetMeasurespath should not happen because measurespath is checked to not be None above, but just in case
117
+ print(str(exc))
118
+ print("This exception should not happen, check the previous messages for additional information and try a different path")
119
+ sys.exit(1)
120
+
121
+ except casaconfig.BadReadme as exc:
122
+ print(str(exc))
123
+ sys.exit(1)
124
+
125
+ except casaconfig.RemoteError as exc:
126
+ print(str(exc))
127
+ print("This is likely due to no network connection or bad connectivity to a remote site, wait and try again")
128
+ sys.exit(1)
129
+
130
+ except casaconfig.BadLock as exc:
131
+ # the output produced by the update functions is sufficient, just re-echo the exception text itself
132
+ print(str(exc))
133
+ sys.exit(1)
134
+
135
+ except casaconfig.NotWritable as exc:
136
+ print(str(exc))
137
+ sys.exit(1)
138
+
139
+ 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
@@ -29,18 +29,25 @@ def data_available():
29
29
  changing casaconfig functions that use those tarballs). The full filename is
30
30
  the casarundata version expected in casaconfig functions.
31
31
 
32
- Parameters
32
+ Parameters:
33
33
  None
34
34
 
35
- Returns
36
- list - version names returned as list of strings
35
+ Returns:
36
+ list: version names returned as list of strings
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
37
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
- print("ERROR! : unexpected exception while getting list of available casarundata versions")
73
- print("ERROR! : %s" % exc)
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
- If no update is necessary then this function will silently return.
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).
@@ -92,35 +94,51 @@ def data_update(path=None, version=None, force=False, logger=None, auto_update_r
92
94
  **Note:** the most recent casarundata may not include the most recent measures data. A data_update
93
95
  is typically followed by a measures_update.
94
96
 
95
- Parameters
96
- - path (str=None) - Folder path to update. Must contain a valid readme.txt. If not set then config.measurespath is used.
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.
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.
99
- - logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal.
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.
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.
101
104
 
102
- Returns
105
+ Returns:
103
106
  None
104
107
 
108
+ Raises:
109
+ AutoUpdatesNotAllowed : raised when path does not exist as a directory or is not owned by the user
110
+ BadLock : raised when the lock file was not empty when an attempt was made to obtain the lock
111
+ BadReadme : raised when the readme.txt file at path did not contain the expected list of installed files or was incorrectly formatted
112
+ NoReadme : raised when the readme.txt file is not found at path (path also may not exist)
113
+ NotWritable : raised when the user does not have permission to write to path
114
+ RemoteError : raised by data_available when the list of available data versions could not be fetched
115
+ 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 .data_available import data_available
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
- print_log_messages('path is None and has not been set in config.measurespath. Provide a valid path and retry.', logger, True)
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
- msgs = []
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
- print_log_messages('No readme.txt file found at path. Nothing updated or checked.', logger, True);
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
- print_log_messages('No permission to write to path, cannot update : %s' % path, logger, True)
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
- msgs = []
192
- msgs.append('The readme.txt file at path did not contain the expected list of installed files')
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
- # normal use is silent, this line is useful during debugging
201
- # print_log_messages('data_update latest version checked recently in %s, using version %s' % (path, currentVersion), logger)
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
- # normal use is silent, this line is useful during debugging
242
- # print_log_messages('data_update requested "release" version of casarundata and measures are already installed.', logger)
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
- # print_log_messages('The latest version is already installed in %s, using version %s' % (path, currentVersion), logger)
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
- #else:
253
- # print_log_messages('Requested casarundata is installed in %s, using version %s' % (path, currentVersion), logger)
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
- # if lock_fd is None it means the lock file was not empty - because we know that path exists at this point
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
- do_update = False
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, do not do an update
316
- do_update = False
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
- # truncate the lock file
332
- lock_fd.truncate(0)
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
- # leave the contents of the lock file as is to aid in debugging
340
- # import traceback
341
- # traceback.print_exc()
342
-
343
- # if the lock file is not closed, do that now to release the lock
344
- if lock_fd is not None and not lock_fd.closed:
345
- lock_fd.close()
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
- Paramters
37
- - configDict (dict) - A config dictionary previously set.
38
- - logger (casatools.logsink=None) - Instance of the casalogger to use for writing messages. Default None writes messages to the terminal.
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
39
 
40
- Returns
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:
41
48
  None
42
49
 
50
+ Raises:
51
+ 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
- msgs = []
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
- return
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,15 +23,15 @@ def do_pull_data(path, version, installed_files, currentVersion, currentDate, lo
23
23
  calling function has already examined any existing readme file and used that
24
24
  to set the installed_files list as appropriate.
25
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.
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
33
 
34
- Returns
34
+ Returns:
35
35
  None
36
36
 
37
37
  """