You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2022-04-05.02:35:58.785>created_at=<Date2022-03-13.03:06:37.673>labels= ['library', '3.11']
title='Allow subclassing Any at runtime'updated_at=<Date2022-04-05.02:35:58.784>user='https://github.com/hauntsaninja'
I understand the rationale for this change, but it does complicate the type system in unspecified (and not fully understood ways). For example
What does it mean to subclass Any in a) a generic class b) a protocol c) a typing.NamedTuple d) a typing.TypedDict?
Are Any subclasses plain subtypes of Any? Does this question even make sense?
How do Any subclasses interact with Any? Are they consistent with Any? Are they consistent subtypes of Any?
etc
I know it is too late to revert this in 3.11, but is there a chance we could revisit the decision to make Any subclassable and put together a deprecation plan, where this behavior ultimately is going away?
We can always decide to change our mind and deprecate this feature, but that's putting the cart before the horse. Type checkers must support Any as a base class (it will come up if you inherit from a class in an untyped library), so the concept needs to be part of the type system somehow. Formalizing what subclassing Any means could be useful, but existing type checkers manage without it.
Is there a better forum to continue this discussion?
I'm not sure I understand why inheriting from Any is necessary in the type system. In my mind, inheriting from a class in an untyped library is very different. An untyped class is syntactically known to be a class, i.e. a static type, whereas Any is a gradual type.
Is there a better forum to continue this discussion?
@superbobry I'm a little confused here, because this was a change to runtime behaviour, but your concern seems to be with whether type checkers should allow Any to be subclassed or not. Whether it's allowed at runtime or not is pretty tangential to that discussion -- there are lots of things that are allowed at runtime that aren't allowed by some or all type checkers, and that's how it should be. If you want to write a type checker that disallows Any from ever being subclassed, it's your right to do so (though it's not one that most type checkers have taken), but the decision we took here to change the runtime behaviour has little bearing on that.
My concern is that this change does not just affect the runtime behavior as type checkers will now observe Any subclasses in the source and will need to decide what to do with them.
I just discovered this behavior change recently, when our codebase upgraded to python 3.11. I would have expected Any to perhaps be a GenericAlias whose __mro_entries__ method returns (object,) or something like that, no? That way, the "subclasses" of Any are still just subclasses of object.
But also, an object can get the same behavior of inheriting from Any by implementing __getattr__ that returns Any, right? And I assume all the mock-like objects already do that, no?
Activity
hauntsaninja commentedon Mar 13, 2022
Discussed on typing-sig at https://mail.python.org/archives/list/typing-sig@python.org/thread/GULRKYI7XOB3FLAEFC6OYSTBS5FIA5PU/
JelleZijlstra commentedon Apr 5, 2022
New changeset 5a4973e by Shantanu in branch 'main':
bpo-46998: Allow subclassing Any at runtime (GH-31841)
5a4973e
JelleZijlstra commentedon Apr 5, 2022
Thanks for the idea and patch!
superbobry commentedon Aug 1, 2023
I understand the rationale for this change, but it does complicate the type system in unspecified (and not fully understood ways). For example
Anyin a) a generic class b) a protocol c) atyping.NamedTupled) atyping.TypedDict?Anysubclasses plain subtypes ofAny? Does this question even make sense?Anysubclasses interact withAny? Are they consistent withAny? Are they consistent subtypes ofAny?I know it is too late to revert this in 3.11, but is there a chance we could revisit the decision to make
Anysubclassable and put together a deprecation plan, where this behavior ultimately is going away?JelleZijlstra commentedon Aug 1, 2023
We can always decide to change our mind and deprecate this feature, but that's putting the cart before the horse. Type checkers must support Any as a base class (it will come up if you inherit from a class in an untyped library), so the concept needs to be part of the type system somehow. Formalizing what subclassing Any means could be useful, but existing type checkers manage without it.
superbobry commentedon Aug 1, 2023
Is there a better forum to continue this discussion?
I'm not sure I understand why inheriting from
Anyis necessary in the type system. In my mind, inheriting from a class in an untyped library is very different. An untyped class is syntactically known to be a class, i.e. a static type, whereasAnyis a gradual type.AlexWaygood commentedon Aug 1, 2023
@superbobry I'm a little confused here, because this was a change to runtime behaviour, but your concern seems to be with whether type checkers should allow
Anyto be subclassed or not. Whether it's allowed at runtime or not is pretty tangential to that discussion -- there are lots of things that are allowed at runtime that aren't allowed by some or all type checkers, and that's how it should be. If you want to write a type checker that disallowsAnyfrom ever being subclassed, it's your right to do so (though it's not one that most type checkers have taken), but the decision we took here to change the runtime behaviour has little bearing on that.Nonetheless, if you do want to argue that we should standardise the behaviour of type checkers so that they always disallow subclassing
Any, feel free to open an issue at https://github.com/python/typing or to start a thread on the typing-sig mailing list (https://mail.python.org/archives/list/typing-sig@python.org/).superbobry commentedon Aug 2, 2023
Thanks for chiming in @AlexWaygood!
My concern is that this change does not just affect the runtime behavior as type checkers will now observe
Anysubclasses in the source and will need to decide what to do with them.I will follow up on typing-sig@.
kmoffett commentedon Dec 7, 2023
I just discovered this behavior change recently, when our codebase upgraded to python 3.11. I would have expected
Anyto perhaps be aGenericAliaswhose__mro_entries__method returns(object,)or something like that, no? That way, the "subclasses" ofAnyare still just subclasses ofobject.But also, an object can get the same behavior of inheriting from
Anyby implementing__getattr__that returnsAny, right? And I assume all the mock-like objects already do that, no?