@@ -63,40 +63,68 @@ def _make_header(labels, field_names, *, fields_match="exact", ignore_case=False
6363 "labels, field_names, fields_match, ignore_case, expected_names" ,
6464 [
6565 pytest .param (
66- ["a" , "b" ], ["a" , "b" ], "exact" , False , ["a" , "b" ],
66+ ["a" , "b" ],
67+ ["a" , "b" ],
68+ "exact" ,
69+ False ,
70+ ["a" , "b" ],
6771 id = "exact: schema fields are returned as-is" ,
6872 ),
6973 pytest .param (
70- ["b" , "a" ], ["a" , "b" ], "exact" , False , ["a" , "b" ],
74+ ["b" , "a" ],
75+ ["a" , "b" ],
76+ "exact" ,
77+ False ,
78+ ["a" , "b" ],
7179 id = "exact: schema order is kept even if labels differ" ,
7280 ),
7381 pytest .param (
74- ["a" , "extra" ], ["a" ], "exact" , False , ["a" ],
82+ ["a" , "extra" ],
83+ ["a" ],
84+ "exact" ,
85+ False ,
86+ ["a" ],
7587 id = "exact: extra labels get no field" ,
7688 ),
7789 * [
7890 pytest .param (
79- ["b" , "a" ], ["a" , "b" ], mode , False , ["b" , "a" ],
91+ ["b" , "a" ],
92+ ["a" , "b" ],
93+ mode ,
94+ False ,
95+ ["b" , "a" ],
8096 id = f"{ mode } : fields are reordered to match labels" ,
8197 )
8298 for mode in NAME_MATCHED
8399 ],
84100 * [
85101 pytest .param (
86- ["a" , "extra" ], ["a" ], mode , False , ["a" , "extra" ],
102+ ["a" , "extra" ],
103+ ["a" ],
104+ mode ,
105+ False ,
106+ ["a" , "extra" ],
87107 id = f"{ mode } : extra labels get a default any-typed field" ,
88108 )
89109 for mode in NAME_MATCHED
90110 ],
91111 * [
92112 pytest .param (
93- ["a" ], ["a" , "b" ], mode , False , ["a" ],
113+ ["a" ],
114+ ["a" , "b" ],
115+ mode ,
116+ False ,
117+ ["a" ],
94118 id = f"{ mode } : fields absent from labels are dropped" ,
95119 )
96120 for mode in NAME_MATCHED
97121 ],
98122 pytest .param (
99- ["B" , "A" ], ["a" , "b" ], "partial" , True , ["b" , "a" ],
123+ ["B" , "A" ],
124+ ["a" , "b" ],
125+ "partial" ,
126+ True ,
127+ ["b" , "a" ],
100128 id = "partial + ignore_case: matching is case-insensitive" ,
101129 ),
102130 ],
@@ -132,11 +160,7 @@ def test_get_expected_fields_exact_tolerates_duplicate_labels():
132160 assert [f .name for f in header .get_expected_fields ()] == ["a" , "b" ]
133161
134162
135- # Tolerated and reported mismatches, per mode
136- #
137- # Each mode differs only in which mismatch it tolerates: a label with no
138- # matching field (`extra-label`) and a field with no matching label
139- # (`missing-label`). What is reported is observed through `header.errors`.
163+ # Tolerated and reported header mismatches, per fieldsMatch value
140164
141165
142166def _errors (header ):
@@ -197,8 +221,7 @@ def test_errors_on_missing_field(fields_match, expected):
197221
198222@pytest .mark .parametrize ("fields_match" , ["superset" , "partial" ])
199223def test_errors_on_missing_required_field (fields_match ):
200- # The modes that tolerate fewer fields still require the fields that the
201- # schema declares as required.
224+ # Required fields are mandatory even for "superset" and "partial" fieldsMatch.
202225 header = _make_header_with_required (
203226 ["a" ], ["a" , "b" ], required = ["b" ], fields_match = fields_match
204227 )
@@ -237,32 +260,18 @@ def test_errors_partial_with_a_schema_without_fields():
237260
238261@pytest .mark .parametrize ("fields_match" , ["exact" , "equal" , "subset" , "superset" ])
239262def test_errors_unmatched_header_is_specific_to_partial (fields_match ):
240- # The other modes report the mismatch label by label or field by field:
241- # extra labels are errors in `equal` and `superset`, missing fields are
242- # errors in `exact`, `equal` and `subset`.
243263 header = _make_header (["x" , "y" ], ["a" , "b" ], fields_match = fields_match )
244264 assert "unmatched-header" not in [e .type for e in header .errors ]
245265
246266
247- @pytest .mark .parametrize ("fields_match" , ["exact" , * NAME_MATCHED ])
248- def test_errors_a_header_matching_nothing_is_never_silent (fields_match ):
249- # Only the diagnosis differs between modes; the verdict does not. `partial`
250- # tolerates extra labels *and* missing fields, so it is the only mode that
251- # would stay silent here -- which is what its "at least one" rule prevents.
252- header = _make_header (["x" , "y" ], ["a" , "b" ], fields_match = fields_match )
253- assert header .errors != []
254-
255-
256267def test_errors_extra_label_is_reported_at_its_position_in_the_data ():
257- # Under name matching the extra label can sit anywhere, so it is reported
258- # where it actually is rather than after the declared fields.
259268 header = _make_header (["extra" , "a" , "b" ], ["a" , "b" ], fields_match = "equal" )
260269 assert _errors (header ) == [("extra-label" , "extra" , "" , 1 )]
261270
262271
263272# The schema below declares a single field, so a header that doesn't carry it
264- # shares nothing with the schema: `partial` (the mode schema_sync maps to)
265- # reports that as an `unmatched-header` on top of the missing label .
273+ # shares nothing with the schema: `partial` reports that as an
274+ # `unmatched-header`.
266275UNMATCHED = ["unmatched-header" , "missing-label" ]
267276
268277
0 commit comments