2.10.0
Added
-
Pydantic v2 models in structural matching.
matches_structure(),satisfies(match.structure(...)),each(...), and the==form now accept a Pydantic model directly (viamodel_dump()) and report a path-level diff. Previously a model raisedTypeError: val must be a dict- you had to call.model_dump()yourself.class User(BaseModel): name: str role: str user = User(name="Alice", role="superadmin") # Before 2.10.0: assert_that(user.model_dump()).matches_structure({...}) # TypeError otherwise # Now: assert_that(user).matches_structure({"role": match.is_in("admin", "user")}) # diff (match): # role: expected a value in <('admin', 'user')>, but was 'superadmin'
-
Pydantic v2 models in
extracting().
Pull attributes straight off model instances. Previously a list of models raisedTypeError: item <User> does not have [] accessor(models are iterable but not subscriptable).users = [User(name="Alice", role="admin"), User(name="Bob", role="editor")] assert_that(users).extracting("name").contains("Alice", "Bob") assert_that(users).extracting("name", "role").is_equal_to( [("Alice", "admin"), ("Bob", "editor")] )
Improved
-
Richer nested diffs.
Nested sequences and dataclass fields are now decomposed to the exact differing path, matching the detail already shown at the top level.@dataclass class Matrix: rows: list[list[int]] assert_that(Matrix([[1, 2], [3, 4]])).is_equal_to(Matrix([[1, 2], [3, 9]])) # Before 2.10.0 - the whole nested list was one leaf: # .rows: # - [[1, 2], [3, 4]] # + [[1, 2], [3, 9]] # # Now - decomposed to the exact index: # .rows[1][1]: # - 4 # + 9
Internal
- Mutation-testing gaps closed.
Hardened the rich-diff ordering guards andfile.is_named. - Tooling and docs.
Refreshed diff screenshots and docs; bumped dev type-checkertyto 0.0.54.