Skip to content

Commit

Permalink
Fixed signature check raising ValueError for a built-in function
Browse files Browse the repository at this point in the history
Fixes #504.
  • Loading branch information
agronholm committed Feb 16, 2025
1 parent 8559911 commit 056a9a8
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 1 deletion.
3 changes: 3 additions & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ This library adheres to
(`#492 <https://github.com/agronholm/typeguard/pull/492>`_; PR by @JelleZijlstra)
- Fixed ``TypeError`` when using an assignment expression
(`#510 <https://github.com/agronholm/typeguard/issues/510>`_; PR by @JohannesK71083)
- Fixed ``ValueError: no signature found for builtin`` when checking against a protocol
and a matching attribute in the subject is a built-in function
(`#504 <https://github.com/agronholm/typeguard/issues/504>`_)

**4.4.1** (2024-11-03)

Expand Down
7 changes: 6 additions & 1 deletion src/typeguard/_checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,12 @@ def check_io(


def check_signature_compatible(subject: type, protocol: type, attrname: str) -> None:
subject_sig = inspect.signature(getattr(subject, attrname))
subject_attr = getattr(subject, attrname)
try:
subject_sig = inspect.signature(subject_attr)
except ValueError:
return # this can happen with builtins where the signature cannot be retrieved

protocol_sig = inspect.signature(getattr(protocol, attrname))
protocol_type: typing.Literal["instance", "class", "static"] = "instance"
subject_type: typing.Literal["instance", "class", "static"] = "instance"
Expand Down
13 changes: 13 additions & 0 deletions tests/test_checkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sys
import types
from contextlib import nullcontext
from datetime import timedelta
from functools import partial
from io import BytesIO, StringIO
from pathlib import Path
Expand Down Expand Up @@ -1383,6 +1384,18 @@ def meth(self) -> None:
f"be a class method but it's an instance method"
)

def test_builtin_signature_check(self) -> None:
class MyProtocol(Protocol):
def attr(self) -> None:
pass

class Foo:
attr = timedelta

# Foo.attr is incompatible but timedelta has not inspectable signature so the
# check is skipped
check_type(Foo(), MyProtocol)


class TestRecursiveType:
def test_valid(self):
Expand Down

0 comments on commit 056a9a8

Please sign in to comment.