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
{{ message }}
Repository navigation
Python 3.11.9 catches all exceptions raised in Generic.__setattr__("__orig_class__", type_parameter) #117744
In Python 3.11.9, the following code does not raise an Exception:
fromtypingimportAny, Generic, TypeVarT=TypeVar("T")
classDataSet(Generic[T]):
def__setattr__(self, name: str, value: Any) ->None:
object.__setattr__(self, name, value)
ifname=="__orig_class__":
raiseException("Just randomly raising an exception for illustrative purposes.")
classSchema:
pass# initializing an object with type parameter `Schema` will call # `__setattr__("__orig_class__", (Schema,))`df=DataSet[Schema]()
In other versions of Python (e.g. 3.11.8 or 3.12.2) this raises an Exception, but in Python 3.11.9 it appears this Exception is caught.
I use something similar to the above logic in typedspark to check whether the DataSet follows the schema specified in Schema, and I raise an Exception if it doesn't. As of Python 3.11.9, these exceptions are caught, hence breaking my logic.
__orig_class__ itself is semi-documented state. It's documented in PEP but as internal typing implementation detail. A public api to retrieve them did get added here, but I think setting/modifying them remains internal behavior/undocumented on whether it should work.
Also from motivation of that PR I don't see a reasonable way to revert that pr without breaking original issue it was intended for. So I'd discourage relying on modifying __orig_class__ or if you do accepting that it's unstable and may change rules.
edit: I misremembered PEP 560. __orig_bases__ is mentioned in PEP with typing internal motivation. __orig_class__ I'm unsure if it is mentioned at all in any public documentation/pep.
orig_class itself is semi-documented state. It's documented in PEP but as internal typing implementation detail. A public api to retrieve them did get added #101688, but I think setting/modifying them remains internal behavior/undocumented on whether it should work.
RIght, I appreciate that __orig_class__ is an internal typing implementation detail and hence I cannot trust its interface to remain stable. That said...
Also from motivation of that PR I don't see a reasonable way to revert that pr without breaking original issue it was intended for.
Catching all Exceptions seems a bit extreme to me. Why not catch TypeError and AttributeError specifically? That would solve the original issue, right?
Tweaking the set of exceptions caught is bound to cause more bugs in the future, if someone has a buggy __setattr__ that raises an unexpected exception.
My inclination is to close this as "won't fix", and decide that your use case is unsupported.
Why not catch TypeError and AttributeError specifically?
Honestly, I think the only reasonable exception for people to raise in __setattr__ methods, property setters and similar is AttributeError. Which would imply that we should only catch AttributeError when setting __orig_class__ (the behaviour we had prior to #115213). But in the "real world", there's lots of "unreasonable" code out there -- it's sadly pretty common for people to raise all sorts of exceptions from __setattr__ methods.
Note that although #115165 was only reported regarding typing.Annotated, the actual bug there affected all generic aliases, such that code like this would raise RuntimeError:
Activity
aisk commentedon Apr 11, 2024
I'm using Windows, and found that Python 3.12.3 and current main branch (02f1385) doesn't raise the exception too.
nanne-aben commentedon Apr 11, 2024
It looks like this behavior was introduced in this PR, corresponding to this ticket.
hmc-cs-mdrissi commentedon Apr 11, 2024
__orig_class__itself is semi-documented state. It's documented in PEP but as internal typing implementation detail. A public api to retrieve them did get added here, but I think setting/modifying them remains internal behavior/undocumented on whether it should work.Also from motivation of that PR I don't see a reasonable way to revert that pr without breaking original issue it was intended for. So I'd discourage relying on modifying
__orig_class__or if you do accepting that it's unstable and may change rules.edit: I misremembered PEP 560.
__orig_bases__is mentioned in PEP with typing internal motivation.__orig_class__I'm unsure if it is mentioned at all in any public documentation/pep.nanne-aben commentedon Apr 12, 2024
Thank you for your reply!
RIght, I appreciate that
__orig_class__is an internal typing implementation detail and hence I cannot trust its interface to remain stable. That said...Catching all
Exceptionsseems a bit extreme to me. Why not catchTypeErrorandAttributeErrorspecifically? That would solve the original issue, right?JelleZijlstra commentedon Apr 12, 2024
Tweaking the set of exceptions caught is bound to cause more bugs in the future, if someone has a buggy
__setattr__that raises an unexpected exception.My inclination is to close this as "won't fix", and decide that your use case is unsupported.
AlexWaygood commentedon Apr 12, 2024
Honestly, I think the only reasonable exception for people to raise in
__setattr__methods, property setters and similar isAttributeError. Which would imply that we should only catchAttributeErrorwhen setting__orig_class__(the behaviour we had prior to #115213). But in the "real world", there's lots of "unreasonable" code out there -- it's sadly pretty common for people to raise all sorts of exceptions from__setattr__methods.Note that although #115165 was only reported regarding
typing.Annotated, the actual bug there affected all generic aliases, such that code like this would raiseRuntimeError:That feels like really surprising behaviour to me; I think it would be unacceptable to go back to that.
I agree with @JelleZijlstra here; I think we have to close this as "won't fix".
nanne-aben commentedon Apr 12, 2024
Alright, got it! Think I might have found a way to resolve this without relying on
__orig_class__too, which is probably for the best.Thanks for you time and feedback!
AlexWaygood commentedon Apr 12, 2024
No problem -- thanks for the well-written bug report @nanne-aben!