typing.Any subclasses
![](https://secure.gravatar.com/avatar/1edcf99e3b405ba3565952a194f79ca3.jpg?s=120&d=mm&r=g)
Hi typing-sig@, Python 3.11 came out with a seemingly minor change allowing typing.Any to be subclassed <https://github.com/python/cpython/issues/91154>, So, for example, from typing import Any class A(Any): x: int is now valid Python. The intent of the change was to have a way of expressing mock-like types which are assignable to and from any type, in the same way typing.Any is. I think this behavior needs to be deprecated and removed. typing.Any is a gradual type with special properties, which is distinct from class types introduced via class definitions. Allowing the two to mix complicates the Python type system in unspecified (and not fully understood) ways. For example, we now need to figure out * What does it mean to subclass typing.Any in a) a generic class b) a protocol c) a typing.NamedTuple d) a typing.TypedDict? * What does it mean for a typing.Any subclass to have attributes? * Are Any subclasses plain subtypes of typing.Any? Does this question even make sense? * How do typing.Any subclasses interact with typing.Any? Are they consistent with typing.Any? Are they consistent subtypes of typing.Any? * etc Sergei
![](https://secure.gravatar.com/avatar/3247bfd67c8fa4c4a08b8d30e49eab39.jpg?s=120&d=mm&r=g)
Static type checkers already need to handle the case where the type of a base class cannot be determined statically and is therefore treated as `Any`. This can occur for many reasons including dynamic code, failure to resolve an import at static analysis time, etc. Disallowing an explicit `Any` from being used as a base class doesn't eliminate the problem. I agree with your observation that this case isn't well spec'ed and creates potential inconsistencies in the type system. It also potentially leads to differences in behavior across type checkers, since the behavior isn't precisely spec'd. In practice, this hasn't been a problem. Type checkers do "the obvious thing" when they encounter an `Any` base class. This can lead to false negatives, but that's generally true for `Any`. I think this is a case where it's more important to be pragmatic than to be technically correct. And I don't see any benefit to deprecating the use of `typing.Any` as a base class at runtime. Eric Traut Contributor to pyright & pylance
![](https://secure.gravatar.com/avatar/53d7739ff0a8bcc486caeb1228ed4983.jpg?s=120&d=mm&r=g)
At the very least, this change should not have been done without updating PEP 483 <https://peps.python.org/pep-0483/#:~:text=No%20types%20defined,derived%20fro...>, since that states:
- No types defined below [(i.e. Any, Union, etc.)] can be subclassed, except for Generic and classes derived from it.
-- Teddy -- Teddy On Wed, Aug 2, 2023 at 9:20 AM Eric Traut wrote: > > Static type checkers already need to handle the case where the type of a base class cannot be determined statically and is therefore treated as `Any`. This can occur for many reasons including dynamic code, failure to resolve an import at static analysis time, etc. Disallowing an explicit `Any` from being used as a base class doesn't eliminate the problem. > > I agree with your observation that this case isn't well spec'ed and creates potential inconsistencies in the type system. It also potentially leads to differences in behavior across type checkers, since the behavior isn't precisely spec'd. In practice, this hasn't been a problem. Type checkers do "the obvious thing" when they encounter an `Any` base class. This can lead to false negatives, but that's generally true for `Any`. > > I think this is a case where it's more important to be pragmatic than to be technically correct. And I don't see any benefit to deprecating the use of `typing.Any` as a base class at runtime. > > Eric Traut > Contributor to pyright & pylance > _______________________________________________ > Typing-sig mailing list -- typing-sig@python.org > To unsubscribe send an email to typing-sig-leave@python.org > https://mail.python.org/mailman3/lists/typing-sig.python.org/ > Member address: tsudol@google.com
![](https://secure.gravatar.com/avatar/1edcf99e3b405ba3565952a194f79ca3.jpg?s=120&d=mm&r=g)
I agree that the problem of unresolvable bases (or an unresolvable metaclass) existed before the PR in question. I would be okay with type checkers handling that case differently, e.g. by emitting a static error or by marking the whole class as typing.Any or by doing something else. However, *explicitly* allowing typing.Any -- a non-class type -- in bases does not feel right. Surely, making the (already very complex) type system less predictable and less specified cannot be pragmatic? Sergei On Wed, Aug 2, 2023 at 5:20 PM Eric Traut <eric@traut.com> wrote:
Static type checkers already need to handle the case where the type of a base class cannot be determined statically and is therefore treated as `Any`. This can occur for many reasons including dynamic code, failure to resolve an import at static analysis time, etc. Disallowing an explicit `Any` from being used as a base class doesn't eliminate the problem.
I agree with your observation that this case isn't well spec'ed and creates potential inconsistencies in the type system. It also potentially leads to differences in behavior across type checkers, since the behavior isn't precisely spec'd. In practice, this hasn't been a problem. Type checkers do "the obvious thing" when they encounter an `Any` base class. This can lead to false negatives, but that's generally true for `Any`.
I think this is a case where it's more important to be pragmatic than to be technically correct. And I don't see any benefit to deprecating the use of `typing.Any` as a base class at runtime.
Eric Traut Contributor to pyright & pylance _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: sergei.a.lebedev@gmail.com
![](https://secure.gravatar.com/avatar/833c1ef94aebf738851577a5cb0b71e7.jpg?s=120&d=mm&r=g)
I agree, it doesn't feel right. In fact, I don't really know what it means to subclass `Any`; even if you don't subclass from `Any`, it's still type-matched against `Any`. What is the case for allowing it at all? On Wed, Aug 2, 2023, at 12:45, Sergei Lebedev wrote:
I agree that the problem of unresolvable bases (or an unresolvable metaclass) existed before the PR in question. I would be okay with type checkers handling that case differently, e.g. by emitting a static error or by marking the whole class as typing.Any or by doing something else.
However, *explicitly* allowing typing.Any -- a non-class type -- in bases does not feel right. Surely, making the (already very complex) type system less predictable and less specified cannot be pragmatic?
Sergei
On Wed, Aug 2, 2023 at 5:20 PM Eric Traut <eric@traut.com> wrote:
Static type checkers already need to handle the case where the type of a base class cannot be determined statically and is therefore treated as `Any`. This can occur for many reasons including dynamic code, failure to resolve an import at static analysis time, etc. Disallowing an explicit `Any` from being used as a base class doesn't eliminate the problem.
I agree with your observation that this case isn't well spec'ed and creates potential inconsistencies in the type system. It also potentially leads to differences in behavior across type checkers, since the behavior isn't precisely spec'd. In practice, this hasn't been a problem. Type checkers do "the obvious thing" when they encounter an `Any` base class. This can lead to false negatives, but that's generally true for `Any`.
I think this is a case where it's more important to be pragmatic than to be technically correct. And I don't see any benefit to deprecating the use of `typing.Any` as a base class at runtime.
Eric Traut Contributor to pyright & pylance _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: sergei.a.lebedev@gmail.com
Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: pbryan@anode.ca
![](https://secure.gravatar.com/avatar/1edcf99e3b405ba3565952a194f79ca3.jpg?s=120&d=mm&r=g)
What would be the best way to move forward, assuming there is consensus this change needs to be rolled back? On Wed, Aug 2, 2023 at 8:55 PM Paul Bryan <pbryan@anode.ca> wrote:
I agree, it doesn't feel right. In fact, I don't really know what it means to subclass `Any`; even if you don't subclass from `Any`, it's still type-matched against `Any`. What is the case for allowing it at all?
On Wed, Aug 2, 2023, at 12:45, Sergei Lebedev wrote:
I agree that the problem of unresolvable bases (or an unresolvable metaclass) existed before the PR in question. I would be okay with type checkers handling that case differently, e.g. by emitting a static error or by marking the whole class as typing.Any or by doing something else.
However, *explicitly* allowing typing.Any -- a non-class type -- in bases does not feel right. Surely, making the (already very complex) type system less predictable and less specified cannot be pragmatic?
Sergei
On Wed, Aug 2, 2023 at 5:20 PM Eric Traut <eric@traut.com> wrote:
Static type checkers already need to handle the case where the type of a base class cannot be determined statically and is therefore treated as `Any`. This can occur for many reasons including dynamic code, failure to resolve an import at static analysis time, etc. Disallowing an explicit `Any` from being used as a base class doesn't eliminate the problem.
I agree with your observation that this case isn't well spec'ed and creates potential inconsistencies in the type system. It also potentially leads to differences in behavior across type checkers, since the behavior isn't precisely spec'd. In practice, this hasn't been a problem. Type checkers do "the obvious thing" when they encounter an `Any` base class. This can lead to false negatives, but that's generally true for `Any`.
I think this is a case where it's more important to be pragmatic than to be technically correct. And I don't see any benefit to deprecating the use of `typing.Any` as a base class at runtime.
Eric Traut Contributor to pyright & pylance _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: sergei.a.lebedev@gmail.com
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: pbryan@anode.ca
![](https://secure.gravatar.com/avatar/3247bfd67c8fa4c4a08b8d30e49eab39.jpg?s=120&d=mm&r=g)
I don't think there is consensus. I don't think there has been a compelling argument made here. Just because something "doesn't feel right" to a few people doesn't mean that it should be changed. Deprecating functionality and breaking backward compatibility requires a solid justification, and I don't think anyone has presented one yet. As I pointed out above, type checkers already need to deal with the case where a base class is unknown (and therefore has an `Any` type). Disallowing `Any` as an explicit base class won't change that. If you feel that there's a need to standardize the behavior of type checkers when the type of a base class is unknown, then let's talk about what form that specification might take (e.g. PEP or official Python documentation). I personally don't think there's a strong need here because I don't recall any issue arising from this in the pyright or mypy issue trackers. If you are aware of any real problems caused by inconsistencies between type checkers in this regard, please let us know.
![](https://secure.gravatar.com/avatar/833c1ef94aebf738851577a5cb0b71e7.jpg?s=120&d=mm&r=g)
I had posed the questions: 1. What does subclassing `Any` even mean, given everything type matches `Any`? 2. Is there a valid use case for a subclass of `Any`? If neither of these can be reasonably answered, I certainly wouldn't feel bad about breaking backward compatibility with a nonsensical construct. On Sun, Aug 13, 2023, at 10:36, Eric Traut wrote:
I don't think there is consensus. I don't think there has been a compelling argument made here. Just because something "doesn't feel right" to a few people doesn't mean that it should be changed. Deprecating functionality and breaking backward compatibility requires a solid justification, and I don't think anyone has presented one yet.
As I pointed out above, type checkers already need to deal with the case where a base class is unknown (and therefore has an `Any` type). Disallowing `Any` as an explicit base class won't change that.
If you feel that there's a need to standardize the behavior of type checkers when the type of a base class is unknown, then let's talk about what form that specification might take (e.g. PEP or official Python documentation). I personally don't think there's a strong need here because I don't recall any issue arising from this in the pyright or mypy issue trackers. If you are aware of any real problems caused by inconsistencies between type checkers in this regard, please let us know. _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: pbryan@anode.ca
![](https://secure.gravatar.com/avatar/99e65149f8ee94c66958818c2a51106c.jpg?s=120&d=mm&r=g)
I agree with everything Eric Traut has said so far in this thread.In particular, "it doesn't feel right" isn't a strong enough justification for a deprecation period that could force people to change existing, working code just to avoid deprecation warnings at runtime. Since this is now established behaviour in Python 3.11 (and it's much too late to change it in Python 3.12), you don't just need to explain why you disagree with the previous change — you need to justify this change in behaviour independently, as a change in its own right. See PEP 387 for the full details on CPython's backwards-compatibility policy at runtime.I also still don't understand why "I have quibbles with the fact that static type checkers allow `Any` to be subclassed" has really any bearing on whether we allow it to be subclassed at runtime. We made the runtime change because all major static type checkers allow `Any` to be subclassed at "typing time", and it's best to avoid inconsistencies between runtime and typing time where possible. But that doesn't force any type checker to permit `Any` to be subclassed at typing time. Most major type checkers still provide an option which, when enabled, means they will emit an error when `Any` is subclassed. It's best for the runtime behaviour to be no more restrictive than static type checkers, but the reverse doesn't hold — there are many situations in which things are allowed at runtime but banned by type checkers, and that's perfectly fine.Lastly — yes, strictly speaking, behaviour specified in a PEP should usually not be changed unless a new PEP has been written and accepted, and the new PEP specifies that the behaviour should be changed. If you like, I _suppose_ you could bring this to the attention of the Python Steering Council, who have the power to demand that the change be reverted if they feel like the proper process wasn't followed. However, this honestly seems like a pretty minor detail of PEP 484, and the proposed change was advertised on this mailing list before being made, in order to check whether anybody disagreed with the change. (Nobody did.) I think it's unlikely that the Steering Council would be sympathetic to your case, especially since it's been a while since the change was made.Best,Alex -------- Original message --------From: Paul Bryan <pbryan@anode.ca> Date: 13/08/2023 18:57 (GMT+00:00) To: typing-sig@python.org Subject: [Typing-sig] Re: typing.Any subclasses I had posed the questions:1. What does subclassing `Any` even mean, given everything type matches `Any`?2. Is there a valid use case for a subclass of `Any`?If neither of these can be reasonably answered, I certainly wouldn't feel bad about breaking backward compatibility with a nonsensical construct.On Sun, Aug 13, 2023, at 10:36, Eric Traut wrote:I don't think there is consensus. I don't think there has been a compelling argument made here. Just because something "doesn't feel right" to a few people doesn't mean that it should be changed. Deprecating functionality and breaking backward compatibility requires a solid justification, and I don't think anyone has presented one yet.As I pointed out above, type checkers already need to deal with the case where a base class is unknown (and therefore has an `Any` type). Disallowing `Any` as an explicit base class won't change that.If you feel that there's a need to standardize the behavior of type checkers when the type of a base class is unknown, then let's talk about what form that specification might take (e.g. PEP or official Python documentation). I personally don't think there's a strong need here because I don't recall any issue arising from this in the pyright or mypy issue trackers. If you are aware of any real problems caused by inconsistencies between type checkers in this regard, please let us know._______________________________________________Typing-sig mailing list -- typing-sig@python.orgTo unsubscribe send an email to typing-sig-leave@python.orghttps://mail.python.org/mailman3/lists/typing-sig.python.org/Member address: pbryan@anode.ca
![](https://secure.gravatar.com/avatar/7b5bbadd9baf9c6b33a053e9687ce97e.jpg?s=120&d=mm&r=g)
There isn't consensus. I just haven't chimed in because Eric has said everything I would want to say. On use cases: We've used subclassing of Any as a way to type Mock's in typeshed for basically forever. This is mentioned in Python 3.11's What's New, the original typing-sig thread and discussed at PyCon US 2022. I've used this for a very dynamic parametrisation situation, where I had specific objects that I wanted to be able to duck type as anything (while ideally preserving its extra methods). I've also used it as a way to more easily duck type through an incorrectly strictly typed interface that I couldn't change. I remember recommending this to people on gitter.im / stackoverflow, but I don't remember the specifics of their use cases, possibly something something metaclass. Paul, I'll also say that when proposing a revert, coming at the question with the assumption that "neither of these can be reasonably answered" is maybe not the best approach. It feels very Cunningham's Law. On the process to make the original change: Given that all major type checkers already supported it, typeshed already used it since antiquity, no concerns were raised on the typing-sig thread, it made syntax in pyi usable in py (without hacks), this wasn't a controversial change. On interpretation: Eric's already mentioned how it should be interpreted, but since you asked again: type checkers should treat subclassing of Any the same way they would subclassing of an unknown symbol. This typically looks something like the example below, but semantics here haven't been standardised, so a type checker could choose to approach this differently: ``` from unknown import anybaseclass class X(anybaseclass): def foo(self) -> int: ... reveal_type(X().foo()) # reveals int reveal_type(X().bar()) # reveals Any class A: ... def takes_A(a: A): ... takes_A(X()) # okay ``` On how to revert: The onus is on you to prove why this should be reverted (the default position is that features do not get reverted). Arguments that I think could lead to a revert are showing why this breaks the type system or is an unreasonable lift for type checkers. I think it will be hard to make those arguments, since this was already part of our gradual type system, and all type checkers already had to have behaviour to handle it. On Sun, 13 Aug 2023 at 11:09, Alex Waygood <alex.waygood@gmail.com> wrote:
I agree with everything Eric Traut has said so far in this thread.
In particular, "it doesn't feel right" isn't a strong enough justification for a deprecation period that could force people to change existing, working code just to avoid deprecation warnings at runtime. Since this is now established behaviour in Python 3.11 (and it's much too late to change it in Python 3.12), you don't just need to explain why you disagree with the previous change — you need to justify this change in behaviour independently, as a change in its own right. See PEP 387 for the full details on CPython's backwards-compatibility policy at runtime.
I also still don't understand why "I have quibbles with the fact that static type checkers allow `Any` to be subclassed" has really any bearing on whether we allow it to be subclassed at runtime. We made the runtime change because all major static type checkers allow `Any` to be subclassed at "typing time", and it's best to avoid inconsistencies between runtime and typing time where possible. But that doesn't *force* any type checker to permit `Any` to be subclassed at typing time. Most major type checkers still provide an option which, when enabled, means they will emit an error when `Any` is subclassed. It's best for the runtime behaviour to be no more restrictive than static type checkers, but the reverse doesn't hold — there are many situations in which things are allowed at runtime but banned by type checkers, and that's perfectly fine.
Lastly — yes, strictly speaking, behaviour specified in a PEP should usually not be changed unless a new PEP has been written and accepted, and the new PEP specifies that the behaviour should be changed. If you like, I _suppose_ you could bring this to the attention of the Python Steering Council, who have the power to demand that the change be reverted if they feel like the proper process wasn't followed. However, this honestly seems like a pretty minor detail of PEP 484, and the proposed change was advertised on this mailing list before being made, in order to check whether anybody disagreed with the change. (Nobody did.) I think it's unlikely that the Steering Council would be sympathetic to your case, especially since it's been a while since the change was made.
Best, Alex
-------- Original message -------- From: Paul Bryan <pbryan@anode.ca> Date: 13/08/2023 18:57 (GMT+00:00) To: typing-sig@python.org Subject: [Typing-sig] Re: typing.Any subclasses
I had posed the questions:
1. What does subclassing `Any` even mean, given everything type matches `Any`? 2. Is there a valid use case for a subclass of `Any`?
If neither of these can be reasonably answered, I certainly wouldn't feel bad about breaking backward compatibility with a nonsensical construct.
On Sun, Aug 13, 2023, at 10:36, Eric Traut wrote:
I don't think there is consensus. I don't think there has been a compelling argument made here. Just because something "doesn't feel right" to a few people doesn't mean that it should be changed. Deprecating functionality and breaking backward compatibility requires a solid justification, and I don't think anyone has presented one yet.
As I pointed out above, type checkers already need to deal with the case where a base class is unknown (and therefore has an `Any` type). Disallowing `Any` as an explicit base class won't change that.
If you feel that there's a need to standardize the behavior of type checkers when the type of a base class is unknown, then let's talk about what form that specification might take (e.g. PEP or official Python documentation). I personally don't think there's a strong need here because I don't recall any issue arising from this in the pyright or mypy issue trackers. If you are aware of any real problems caused by inconsistencies between type checkers in this regard, please let us know. _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: pbryan@anode.ca
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: hauntsaninja@gmail.com
![](https://secure.gravatar.com/avatar/1edcf99e3b405ba3565952a194f79ca3.jpg?s=120&d=mm&r=g)
typing.Any subclasses are allowed at runtime, but they are not part of
typing.Any subclasses should be treated in the same way as classes with a
Hi everyone, Very happy to see the thread being alive again. Thank you all for sharing your thoughts. I agree with Eric that deprecating existing functionality should not be done without a compelling reason. However, from my point of view, the same principle should apply to *all* changes and not just deprecations. So, I think it is important to specify the static behavior of typing.Any subclasses and accept the extra complexity it brings, if deprecation isn't an option. For example, we could agree that the static Python type system and thus static type checkers are free to reject such code. or that base which fails to resolve as suggested by multiple people on this thread. Note that this option requires us to also describe - how unresolved bases are represented in the type system – Eric suggested using typing.Any; - how these are treated in subtyping; - how to type check e.g. attribute lookups on such classes and their instances; - how they interact with various special forms: typing.TypedDict, typing.Protocol, typing.dataclass_transform etc. At the moment, the static behavior is completely unspecified, and if I were to implement a new type checker, it is unclear how it should treat typing.Any subclasses. I could of course copy whatever mypy or pyright is doing, but I would much rather have this documented either in the typing module docs or in the form of a PEP (if it is possible to write one retroactively). On why this is not a purely runtime change: in my experience people often use runtime behavior to build intuition about the static type system. Thus, by allowing typing.Any to be subclassed at runtime we hint to users that this could also be accepted by static type checkers. Moreover, if this works at runtime, people *will* write the code subclassing typing.Any, and type checkers *will* need to make sense of it. Sergei On Sun, Aug 13, 2023 at 8:17 PM Shantanu Jain <hauntsaninja@gmail.com> wrote:
There isn't consensus. I just haven't chimed in because Eric has said everything I would want to say.
On use cases: We've used subclassing of Any as a way to type Mock's in typeshed for basically forever. This is mentioned in Python 3.11's What's New, the original typing-sig thread and discussed at PyCon US 2022. I've used this for a very dynamic parametrisation situation, where I had specific objects that I wanted to be able to duck type as anything (while ideally preserving its extra methods). I've also used it as a way to more easily duck type through an incorrectly strictly typed interface that I couldn't change. I remember recommending this to people on gitter.im / stackoverflow, but I don't remember the specifics of their use cases, possibly something something metaclass.
Paul, I'll also say that when proposing a revert, coming at the question with the assumption that "neither of these can be reasonably answered" is maybe not the best approach. It feels very Cunningham's Law.
On the process to make the original change: Given that all major type checkers already supported it, typeshed already used it since antiquity, no concerns were raised on the typing-sig thread, it made syntax in pyi usable in py (without hacks), this wasn't a controversial change.
On interpretation: Eric's already mentioned how it should be interpreted, but since you asked again: type checkers should treat subclassing of Any the same way they would subclassing of an unknown symbol. This typically looks something like the example below, but semantics here haven't been standardised, so a type checker could choose to approach this differently: ``` from unknown import anybaseclass
class X(anybaseclass): def foo(self) -> int: ...
reveal_type(X().foo()) # reveals int reveal_type(X().bar()) # reveals Any
class A: ...
def takes_A(a: A): ... takes_A(X()) # okay ```
On how to revert: The onus is on you to prove why this should be reverted (the default position is that features do not get reverted). Arguments that I think could lead to a revert are showing why this breaks the type system or is an unreasonable lift for type checkers. I think it will be hard to make those arguments, since this was already part of our gradual type system, and all type checkers already had to have behaviour to handle it.
On Sun, 13 Aug 2023 at 11:09, Alex Waygood <alex.waygood@gmail.com> wrote:
I agree with everything Eric Traut has said so far in this thread.
In particular, "it doesn't feel right" isn't a strong enough justification for a deprecation period that could force people to change existing, working code just to avoid deprecation warnings at runtime. Since this is now established behaviour in Python 3.11 (and it's much too late to change it in Python 3.12), you don't just need to explain why you disagree with the previous change — you need to justify this change in behaviour independently, as a change in its own right. See PEP 387 for the full details on CPython's backwards-compatibility policy at runtime.
I also still don't understand why "I have quibbles with the fact that static type checkers allow `Any` to be subclassed" has really any bearing on whether we allow it to be subclassed at runtime. We made the runtime change because all major static type checkers allow `Any` to be subclassed at "typing time", and it's best to avoid inconsistencies between runtime and typing time where possible. But that doesn't *force* any type checker to permit `Any` to be subclassed at typing time. Most major type checkers still provide an option which, when enabled, means they will emit an error when `Any` is subclassed. It's best for the runtime behaviour to be no more restrictive than static type checkers, but the reverse doesn't hold — there are many situations in which things are allowed at runtime but banned by type checkers, and that's perfectly fine.
Lastly — yes, strictly speaking, behaviour specified in a PEP should usually not be changed unless a new PEP has been written and accepted, and the new PEP specifies that the behaviour should be changed. If you like, I _suppose_ you could bring this to the attention of the Python Steering Council, who have the power to demand that the change be reverted if they feel like the proper process wasn't followed. However, this honestly seems like a pretty minor detail of PEP 484, and the proposed change was advertised on this mailing list before being made, in order to check whether anybody disagreed with the change. (Nobody did.) I think it's unlikely that the Steering Council would be sympathetic to your case, especially since it's been a while since the change was made.
Best, Alex
-------- Original message -------- From: Paul Bryan <pbryan@anode.ca> Date: 13/08/2023 18:57 (GMT+00:00) To: typing-sig@python.org Subject: [Typing-sig] Re: typing.Any subclasses
I had posed the questions:
1. What does subclassing `Any` even mean, given everything type matches `Any`? 2. Is there a valid use case for a subclass of `Any`?
If neither of these can be reasonably answered, I certainly wouldn't feel bad about breaking backward compatibility with a nonsensical construct.
On Sun, Aug 13, 2023, at 10:36, Eric Traut wrote:
I don't think there is consensus. I don't think there has been a compelling argument made here. Just because something "doesn't feel right" to a few people doesn't mean that it should be changed. Deprecating functionality and breaking backward compatibility requires a solid justification, and I don't think anyone has presented one yet.
As I pointed out above, type checkers already need to deal with the case where a base class is unknown (and therefore has an `Any` type). Disallowing `Any` as an explicit base class won't change that.
If you feel that there's a need to standardize the behavior of type checkers when the type of a base class is unknown, then let's talk about what form that specification might take (e.g. PEP or official Python documentation). I personally don't think there's a strong need here because I don't recall any issue arising from this in the pyright or mypy issue trackers. If you are aware of any real problems caused by inconsistencies between type checkers in this regard, please let us know. _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: pbryan@anode.ca
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: hauntsaninja@gmail.com
_______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: sergei.a.lebedev@gmail.com
participants (6)
-
Alex Waygood
-
Eric Traut
-
Paul Bryan
-
Sergei Lebedev
-
Shantanu Jain
-
Teddy Sudol