Skip to content

Commit

Permalink
Fixed wrong self_type being assigned to the memo in the __new__() m…
Browse files Browse the repository at this point in the history
…ethod
  • Loading branch information
agronholm committed Apr 30, 2023
1 parent fc673d4 commit b57a536
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This library adheres to `Semantic Versioning 2.0 <https://semver.org/#semantic-v
- Fixed ``TypeError: isinstance() arg 2 must be a type or tuple of types`` when
instrumented code tries to check a value against a naked (``str``, not ``ForwardRef``)
forward reference
- Fixed instrumentation using the wrong "self" type in the ``__new__()`` method

**4.0.0rc4** (2023-04-15)

Expand Down
15 changes: 10 additions & 5 deletions src/typeguard/_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,11 +795,16 @@ def visit_FunctionDef(
break
else:
if node.args.args:
memo_kwargs["self_type"] = Attribute(
Name(id=node.args.args[0].arg, ctx=Load()),
"__class__",
ctx=Load(),
)
if node.name == "__new__":
memo_kwargs["self_type"] = Name(
id=node.args.args[0].arg, ctx=Load()
)
else:
memo_kwargs["self_type"] = Attribute(
Name(id=node.args.args[0].arg, ctx=Load()),
"__class__",
ctx=Load(),
)

# Construct the function reference
# Nested functions get special treatment: the function name is added
Expand Down
32 changes: 32 additions & 0 deletions tests/test_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,38 @@ def foo(x: int) -> int:
)


def test_new() -> None:
node = parse(
dedent(
"""
from typing import Self
class Foo:
def __new__(cls) -> Self:
return super().__new__(cls)
"""
)
)
TypeguardTransformer().visit(node)
assert (
unparse(node)
== dedent(
"""
from typeguard import TypeCheckMemo
from typeguard._functions import check_return_type
from typing import Self
class Foo:
def __new__(cls) -> Self:
memo = TypeCheckMemo(globals(), locals(), self_type=cls)
return check_return_type('Foo.__new__', super().__new__(cls), \
Self, memo)
"""
).strip()
)


def test_local_function() -> None:
node = parse(
dedent(
Expand Down

0 comments on commit b57a536

Please sign in to comment.