esgf-qa 0.3.0__py3-none-any.whl → 0.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.
- esgf_qa/_constants.py +42 -1
- esgf_qa/_version.py +2 -2
- esgf_qa/cluster_results.py +466 -0
- esgf_qa/con_checks.py +209 -11
- esgf_qa/run_qa.py +247 -418
- {esgf_qa-0.3.0.dist-info → esgf_qa-0.4.0.dist-info}/METADATA +42 -28
- esgf_qa-0.4.0.dist-info/RECORD +19 -0
- {esgf_qa-0.3.0.dist-info → esgf_qa-0.4.0.dist-info}/top_level.txt +1 -1
- tests/test_cli.py +267 -0
- tests/test_cluster_results.py +166 -0
- tests/test_con_checks.py +263 -0
- tests/test_qaviewer.py +147 -0
- tests/test_run_dummy_qa.py +191 -0
- tests/test_run_qa.py +181 -0
- docs/esgf-qa_Logo.png +0 -0
- esgf_qa-0.3.0.dist-info/RECORD +0 -13
- {esgf_qa-0.3.0.dist-info → esgf_qa-0.4.0.dist-info}/WHEEL +0 -0
- {esgf_qa-0.3.0.dist-info → esgf_qa-0.4.0.dist-info}/entry_points.txt +0 -0
- {esgf_qa-0.3.0.dist-info → esgf_qa-0.4.0.dist-info}/licenses/LICENSE +0 -0
tests/test_run_qa.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
|
|
6
|
+
from esgf_qa._constants import (
|
|
7
|
+
checker_dict,
|
|
8
|
+
checker_dict_ext,
|
|
9
|
+
checker_release_versions,
|
|
10
|
+
)
|
|
11
|
+
from esgf_qa.run_qa import (
|
|
12
|
+
_verify_options_dict,
|
|
13
|
+
get_checker_release_versions,
|
|
14
|
+
get_default_result_dir,
|
|
15
|
+
get_dsid,
|
|
16
|
+
parse_options,
|
|
17
|
+
track_checked_datasets,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Test get_default_result_dir
|
|
22
|
+
def test_get_default_result_dir(tmpdir):
|
|
23
|
+
"""
|
|
24
|
+
Test the get_default_result_dir function.
|
|
25
|
+
"""
|
|
26
|
+
os.chdir(tmpdir)
|
|
27
|
+
cwd = re.escape(os.getcwd())
|
|
28
|
+
result_dir = get_default_result_dir()
|
|
29
|
+
result_dir2 = get_default_result_dir()
|
|
30
|
+
# Assert that the result directories are the same
|
|
31
|
+
# (they depend on when the library was imported /
|
|
32
|
+
# the program was executed)
|
|
33
|
+
assert result_dir == result_dir2
|
|
34
|
+
# Example: /path/to/cwd/esgf-qa-results_20251103-1209_bf5ae0fafabf6cc03e71180efe3e468c
|
|
35
|
+
assert re.match(
|
|
36
|
+
rf"^{cwd}/esgf-qa-results_\d{{8}}-\d{{4}}_[a-f0-9]{{32}}$", result_dir
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_get_dsid():
|
|
41
|
+
"""
|
|
42
|
+
Test the get_dsid function.
|
|
43
|
+
"""
|
|
44
|
+
project_id = "my_project"
|
|
45
|
+
files_to_check_dict = {
|
|
46
|
+
f"/path/to/{project_id}/drs/elements/until/file1_1950-1960.nc": {
|
|
47
|
+
"id_dir": f"/path/to/{project_id}/drs/elements/until",
|
|
48
|
+
"id_fn": "file1",
|
|
49
|
+
},
|
|
50
|
+
f"/path/to/{project_id}/drs2/elements2/until2/file2_1955-1960.nc": {
|
|
51
|
+
"id_dir": f"/path/to/{project_id}/drs2/elements2/until2",
|
|
52
|
+
"id_fn": "file2",
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
dataset_files_map_ext = {
|
|
56
|
+
f"/path/to/{project_id}/drs/elements/until": {
|
|
57
|
+
"file1": ["file1_1950-1960.nc"],
|
|
58
|
+
},
|
|
59
|
+
f"/path/to/{project_id}/drs2/elements2/until2": {
|
|
60
|
+
"file2": ["file2_1955-1960.nc"],
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
file_path = f"/path/to/{project_id}/drs/elements/until/file1_1950-1960.nc"
|
|
64
|
+
dsid = get_dsid(files_to_check_dict, dataset_files_map_ext, file_path, project_id)
|
|
65
|
+
assert dsid == "my_project.drs.elements.until"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_get_checker_release_versions():
|
|
69
|
+
"""
|
|
70
|
+
Test function get_checker_release_versions.
|
|
71
|
+
|
|
72
|
+
Verifies that known checkers update the global checker_release_versions
|
|
73
|
+
dictionary with the correct version values.
|
|
74
|
+
"""
|
|
75
|
+
# reset globals
|
|
76
|
+
checker_release_versions.clear()
|
|
77
|
+
checker_dict.clear()
|
|
78
|
+
checker_dict_ext.clear()
|
|
79
|
+
|
|
80
|
+
# prepare minimal fake environment
|
|
81
|
+
checker_dict.update({"cf": "", "cc6": "", "wcrp_cmip6": ""})
|
|
82
|
+
checker_dict_ext.update({**checker_dict, "cons": ""})
|
|
83
|
+
|
|
84
|
+
# instantiate a real CheckSuite with empty options
|
|
85
|
+
checkers = ["cf:1.6", "cc6:latest", "wcrp_cmip6:latest"]
|
|
86
|
+
get_checker_release_versions(checkers)
|
|
87
|
+
|
|
88
|
+
# check that the dictionary is filled correctly
|
|
89
|
+
assert "cf" in checker_release_versions
|
|
90
|
+
assert "cc6" in checker_release_versions
|
|
91
|
+
assert "wcrp_cmip6" in checker_release_versions
|
|
92
|
+
|
|
93
|
+
# ensure non-empty version strings (format check)
|
|
94
|
+
for version in checker_release_versions.values():
|
|
95
|
+
assert isinstance(version, str)
|
|
96
|
+
assert len(version) > 0
|
|
97
|
+
assert checker_release_versions["cf"] == "1.6"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_track_checked_datasets(tmpdir):
|
|
101
|
+
"""
|
|
102
|
+
Test the track_checked_datasets function.
|
|
103
|
+
"""
|
|
104
|
+
# Create a temporary file
|
|
105
|
+
checked_datasets_file = tmpdir.join("checked_datasets.csv")
|
|
106
|
+
# Call the track_checked_datasets function
|
|
107
|
+
checked_datasets = ["dataset1", "dataset2"]
|
|
108
|
+
track_checked_datasets(str(checked_datasets_file), checked_datasets)
|
|
109
|
+
# Check that the file was created and contains the expected data
|
|
110
|
+
with open(checked_datasets_file) as file:
|
|
111
|
+
reader = csv.reader(file)
|
|
112
|
+
rows = list(reader)
|
|
113
|
+
assert len(rows) == 2
|
|
114
|
+
assert rows[0] == ["dataset1"]
|
|
115
|
+
assert rows[1] == ["dataset2"]
|
|
116
|
+
|
|
117
|
+
# Call the track_checked_datasets function again
|
|
118
|
+
checked_datasets = ["dataset3"]
|
|
119
|
+
track_checked_datasets(str(checked_datasets_file), checked_datasets)
|
|
120
|
+
# Check that the file was updated and contains the expected data
|
|
121
|
+
with open(checked_datasets_file) as file:
|
|
122
|
+
reader = csv.reader(file)
|
|
123
|
+
rows = list(reader)
|
|
124
|
+
assert len(rows) == 3
|
|
125
|
+
assert rows[0] == ["dataset1"]
|
|
126
|
+
assert rows[1] == ["dataset2"]
|
|
127
|
+
assert rows[2] == ["dataset3"]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def test_verify_options_dict():
|
|
131
|
+
"""
|
|
132
|
+
Test the _verify_options_dict function.
|
|
133
|
+
"""
|
|
134
|
+
# Test case 1: empty options dictionary
|
|
135
|
+
options = {}
|
|
136
|
+
assert _verify_options_dict(options) is True
|
|
137
|
+
|
|
138
|
+
# Test case 2: options dictionary with one key-value pair
|
|
139
|
+
options = {"checker_type": {"opt1": "value"}}
|
|
140
|
+
assert _verify_options_dict(options) is True
|
|
141
|
+
|
|
142
|
+
# Test case 3: options dictionary with nested structure
|
|
143
|
+
options = {
|
|
144
|
+
"checker_type1": {"opt1": "value1", "opt2": 123},
|
|
145
|
+
"checker_type2": {"opt1": "value2", "opt3": False},
|
|
146
|
+
}
|
|
147
|
+
assert _verify_options_dict(options) is True
|
|
148
|
+
|
|
149
|
+
# Test case 4: options dictionary with invalid value type
|
|
150
|
+
options = {"checker_type": {"opt1": "value", "opt2": 123, "opt3": {}}}
|
|
151
|
+
assert _verify_options_dict(options) is False
|
|
152
|
+
|
|
153
|
+
# Test case 5: options dictionary with non-dict value
|
|
154
|
+
options = {"checker_type": "opt1"}
|
|
155
|
+
assert _verify_options_dict(options) is False
|
|
156
|
+
options = {"checker_type": ["opt1", "opt2"]}
|
|
157
|
+
assert _verify_options_dict(options) is False
|
|
158
|
+
|
|
159
|
+
# Test case 6: options dictionary with empty dict as value
|
|
160
|
+
options = {"checker_type": {"opt1": {}}}
|
|
161
|
+
assert _verify_options_dict(options) is False
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def test_parse_options():
|
|
165
|
+
"""Test the option parser"""
|
|
166
|
+
# Simple test checker_type:checker_opt
|
|
167
|
+
opt_dict = parse_options(["cf:enable_appendix_a_checks"])
|
|
168
|
+
assert opt_dict == defaultdict(dict, {"cf": {"enable_appendix_a_checks": True}})
|
|
169
|
+
assert _verify_options_dict(opt_dict) is True
|
|
170
|
+
# Test case checker_type:checker_opt:checker_val
|
|
171
|
+
opt_dict = parse_options(
|
|
172
|
+
["type:opt:val", "type:opt2:val:2", "cf:enable_appendix_a_checks"],
|
|
173
|
+
)
|
|
174
|
+
assert opt_dict == defaultdict(
|
|
175
|
+
dict,
|
|
176
|
+
{
|
|
177
|
+
"type": {"opt": "val", "opt2": "val:2"},
|
|
178
|
+
"cf": {"enable_appendix_a_checks": True},
|
|
179
|
+
},
|
|
180
|
+
)
|
|
181
|
+
assert _verify_options_dict(opt_dict) is True
|
docs/esgf-qa_Logo.png
DELETED
|
Binary file
|
esgf_qa-0.3.0.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
docs/esgf-qa_Logo.png,sha256=xDzwInzL1RgneFyi0iF2CswTKFRNvScE0nFwCJODO88,108608
|
|
2
|
-
esgf_qa/__init__.py,sha256=iLmy2rOkHS_4KZWMD8BgT7R3tLMKeaTCDVf3B4FyYxM,91
|
|
3
|
-
esgf_qa/_constants.py,sha256=dhblrqa0DZHmIZ74SnYkzzURHX0jDtXWQv36epHy1Zo,1641
|
|
4
|
-
esgf_qa/_version.py,sha256=5zTqm8rgXsWYBpB2M3Zw_K1D-aV8wP7NsBLrmMKkrAQ,704
|
|
5
|
-
esgf_qa/con_checks.py,sha256=tGt2jGxY54yKIR4gQwWKUsN6q4iwPO-P_J0FWjuS75k,24067
|
|
6
|
-
esgf_qa/qaviewer.py,sha256=myt9lq47E40sD7KrMjVcAvy8sqocVinBSUYf4nOPD80,8843
|
|
7
|
-
esgf_qa/run_qa.py,sha256=V5lm5351EEv3wos4IJAKYJQXiR05x3VDv5u7rom9Hq4,51466
|
|
8
|
-
esgf_qa-0.3.0.dist-info/licenses/LICENSE,sha256=S1WmzAIRoXFV26FENC3SW_XsmvkGtCs-4_gm7PrPYWg,12636
|
|
9
|
-
esgf_qa-0.3.0.dist-info/METADATA,sha256=pCsIpgAEK7P7gQv2sY_9RkYa1kcopj5lCb9gd79WqCQ,10014
|
|
10
|
-
esgf_qa-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
-
esgf_qa-0.3.0.dist-info/entry_points.txt,sha256=ZGMG_3eS7nyUJE6ZJ9v23Thcf-r29ZSZ7e8voBVwbf4,82
|
|
12
|
-
esgf_qa-0.3.0.dist-info/top_level.txt,sha256=trrotu-Mkkpq5ry2FRdEZ1k2qb9EtvP0eSrsBPBf3KI,13
|
|
13
|
-
esgf_qa-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|