dkist-header-validator 5.2.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.
- dkist_header_validator/__init__.py +12 -0
- dkist_header_validator/api/__init__.py +0 -0
- dkist_header_validator/api/validate.py +66 -0
- dkist_header_validator/base_validator.py +751 -0
- dkist_header_validator/exceptions.py +51 -0
- dkist_header_validator/spec_validators.py +54 -0
- dkist_header_validator/tests/__init__.py +0 -0
- dkist_header_validator/tests/conftest.py +639 -0
- dkist_header_validator/tests/test_base_validator.py +494 -0
- dkist_header_validator/tests/test_spec122_translation.py +233 -0
- dkist_header_validator/tests/test_spec122_validation+.py +144 -0
- dkist_header_validator/tests/test_spec122_validation-.py +118 -0
- dkist_header_validator/tests/test_spec214_validation+.py +402 -0
- dkist_header_validator/tests/test_spec214_validation-.py +211 -0
- dkist_header_validator/tests/test_translator.py +114 -0
- dkist_header_validator/translator.py +251 -0
- dkist_header_validator/utils/__init__.py +0 -0
- dkist_header_validator/utils/expansions.py +18 -0
- dkist_header_validator/version.py +8 -0
- dkist_header_validator-5.2.0.dist-info/METADATA +151 -0
- dkist_header_validator-5.2.0.dist-info/RECORD +24 -0
- dkist_header_validator-5.2.0.dist-info/WHEEL +5 -0
- dkist_header_validator-5.2.0.dist-info/entry_points.txt +2 -0
- dkist_header_validator-5.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test for the base validator
|
|
3
|
+
"""
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pytest
|
|
8
|
+
import voluptuous as vol
|
|
9
|
+
import yaml
|
|
10
|
+
from astropy.io import fits
|
|
11
|
+
from deepdiff import DeepDiff
|
|
12
|
+
|
|
13
|
+
from dkist_header_validator.base_validator import SpecSchema
|
|
14
|
+
from dkist_header_validator.base_validator import SpecValidator
|
|
15
|
+
from dkist_header_validator.exceptions import SpecSchemaDefinitionException
|
|
16
|
+
from dkist_header_validator.exceptions import SpecValidationException
|
|
17
|
+
from dkist_header_validator.exceptions import ValidationException
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_parse_spec_schema_definitions():
|
|
21
|
+
"""
|
|
22
|
+
Given: A valid schema definition, can be in one of the following formats:
|
|
23
|
+
dict[str, dict[str, Any]]
|
|
24
|
+
When: Validating the schema
|
|
25
|
+
Then: SpecSchema(definition) returns the schema definition in dict form
|
|
26
|
+
"""
|
|
27
|
+
example_schema = {
|
|
28
|
+
"fits": {
|
|
29
|
+
"key_004": {
|
|
30
|
+
"expand": True,
|
|
31
|
+
"required": False,
|
|
32
|
+
"comment": "comment 4",
|
|
33
|
+
"type": "bool",
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
SpecSchema._parse_spec_schema_definitions(example_schema)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.fixture(scope="module")
|
|
41
|
+
def invalid_definition_format_params(tmpdir_factory):
|
|
42
|
+
"""
|
|
43
|
+
Create a dict of invalid schema definition formats to be used in
|
|
44
|
+
failing format tests below.
|
|
45
|
+
"""
|
|
46
|
+
invalid_dict = {"specxxx": {"this is not a valid yaml file"}}
|
|
47
|
+
|
|
48
|
+
temp_dir = tmpdir_factory.mktemp("invalid_definitions_temp")
|
|
49
|
+
file_name = temp_dir.join("invalid_yaml_file.yml")
|
|
50
|
+
file_name.write(yaml.safe_dump_all(invalid_dict))
|
|
51
|
+
|
|
52
|
+
test_params = {
|
|
53
|
+
"invalid Dict": dict(),
|
|
54
|
+
"invalid schema type1": "non valid schema type",
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
yield test_params
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@pytest.fixture(
|
|
61
|
+
scope="function",
|
|
62
|
+
params=[
|
|
63
|
+
"invalid Dict",
|
|
64
|
+
"invalid schema type1",
|
|
65
|
+
],
|
|
66
|
+
)
|
|
67
|
+
def invalid_definition_format(request, invalid_definition_format_params):
|
|
68
|
+
yield invalid_definition_format_params[request.param]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_parse_spec_schema_definitions_fail(invalid_definition_format):
|
|
72
|
+
"""
|
|
73
|
+
Given: A schema definition that is empty or not in one of the valid formats:
|
|
74
|
+
List[dict]
|
|
75
|
+
When: Validating the schema
|
|
76
|
+
Then: raises a SpecSchemaDefinitionException
|
|
77
|
+
"""
|
|
78
|
+
with pytest.raises(SpecSchemaDefinitionException):
|
|
79
|
+
SpecSchema._parse_spec_schema_definitions(invalid_definition_format)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@pytest.fixture(scope="module")
|
|
83
|
+
def valid_schema_definition_params():
|
|
84
|
+
"""
|
|
85
|
+
Create a dict of schema definition parameters that spans the valid
|
|
86
|
+
parameter space. To be used in successful schema definition tests below.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
test_params = {
|
|
90
|
+
"required int": {"fits": {"keyword_name": {"required": True, "type": "int"}}},
|
|
91
|
+
"optional int": {"fits": {"keyword_name": {"required": False, "type": "int"}}},
|
|
92
|
+
"required float": {"fits": {"keyword_name": {"required": True, "type": "float"}}},
|
|
93
|
+
"optional float": {"fits": {"keyword_name": {"required": False, "type": "float"}}},
|
|
94
|
+
"required str": {"fits": {"keyword_name": {"required": True, "type": "str"}}},
|
|
95
|
+
"optional str": {"fits": {"keyword_name": {"required": False, "type": "str"}}},
|
|
96
|
+
"required bool": {"fits": {"keyword_name": {"required": True, "type": "bool"}}},
|
|
97
|
+
"optional bool": {"fits": {"keyword_name": {"required": False, "type": "bool"}}},
|
|
98
|
+
"optional key-value pair 1": {
|
|
99
|
+
"fits": {"keyword_name": {"required": True, "type": "int", "optional1": "value1"}}
|
|
100
|
+
},
|
|
101
|
+
"optional key-value pair 2": {
|
|
102
|
+
"fits": {"keyword_name": {"required": False, "type": "int", "optional2": "value2"}}
|
|
103
|
+
},
|
|
104
|
+
"optional key-value pair 3": {
|
|
105
|
+
"fits": {"keyword_name": {"required": True, "type": "float", "optional3": "value3"}}
|
|
106
|
+
},
|
|
107
|
+
"optional key-value pair 4": {
|
|
108
|
+
"fits": {"keyword_name": {"required": False, "type": "float", "optional4": "value4"}}
|
|
109
|
+
},
|
|
110
|
+
"optional key-value pair 5": {
|
|
111
|
+
"fits": {"keyword_name": {"required": True, "type": "str", "optional5": "value5"}}
|
|
112
|
+
},
|
|
113
|
+
"optional key-value pair 6": {
|
|
114
|
+
"fits": {"keyword_name": {"required": False, "type": "str", "optional6": "value6"}}
|
|
115
|
+
},
|
|
116
|
+
"optional key-value pair 7": {
|
|
117
|
+
"fits": {"keyword_name": {"required": True, "type": "bool", "optional7": "value7"}}
|
|
118
|
+
},
|
|
119
|
+
"optional key-value pair 8": {
|
|
120
|
+
"fits": {"keyword_name": {"required": False, "type": "bool", "optional8": "value8"}}
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return test_params
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@pytest.fixture(
|
|
128
|
+
scope="function",
|
|
129
|
+
params=[
|
|
130
|
+
"required int",
|
|
131
|
+
"optional int",
|
|
132
|
+
"required float",
|
|
133
|
+
"optional float",
|
|
134
|
+
"required str",
|
|
135
|
+
"optional str",
|
|
136
|
+
"required bool",
|
|
137
|
+
"optional bool",
|
|
138
|
+
"optional key-value pair 1",
|
|
139
|
+
"optional key-value pair 2",
|
|
140
|
+
"optional key-value pair 3",
|
|
141
|
+
"optional key-value pair 4",
|
|
142
|
+
"optional key-value pair 5",
|
|
143
|
+
"optional key-value pair 6",
|
|
144
|
+
"optional key-value pair 7",
|
|
145
|
+
"optional key-value pair 8",
|
|
146
|
+
],
|
|
147
|
+
)
|
|
148
|
+
def valid_schema_definition(request, valid_schema_definition_params):
|
|
149
|
+
|
|
150
|
+
yield valid_schema_definition_params[request.param]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def test_validate_spec_schema_definitions(valid_schema_definition):
|
|
154
|
+
"""
|
|
155
|
+
Given: Valid schema definitions that span the parameter space of the definition schema
|
|
156
|
+
When: Validating the schema
|
|
157
|
+
Then: SpecSchema(definition) successfully validates the definition against
|
|
158
|
+
the definition schema. Success means no exception is raised.
|
|
159
|
+
"""
|
|
160
|
+
SpecSchema(valid_schema_definition)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@pytest.fixture(scope="module")
|
|
164
|
+
def invalid_schema_definition_params():
|
|
165
|
+
"""
|
|
166
|
+
Create a dict of invalid schema definition parameters to be used in
|
|
167
|
+
failing tests below.
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
test_params = {
|
|
171
|
+
"missing required": {"specxxx": {"keyword": {"type": "int"}}},
|
|
172
|
+
"missing type": {"specxxx": {"keyword": {"required": True}}},
|
|
173
|
+
"missing both, no optional": {"specxxx": {"keyword": {}}},
|
|
174
|
+
"missing both, with optional": {"specxxx": {"keyword": {"optional": "value"}}},
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
yield test_params
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@pytest.fixture(
|
|
181
|
+
scope="function",
|
|
182
|
+
params=[
|
|
183
|
+
"missing required",
|
|
184
|
+
"missing type",
|
|
185
|
+
"missing both, no optional",
|
|
186
|
+
"missing both, with optional",
|
|
187
|
+
],
|
|
188
|
+
)
|
|
189
|
+
def invalid_schema_definition(request, invalid_schema_definition_params):
|
|
190
|
+
|
|
191
|
+
yield invalid_schema_definition_params[request.param]
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_validate_spec_schema_definitions_fail(invalid_schema_definition):
|
|
195
|
+
"""
|
|
196
|
+
Given: Schema definitions that do not meet the definition schema
|
|
197
|
+
When: Validating the schema
|
|
198
|
+
Then: SpecSchema(definition) raises a SpecSchemaDefinitionException
|
|
199
|
+
"""
|
|
200
|
+
with pytest.raises(SpecSchemaDefinitionException):
|
|
201
|
+
SpecSchema(invalid_schema_definition)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@pytest.fixture(scope="module")
|
|
205
|
+
def valid_values_list_params():
|
|
206
|
+
"""
|
|
207
|
+
Create a dict of valid values lists to be used in successful tests below
|
|
208
|
+
"""
|
|
209
|
+
test_params = {
|
|
210
|
+
"str list": ["a", "b", "c"],
|
|
211
|
+
"int list": [1, 2, 3],
|
|
212
|
+
"float list": [1.0, 2.0, 3.0],
|
|
213
|
+
"bool list": [True, False, False, True],
|
|
214
|
+
"mixed list": ["a", 1, 2.0, True],
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
yield test_params
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@pytest.fixture(
|
|
221
|
+
scope="function", params=["str list", "int list", "float list", "bool list", "mixed list"]
|
|
222
|
+
)
|
|
223
|
+
def valid_values_list(request, valid_values_list_params):
|
|
224
|
+
yield valid_values_list_params[request.param]
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def test_validate_spec_schema_definitions_values_list(valid_values_list):
|
|
228
|
+
"""
|
|
229
|
+
Given: Schema definitions that have valid values lists
|
|
230
|
+
When: Validating the schema
|
|
231
|
+
Then: SpecSchema(definition) does not raise a SpecSchemaDefinitionException
|
|
232
|
+
"""
|
|
233
|
+
test_schema = {
|
|
234
|
+
"fits": {"keyword_name": {"required": True, "type": "int", "values": valid_values_list}}
|
|
235
|
+
}
|
|
236
|
+
SpecSchema(test_schema)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
@pytest.fixture(scope="module")
|
|
240
|
+
def invalid_values_list_params():
|
|
241
|
+
"""
|
|
242
|
+
Create a dict of invalid values 'lists' to be used in failing tests below
|
|
243
|
+
"""
|
|
244
|
+
test_params = {
|
|
245
|
+
"non-list (set)": {"a", 1, 2.0, True},
|
|
246
|
+
"non-list (tuple)": ("a", 1, 2.0, True),
|
|
247
|
+
"non-list (scalar)": 1,
|
|
248
|
+
"non-list (string)": "some string",
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
yield test_params
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@pytest.fixture(
|
|
255
|
+
scope="function",
|
|
256
|
+
params=["non-list (set)", "non-list (tuple)", "non-list (scalar)", "non-list (string)"],
|
|
257
|
+
)
|
|
258
|
+
def invalid_values_list(request, invalid_values_list_params):
|
|
259
|
+
yield invalid_values_list_params[request.param]
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def test_validate_spec_schema_definitions_values_list_fail(invalid_values_list):
|
|
263
|
+
"""
|
|
264
|
+
Given: Schema definitions that have invalid values lists
|
|
265
|
+
When: Validating the schema
|
|
266
|
+
Then: SpecSchema(definition) raises a SpecSchemaDefinitionException
|
|
267
|
+
"""
|
|
268
|
+
test_schema = {
|
|
269
|
+
"fits": {
|
|
270
|
+
"keyword_name": {
|
|
271
|
+
"required": True,
|
|
272
|
+
"type": "int",
|
|
273
|
+
"values": invalid_values_list,
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
with pytest.raises(SpecSchemaDefinitionException):
|
|
279
|
+
SpecSchema(test_schema)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
@pytest.fixture(scope="module")
|
|
283
|
+
def define_test_schema_definition():
|
|
284
|
+
"""
|
|
285
|
+
Create a test schema to be used tested against in both successful and failing
|
|
286
|
+
tests below.
|
|
287
|
+
"""
|
|
288
|
+
test_schema_definition = {
|
|
289
|
+
"fits": {
|
|
290
|
+
"key_001": {
|
|
291
|
+
"expand": False,
|
|
292
|
+
"required": False,
|
|
293
|
+
"comment": "comment 1",
|
|
294
|
+
"type": "float",
|
|
295
|
+
},
|
|
296
|
+
"key_002": {
|
|
297
|
+
"expand": False,
|
|
298
|
+
"required": True,
|
|
299
|
+
"comment": "comment 2",
|
|
300
|
+
"type": "str",
|
|
301
|
+
},
|
|
302
|
+
"key_003": {
|
|
303
|
+
"expand": False,
|
|
304
|
+
"required": True,
|
|
305
|
+
"comment": "comment 3",
|
|
306
|
+
"type": "int",
|
|
307
|
+
},
|
|
308
|
+
"key_004": {
|
|
309
|
+
"expand": False,
|
|
310
|
+
"required": False,
|
|
311
|
+
"comment": "comment 4",
|
|
312
|
+
"type": "bool",
|
|
313
|
+
},
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
yield test_schema_definition
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def test_create_spec_schema(define_test_schema_definition):
|
|
321
|
+
"""
|
|
322
|
+
Given: A valid schema definition and a valid test schema for the definition
|
|
323
|
+
When: Creating the schema
|
|
324
|
+
Then: The valid test schema is successfully parsed by the schema definition
|
|
325
|
+
"""
|
|
326
|
+
schema = SpecSchema(define_test_schema_definition)
|
|
327
|
+
|
|
328
|
+
input_dict = {"key_002": "value_002", "key_003": 314159, "key_001": 3.14159}
|
|
329
|
+
|
|
330
|
+
assert not DeepDiff(input_dict, schema(input_dict, extra=True), ignore_order=True)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def test_create_spec_schema_fail(define_test_schema_definition):
|
|
334
|
+
"""
|
|
335
|
+
Given: A valid schema definition and an invalid test schema for the definition
|
|
336
|
+
When: Creating the schema
|
|
337
|
+
Then: The invalid test schema is not successfully parsed by the schema definition
|
|
338
|
+
and a voluptuous exception is raised.
|
|
339
|
+
"""
|
|
340
|
+
schema = SpecSchema(define_test_schema_definition)
|
|
341
|
+
|
|
342
|
+
# Required key key_003 is missing:
|
|
343
|
+
input_dict = {"fits": {"key_002": "value_002", "key_004": False, "key_001": 3.14159}}
|
|
344
|
+
with pytest.raises(vol.MultipleInvalid):
|
|
345
|
+
schema(input_dict, extra=True)
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
@pytest.fixture(scope="module")
|
|
349
|
+
def spec_validator():
|
|
350
|
+
"""
|
|
351
|
+
Create a schema validator to test fits headers against below.
|
|
352
|
+
"""
|
|
353
|
+
test_schema = {
|
|
354
|
+
"fits": {
|
|
355
|
+
"BITPIX": {
|
|
356
|
+
"expand": False,
|
|
357
|
+
"required": True,
|
|
358
|
+
"type": "int",
|
|
359
|
+
"values": [8, 16, 32, 64, -32, -64],
|
|
360
|
+
},
|
|
361
|
+
"NAXIS": {"expand": True, "required": True, "type": "int", "values": [3]},
|
|
362
|
+
"NAXIS1": {"expand": False, "required": True, "type": "int"},
|
|
363
|
+
"NAXIS2": {"expand": False, "required": True, "type": "int"},
|
|
364
|
+
"NAXIS3": {"expand": False, "required": True, "type": "int", "default_value": 1},
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
spec_schema = SpecSchema(test_schema)
|
|
369
|
+
spec_validator = SpecValidator(spec_schema)
|
|
370
|
+
|
|
371
|
+
yield spec_validator
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
@pytest.fixture(scope="module")
|
|
375
|
+
def valid_test_header_params(tmpdir_factory):
|
|
376
|
+
"""
|
|
377
|
+
Create a dict with a valid header in various formats to be successfully tested
|
|
378
|
+
against the schema defined above
|
|
379
|
+
"""
|
|
380
|
+
temp_dir = tmpdir_factory.mktemp("valid test_headers_temp")
|
|
381
|
+
file_name = temp_dir.join("tmp_fits_file.fits")
|
|
382
|
+
valid_array = np.ones((1, 1, 1), dtype=float)
|
|
383
|
+
valid_hdu = fits.PrimaryHDU(valid_array)
|
|
384
|
+
valid_hdu_list = fits.HDUList([valid_hdu])
|
|
385
|
+
valid_hdu_list.writeto(str(file_name))
|
|
386
|
+
|
|
387
|
+
yield {
|
|
388
|
+
"valid_hdu_list": valid_hdu_list,
|
|
389
|
+
"valid_fits_header": valid_hdu_list[0].header,
|
|
390
|
+
"valid_fits_file": Path(file_name),
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
@pytest.fixture(
|
|
395
|
+
scope="function",
|
|
396
|
+
params=["valid_hdu_list", "valid_fits_header", "valid_fits_file"],
|
|
397
|
+
)
|
|
398
|
+
def valid_test_header(request, valid_test_header_params):
|
|
399
|
+
yield valid_test_header_params[request.param]
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def test_spec_validator(spec_validator, valid_test_header):
|
|
403
|
+
"""
|
|
404
|
+
Given: A valid schema and a valid fits header to test against the schema
|
|
405
|
+
When: Header validation
|
|
406
|
+
Then: SpecValidator successfully validates the header and does not raise an exception
|
|
407
|
+
"""
|
|
408
|
+
spec_validator.validate(valid_test_header)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
@pytest.fixture(scope="module")
|
|
412
|
+
def valid_test_compressed_file(tmpdir_factory):
|
|
413
|
+
"""
|
|
414
|
+
Create a compressed file with a valid header in various formats to be successfully tested
|
|
415
|
+
against the schema defined above
|
|
416
|
+
"""
|
|
417
|
+
temp_dir = tmpdir_factory.mktemp("valid test_headers_temp")
|
|
418
|
+
file_name = temp_dir.join("tmp_fits_file.fits")
|
|
419
|
+
valid_array = np.ones((1, 1, 1), dtype=float)
|
|
420
|
+
primary_hdu = fits.PrimaryHDU()
|
|
421
|
+
valid_hdu = fits.CompImageHDU(valid_array)
|
|
422
|
+
valid_hdu_list = fits.HDUList([primary_hdu, valid_hdu])
|
|
423
|
+
valid_hdu_list.writeto(str(file_name))
|
|
424
|
+
|
|
425
|
+
yield {
|
|
426
|
+
"valid_compressed.fits.fz": Path(file_name),
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
@pytest.fixture(
|
|
431
|
+
scope="function",
|
|
432
|
+
params=["valid_compressed.fits.fz"],
|
|
433
|
+
)
|
|
434
|
+
def valid_test_compressed_files(request, valid_test_compressed_file):
|
|
435
|
+
yield valid_test_compressed_file[request.param]
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def test_spec_validator_file(spec_validator, valid_test_compressed_files):
|
|
439
|
+
"""
|
|
440
|
+
Given: A valid schema and a valid compressed fits file to test against the schema
|
|
441
|
+
When: Header validation
|
|
442
|
+
Then: SpecValidator successfully validates the header and does not raise an exception
|
|
443
|
+
"""
|
|
444
|
+
spec_validator.validate(valid_test_compressed_files)
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
@pytest.fixture(scope="module")
|
|
448
|
+
def invalid_test_header_params(tmpdir_factory):
|
|
449
|
+
"""
|
|
450
|
+
Create a dict with an invalid header to be tested against the schema defined above.
|
|
451
|
+
The header is invalid because the schema requires NAXIS to be 3 and here we create
|
|
452
|
+
a 2D array which means NAXIS=2.
|
|
453
|
+
"""
|
|
454
|
+
temp_dir = tmpdir_factory.mktemp("invalid_test_headers_temp")
|
|
455
|
+
file_name = temp_dir.join("tmp_fits_file.fits")
|
|
456
|
+
invalid_array = np.ones((1, 1), dtype=float)
|
|
457
|
+
primary_hdu = fits.PrimaryHDU()
|
|
458
|
+
invalid_hdu = fits.CompImageHDU(invalid_array)
|
|
459
|
+
invalid_hdu_list = fits.HDUList([primary_hdu, invalid_hdu])
|
|
460
|
+
invalid_hdu_list.writeto(str(file_name))
|
|
461
|
+
|
|
462
|
+
yield {
|
|
463
|
+
"invalid_hdu_list": invalid_hdu_list,
|
|
464
|
+
"invalid_fits_header": invalid_hdu_list[0].header,
|
|
465
|
+
"invalid_fits_file": Path(file_name),
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
@pytest.fixture(scope="function", params=["invalid_hdu_list", "invalid_fits_file"])
|
|
470
|
+
def invalid_test_header(request, invalid_test_header_params):
|
|
471
|
+
yield invalid_test_header_params[request.param]
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def test_spec_validator_fail(spec_validator, invalid_test_header):
|
|
475
|
+
"""
|
|
476
|
+
Given: A valid schema and an invalid fits header to test against the schema
|
|
477
|
+
When: Header validation
|
|
478
|
+
Then: SpecValidator raises a SpecValidationException
|
|
479
|
+
"""
|
|
480
|
+
with pytest.raises(SpecValidationException):
|
|
481
|
+
spec_validator.validate(invalid_test_header)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def test_validation_exception():
|
|
485
|
+
"""
|
|
486
|
+
Test ValidationException string format
|
|
487
|
+
Given: a ValidationException class
|
|
488
|
+
When: instance created with message and errors
|
|
489
|
+
Then: String of ValidationException is as expected
|
|
490
|
+
"""
|
|
491
|
+
message = "test message"
|
|
492
|
+
errors = {"error1": "error text"}
|
|
493
|
+
s = ValidationException(message, errors=errors)
|
|
494
|
+
assert str(s) == f"{message}: errors={errors}"
|