Make Matcher contravariant to fix type checking (issue #222)#273
Open
brunns wants to merge 3 commits intohamcrest:mainfrom
Open
Make Matcher contravariant to fix type checking (issue #222)#273brunns wants to merge 3 commits intohamcrest:mainfrom
brunns wants to merge 3 commits intohamcrest:mainfrom
Conversation
Fixes hamcrest#222: Matchers should be contravariant with respect to their type parameter. This allows more flexible type assignments where a Matcher[Base] can be used where a Matcher[Derived] is expected, which is the correct variance for types that consume their type parameter. Changes: - Make Matcher's TypeVar contravariant in src/hamcrest/core/matcher.py - Add type: ignore comment to is_() overload to suppress mypy's overly strict overlap detection (the overloads work correctly at runtime) - Add test cases for issues hamcrest#222 and hamcrest#234 in test_assert_that.yml - Add comprehensive type tests for all common matchers to verify no regressions in tests/type-hinting/test_common_matchers.yml Example now working: matcher: Matcher[str] = has_length(greater_than(0)) Since str is Sized, Matcher[Sized] can now be assigned to Matcher[str] because Matcher is contravariant. This makes the type system more flexible and correct. Testing: - All mypy type checking passes - All type-hinting tests pass (17 tests covering all major matchers) - Comprehensive tests added for core, logical, collection, number, object, and text matchers - No functional regressions detected Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
823a95d to
7ef70a8
Compare
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Member
Author
|
Relies on #272 I think. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #222: Makes
Matchercontravariant with respect to its type parameter, allowing more flexible and correct type assignments.Problem
Previously,
Matcherwas invariant, which meant thatMatcher[Sized]could not be assigned toMatcher[str]even thoughstris aSizedtype. This violated the principle of contravariance for types that consume their type parameter.Solution
Matcher'sTypeVarcontravariant:T = TypeVar("T", contravariant=True)type: ignore[overload-overlap]tois_()overload to suppress mypy's overly strict overlap detectionExample Now Working
Testing
Added comprehensive type tests to ensure contravariance doesn't break existing matchers:
New Test Coverage (17 tests, all passing)
equal_to,is_,is_not,none,not_none,same_instance,instance_of,anythingall_of,any_ofhas_item,has_items,contains_exactly,contains_inanyorder,has_entry,has_entries,has_key,has_value,empty,is_in,only_containsgreater_than,less_than,close_to, etc.has_property,has_properties,has_length,has_stringcontains_string,starts_with,ends_with,matches_regexp, etc.has_item(greater_than(3))Results
Note on Issue #234
While investigating #222, discovered that issue #234 (sequence matcher type warnings) appears to already be fixed in the current codebase. Added tests to verify.
🤖 Generated with Claude Code