Skip to content

Commit 269f623

Browse files
sethfitzvcschapp
authored andcommitted
Fix mypy errors in test subdirectories, check recursively
The mypy target only checked top-level test files via `packages/*/tests/*.py`. Subdirectory tests (model_constraint/, ref/, scoping/) were never type-checked. Switch to per-directory find so mypy discovers all test files while keeping each package's conftest.py visible (avoids duplicate module conflicts across packages). Fixes in test code: - Mapping[str, object] in assert_subset (dict invariance) - Missing return type annotations on test functions - Duplicate TestModel names within same scope - JsonDict annotations for ConfigDict json_schema_extra - type: ignore for dynamically-created .When classes
1 parent 2887482 commit 269f623

11 files changed

Lines changed: 32 additions & 23 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ mypy: uv-sync
4343
| tr - . \
4444
| sed 's|^packages/|-p |' \
4545
| xargs uv run mypy --no-error-summary
46-
@uv run mypy --no-error-summary packages/*/tests/*.py
46+
@for d in packages/*/tests; do find "$$d" -name "*.py" | sort | xargs uv run mypy --no-error-summary || exit 1; done
4747

4848
reset-baseline-schemas:
4949
@find . -name \*_baseline_schema.json -delete

packages/overture-schema-core/tests/scoping/test_scoped.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ class SingleScoped(BaseModel):
181181
when_field_info = SingleScoped.model_fields["when"]
182182
assert when_field_info.is_required() == required
183183

184-
when_class = SingleScoped.When
184+
when_class = SingleScoped.When # type: ignore[attr-defined]
185185
assert issubclass(when_class, BaseModel)
186186
assert len(when_class.model_fields) == 1
187187

@@ -200,7 +200,7 @@ class MultiScopedWhenAllFieldsOptional(BaseModel):
200200
when_field_info = MultiScopedWhenAllFieldsOptional.model_fields["when"]
201201
assert not when_field_info.is_required()
202202

203-
when_class = MultiScopedWhenAllFieldsOptional.When
203+
when_class = MultiScopedWhenAllFieldsOptional.When # type: ignore[attr-defined]
204204
assert issubclass(when_class, BaseModel)
205205
assert len(when_class.model_fields) == 2
206206

@@ -229,7 +229,7 @@ class MultiScopedWhenSomeFieldsRequired(BaseModel):
229229
when_field_info = MultiScopedWhenSomeFieldsRequired.model_fields["when"]
230230
assert when_field_info.is_required()
231231

232-
when_class = MultiScopedWhenSomeFieldsRequired.When
232+
when_class = MultiScopedWhenSomeFieldsRequired.When # type: ignore[attr-defined]
233233
assert issubclass(when_class, BaseModel)
234234
assert len(when_class.model_fields) == 3
235235

@@ -270,7 +270,7 @@ class Complex(BaseModel):
270270
when_field_info = Complex.model_fields["when"]
271271
assert when_field_info.is_required()
272272

273-
when_class = Complex.When
273+
when_class = Complex.When # type: ignore[attr-defined]
274274
assert issubclass(when_class, BaseModel)
275275
assert len(when_class.model_fields) == 3
276276

packages/overture-schema-system/tests/model_constraint/test_forbid_if.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717

1818
@pytest.mark.parametrize("field_names", [[], ()])
19-
def test_error_not_enough_field_names(field_names: list[str]):
19+
def test_error_not_enough_field_names(field_names: list[str]) -> None:
2020
with pytest.raises(ValueError, match="`field_names` cannot be empty, but it is"):
2121
forbid_if(field_names, FieldEqCondition("foo", 42))
2222

packages/overture-schema-system/tests/model_constraint/test_min_fields_set.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import pytest
55
from pydantic import BaseModel, ConfigDict
6+
from pydantic.json_schema import JsonDict
67
from util import assert_subset
78

89
from overture.schema.system import create_model
@@ -195,7 +196,7 @@ class TestModel(BaseModel):
195196

196197

197198
def test_model_json_schema_already_set_same() -> None:
198-
expect = {"minProperties": 3, "hello": "world"}
199+
expect: JsonDict = {"minProperties": 3, "hello": "world"}
199200

200201
@min_fields_set(3)
201202
class TestModel(BaseModel):
@@ -211,7 +212,7 @@ class TestModel(BaseModel):
211212

212213

213214
def test_model_json_schema_error_already_set_different() -> None:
214-
expect = {"minProperties": 1, "hello": "world"}
215+
expect: JsonDict = {"minProperties": 1, "hello": "world"}
215216

216217
with pytest.raises(
217218
RuntimeError,

packages/overture-schema-system/tests/model_constraint/test_multi_constraint.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
)
2020

2121

22-
def test_many_constraints():
22+
def test_many_constraints() -> None:
2323
@forbid_if(["corge", "garply"], FieldEqCondition("qux", "hello"))
2424
@min_fields_set(3)
2525
@no_extra_fields

packages/overture-schema-system/tests/model_constraint/test_no_extra_fields.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
def test_error_invalid_model_class() -> None:
12-
expect_pattern = r"can't apply `@?\w+` to model class `TestModel`: existing `model_config\['extra'\]` is already set to '\w+'"
12+
expect_pattern = r"can't apply `@?\w+` to model class `\w+`: existing `model_config\['extra'\]` is already set to '\w+'"
1313

1414
with pytest.raises(TypeError, match=expect_pattern):
1515

@@ -19,10 +19,10 @@ class TestModel(BaseModel):
1919

2020
with pytest.raises(TypeError, match=expect_pattern):
2121

22-
class TestModel(BaseModel):
22+
class TestModelAllow(BaseModel):
2323
model_config = ConfigDict(extra="allow")
2424

25-
NoExtraFieldsConstraint().validate_class(TestModel)
25+
NoExtraFieldsConstraint().validate_class(TestModelAllow)
2626

2727

2828
@pytest.mark.parametrize(

packages/overture-schema-system/tests/model_constraint/test_radio_group.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515

1616
@pytest.mark.parametrize("field_names", [[], (), ["foo"], ("bar",)])
17-
def test_error_not_enough_field_names(field_names: list[str]):
17+
def test_error_not_enough_field_names(field_names: list[str]) -> None:
1818
with pytest.raises(
1919
ValueError, match="`field_names` must contain at least two items"
2020
):
@@ -108,7 +108,7 @@ class TestModel(BaseModel):
108108
def test_model_json_schema_no_model_config() -> None:
109109
@radio_group("foo", "baz", "qux")
110110
class TestModel(BaseModel):
111-
foo: bool = Field(default=None, alias="bar")
111+
foo: bool | None = Field(default=None, alias="bar")
112112
baz: bool
113113
qux: bool = Field(alias="corge")
114114

packages/overture-schema-system/tests/model_constraint/test_require_any_of.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ def test_error_duplicate_field_names(field_names: list[str]) -> None:
2525

2626

2727
def test_error_invalid_model_class() -> None:
28-
expect = "specifies one or more fields that are not in the model class `TestModel`: foo, bar"
28+
expect = (
29+
r"specifies one or more fields that are not in the model class `\w+`: foo, bar"
30+
)
2931

3032
with pytest.raises(TypeError, match=expect):
3133

@@ -35,10 +37,10 @@ class TestModel(BaseModel):
3537

3638
with pytest.raises(TypeError, match=expect):
3739

38-
class TestModel(BaseModel):
40+
class TestModel2(BaseModel):
3941
baz: int
4042

41-
RequireAnyOfConstraint("foo", "bar").validate_class(TestModel)
43+
RequireAnyOfConstraint("foo", "bar").validate_class(TestModel2)
4244

4345

4446
def test_error_invalid_model_instance() -> None:

packages/overture-schema-system/tests/model_constraint/test_require_if.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717

1818
@pytest.mark.parametrize("field_names", [[], ()])
19-
def test_error_not_enough_field_names(field_names: list[str]):
19+
def test_error_not_enough_field_names(field_names: list[str]) -> None:
2020
with pytest.raises(ValueError, match="`field_names` cannot be empty, but it is"):
2121
require_if(field_names, FieldEqCondition("foo", 42))
2222

@@ -107,7 +107,7 @@ class TestModel(BaseModel):
107107

108108

109109
@pytest.mark.parametrize("field_names", [["foo"], ["bar"], ["foo", "bar"]])
110-
def test_valid_model_instance_condition_false(field_names) -> None:
110+
def test_valid_model_instance_condition_false(field_names: list[str]) -> None:
111111
class TestModel(BaseModel):
112112
foo: int | None = None
113113
bar: int | None = None

packages/overture-schema-system/tests/ref/test_id.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ class TestIdentifiedFeature:
1010
class IdentifiedFeature(Identified, Feature):
1111
pass
1212

13-
def test_id_required_in_model_fields(self):
13+
def test_id_required_in_model_fields(self) -> None:
1414
id_field = TestIdentifiedFeature.IdentifiedFeature.model_fields["id"]
1515

1616
assert id_field.is_required()
1717

18-
def test_description_same_in_model_fields(self):
18+
def test_description_same_in_model_fields(self) -> None:
1919
base_id_field = Identified.model_fields["id"]
2020
derived_id_field = TestIdentifiedFeature.IdentifiedFeature.model_fields["id"]
2121

0 commit comments

Comments
 (0)