CMIP7-data-request-api 1.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CMIP7_data_request_api-1.1.2.dist-info/LICENSE +21 -0
- CMIP7_data_request_api-1.1.2.dist-info/METADATA +210 -0
- CMIP7_data_request_api-1.1.2.dist-info/RECORD +36 -0
- CMIP7_data_request_api-1.1.2.dist-info/WHEEL +5 -0
- CMIP7_data_request_api-1.1.2.dist-info/entry_points.txt +2 -0
- CMIP7_data_request_api-1.1.2.dist-info/top_level.txt +1 -0
- data_request_api/__init__.py +1 -0
- data_request_api/command_line/__init__.py +0 -0
- data_request_api/command_line/export_dreq_lists_json.py +136 -0
- data_request_api/dev/JA/__init__.py +0 -0
- data_request_api/dev/JA/check_plev_requests.py +416 -0
- data_request_api/dev/JA/read_feedback_spreadsheet.py +141 -0
- data_request_api/dev/JA/workflow_example_GRtest.py +275 -0
- data_request_api/dev/JA/workflow_example_test.py +222 -0
- data_request_api/dev/MM/checksum.py +68 -0
- data_request_api/dev/MM/walking_data_request.ipynb +380 -0
- data_request_api/dev/MS/dreq_content_and_walking_data_request.ipynb +3755 -0
- data_request_api/dev/__init__.py +0 -0
- data_request_api/stable/__init__.py +0 -0
- data_request_api/stable/content/README.MD +106 -0
- data_request_api/stable/content/__init__.py +0 -0
- data_request_api/stable/content/dreq_api/__init__.py +0 -0
- data_request_api/stable/content/dreq_api/consolidate_export.py +488 -0
- data_request_api/stable/content/dreq_api/dreq_content.py +593 -0
- data_request_api/stable/content/dreq_api/mapping_table.py +335 -0
- data_request_api/stable/content/dreq_api/test_dreq_content.py +194 -0
- data_request_api/stable/content/dump_transformation.py +550 -0
- data_request_api/stable/query/__init__.py +0 -0
- data_request_api/stable/query/data_request.py +1120 -0
- data_request_api/stable/query/dreq_classes.py +372 -0
- data_request_api/stable/query/dreq_query.py +981 -0
- data_request_api/stable/query/vocabulary_server.py +208 -0
- data_request_api/stable/utilities/__init__.py +0 -0
- data_request_api/stable/utilities/logger.py +71 -0
- data_request_api/stable/utilities/tools.py +49 -0
- data_request_api/version.py +16 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Mapping Table
|
|
3
|
+
|
|
4
|
+
The mapping_table dictionary defines how to map the three-base structure to the one-base structure.
|
|
5
|
+
Each entry in the dictionary represents a table in the one-base structure and includes the information
|
|
6
|
+
how to obtain it from the three-base structure.
|
|
7
|
+
|
|
8
|
+
Explanation of the dictionary keys:
|
|
9
|
+
|
|
10
|
+
Base ("source_base"):
|
|
11
|
+
The base containing the table to be selected.
|
|
12
|
+
|
|
13
|
+
Table ("source_table"):
|
|
14
|
+
The table to be selected from the "source_base".
|
|
15
|
+
|
|
16
|
+
Internal Mapping of record attributes ("internal_mapping"):
|
|
17
|
+
Record attributes may point to records of other tables.
|
|
18
|
+
However, there is no cross-linkage between the three bases,
|
|
19
|
+
so these links need to be mapped as well.
|
|
20
|
+
"internal_mapping" is a dictionary with the key corresponding
|
|
21
|
+
to the record attributes to be mapped and the values containing
|
|
22
|
+
the actual mapping information.
|
|
23
|
+
|
|
24
|
+
The mapping information is again a dictionary with the following keys:
|
|
25
|
+
- base_copy_of_table:
|
|
26
|
+
If a copy of table corresponding to the record attribute exists in the current base,
|
|
27
|
+
provide the name; otherwise, set to False.
|
|
28
|
+
- base:
|
|
29
|
+
The base containing the original table the record attribute points to.
|
|
30
|
+
- table:
|
|
31
|
+
The original table the record attribute points to.
|
|
32
|
+
- operation:
|
|
33
|
+
The operation to perform on the attribute value (either "split" or "", if it is
|
|
34
|
+
already provided as list or a string without comma separated values).
|
|
35
|
+
- map_by_key:
|
|
36
|
+
A list of keys to map by.
|
|
37
|
+
- entry_type:
|
|
38
|
+
The type of entry (either "record_id" or "name").
|
|
39
|
+
|
|
40
|
+
(Internal) Filters of record attributes ("internal_filters"):
|
|
41
|
+
Not all records of the raw export shall be included since they may be
|
|
42
|
+
labeled as junk or not be approved by the community. The filters are applied on all records
|
|
43
|
+
and also internally on links to other records. "internal_filters" is a dictionary
|
|
44
|
+
with the key corresponding to the record attributes used for filtering and the value
|
|
45
|
+
another dictionary with the following possible keys:
|
|
46
|
+
- operator: Can be one of "nonempty", "in", "not in"
|
|
47
|
+
- values: A list of values, not necessary for "nonempty" operator.
|
|
48
|
+
|
|
49
|
+
Example Configuration
|
|
50
|
+
|
|
51
|
+
Suppose we want to map the "CMIP7 Variable Groups" key in the "Variables" table of the "Data Request Variables (Public)"
|
|
52
|
+
base to a list of record IDs of "Variable Group" records in the "Data Request Opportunities (Public)" base.
|
|
53
|
+
|
|
54
|
+
We would define the mapping_table as follows:
|
|
55
|
+
mapping_table = {
|
|
56
|
+
"Variables": {
|
|
57
|
+
"base": "Data Request Variables (Public)",
|
|
58
|
+
"source_table": "Variables",
|
|
59
|
+
"internal_mapping": {
|
|
60
|
+
"CMIP7 Variable Groups": {
|
|
61
|
+
"base_copy_of_table": False,
|
|
62
|
+
"base": "Data Request Opportunities (Public)",
|
|
63
|
+
"table": "Variable Group",
|
|
64
|
+
"operation": "split",
|
|
65
|
+
"map_by_key": ["Name"],
|
|
66
|
+
"entry_type": "name",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
"internal_filters": {
|
|
70
|
+
"Status": {"operator": "not in", "values": ["Junk"]},
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
mapping_table = {
|
|
77
|
+
"CF Standard Names": {
|
|
78
|
+
"source_base": "Data Request Physical Parameters (Public)",
|
|
79
|
+
"source_table": "CF Standard Name",
|
|
80
|
+
"internal_mapping": {},
|
|
81
|
+
"internal_filters": {},
|
|
82
|
+
"rm_keys": ["Physical Parameters", "Physical Parameters 2"],
|
|
83
|
+
},
|
|
84
|
+
"Cell Measures": {
|
|
85
|
+
"source_base": "Data Request Variables (Public)",
|
|
86
|
+
"source_table": "Cell Measures",
|
|
87
|
+
"internal_mapping": {},
|
|
88
|
+
"internal_filters": {},
|
|
89
|
+
"rm_keys": ["Variables"],
|
|
90
|
+
},
|
|
91
|
+
"Cell Methods": {
|
|
92
|
+
"source_base": "Data Request Variables (Public)",
|
|
93
|
+
"source_table": "Cell Methods",
|
|
94
|
+
"internal_mapping": {},
|
|
95
|
+
"internal_filters": {},
|
|
96
|
+
"rm_keys": ["Structures", "Variables"],
|
|
97
|
+
},
|
|
98
|
+
"Coordinates and Dimensions": {
|
|
99
|
+
"source_base": "Data Request Variables (Public)",
|
|
100
|
+
"source_table": "Coordinate or Dimension",
|
|
101
|
+
"internal_mapping": {},
|
|
102
|
+
"internal_filters": {},
|
|
103
|
+
"rm_keys": ["Structure", "Variables"],
|
|
104
|
+
},
|
|
105
|
+
"Data Request Themes": {
|
|
106
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
107
|
+
"source_table": "Data Request Themes",
|
|
108
|
+
"internal_mapping": {},
|
|
109
|
+
"internal_filters": {},
|
|
110
|
+
"rm_keys": [],
|
|
111
|
+
},
|
|
112
|
+
"Docs for Opportunities": {
|
|
113
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
114
|
+
"source_table": "Docs for Opportunities",
|
|
115
|
+
"internal_mapping": {},
|
|
116
|
+
"internal_filters": {},
|
|
117
|
+
"rm_keys": [],
|
|
118
|
+
},
|
|
119
|
+
"ESM-BCV 1.3": {
|
|
120
|
+
"source_base": "Data Request Variables (Public)",
|
|
121
|
+
"source_table": "ESM-BCV 1.3",
|
|
122
|
+
"internal_mapping": {},
|
|
123
|
+
"internal_filters": {},
|
|
124
|
+
"rm_keys": [],
|
|
125
|
+
},
|
|
126
|
+
"Experiment Group": {
|
|
127
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
128
|
+
"source_table": "Experiment Group",
|
|
129
|
+
"internal_mapping": {},
|
|
130
|
+
"internal_filters": {
|
|
131
|
+
"Status": {"operator": "not in", "values": ["Junk"]},
|
|
132
|
+
"Status (from Opportunity)": {
|
|
133
|
+
"operator": "in",
|
|
134
|
+
"values": ["New", "Under review", "Accepted"],
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
"rm_keys": ["Opportunity"],
|
|
138
|
+
},
|
|
139
|
+
"Experiments": {
|
|
140
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
141
|
+
"source_table": "Experiment",
|
|
142
|
+
"internal_mapping": {},
|
|
143
|
+
"internal_filters": {},
|
|
144
|
+
"rm_keys": ["Experiment Group"],
|
|
145
|
+
},
|
|
146
|
+
"CMIP6 Frequency (legacy)": {
|
|
147
|
+
"source_base": "Data Request Variables (Public)",
|
|
148
|
+
"source_table": "CMIP6 Frequency (legacy)",
|
|
149
|
+
"internal_mapping": {},
|
|
150
|
+
"internal_filters": {},
|
|
151
|
+
"rm_keys": [],
|
|
152
|
+
},
|
|
153
|
+
"CMIP7 Frequency": {
|
|
154
|
+
"source_base": "Data Request Variables (Public)",
|
|
155
|
+
"source_table": "CMIP7 Frequency",
|
|
156
|
+
"internal_mapping": {},
|
|
157
|
+
"internal_filters": {},
|
|
158
|
+
"rm_keys": ["Table Identifiers", "Variables"],
|
|
159
|
+
},
|
|
160
|
+
"Glossary": {
|
|
161
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
162
|
+
"source_table": "Glossary",
|
|
163
|
+
"internal_mapping": {},
|
|
164
|
+
"internal_filters": {},
|
|
165
|
+
"rm_keys": ["Opportunity"],
|
|
166
|
+
},
|
|
167
|
+
"MIPs": {
|
|
168
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
169
|
+
"source_table": "MIP",
|
|
170
|
+
"internal_mapping": {},
|
|
171
|
+
"internal_filters": {},
|
|
172
|
+
"rm_keys": ["Variable Group"],
|
|
173
|
+
},
|
|
174
|
+
"Modelling Realm": {
|
|
175
|
+
"source_base": "Data Request Variables (Public)",
|
|
176
|
+
"source_table": "Modelling Realm",
|
|
177
|
+
"internal_mapping": {},
|
|
178
|
+
"internal_filters": {},
|
|
179
|
+
"rm_keys": ["Variables"],
|
|
180
|
+
},
|
|
181
|
+
"Opportunity": {
|
|
182
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
183
|
+
"source_table": "Opportunity",
|
|
184
|
+
"internal_mapping": {},
|
|
185
|
+
"internal_filters": {
|
|
186
|
+
"Status": {"operator": "any", "values": ["Under review", "Accepted"]},
|
|
187
|
+
},
|
|
188
|
+
"rm_keys": [],
|
|
189
|
+
},
|
|
190
|
+
"Opportunity/Variable Group Comments": {
|
|
191
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
192
|
+
"source_table": "Comment",
|
|
193
|
+
"internal_mapping": {},
|
|
194
|
+
"internal_filters": {},
|
|
195
|
+
"rm_keys": ["Experiment Groups", "Opportunities", "Theme", "Variable Groups"],
|
|
196
|
+
},
|
|
197
|
+
"Physical Parameter Comments": {
|
|
198
|
+
"source_base": "Data Request Physical Parameters (Public)",
|
|
199
|
+
"source_table": "Comment",
|
|
200
|
+
"internal_mapping": {},
|
|
201
|
+
"internal_filters": {},
|
|
202
|
+
"rm_keys": ["Physical parameters"],
|
|
203
|
+
},
|
|
204
|
+
"Physical Parameters": {
|
|
205
|
+
"source_base": "Data Request Physical Parameters (Public)",
|
|
206
|
+
"source_table": "Physical Parameter",
|
|
207
|
+
"internal_mapping": {},
|
|
208
|
+
"internal_filters": {},
|
|
209
|
+
"rm_keys": ["Variables"],
|
|
210
|
+
},
|
|
211
|
+
"Priority Level": {
|
|
212
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
213
|
+
"source_table": "Priority Level",
|
|
214
|
+
"internal_mapping": {},
|
|
215
|
+
"internal_filters": {},
|
|
216
|
+
"rm_keys": ["Variable Group"],
|
|
217
|
+
},
|
|
218
|
+
"Ranking": {
|
|
219
|
+
"source_base": "Data Request Variables (Public)",
|
|
220
|
+
"source_table": "Ranking",
|
|
221
|
+
"internal_mapping": {},
|
|
222
|
+
"internal_filters": {},
|
|
223
|
+
"rm_keys": [],
|
|
224
|
+
},
|
|
225
|
+
"Spatial Shape": {
|
|
226
|
+
"source_base": "Data Request Variables (Public)",
|
|
227
|
+
"source_table": "Spatial Shape",
|
|
228
|
+
"internal_mapping": {},
|
|
229
|
+
"internal_filters": {},
|
|
230
|
+
"rm_keys": ["Dimensions", "Structure", "Variables"],
|
|
231
|
+
},
|
|
232
|
+
"Structure": {
|
|
233
|
+
"source_base": "Data Request Variables (Public)",
|
|
234
|
+
"source_table": "Structure",
|
|
235
|
+
"internal_mapping": {},
|
|
236
|
+
"internal_filters": {},
|
|
237
|
+
"rm_keys": ["Variables"],
|
|
238
|
+
},
|
|
239
|
+
"Table Identifiers": {
|
|
240
|
+
"source_base": "Data Request Variables (Public)",
|
|
241
|
+
"source_table": "Table Identifiers",
|
|
242
|
+
"internal_mapping": {},
|
|
243
|
+
"internal_filters": {},
|
|
244
|
+
"rm_keys": ["Variables"],
|
|
245
|
+
},
|
|
246
|
+
"Temporal Shape": {
|
|
247
|
+
"source_base": "Data Request Variables (Public)",
|
|
248
|
+
"source_table": "Temporal Shape",
|
|
249
|
+
"internal_mapping": {},
|
|
250
|
+
"internal_filters": {},
|
|
251
|
+
"rm_keys": ["Dimensions", "Structure", "Variables"],
|
|
252
|
+
},
|
|
253
|
+
"Time Slice": {
|
|
254
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
255
|
+
"source_table": "Time Slice",
|
|
256
|
+
"internal_mapping": {},
|
|
257
|
+
"internal_filters": {},
|
|
258
|
+
"rm_keys": [],
|
|
259
|
+
},
|
|
260
|
+
"Variable Comments": {
|
|
261
|
+
"source_base": "Data Request Variables (Public)",
|
|
262
|
+
"source_table": "Comment",
|
|
263
|
+
"internal_mapping": {},
|
|
264
|
+
"internal_filters": {},
|
|
265
|
+
"rm_keys": ["Variables"],
|
|
266
|
+
},
|
|
267
|
+
"Variable Group": {
|
|
268
|
+
"source_base": "Data Request Opportunities (Public)",
|
|
269
|
+
"source_table": "Variable Group",
|
|
270
|
+
"internal_mapping": {
|
|
271
|
+
"Variables": {
|
|
272
|
+
"base_copy_of_table": "Variables",
|
|
273
|
+
"base": "Data Request Variables (Public)",
|
|
274
|
+
"table": "Variable",
|
|
275
|
+
"operation": "",
|
|
276
|
+
"map_by_key": ["UID", "Compound Name"],
|
|
277
|
+
"entry_type": "record_id",
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"internal_filters": {
|
|
281
|
+
"Final Opportunity selection": {"operator": "nonempty"},
|
|
282
|
+
"Status (from Final Opportunity selection)": {
|
|
283
|
+
"operator": "in",
|
|
284
|
+
"values": ["Under review", "Accepted"],
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
"rm_keys": ["Opportunity", "Theme"],
|
|
288
|
+
},
|
|
289
|
+
"Variables": {
|
|
290
|
+
"source_base": "Data Request Variables (Public)",
|
|
291
|
+
"source_table": "Variable",
|
|
292
|
+
"internal_mapping": {
|
|
293
|
+
"CMIP7 Variable Groups": {
|
|
294
|
+
"base_copy_of_table": False,
|
|
295
|
+
"base": "Data Request Opportunities (Public)",
|
|
296
|
+
"table": "Variable Group",
|
|
297
|
+
"operation": "split",
|
|
298
|
+
"map_by_key": ["Name"],
|
|
299
|
+
"entry_type": "name",
|
|
300
|
+
},
|
|
301
|
+
"Physical Parameter": {
|
|
302
|
+
"base_copy_of_table": "Physical Parameter",
|
|
303
|
+
"base": "Data Request Physical Parameters (Public)",
|
|
304
|
+
"table": "Physical Parameter",
|
|
305
|
+
"operation": "",
|
|
306
|
+
"map_by_key": ["UID", "Name"],
|
|
307
|
+
"entry_type": "record_id",
|
|
308
|
+
},
|
|
309
|
+
"CF Standard Name (from MIP Variables)": {
|
|
310
|
+
"base_copy_of_table": False,
|
|
311
|
+
"base": "Data Request Physical Parameters (Public)",
|
|
312
|
+
"table": "CF Standard Name",
|
|
313
|
+
"operation": "",
|
|
314
|
+
"map_by_key": ["name"],
|
|
315
|
+
"entry_type": "name",
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
"internal_filters": {
|
|
319
|
+
"CMIP7 Variable Groups": {"operator": "nonempty"},
|
|
320
|
+
"Opportunity Status (from CMIP7 Variable Groups)": {
|
|
321
|
+
"operator": "in",
|
|
322
|
+
"values": ["Under review", "Accepted"],
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
"rm_keys": ["CMIP7 Variable Groups"],
|
|
326
|
+
},
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
# Renaming of certain tables dependent on the release version
|
|
330
|
+
# version : {table_name_old : table_name_new}
|
|
331
|
+
version_consistency = {
|
|
332
|
+
"v1.0alpha": {
|
|
333
|
+
"Frequency": "CMIP7 Frequency",
|
|
334
|
+
},
|
|
335
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from data_request_api.stable.content.dreq_api import dreq_content as dc
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_parse_version():
|
|
8
|
+
"Test the _parse_version function with different version strings."
|
|
9
|
+
assert dc._parse_version("v1.0.0") == (1, 0, 0, "", 0)
|
|
10
|
+
assert dc._parse_version("v1.0alpha2") == (1, 0, 0, "a", 2)
|
|
11
|
+
assert dc._parse_version("1.0.0a3") == (1, 0, 0, "a", 3)
|
|
12
|
+
assert dc._parse_version("1.0.0beta") == (1, 0, 0, "b", 0)
|
|
13
|
+
assert dc._parse_version("something") == (0, 0, 0, "", 0)
|
|
14
|
+
with pytest.raises(TypeError):
|
|
15
|
+
dc._parse_version(None)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_get_versions():
|
|
19
|
+
"Test the get_versions function."
|
|
20
|
+
versions = dc.get_versions()
|
|
21
|
+
assert "dev" in versions
|
|
22
|
+
assert "v1.0alpha" in versions
|
|
23
|
+
assert "v1.0beta" in versions
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_get_versions_list_branches():
|
|
27
|
+
"Test the get_versions function for branches."
|
|
28
|
+
branches = dc.get_versions(target="branches")
|
|
29
|
+
assert "dev" not in branches
|
|
30
|
+
assert "main" not in branches
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_get_latest_version(monkeypatch):
|
|
34
|
+
"Test the _get_latest_version function."
|
|
35
|
+
monkeypatch.setattr(dc, "get_versions", lambda: ["1.0.0", "2.0.2b", "2.0.2a"])
|
|
36
|
+
assert dc._get_latest_version() == "1.0.0"
|
|
37
|
+
assert dc._get_latest_version(stable=False) == "2.0.2b"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_get_cached(tmp_path):
|
|
41
|
+
"Test the get_cached function."
|
|
42
|
+
# Create a temporary directory with a subdirectory containing a dreq.json file
|
|
43
|
+
version_dir = tmp_path / "v1.0.0"
|
|
44
|
+
version_dir.mkdir()
|
|
45
|
+
(version_dir / dc._json_release).touch()
|
|
46
|
+
|
|
47
|
+
# Set the _dreq_res variable to the temporary directory
|
|
48
|
+
dc._dreq_res = str(tmp_path)
|
|
49
|
+
|
|
50
|
+
# Test the get_cached function
|
|
51
|
+
cached_versions = dc.get_cached()
|
|
52
|
+
assert cached_versions == ["v1.0.0"]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_retrieve(tmp_path, capfd):
|
|
56
|
+
"Test the retrieval function."
|
|
57
|
+
dc._dreq_res = str(tmp_path)
|
|
58
|
+
|
|
59
|
+
# Retrieve 'dev' version
|
|
60
|
+
json_path = dc.retrieve("dev")["dev"]
|
|
61
|
+
assert os.path.isfile(json_path)
|
|
62
|
+
|
|
63
|
+
# Alter on disk (delete first line)
|
|
64
|
+
with open(json_path) as f:
|
|
65
|
+
lines = f.read().splitlines(keepends=True)
|
|
66
|
+
with open(json_path, "w") as f:
|
|
67
|
+
f.writelines(lines[1:])
|
|
68
|
+
|
|
69
|
+
# Make sure it updates
|
|
70
|
+
json_path = dc.retrieve("dev")["dev"]
|
|
71
|
+
stdout = capfd.readouterr().out.splitlines()
|
|
72
|
+
assert len(stdout) == 2
|
|
73
|
+
assert "Retrieved version 'dev'." in stdout
|
|
74
|
+
assert "Updated version 'dev'." in stdout
|
|
75
|
+
# ... and the file was replaced
|
|
76
|
+
with open(json_path) as f:
|
|
77
|
+
lines_update = f.read().splitlines(keepends=True)
|
|
78
|
+
assert lines == lines_update
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_retrieve_with_invalid_version(tmp_path):
|
|
82
|
+
"Test the retrieval function with an invalid version."
|
|
83
|
+
dc._dreq_res = str(tmp_path)
|
|
84
|
+
with pytest.raises(ValueError):
|
|
85
|
+
dc.retrieve(" invalid-version ")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_api_and_html_request():
|
|
89
|
+
"Test the _send_api_request and _send_html_request functions."
|
|
90
|
+
tags1 = set(dc._send_api_request(dc.REPO_API_URL, "", "tags"))
|
|
91
|
+
tags2 = set(dc._send_html_request(dc.REPO_PAGE_URL, "tags"))
|
|
92
|
+
assert tags1 == tags2
|
|
93
|
+
|
|
94
|
+
branches1 = set(dc._send_api_request(dc.REPO_API_URL, "", "branches"))
|
|
95
|
+
branches2 = set(dc._send_html_request(dc.REPO_PAGE_URL, "branches"))
|
|
96
|
+
assert branches1 == branches2
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_load(tmp_path):
|
|
100
|
+
"Test the load function."
|
|
101
|
+
dc._dreq_res = str(tmp_path)
|
|
102
|
+
|
|
103
|
+
with pytest.raises(ValueError):
|
|
104
|
+
jsondict = dc.load(" invalid-version ")
|
|
105
|
+
|
|
106
|
+
jsondict = dc.load("dev")
|
|
107
|
+
assert isinstance(jsondict, dict)
|
|
108
|
+
assert os.path.isfile(tmp_path / "dev" / dc._json_raw)
|
|
109
|
+
assert not os.path.isfile(tmp_path / "dev" / dc._json_release)
|
|
110
|
+
|
|
111
|
+
jsondict = dc.load("dev", export="release")
|
|
112
|
+
assert isinstance(jsondict, dict)
|
|
113
|
+
assert os.path.isfile(tmp_path / "dev" / dc._json_release)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class TestDreqContent:
|
|
117
|
+
"""
|
|
118
|
+
Test various functions of the dreq_content module.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
@pytest.fixture(autouse=True, scope="function")
|
|
122
|
+
def setup(self, tmp_path):
|
|
123
|
+
self.versions = ["v1.0.0", "1.0.1", "2.0.1b", "2.0.1", "2.0.2b"]
|
|
124
|
+
self.branches = ["one", "or", "another"]
|
|
125
|
+
self.dreq_res = tmp_path
|
|
126
|
+
for v in self.versions:
|
|
127
|
+
(self.dreq_res / v).mkdir()
|
|
128
|
+
(self.dreq_res / v / dc._json_release).write_text("{}")
|
|
129
|
+
for b in self.branches:
|
|
130
|
+
(self.dreq_res / b).mkdir()
|
|
131
|
+
(self.dreq_res / b / dc._json_raw).write_text("{}")
|
|
132
|
+
|
|
133
|
+
def test_get_cached(self):
|
|
134
|
+
"Test the get_cached function."
|
|
135
|
+
dc._dreq_res = self.dreq_res
|
|
136
|
+
# Basic
|
|
137
|
+
cached_versions = dc.get_cached()
|
|
138
|
+
assert set(cached_versions) == set(self.versions + self.branches)
|
|
139
|
+
|
|
140
|
+
# With export kwarg "release"
|
|
141
|
+
cached_tags = dc.get_cached(export="release")
|
|
142
|
+
assert set(cached_tags) == set(self.versions)
|
|
143
|
+
|
|
144
|
+
# With export kwarg "raw"
|
|
145
|
+
cached_branches = dc.get_cached(export="raw")
|
|
146
|
+
assert set(cached_branches) == set(self.branches)
|
|
147
|
+
|
|
148
|
+
# With invalid export kwarg
|
|
149
|
+
with pytest.warns(UserWarning, match="Unknown export type"):
|
|
150
|
+
dc.get_cached(export="invalid")
|
|
151
|
+
|
|
152
|
+
def test_delete(self, capfd):
|
|
153
|
+
"Test the delete function."
|
|
154
|
+
dc._dreq_res = self.dreq_res
|
|
155
|
+
# Delete non-existent version
|
|
156
|
+
dc.delete("notpresent")
|
|
157
|
+
stdout = capfd.readouterr().out.splitlines()
|
|
158
|
+
assert len(stdout) == 1
|
|
159
|
+
assert "No version(s) found to delete." in stdout
|
|
160
|
+
|
|
161
|
+
# Delete only branches / dryrun
|
|
162
|
+
dc.delete("all", export="raw", dryrun=True)
|
|
163
|
+
stdout = capfd.readouterr().out.splitlines()
|
|
164
|
+
assert len(stdout) == 5
|
|
165
|
+
assert "Deleting the following version(s):" in stdout
|
|
166
|
+
for b in self.branches:
|
|
167
|
+
assert (
|
|
168
|
+
f"Dryrun: would delete '{dc._dreq_res / b / dc._json_raw}'." in stdout
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Delete all but latest
|
|
172
|
+
dc.delete(keep_latest=True)
|
|
173
|
+
assert set(dc.get_cached()) == {"2.0.1", "2.0.2b"}
|
|
174
|
+
assert dc.get_cached(export="raw") == []
|
|
175
|
+
|
|
176
|
+
# Delete 2.0.1 with warning
|
|
177
|
+
with pytest.warns(UserWarning, match=" option is ignored "):
|
|
178
|
+
dc.delete("2.0.1", keep_latest=True)
|
|
179
|
+
|
|
180
|
+
# Delete all with ValueError for kwargs
|
|
181
|
+
with pytest.raises(ValueError):
|
|
182
|
+
dc.delete(export="none")
|
|
183
|
+
|
|
184
|
+
# Delete all
|
|
185
|
+
dc.delete()
|
|
186
|
+
assert dc.get_cached() == []
|
|
187
|
+
|
|
188
|
+
# Now there is no ValueError since no version is found
|
|
189
|
+
dc.delete(export="none")
|
|
190
|
+
|
|
191
|
+
# def test_load(self):
|
|
192
|
+
# dc._dreq_res = self.tmp_dir.name
|
|
193
|
+
# data = dc.load("1.0.0")
|
|
194
|
+
# assert data == {}
|