Skip to content

Conversation

@randolf-scholz
Copy link
Contributor

@randolf-scholz randolf-scholz commented Jan 24, 2026

Fixes #15307

See Also: #15319

This PR changes the generic type of collections.abc.Container from covariant to contravariant and lets the key be of this type rather than object.

The current definition forces a lot ofpeople to resort to type: ignore[override].

Potential Backward Compatibility issue

The way I modified the class, if someone uses something like

class MyClass[T](Iterable[T], Container[T]): ...

This change will make their class invariant, where it was covariant before.
Inside collections.abc.Collection I addressed this issue by changing Container[_T_co] to Container[Any].

There weren't any other cases in the whole stubs where a type variable was fed into Container, so I believe the breakage in real world code will be extremely limited (as the user also would have have to use PEP 695 style syntax)

@github-actions

This comment has been minimized.

@randolf-scholz randolf-scholz marked this pull request as ready for review January 24, 2026 15:01
@randolf-scholz randolf-scholz changed the title Experiment: Use contravariant type variable rather than object in Container Use contravariant type variable rather than object in Container Jan 24, 2026
@randolf-scholz
Copy link
Contributor Author

cc @hauntsaninja @AlexWaygood as you authored #8785, what do you think of this change?

@randolf-scholz
Copy link
Contributor Author

The only notable primer change is from trio:

    def filter_tasks(self, tasks: Container[Task]) -> Iterable[tuple[str, Task | None]]:
        for item in self.record:
            if item[0] in ("schedule", "before", "after") and item[1] in tasks:
                yield item

since Container is now contravariant, they need to annotate with Container[Task | None].

@github-actions

This comment has been minimized.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this makes sense to me, thanks

@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

mypy (https://github.com/python/mypy)
+ mypy/server/aststrip.py:140: error: Unused "type: ignore" comment  [unused-ignore]

trio (https://github.com/python-trio/trio)
+ src/trio/_core/_tests/test_instrumentation.py:40: error: Unsupported operand types for in ("Task | None" and "Container[Task]")  [operator]

dulwich (https://github.com/dulwich/dulwich)
+ dulwich/refs.py:127: error: Unused "type: ignore" comment  [unused-ignore]
+ dulwich/refs.py:129: error: Unused "type: ignore" comment  [unused-ignore]
+ dulwich/refs.py:131: error: Unused "type: ignore" comment  [unused-ignore]
+ dulwich/refs.py:140: error: Unused "type: ignore" comment  [unused-ignore]
+ dulwich/refs.py:142: error: Unused "type: ignore" comment  [unused-ignore]

urllib3 (https://github.com/urllib3/urllib3)
+ test/test_collections.py:336: error: Unused "type: ignore" comment  [unused-ignore]
+ test/test_collections.py:337: error: Unused "type: ignore" comment  [unused-ignore]
+ test/test_collections.py:398: error: Unused "type: ignore" comment  [unused-ignore]
+ test/test_collections.py:399: error: Unused "type: ignore" comment  [unused-ignore]

core (https://github.com/home-assistant/core)
+ homeassistant/components/homekit/__init__.py:981: error: Unused "type: ignore" comment  [unused-ignore]

ibis (https://github.com/ibis-project/ibis)
- ibis/expr/datatypes/core.py:613: error: Argument 1 of "__contains__" is incompatible with supertype "typing.Container"; supertype defines the argument type as "object"  [override]

discord.py (https://github.com/Rapptz/discord.py)
- ...typeshed_to_test/stdlib/typing.pyi:1046: note: "update" of "TypedDict" defined here
+ ...typeshed_to_test/stdlib/typing.pyi:1049: note: "update" of "TypedDict" defined here

operator (https://github.com/canonical/operator)
- ops/model.py:885: error: Argument 1 of "__contains__" is incompatible with supertype "typing.Container"; supertype defines the argument type as "object"  [override]
- ops/model.py:932: error: Argument 1 of "__contains__" is incompatible with supertype "typing.Container"; supertype defines the argument type as "object"  [override]
- ops/model.py:1961: error: Argument 1 of "__contains__" is incompatible with supertype "typing.Container"; supertype defines the argument type as "object"  [override]
- ops/model.py:2402: error: Argument 1 of "__contains__" is incompatible with supertype "typing.Container"; supertype defines the argument type as "object"  [override]

@srittau srittau merged commit 35b688e into python:main Jan 24, 2026
63 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should collections.abc.Container be generic?

3 participants