casaconfig 1.2.0__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- casaconfig/__init__.py +7 -0
- casaconfig/config.py +34 -21
- casaconfig/private/config_defaults.py +4 -2
- casaconfig/private/config_defaults_static.py +22 -0
- casaconfig/private/data_available.py +17 -37
- casaconfig/private/data_update.py +22 -26
- casaconfig/private/do_auto_updates.py +4 -3
- casaconfig/private/do_pull_data.py +7 -27
- casaconfig/private/do_untar_url.py +94 -0
- casaconfig/private/get_available_files.py +94 -0
- casaconfig/private/get_data_info.py +35 -20
- casaconfig/private/measures_available.py +212 -36
- casaconfig/private/measures_update.py +179 -126
- casaconfig/private/print_log_messages.py +7 -3
- casaconfig/private/pull_data.py +11 -6
- casaconfig/private/read_readme.py +57 -13
- casaconfig/private/set_casacore_path.py +2 -2
- casaconfig/private/summary.py +3 -0
- casaconfig/private/update_all.py +6 -5
- casaconfig-1.4.0.dist-info/METADATA +92 -0
- casaconfig-1.4.0.dist-info/RECORD +34 -0
- {casaconfig-1.2.0.dist-info → casaconfig-1.4.0.dist-info}/WHEEL +1 -1
- tests/test_casaconfig.py +190 -17
- casaconfig-1.2.0.dist-info/METADATA +0 -293
- casaconfig-1.2.0.dist-info/RECORD +0 -32
- {casaconfig-1.2.0.dist-info → casaconfig-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {casaconfig-1.2.0.dist-info → casaconfig-1.4.0.dist-info}/top_level.txt +0 -0
@@ -16,45 +16,89 @@ def read_readme(path):
|
|
16
16
|
"""
|
17
17
|
Read and parse the contents of a readme.txt file used by casaconfig.
|
18
18
|
|
19
|
-
A dictionary containing the 'version', 'date', and 'extra' (containing
|
19
|
+
A dictionary containing the 'version', 'date', 'site', and 'extra' (containing
|
20
20
|
a list of optional extra lines found). On error, the return values is None.
|
21
21
|
|
22
22
|
The extra lines are stripped and do not include lines begining with '#'
|
23
23
|
|
24
24
|
The format is assumed to be:
|
25
25
|
a line begining with #, which is ignored.
|
26
|
+
a line "site: the site url string"
|
26
27
|
a line "version : the versions string"
|
27
28
|
a line "date : the date"
|
28
29
|
optional extra lines (the manifest of installed files for the main readme)
|
29
30
|
|
30
|
-
The version
|
31
|
+
The version, site and date strings are stripped of leading and trailing whitespace.
|
32
|
+
|
33
|
+
The site string only appears in measures data and is missing is early readme
|
34
|
+
files for measures data. If no site string is seen the value in the dictionary
|
35
|
+
is None.
|
36
|
+
|
37
|
+
The version and date strings are required. If they are not found a BadReadme
|
38
|
+
exception is raised.
|
31
39
|
|
32
40
|
Parameters
|
33
41
|
- path (str) - the path to the file to be read
|
34
42
|
|
35
43
|
Returns
|
36
|
-
Dictionary of '
|
37
|
-
'extra' (a list of any extra lines found).
|
44
|
+
Dictionary of 'site' ( the site URL or None), 'version' (the version string),
|
45
|
+
'date' (the date string), 'extra' (a list of any extra lines found).
|
46
|
+
The return value is None on error except that format errors raise
|
47
|
+
a BadReadme exception.
|
48
|
+
|
49
|
+
Raises
|
50
|
+
- casaconfig.BadReadme - raised when there is a format error in the file at path
|
38
51
|
"""
|
39
52
|
|
40
53
|
import os
|
54
|
+
from casaconfig import BadReadme
|
41
55
|
|
56
|
+
site = None
|
42
57
|
version = ""
|
43
58
|
date = ""
|
44
59
|
extra = []
|
45
60
|
result = None
|
46
|
-
|
61
|
+
|
47
62
|
try:
|
48
63
|
with open(path, 'r') as fid:
|
49
64
|
readmeLines = fid.readlines()
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
65
|
+
# order is unimportant except the first line must start with
|
66
|
+
# an "#" and the second line starting with "#" indicates the
|
67
|
+
# start of the "extra" lines
|
68
|
+
# duplicate instances of the same key in key : value lines are accepted
|
69
|
+
# the last value associated with key is used, that should never happen.
|
70
|
+
inExtraLines = False
|
71
|
+
if readmeLines[0][0] != '#':
|
72
|
+
raise BadReadme('Readme file missing required "#" at start of first line, %s' % path)
|
73
|
+
for line in readmeLines[1:]:
|
74
|
+
if inExtraLines and not (line[0] == '#'):
|
75
|
+
extra.append(line.strip())
|
76
|
+
elif line[0] == '#':
|
77
|
+
inExtraLines = True
|
78
|
+
else:
|
79
|
+
splitLine = line.split(':')
|
80
|
+
if len(splitLine) < 2:
|
81
|
+
raise BadReadme('A line did not have an expected ":" separating into at least two parts, %s' % path)
|
82
|
+
key = splitLine[0].strip()
|
83
|
+
if key == 'site':
|
84
|
+
# the URL likely also has a ":" so rejoin the second part and then strip that
|
85
|
+
siteURL = ":".join(splitLine[1:])
|
86
|
+
site = siteURL.strip()
|
87
|
+
elif key == 'version':
|
88
|
+
version = splitLine[1].strip()
|
89
|
+
elif key == 'date':
|
90
|
+
date = splitLine[1].strip()
|
91
|
+
# anything else is OK and silently ignored
|
92
|
+
result = {'site':site, 'version':version, 'date':date, 'extra':extra}
|
93
|
+
except BadReadme as exc:
|
94
|
+
# reraise it
|
95
|
+
raise
|
96
|
+
except Exception as exc:
|
97
|
+
# silently return None, handled elsewhere
|
58
98
|
result = None
|
59
99
|
|
100
|
+
# require that date and version are now set in result
|
101
|
+
if result is not None and ((len(result['version'])==0) or (len(result['date'])==0)):
|
102
|
+
raise BadReadme('Readme file missing required version or date fields, %s' % path)
|
103
|
+
|
60
104
|
return result
|
@@ -32,12 +32,12 @@ def set_casacore_path(path=None):
|
|
32
32
|
None
|
33
33
|
|
34
34
|
"""
|
35
|
-
import
|
35
|
+
import importlib.resources
|
36
36
|
import os
|
37
37
|
import re
|
38
38
|
import sys
|
39
39
|
|
40
|
-
if path is None: path =
|
40
|
+
if path is None: path = str(importlib.resources.files('casaconfig').joinpath('data/'))
|
41
41
|
path = os.path.abspath(os.path.expanduser(path))
|
42
42
|
|
43
43
|
rctext = 'measures.directory: %s\n' % path
|
casaconfig/private/summary.py
CHANGED
@@ -80,6 +80,9 @@ def summary(configDict = None):
|
|
80
80
|
msg += "; legacy data not maintained by casaconfig"
|
81
81
|
elif measVers == "error":
|
82
82
|
msg += "; unexpected readme.txt file, measures should be reinstalled"
|
83
|
+
measSite = dataInfo['measures']['site']
|
84
|
+
if measSite is not None and len(measSite) > 0:
|
85
|
+
msg = msg + " site : " + measSite
|
83
86
|
print(msg)
|
84
87
|
|
85
88
|
if (dataInfo['release'] is None):
|
casaconfig/private/update_all.py
CHANGED
@@ -87,7 +87,8 @@ def update_all(path=None, logger=None, force=False, verbose=None):
|
|
87
87
|
msgs = []
|
88
88
|
msgs.append("Warning: path must exist as a directory and it must be owned by the user, path = %s" % path)
|
89
89
|
msgs.append("Warning: no updates are possible on this path by this user.")
|
90
|
-
|
90
|
+
# always print and log this although it's only a warning
|
91
|
+
print_log_messages(msgs, logger, False, 2)
|
91
92
|
return
|
92
93
|
|
93
94
|
# if path is empty, first use pull_data
|
@@ -95,7 +96,7 @@ def update_all(path=None, logger=None, force=False, verbose=None):
|
|
95
96
|
pull_data(path, logger, verbose=verbose)
|
96
97
|
# double check that it's not empty
|
97
98
|
if len(os.listdir(path))==0:
|
98
|
-
print_log_messages("pull_data failed, see the error messages for more details. update_all can not continue")
|
99
|
+
print_log_messages("pull_data failed, see the error messages for more details. update_all can not continue", logger, True)
|
99
100
|
return
|
100
101
|
|
101
102
|
# readme.txt must exist in path at this point, using get_data_info provides more possible feedback
|
@@ -105,15 +106,15 @@ def update_all(path=None, logger=None, force=False, verbose=None):
|
|
105
106
|
print_log_messages('could not find any data information about %s, can not continue with update_all' % path, logger, True)
|
106
107
|
|
107
108
|
if dataInfo['casarundata'] is None:
|
108
|
-
print_log_messages('readme.txt not found at path, update_all can not continue, path = %s' % path, logger)
|
109
|
+
print_log_messages('readme.txt not found at path, update_all can not continue, path = %s' % path, logger, True)
|
109
110
|
return
|
110
111
|
|
111
112
|
if dataInfo['casarundata'] == 'invalid':
|
112
|
-
print_log_messages('readme.txt is invalid at path, update_all can not continue, path = %s' % path, logger)
|
113
|
+
print_log_messages('readme.txt is invalid at path, update_all can not continue, path = %s' % path, logger, True)
|
113
114
|
return
|
114
115
|
|
115
116
|
if dataInfo['casarundata'] == 'unknown':
|
116
|
-
print_log_messages('contents at path appear to be casarundata but no readme.txt was found, casaconfig did not populate this data and update_all can not continue, path = %s', path, logger)
|
117
|
+
print_log_messages('contents at path appear to be casarundata but no readme.txt was found, casaconfig did not populate this data and update_all can not continue, path = %s', path, logger, True)
|
117
118
|
return
|
118
119
|
|
119
120
|
# the updates should work now
|
@@ -0,0 +1,92 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: casaconfig
|
3
|
+
Version: 1.4.0
|
4
|
+
Summary: CASA Operational Configuration Package
|
5
|
+
Author-email: National Radio Astronomy Observatory <casa-feedback@nrao.edu>
|
6
|
+
License-Expression: Apache-2.0
|
7
|
+
Project-URL: Homepage, https://casa.nrao.edu/
|
8
|
+
Project-URL: Documentation, https://casadocs.readthedocs.io/
|
9
|
+
Project-URL: Repository, https://github.com/casangi/casaconfig.git
|
10
|
+
Requires-Python: >=3.10
|
11
|
+
Description-Content-Type: text/markdown
|
12
|
+
License-File: LICENSE
|
13
|
+
Requires-Dist: certifi>=2023.5.7
|
14
|
+
Dynamic: license-file
|
15
|
+
|
16
|
+
# casaconfig
|
17
|
+
Runtime data necessary for CASA operation.
|
18
|
+
|
19
|
+
- [latest casaconfig API on casadocs](https://casadocs.readthedocs.io/en/latest/api/casaconfig.html)
|
20
|
+
- [stable casaconfig API on casadocs](https://casadocs.readthedocs.io/en/stable/api/casaconfig.html)
|
21
|
+
|
22
|
+
|
23
|
+
## Release Instructions
|
24
|
+
1. Create a release branch with a version name (ie v1.6.2)
|
25
|
+
2. Ensure the version number in pyproject.toml on the branch is set correctly
|
26
|
+
3. Create a tag of the release branch (ie v1.6.2-1)
|
27
|
+
4. Github Action runs automatically to publish a pip package to pypi
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
```
|
32
|
+
$: pip install casaconfig
|
33
|
+
```
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
See the casaconfig API documentation on casadocs (links above).
|
38
|
+
|
39
|
+
Also see the External Data section of casadocs for additional details
|
40
|
+
|
41
|
+
- [latest External Data section on casadocs](https://casadocs.readthedocs.io/en/latest/notebooks/external-data.html)
|
42
|
+
- [stable External Data section on casadocs](https://casadocs.readthedocs.io/en/stable/notebooks/external-data.html)
|
43
|
+
|
44
|
+
## Developers Instructions
|
45
|
+
1. every push to the casaconfig repository will push a new wheel to [test pypi](https://test.pypi.org/project/casaconfig/#history)
|
46
|
+
2. the version in pyproject.toml must be updated before each push so that the wheel has a unique name (e.g. "1.2.3dev2", where "dev?" could be incremented during development; see the [specification](https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers) for more information about valid version signifiers)
|
47
|
+
3. When testing with a casatools build, "pip install" the development casaconfig wheel before running any tests - it may be installed before casatools is installed or after since the casatools build does not depend on casasconfig (uninstall any already installed casaconfig if necessary).
|
48
|
+
4. For release, follow the above instructions.
|
49
|
+
|
50
|
+
Wheels can be built locally following the same process used by the CI actions. To install the build-system dependencies as defined in pyproject.toml and then generate a source distribution and wheel:
|
51
|
+
```
|
52
|
+
python3 -m pip install build setuptools --user
|
53
|
+
python3 -m build
|
54
|
+
```
|
55
|
+
This will create:
|
56
|
+
```
|
57
|
+
casaconfig.egg-info
|
58
|
+
├── PKG-INFO
|
59
|
+
├── SOURCES.txt
|
60
|
+
├── dependency_links.txt
|
61
|
+
├── requires.txt
|
62
|
+
└── top_level.txt
|
63
|
+
dist
|
64
|
+
├── casaconfig-[VERSION]-py3-none-any.whl
|
65
|
+
└── casaconfig-[VERSION].tar.gz
|
66
|
+
```
|
67
|
+
|
68
|
+
### Setting up CASA branches for casaconfig development
|
69
|
+
|
70
|
+
The casaconfig build process publishes test wheels to test.pypi.org
|
71
|
+
|
72
|
+
In order to test these with Casa packages, two changes are needed in the casa6 repository branch.
|
73
|
+
|
74
|
+
1) Add a line to casa6/build.conf with the appropriate wheel version. For example:
|
75
|
+
|
76
|
+
```
|
77
|
+
casaconfig==1.0.3.dev2
|
78
|
+
```
|
79
|
+
2) Add the following line with the apppropriate branch name to casa6/casatools/setup.py
|
80
|
+
|
81
|
+
```
|
82
|
+
META_DATA["install_requires"] = "casaconfig@git+https://github.com/casangi/casaconfig@CAS-14512"
|
83
|
+
```
|
84
|
+
|
85
|
+
This adds the casaconfig branch as a casatools install time dependency. It will not use the wheel, but rather build the branch in place. This is required in order to avoid adding test.pypi.org as a pip extra-index-url, which might cause other development packages to be installed inadvertently. Note that casaconfig dependency is typically defined in setup.cfg, but the syntax above does not work with setup.cfg.
|
86
|
+
|
87
|
+
|
88
|
+
### Preparing the casa6 branch for merge
|
89
|
+
|
90
|
+
1) Merge the casaconfig branch to main and create a wheel
|
91
|
+
2) Update casa6/build.conf to use that wheel
|
92
|
+
3) Comment out the extra "install_requires" line from setup.py
|
@@ -0,0 +1,34 @@
|
|
1
|
+
casaconfig/__init__.py,sha256=1PgCLSWtmkHm8kZ0O01RUaDdkPodfpl2VKX5h3rjotY,787
|
2
|
+
casaconfig/__main__.py,sha256=rmkK1hRFQSwNoVDJ3AV8Ht_36VY4DAceglevbcBNHcA,7541
|
3
|
+
casaconfig/config.py,sha256=LtDCEvRVo8PS-sNv2QHBF9N19_VoaQEj3LzjkiioWcQ,7711
|
4
|
+
casaconfig/private/CasaconfigErrors.py,sha256=5jgBGiFSussmC7tUAA-w0awYx-7hC6Dhv_OXNihJkkY,1519
|
5
|
+
casaconfig/private/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
casaconfig/private/casasiteconfig_example.py,sha256=J5C9an1iVhxqSbtYT_FiopDXx8SZDcVQkLWKufA_fnc,653
|
7
|
+
casaconfig/private/config_defaults.py,sha256=Qa105jNlH_k28kob_qFW7dTm0KtDMuxwnziPlQxxLFk,2127
|
8
|
+
casaconfig/private/config_defaults_static.py,sha256=MOm3xyqEXZZNisqcZY1b6QmBjJas1ol-ccMePT0v8MI,3459
|
9
|
+
casaconfig/private/data_available.py,sha256=osjljEt4RMwFd62PsYNh8Nsiw0FjLIBWolUuqqPO-3g,3108
|
10
|
+
casaconfig/private/data_update.py,sha256=7qQVrkmtsq9vGYtB-dL2egWx85E0zbt4aUW4wadGFOA,20575
|
11
|
+
casaconfig/private/do_auto_updates.py,sha256=GaPx9_Dt1kAUlcsA-cACV2-OTl19EDIf1pHDkVLPIdY,3551
|
12
|
+
casaconfig/private/do_pull_data.py,sha256=6CKFjX1qOdYFPexXXiLMal70gNoM36rcdZY-OfrfAuA,5705
|
13
|
+
casaconfig/private/do_untar_url.py,sha256=EWpwNGPcm6-G1TIhBjdlhS0j2YrQR3BSS7pWZv5W66w,4359
|
14
|
+
casaconfig/private/get_argparser.py,sha256=-pwPMplwBJssSiEOVte89MqBRuxbZ3jLNVluQrv_eGc,1670
|
15
|
+
casaconfig/private/get_available_files.py,sha256=iV7XBrhrJGD2iOQIancvcJJDWypeHftV_ICuGsCf0MQ,3733
|
16
|
+
casaconfig/private/get_config.py,sha256=R_6lZ3hp9NNbfBBhrOBBieXDFhR6Q3MdGHSgUwICbzk,1590
|
17
|
+
casaconfig/private/get_data_info.py,sha256=hZ6yBcJm--lRBzE2jLwhjKF3497aHtWtGrta7rec7Cc,13543
|
18
|
+
casaconfig/private/get_data_lock.py,sha256=JysF75EHwP2FErjffMkfeV-9wy5wJJ9irPDrMvVzSIo,3809
|
19
|
+
casaconfig/private/have_network.py,sha256=zCIbABTG_9ew9Ac3eb8ggNaZ_H61m_G4LCXkFZe7q5M,1410
|
20
|
+
casaconfig/private/io_redirect.py,sha256=9mwl2siS3fFYCEi_u9Mojg7cBtBgzW00mc8H7V1NSEs,2879
|
21
|
+
casaconfig/private/measures_available.py,sha256=SiGLDhr_nKQaXWVrKhiRPGeUOOL1C5LT5T1VtnIJ3dQ,12331
|
22
|
+
casaconfig/private/measures_update.py,sha256=jNTYsX5U6E-DD769oiImstB2dvJDy4E9GSertZrx4aU,25641
|
23
|
+
casaconfig/private/print_log_messages.py,sha256=zF8qRReNBk2I0biyG5OnlZCbXYIXhNnNF-vA7gYoyr8,2202
|
24
|
+
casaconfig/private/pull_data.py,sha256=7vIv0j1luhSdQ6jFF5USrGU2wQ4829iSqh2NDPO3NuQ,17594
|
25
|
+
casaconfig/private/read_readme.py,sha256=4fF5yy3HynkrFwhF6JUcc0DFQ-DP-WZEddrPpog8znI,4354
|
26
|
+
casaconfig/private/set_casacore_path.py,sha256=C6BON-qx1mjrFizUWHYDPzOXubRNEX-wjUJqOeu-ezw,2254
|
27
|
+
casaconfig/private/summary.py,sha256=xHpS9g3ZNv4ASNc_W05chKbZhHE-caeVnWhV9zsfvrY,3597
|
28
|
+
casaconfig/private/update_all.py,sha256=xCxNTHSPQHoqW1Cs237WNDhgUBrOvTXKpXAFbCbYK6E,5601
|
29
|
+
casaconfig-1.4.0.dist-info/licenses/LICENSE,sha256=OMpzmn2zUn6I4jmVqs1Coa_0NJcoJC9eweZ2gx-u0oI,11358
|
30
|
+
tests/test_casaconfig.py,sha256=Zitmb-bmAGQDYAilQvfODgZQViGpYRPNgtMnstCd-O4,53611
|
31
|
+
casaconfig-1.4.0.dist-info/METADATA,sha256=KSPNYf4Wf2gK2mGds-hF8bVDTAZw14res3GGYg4xDuQ,4037
|
32
|
+
casaconfig-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
33
|
+
casaconfig-1.4.0.dist-info/top_level.txt,sha256=Uay9WTPz644aHfLbmj47WXzue19HtKRueFFCXu1N1Co,17
|
34
|
+
casaconfig-1.4.0.dist-info/RECORD,,
|
tests/test_casaconfig.py
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
import unittest
|
2
|
-
import os, shutil, stat, sys, subprocess, time
|
2
|
+
import os, shutil, stat, sys, subprocess, time, re
|
3
|
+
import copy
|
3
4
|
from datetime import date, timedelta
|
4
5
|
import site
|
5
6
|
sitepackages = site.getsitepackages()[0]
|
6
7
|
|
7
8
|
import casaconfig
|
8
9
|
|
10
|
+
def setDefaultConfig():
|
11
|
+
'''sets config to the default values'''
|
12
|
+
from casaconfig import config
|
13
|
+
for k in config.__defaults:
|
14
|
+
config.__dict__[k] = copy.deepcopy(config._config_defaults.__dict__[k])
|
15
|
+
|
9
16
|
class casaconfig_test(unittest.TestCase):
|
10
17
|
|
11
18
|
def setUp(self):
|
@@ -15,6 +22,8 @@ class casaconfig_test(unittest.TestCase):
|
|
15
22
|
self.test_configpath = os.path.join(os.path.expanduser("~/.casa/"),"config.py")
|
16
23
|
self.test_siteconfigpath = os.path.join(os.getcwd(),'testsiteconfig.py')
|
17
24
|
|
25
|
+
setDefaultConfig()
|
26
|
+
|
18
27
|
# testmeasures is used for measures-only tests
|
19
28
|
# testrundata is used for full data install tests (at least casarundata is installed, which includes measures)
|
20
29
|
# emptymeasures is used to test failure modes
|
@@ -38,7 +47,7 @@ class casaconfig_test(unittest.TestCase):
|
|
38
47
|
|
39
48
|
if os.path.isfile(os.path.expanduser("~/.casa/config.py.user")):
|
40
49
|
os.replace(os.path.expanduser("~/.casa/config.py.user"), os.path.expanduser("~/.casa/config.py"))
|
41
|
-
|
50
|
+
|
42
51
|
def rmTestDirs(self):
|
43
52
|
if os.path.exists(self.testMeasPath):
|
44
53
|
shutil.rmtree(self.testMeasPath)
|
@@ -85,12 +94,12 @@ class casaconfig_test(unittest.TestCase):
|
|
85
94
|
self.assertTrue(dataInfo['version']==measVers,"unexpected version installed by populate_testmeasures at %s : %s != %s" % (self.testMeasPath, dataInfo['version'], measVers))
|
86
95
|
|
87
96
|
def populate_testrundata(self):
|
88
|
-
# ensures that there's some casaconfig populated casarundata at self.
|
97
|
+
# ensures that there's some casaconfig populated casarundata at self.testRundataPath
|
89
98
|
# if there's a known version there it leave it as is
|
90
99
|
# if the data info is None then it populates it with the most recent casarundata
|
91
100
|
# the data info version can not be illegal or unknown (something unexpected is already there)
|
92
101
|
# this function works as a test, but it happens on demand in an attempt to limit the calls to pull_data
|
93
|
-
|
102
|
+
|
94
103
|
dataInfo = casaconfig.get_data_info(self.testRundataPath, type='casarundata')
|
95
104
|
if dataInfo is not None:
|
96
105
|
version = dataInfo['version']
|
@@ -230,7 +239,7 @@ class casaconfig_test(unittest.TestCase):
|
|
230
239
|
# final check that the expected version is now installed
|
231
240
|
installedVers = casaconfig.get_data_info(path=self.testRundataPath,type='measures')['version']
|
232
241
|
self.assertTrue(installedVers == vers, "expected version was not installed : %s != %s" % (installedVers, vers))
|
233
|
-
|
242
|
+
|
234
243
|
@unittest.skipIf(not os.path.exists(os.path.join(sitepackages,'casatools')), "casatools not found")
|
235
244
|
def test_auto_update_measures(self):
|
236
245
|
'''Test Automatic Measures Updates to measurespath'''
|
@@ -258,6 +267,7 @@ class casaconfig_test(unittest.TestCase):
|
|
258
267
|
f.write('measurespath = "{}"\n'.format(self.testRundataPath))
|
259
268
|
f.write('measures_auto_update = True\n')
|
260
269
|
f.write('data_auto_update = False\n')
|
270
|
+
f.write('casaconfig_verbose = 2\n')
|
261
271
|
f.close()
|
262
272
|
|
263
273
|
# start a new casatools, which should update the measures to the most recent version
|
@@ -270,7 +280,7 @@ class casaconfig_test(unittest.TestCase):
|
|
270
280
|
# output should contain the latest version string
|
271
281
|
ref = self.get_meas_avail()[-1] in str(output)
|
272
282
|
self.assertTrue(ref, "Update Failed")
|
273
|
-
|
283
|
+
|
274
284
|
@unittest.skipIf(not os.path.exists(os.path.join(sitepackages,'casatools')), "casatools not found")
|
275
285
|
def test_auto_install_data(self):
|
276
286
|
'''Test auto install of all data to measurespath on casatools startup'''
|
@@ -625,6 +635,14 @@ class casaconfig_test(unittest.TestCase):
|
|
625
635
|
# This should work on any non-open path that isn't a measurespath. I think the cwd will
|
626
636
|
# work just fine for that purposes.
|
627
637
|
|
638
|
+
# it needs something there to trigger the NoReadme
|
639
|
+
junkFileCreated = False
|
640
|
+
junkFilePath = os.path.join(os.getcwd(),"_junk_")
|
641
|
+
if not os.path.exists(junkFilePath):
|
642
|
+
with open(junkFilePath,'x') as f:
|
643
|
+
pass
|
644
|
+
junkFileCreated = True
|
645
|
+
|
628
646
|
# data_update NoReadme
|
629
647
|
try:
|
630
648
|
exceptionSeen = False
|
@@ -648,6 +666,10 @@ class casaconfig_test(unittest.TestCase):
|
|
648
666
|
print("unexpected exception seen when testing for NoReadme in measures_update")
|
649
667
|
print(str(exc))
|
650
668
|
self.assertTrue(exceptionSeen, "NoReadme not seen from measures_update")
|
669
|
+
|
670
|
+
# clean up, remove junk
|
671
|
+
if junkFileCreated:
|
672
|
+
os.remove(junkFilePath)
|
651
673
|
|
652
674
|
# NotWritable : path is not writable by the user
|
653
675
|
# use the emptyPath
|
@@ -743,15 +765,13 @@ class casaconfig_test(unittest.TestCase):
|
|
743
765
|
ref = True if "UnsetMeasurespath" in str(output) else False
|
744
766
|
self.assertTrue(ref, "UnsetMeasurespath not seen in output for do_auto_updates and measurespath=None")
|
745
767
|
|
746
|
-
|
747
768
|
def test_exceptions_with_data(self):
|
748
769
|
'''test that exceptions that require data happen when expected'''
|
749
770
|
|
750
771
|
# these tests requires an already installed set of data
|
751
772
|
self.populate_testrundata()
|
752
|
-
|
773
|
+
|
753
774
|
# BadLock
|
754
|
-
print("\nTesting for BadLock in test_exceptions_with_data")
|
755
775
|
# insert a non-empty lock file
|
756
776
|
exceptionSeen = False
|
757
777
|
lockPath = os.path.join(self.testRundataPath,'data_update.lock')
|
@@ -785,8 +805,6 @@ class casaconfig_test(unittest.TestCase):
|
|
785
805
|
self.assertTrue(exceptionSeen, "BadLock not seen as expected in data_update with existing data test")
|
786
806
|
# remove the lock file
|
787
807
|
os.remove(lockPath)
|
788
|
-
print("BadLock test passed in test_exceptions_with_data\n")
|
789
|
-
|
790
808
|
|
791
809
|
# BadReadme
|
792
810
|
|
@@ -850,7 +868,6 @@ class casaconfig_test(unittest.TestCase):
|
|
850
868
|
# this check happens before the age is determined, so no need to backdate the readme.txt file here
|
851
869
|
casaconfig.measures_update(self.testRundataPath)
|
852
870
|
except casaconfig.BadReadme as exc:
|
853
|
-
print(str(exc))
|
854
871
|
exceptionSeen = True
|
855
872
|
except Exception as exc:
|
856
873
|
print("unexpected exception seen when testing for BadRadme in measures_update")
|
@@ -864,12 +881,10 @@ class casaconfig_test(unittest.TestCase):
|
|
864
881
|
|
865
882
|
# get the current permissions of the testRundataPath
|
866
883
|
orig_pstat = stat.S_IMODE(os.stat(self.testRundataPath).st_mode)
|
867
|
-
print('orig_pstat = %s' % orig_pstat)
|
868
884
|
# a bitmask that's the opposite of all of the write permission bits
|
869
885
|
no_write = ~stat.S_IWUSR & ~stat.S_IWGRP & ~stat.S_IWOTH
|
870
886
|
# remove the write permissions
|
871
887
|
pstat = orig_pstat & no_write
|
872
|
-
print('pstat = %s' % pstat)
|
873
888
|
os.chmod(self.testRundataPath,pstat)
|
874
889
|
|
875
890
|
|
@@ -883,16 +898,174 @@ class casaconfig_test(unittest.TestCase):
|
|
883
898
|
except Exception as exc:
|
884
899
|
print("unexpected exception seen when testing for NotWritable in measures_update")
|
885
900
|
print(str(exc))
|
886
|
-
import traceback
|
887
|
-
traceback.print_exc()
|
888
901
|
|
889
902
|
# reset to original permissions before anything else is checked
|
890
903
|
os.chmod(self.testRundataPath,orig_pstat)
|
891
904
|
|
892
905
|
self.assertTrue(exceptionSeen, "NotWritable not seen from measures_update")
|
893
906
|
|
907
|
+
def siteAge(self, ma_site):
|
908
|
+
# given a list returned by measures_available return the age of the last file in the list
|
909
|
+
dateMatch = re.search(r".*_Measures_(\d{4})(\d{2})(\d{2})-.*", ma_site[-1])
|
910
|
+
fileDate = date(int(dateMatch.group(1)), int(dateMatch.group(2)), int(dateMatch.group(3)))
|
911
|
+
dateDiff = date.today() - fileDate
|
912
|
+
return dateDiff.days
|
913
|
+
|
914
|
+
def test_measures_site(self):
|
915
|
+
'''tests related to measures site'''
|
916
|
+
|
917
|
+
from casaconfig import config
|
918
|
+
|
919
|
+
# measures_available should work for the default list and each element individually
|
920
|
+
ma = casaconfig.measures_available()
|
921
|
+
self.assertTrue(ma[0] in config.measures_site, "measures_available first element is not an element of config.measures_site")
|
922
|
+
|
923
|
+
# this test code assumes there are 2 sites, if that ever is not the case someone will need
|
924
|
+
# to make this more general
|
925
|
+
site_0 = config.measures_site[0]
|
926
|
+
site_1 = config.measures_site[1]
|
927
|
+
|
928
|
+
site_0_ma = casaconfig.measures_available(measures_site=site_0)
|
929
|
+
self.assertTrue(site_0_ma[0]==site_0)
|
930
|
+
site_age_0 = self.siteAge(site_0_ma)
|
931
|
+
|
932
|
+
site_1_ma = casaconfig.measures_available(measures_site=site_1)
|
933
|
+
self.assertTrue(site_1_ma[0]==site_1)
|
934
|
+
site_age_1 = self.siteAge(site_1_ma)
|
935
|
+
|
936
|
+
# reversing the list should get the currently second site, unless that site is too old
|
937
|
+
if site_age_1 <= config.measures_site_interval:
|
938
|
+
# site is not too old
|
939
|
+
config.measures_site.reverse()
|
940
|
+
ma = casaconfig.measures_available()
|
941
|
+
self.assertTrue(ma[0]==site_1, "reversing measures_site did not return the second site list as expected")
|
942
|
+
config.measures_site.reverse()
|
943
|
+
else:
|
944
|
+
print("test_measures_site, skipping test of reversing measures_site as %s appears to be out of date" % site_1)
|
945
|
+
|
946
|
+
# everything is out of date, finds the youngest or first site if they are both the same age
|
947
|
+
youngestSite = site_0 if site_age_0 <= site_age_1 else site_1
|
948
|
+
config.measures_site_interval = -1
|
949
|
+
ma = casaconfig.measures_available()
|
950
|
+
self.assertTrue(ma[0]==youngestSite,"list from youngest site not return with measures_site_interval = -1")
|
951
|
+
|
952
|
+
# reverse the list, if they are the same age the first one (now site_1) will be used
|
953
|
+
# otherwise it will still return whatever the youngestSite was above
|
954
|
+
config.measures_site.reverse()
|
955
|
+
if site_age_0 == site_age_1:
|
956
|
+
ma = casaconfig.measures_available()
|
957
|
+
self.assertTrue(ma[0]==site_1, "reversing measures_site with measures_site_interval = -1 did not return list from second site, sites have same age")
|
958
|
+
else:
|
959
|
+
ma = casaconfig.measures_available()
|
960
|
+
self.assertTrue(ma[0]==youngestSite, "reversing measures_site with measures_site_interval = -1 did not return list from youngest site, sites have same age")
|
961
|
+
|
962
|
+
# return to default values
|
963
|
+
config.measures_site = copy.deepcopy(config._config_defaults.measures_site)
|
964
|
+
config.measures_site_interval = config._config_defaults.measures_site_interval
|
965
|
+
|
966
|
+
# the rest of the tests use the test_measures area
|
967
|
+
self.populate_testmeasures()
|
968
|
+
|
969
|
+
# install an older version from each site
|
970
|
+
# check that without specifying the site it finds the site
|
971
|
+
# check that with specifying the correct site it finds the site
|
972
|
+
# check that when given the wrong site it doesn't find it
|
973
|
+
|
974
|
+
site_0_version = site_0_ma[-3]
|
975
|
+
site_1_version = site_1_ma[-4]
|
976
|
+
|
977
|
+
di = casaconfig.get_data_info(path=self.testMeasPath, type='measures')
|
978
|
+
print('di : %s' % str(di))
|
894
979
|
|
895
|
-
|
980
|
+
for site, vers, altSite in [(site_0, site_0_version, site_1), (site_1, site_1_version, site_0)]:
|
981
|
+
# let it find the site
|
982
|
+
casaconfig.measures_update(path=self.testMeasPath, version=vers, force=True)
|
983
|
+
di = casaconfig.get_data_info(path=self.testMeasPath, type='measures')
|
984
|
+
self.assertTrue(di['site']==site and di['version']==vers)
|
985
|
+
|
986
|
+
# give it the site
|
987
|
+
casaconfig.measures_update(path=self.testMeasPath,version=vers,measures_site=site, force=True)
|
988
|
+
di = casaconfig.get_data_info(path=self.testMeasPath, type='measures')
|
989
|
+
self.assertTrue(di['site']==site and di['version']==vers)
|
990
|
+
|
991
|
+
# this fails without throwing an exception, first, force an update to the most recent version at this site
|
992
|
+
casaconfig.measures_update(path=self.testMeasPath, measures_site=site, force=True)
|
993
|
+
di = casaconfig.get_data_info(path=self.testMeasPath, type='measures')
|
994
|
+
# it should not be the vers being checked here
|
995
|
+
self.assertTrue(di['version'] != vers, "unexpected version installed, this should not happen here")
|
996
|
+
installedVersion = di['version']
|
997
|
+
# trying to install this version from the wrong site will not change that version
|
998
|
+
casaconfig.measures_update(path=self.testMeasPath, version=vers, measures_site=altSite, force=True)
|
999
|
+
di = casaconfig.get_data_info(path=self.testMeasPath, type='measures')
|
1000
|
+
self.assertTrue(di['version'] != vers and di['version']==installedVersion, "measures_update unexpectedly installed a version that should not exist at the requested site")
|
1001
|
+
|
1002
|
+
# use a site that exists but has no valid measures files - casarundata
|
1003
|
+
# each of those should raise a RemoteError exception
|
1004
|
+
exceptionCaught = False
|
1005
|
+
casarundataURL = 'https://go.nrao.edu/casarundata'
|
1006
|
+
try:
|
1007
|
+
ma = casaconfig.measures_available(measures_site=[casarundataURL])
|
1008
|
+
except casaconfig.RemoteError as exc:
|
1009
|
+
exceptionCaught = True
|
1010
|
+
self.assertTrue(exceptionCaught, "measures_available on an exisitng site in list with no measures tar files did not raised the expected exception")
|
1011
|
+
|
1012
|
+
exceptionCaught = False
|
1013
|
+
try:
|
1014
|
+
ma = casaconfig.measures_available(measures_site=casarundataURL)
|
1015
|
+
except casaconfig.RemoteError as exc:
|
1016
|
+
exceptionCaught = True
|
1017
|
+
self.assertTrue(exceptionCaught, "measures_available on an exisitng site with no measures tar files did not raised the expected exception")
|
1018
|
+
|
1019
|
+
exceptionCaught = False
|
1020
|
+
try:
|
1021
|
+
ma = casaconfig.measures_update(path=self.testMeasPath, measures_site=casarundataURL, force=True)
|
1022
|
+
except casaconfig.RemoteError as exc:
|
1023
|
+
exceptionCaught = True
|
1024
|
+
self.assertTrue(exceptionCaught, "measures_update on an exisitng site with no[ measures tar files did not raised the expected exception")
|
1025
|
+
|
1026
|
+
# add this in at the head of a measures_site list that contains valid sites should silenently move on to a valid site
|
1027
|
+
siteList = [casarundataURL] + config.measures_site
|
1028
|
+
exceptionCaught = False
|
1029
|
+
try:
|
1030
|
+
ma = casaconfig.measures_available(measures_site=siteList)
|
1031
|
+
except casaconfig.RemoteError as exc:
|
1032
|
+
exceptionCaught = True
|
1033
|
+
self.assertFalse(exceptionCaught, "measures_available on a list with one empty site at head and non-empty sites unexpectedly raised an exception")
|
1034
|
+
|
1035
|
+
def test_update_interval(self):
|
1036
|
+
'''tests use of config update_interval values'''
|
1037
|
+
|
1038
|
+
from casaconfig import config
|
1039
|
+
self.populate_testrundata()
|
1040
|
+
|
1041
|
+
# data
|
1042
|
+
# populate with an older data
|
1043
|
+
da = casaconfig.data_available()
|
1044
|
+
casaconfig.data_update(self.testRundataPath,version=da[-2],force=True)
|
1045
|
+
# default data_update_interval will not allow an update at this point
|
1046
|
+
casaconfig.data_update(self.testRundataPath)
|
1047
|
+
di = casaconfig.get_data_info(self.testRundataPath, type='casarundata')
|
1048
|
+
self.assertTrue(di['version'] == da[-2],'data_update unexpectedly updated when data_update_interval should not have allowed it to update')
|
1049
|
+
# this means data_update always checks and updates if necessary
|
1050
|
+
config.data_update_interval = -1
|
1051
|
+
casaconfig.data_update(self.testRundataPath)
|
1052
|
+
di = casaconfig.get_data_info(self.testRundataPath, type='casarundata')
|
1053
|
+
self.assertFalse(di['version'] == da[-2],'data_update did not update casarundata version as expected with negative data_update_interval')
|
1054
|
+
|
1055
|
+
# measures
|
1056
|
+
# populate with an older data
|
1057
|
+
ma = casaconfig.measures_available()
|
1058
|
+
casaconfig.measures_update(self.testRundataPath,version=ma[-2],force=True)
|
1059
|
+
# default measures_update_interval will not allow an update at this point
|
1060
|
+
casaconfig.measures_update(self.testRundataPath)
|
1061
|
+
di = casaconfig.get_data_info(self.testRundataPath,type='measures')
|
1062
|
+
self.assertTrue(di['version'] == ma[-2],'measures_update unexpectedly updated when measures_update_interval should not have allowed it to update')
|
1063
|
+
# this means measures_update always checks and updates if necessary
|
1064
|
+
config.measures_update_interval = -1
|
1065
|
+
casaconfig.measures_update(self.testRundataPath)
|
1066
|
+
di = casaconfig.get_data_info(self.testRundataPath,type='measures')
|
1067
|
+
self.assertFalse(di['version'] == ma[-2],'measures_update did not update measures version as expected with negative measures_update_interval')
|
1068
|
+
|
896
1069
|
if __name__ == '__main__':
|
897
1070
|
|
898
1071
|
unittest.main()
|