Skip to content

Commit fc4f4e6

Browse files
committed
Cover the decorator's refusal paths and the runtime-only lazy-init branches
The two TypeError guards in deferred_model and plain warm() were untested, and coverage.py counts the never-taken false arc of the `if not TYPE_CHECKING:` guards around the lazy module attributes; that arc belongs to the type checker, so declare it partial by design next to the existing exclusion rules.
1 parent e02caca commit fc4f4e6

3 files changed

Lines changed: 27 additions & 0 deletions

File tree

‎pyproject.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ exclude_also = [
306306
"@overload",
307307
"raise NotImplementedError",
308308
]
309+
# `if not TYPE_CHECKING:` installs runtime-only lazy module attributes; its
310+
# false arc belongs to the type checker and never runs (like `if TYPE_CHECKING:`).
311+
partial_also = ["if not TYPE_CHECKING:"]
309312

310313
# https://coverage.readthedocs.io/en/latest/config.html#paths
311314
[tool.coverage.paths]

‎tests/types/test_deferred.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,28 @@ class Child(Root):
7171
assert str(inspect.signature(cls)) == expected
7272

7373

74+
def test_the_decorator_refuses_a_root_that_would_not_defer_or_that_owns_a_subclass_hook() -> None:
75+
"""`@deferred_model` marks a *deferred* hierarchy root and installs its own subclass hook:
76+
a class without `defer_build`, or one defining `__pydantic_init_subclass__` itself (which
77+
the installed hook would replace), is refused at decoration time."""
78+
79+
class Eager(BaseModel):
80+
value: int
81+
82+
class OwnsHook(BaseModel):
83+
model_config = ConfigDict(defer_build=True)
84+
value: int
85+
86+
@classmethod
87+
def __pydantic_init_subclass__(cls, **kwargs: object) -> None:
88+
raise NotImplementedError # never runs: the decorator refuses the class first
89+
90+
with pytest.raises(TypeError):
91+
deferred_model(Eager)
92+
with pytest.raises(TypeError):
93+
deferred_model(OwnsHook)
94+
95+
7496
def test_unresolvable_model_falls_back_to_the_generic_signature() -> None:
7597
"""A model whose build cannot complete (a forward reference that does not resolve at
7698
that point) reports the generic initializer signature, as pydantic does for any

‎tests/types/test_methods.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,8 @@ def test_warming_a_version_leaves_nothing_for_its_first_messages_to_build():
11131113

11141114
def test_warm_is_idempotent_and_gates_unknown_versions():
11151115
"""SDK-defined: repeating a `warm()` builds nothing more; an unknown version is a ValueError."""
1116+
baseline = methods.warm() # the version-independent set (this process may already have built it)
1117+
assert baseline.elapsed_ms >= 0
11161118
methods.warm(everything=True)
11171119
again = methods.warm(everything=True)
11181120
assert (again.models, again.adapters) == (0, 0)

0 commit comments

Comments
 (0)