Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typing.Annotated fails for functions returning UUIDs #115165

Closed
dave-shawley opened this issue Feb 8, 2024 · 2 comments
Closed

typing.Annotated fails for functions returning UUIDs #115165

dave-shawley opened this issue Feb 8, 2024 · 2 comments
Labels
stdlib Python modules in the Lib dir topic-typing type-bug An unexpected behavior, bug, or error

Comments

@dave-shawley
Copy link
Contributor

dave-shawley commented Feb 8, 2024

Bug report

Bug description:

typing.Annotated tries to set an attribute on the return value of calling an annotated callable. This fails when the returned object is immutable. I believe that adding TypeError to the except clause in typing. _BaseGenericAlias.__call__ will fix the problem. I'm not sure if there are more cases of the same pattern or not.

cpython/Lib/typing.py

Lines 1128 to 1131 in 17689e3

try:
result.__orig_class__ = self
except AttributeError:
pass

Example

import typing
import uuid

class MyAnnotation:
    def __init__(self, **properties) -> None:
        self.properties = properties

def uuid_from_str(s: str) -> uuid.UUID:
    return uuid.UUID(f'urn:uuid:{s}')

coercion = typing.Annotated[uuid_from_str, MyAnnotation(type='str', format='uuid')]
coercion('00000000-0000-0000-0000-000000000000')

Result

Traceback (most recent call last):
  File "/Users/.../foo.py", line 12, in <module>
    coercion('00000000-0000-0000-0000-000000000000')
  File "/Users/.../lib/python3.12/typing.py", line 1142, in __call__
    result.__orig_class__ = self
    ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/.../lib/python3.12/uuid.py", line 278, in __setattr__
    raise TypeError('UUID objects are immutable')
TypeError: UUID objects are immutable

CPython versions tested on:

3.9, 3.10, 3.11, 3.12

Operating systems tested on:

macOS

Linked PRs

@dave-shawley dave-shawley added the type-bug An unexpected behavior, bug, or error label Feb 8, 2024
@AlexWaygood
Copy link
Member

AlexWaygood commented Feb 8, 2024

Thanks for the report!

Arguably there are two bugs here:

  1. Why is the uuid module raising TypeError from a __setattr__ method? That seems like an antipattern; it should probably be raising AttributeError. We probably can't change that now, though, for backwards-compatibility reasons
  2. Yes, the typing module should indeed be more careful here. Feel free to send a PR — I think except Exception might actually be better here than just adding TypeError to the except clause. Otherwise we'll just get this bug reported again when somebody tries to use Annotated with a class that raises e.g. RuntimeError (or whatever) from its __setattr__ method

@AlexWaygood AlexWaygood added the stdlib Python modules in the Lib dir label Feb 8, 2024
dave-shawley added a commit to dave-shawley/cpython that referenced this issue Feb 9, 2024
dave-shawley added a commit to dave-shawley/cpython that referenced this issue Feb 9, 2024
Add comment justifying `except Exception`
dave-shawley added a commit to dave-shawley/cpython that referenced this issue Feb 9, 2024
Renamed test_annotated_callable_returning_immutable to
test_instantiate_immutable and moved it near the other instantiation
tests.
dave-shawley added a commit to dave-shawley/cpython that referenced this issue Feb 9, 2024
Add a test for generic instantiation that trips the same __setattr__
exception in Annotation.
AlexWaygood pushed a commit that referenced this issue Feb 9, 2024
The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Feb 9, 2024
…-115213)

The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
(cherry picked from commit 5643856)

Co-authored-by: dave-shawley <daveshawley@gmail.com>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Feb 9, 2024
…-115213)

The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
(cherry picked from commit 5643856)

Co-authored-by: dave-shawley <daveshawley@gmail.com>
AlexWaygood pushed a commit that referenced this issue Feb 9, 2024
…) (#115227)

gh-115165: Fix `typing.Annotated` for immutable types (GH-115213)

The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
(cherry picked from commit 5643856)

Co-authored-by: dave-shawley <daveshawley@gmail.com>
AlexWaygood pushed a commit that referenced this issue Feb 9, 2024
…) (#115228)

gh-115165: Fix `typing.Annotated` for immutable types (GH-115213)

The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
(cherry picked from commit 5643856)

Co-authored-by: dave-shawley <daveshawley@gmail.com>
@AlexWaygood
Copy link
Member

Thanks for the report, and the fix!

fsc-eriker pushed a commit to fsc-eriker/cpython that referenced this issue Feb 14, 2024
…15213)

The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
AlexWaygood pushed a commit to AlexWaygood/cpython that referenced this issue Feb 22, 2024
The return value from an annotated callable can raise any exception from
__setattr__ for the `__orig_class__` property.
dave-shawley added a commit to dave-shawley/pydantic-tornado that referenced this issue Apr 1, 2024
Note that `typing.Annotated[uuid.UUID, ...]` doesn't work currently
so I created a helper class `routing._UUID` that works around the
defect. This will be fixed in 3.12.3 when it is released. I added an
ignore statement for `ruff check` to allow access to internal names
inside of tests. Otherwise testing `_UUID` required too many `noqa`
comment directives for me.

python/cpython#115165
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir topic-typing type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants