Run-time type checker for Python

Overview
Build Status Code Coverage https://readthedocs.org/projects/typeguard/badge/?version=latest

This library provides run-time type checking for functions defined with PEP 484 argument (and return) type annotations.

Four principal ways to do type checking are provided, each with its pros and cons:

  1. the check_argument_types() and check_return_type() functions:
    • debugger friendly (except when running with the pydev debugger with the C extension installed)
    • does not work reliably with dynamically defined type hints (e.g. in nested functions)
  2. the @typechecked decorator:
    • automatically type checks yields and sends of returned generators (regular and async)
    • adds an extra frame to the call stack for every call to a decorated function
  3. the stack profiler hook (with TypeChecker('packagename'):) (deprecated):
    • emits warnings instead of raising TypeError
    • requires very few modifications to the code
    • multiple TypeCheckers can be stacked/nested
    • does not work reliably with dynamically defined type hints (e.g. in nested functions)
    • may cause problems with badly behaving debuggers or profilers
    • cannot distinguish between an exception being raised and a None being returned
  4. the import hook (typeguard.importhook.install_import_hook()):
    • automatically annotates classes and functions with @typechecked on import
    • no code changes required in target modules
    • requires imports of modules you need to check to be deferred until after the import hook has been installed
    • may clash with other import hooks

See the documentation for further instructions.

Comments
  • Modify check_type to work without memo

    Modify check_type to work without memo

    In my project I would like to check arbitrary object against PEP 484 definition. check_type seems to be what I need, but it requires a memo object which I do not have in my use case.

    opened by Kentzo 39
  • Quoted annotations do not work in cyclic imports

    Quoted annotations do not work in cyclic imports

    Python usually doesn't allow cyclic imports, but they're sometimes necessary for proper static type annotations. When that is the case, the cyclic import is guarded by if TYPE_CHECKING: and annotations for types imported from such a module are quoted like strings to avoid errors at runtime. That's a standard practice recommended by mypy developers.

    However, any program that uses this approach to annotations seems incompatible with typeguard. Consider this example:

    A.py:

    from typeguard import TypeChecker
    
    from B import B
    
    class A:
        def f(self, b: B) -> None:
            b.f(self)
    
    with TypeChecker(('__main__', 'A', 'B')):
        A().f(B())
    

    B.py:

    from typing import TYPE_CHECKING
    
    if TYPE_CHECKING:
        from A import A
    
    class B:
        def f(self, a: 'A') -> None:
            print("OK")
    

    If typeguard is disabled, the program performs fairly well as it is in fact absolutely correct in runtime, and also correct from mypy point of view:

    $ mypy A.py B.py
    $ python3 A.py 
    OK
    

    However if it is run with typeguard, the following fatal exception occurs:

    $ python3 A.py 
    /usr/local/lib/python3.6/dist-packages/typeguard/__init__.py:657: UserWarning: the system profiling hook has changed unexpectedly
      warn('the system profiling hook has changed unexpectedly')
    Traceback (most recent call last):
      File "A.py", line 10, in <module>
        A().f(B())
      File "A.py", line 7, in f
        b.f(self)
      File "/home/vmz/git/userfe/B.py", line 7, in f
        def f(self, a: 'A') -> None:
      File "/usr/local/lib/python3.6/dist-packages/typeguard/__init__.py", line 690, in __call__
        memo = self._call_memos[frame] = _CallMemo(func, frame)
      File "/usr/local/lib/python3.6/dist-packages/typeguard/__init__.py", line 55, in __init__
        hints = get_type_hints(func)
      File "/usr/lib/python3.6/typing.py", line 1543, in get_type_hints
        value = _eval_type(value, globalns, localns)
      File "/usr/lib/python3.6/typing.py", line 350, in _eval_type
        return t._eval_type(globalns, localns)
      File "/usr/lib/python3.6/typing.py", line 245, in _eval_type
        eval(self.__forward_code__, globalns, localns),
      File "<string>", line 1, in <module>
    NameError: name 'A' is not defined
    
    opened by jolaf 37
  • Add ability to override typeguard default checks

    Add ability to override typeguard default checks

    This PR is related to the question here: https://github.com/agronholm/typeguard/issues/184

    After following the path of adding Union[int, np.int64] everywhere, which fixed the problem with typeguard, now I have 30 issues with mypy because np.int64 behaves as an int (so it can be passed to range for example) but mypy will complain if a variable which is typed Union[int, np.int64] is passed to range.

    This PR allows the user to provide a function that, for example, makes typeguard treat np.int64 as int.

    [x] added function register_override [x] added tests [x] extended docs

    opened by luk-f-a 21
  • Test failures with 2.11.1

    Test failures with 2.11.1

    This is also reproduceable for me on 2.11.0 but not on 2.10.0

    This is when running the test suite with python -m pytest

    ==================================== ERRORS ==================================== __________________ ERROR collecting tests/test_importhook.py ___________________ ImportError while importing test module '/builddir/build/BUILD/typeguard-2.11.1/tests/test_importhook.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: /usr/lib64/python3.9/importlib/init.py:127: in import_module return _bootstrap._gcd_import(name[level:], package, level) tests/test_importhook.py:9: in from typeguard.importhook import TypeguardFinder, install_import_hook E ModuleNotFoundError: No module named 'typeguard' ___________________ ERROR collecting tests/test_typeguard.py ___________________ ImportError while importing test module '/builddir/build/BUILD/typeguard-2.11.1/tests/test_typeguard.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: /usr/lib64/python3.9/importlib/init.py:127: in import_module return _bootstrap._gcd_import(name[level:], package, level) tests/test_typeguard.py:16: in from typeguard import ( E ModuleNotFoundError: No module named 'typeguard' ________________ ERROR collecting tests/test_typeguard_py36.py _________________ ImportError while importing test module '/builddir/build/BUILD/typeguard-2.11.1/tests/test_typeguard_py36.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: /usr/lib64/python3.9/importlib/init.py:127: in import_module return _bootstrap._gcd_import(name[level:], package, level) tests/test_typeguard_py36.py:7: in from typeguard import TypeChecker, typechecked E ModuleNotFoundError: No module named 'typeguard' !!!!!!!!!!!!!!!!!!! Interrupted: 3 errors during collection !!!!!!!!!!!!!!!!!!!! ============================== 3 errors in 0.24s ===============================

    opened by snecklifter 20
  • question: use to check type compatibility?

    question: use to check type compatibility?

    I am writing a distributed execution system, in which messages are sent among task nodes implemented by python functions. Before they are run, the flow graph is "compiled". During this step, I would like to check types of messages.

    I can get the type annotation of a message from both sender and receiver, and am searching for a way to check if these two types are compatible with one another. (In particular, if a message created by the sender will be of the type expected by the receiver, if the sender respects the type annotation.) Can I do this with typeguard? An example or pointer to the docs would be much appreciated if it is possible. If not, any suggestions as to another package that can help me?

    question 
    opened by shaunc 20
  • Fill missing type hints

    Fill missing type hints

    Closes: #240

    typeguard.typechecking is too complex to annotate correctly. So please tell me your advice, or annotate it instead of me.

    $ mypy src
    src/typeguard/__init__.py:1133: error: Function is missing a return type
    annotation  [no-untyped-def]
        def typechecked(func=None, *, always=False, _localns: Optional[Dict[st...
        ^
    src/typeguard/__init__.py:1133: error: Function is missing a type annotation
    for one or more arguments  [no-untyped-def]
        def typechecked(func=None, *, always=False, _localns: Optional[Dict[st...
        ^
    src/typeguard/__init__.py:1164: error: No overload variant of "typechecked"
    matches argument types "Union[FunctionType, MethodType, Type[Any]]", "Any",
    "Dict[str, Any]"  [call-overload]
                                typechecked(attr, always=always, _localns=func...
                                ^
    src/typeguard/__init__.py:1164: note: Possible overload variants:
    src/typeguard/__init__.py:1164: note:     def typechecked(*, always: bool = ...) -> Callable[[T_CallableOrType], T_CallableOrType]
    src/typeguard/__init__.py:1164: note:     def [T_CallableOrType] typechecked(func: T_CallableOrType, *, always: bool = ...) -> T_CallableOrType
    src/typeguard/__init__.py:1168: error: No overload variant of "typechecked"
    matches argument types "Callable[..., Any]", "Any", "Dict[str, Any]" 
    [call-overload]
                            wrapped = typechecked(attr.__func__, always=always...
                                      ^
    src/typeguard/__init__.py:1168: note: Possible overload variants:
    src/typeguard/__init__.py:1168: note:     def typechecked(*, always: bool = ...) -> Callable[[T_CallableOrType], T_CallableOrType]
    src/typeguard/__init__.py:1168: note:     def [T_CallableOrType] typechecked(func: T_CallableOrType, *, always: bool = ...) -> T_CallableOrType
    src/typeguard/__init__.py:1174: error: Argument 3 to "getattr" has incompatible
    type "Tuple[]"; expected "bool"  [arg-type]
        ...ty_func is not None and getattr(property_func, "__annotations__", ()):
                                                                             ^
    src/typeguard/__init__.py:1175: error: No overload variant of "typechecked"
    matches argument types "Any", "Any", "Dict[str, Any]"  [call-overload]
                                kwargs[name] = typechecked(
                                               ^
    src/typeguard/__init__.py:1175: note: Possible overload variants:
    src/typeguard/__init__.py:1175: note:     def typechecked(*, always: bool = ...) -> Callable[[T_CallableOrType], T_CallableOrType]
    src/typeguard/__init__.py:1175: note:     def [T_CallableOrType] typechecked(func: T_CallableOrType, *, always: bool = ...) -> T_CallableOrType
    src/typeguard/__init__.py:1179: error: Argument 1 to "property" has
    incompatible type "**Dict[str, Optional[str]]"; expected
    "Optional[Callable[[Any], Any]]"  [arg-type]
                        setattr(func, key, attr.__class__(**kwargs))
                                                            ^
    src/typeguard/__init__.py:1179: error: Argument 1 to "property" has
    incompatible type "**Dict[str, Optional[str]]"; expected
    "Optional[Callable[[Any, Any], None]]"  [arg-type]
                        setattr(func, key, attr.__class__(**kwargs))
                                                            ^
    src/typeguard/__init__.py:1179: error: Argument 1 to "property" has
    incompatible type "**Dict[str, Optional[str]]"; expected
    "Optional[Callable[[Any], None]]"  [arg-type]
                        setattr(func, key, attr.__class__(**kwargs))
                                                            ^
    src/typeguard/__init__.py:1219: error: Returning Any from function declared to
    return
    "Union[TypeCheckedGenerator, TypeCheckedAsyncGenerator, GeneratorType[Any, Any, Any]]"
     [no-any-return]
                return retval
                ^
    Found 10 errors in 1 file (checked 3 source files)
    
    opened by eggplants 18
  • Import hook crashes on pkg_resources

    Import hook crashes on pkg_resources

    The following code:

    from typeguard.importhook import install_import_hook
    
    install_import_hook('')
    
    import pkg_resources
    

    produces the following output:

    $ python3 Test.py 
    Traceback (most recent call last):
      File "Test.py", line 5, in <module>
        import pkg_resources
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 77, in <module>
        __import__('pkg_resources.extern.packaging.requirements')
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/pkg_resources/_vendor/packaging/requirements.py", line 9, in <module>
        from pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 656, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 626, in _load_backward_compatible
      File "/usr/lib/python3/dist-packages/pkg_resources/extern/__init__.py", line 43, in load_module
        __import__(extant)
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/pkg_resources/_vendor/pyparsing.py", line 5353, in <module>
        class pyparsing_common:
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/__init__.py", line 721, in typechecked
        if callable(attr) and attr.__qualname__.startswith(prefix):
    AttributeError: 'Combine' object has no attribute '__qualname__'
    Error in sys.excepthook:
    Traceback (most recent call last):
      File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
        from apport.fileutils import likely_packaged, get_recent_crashes
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
        from apport.report import Report
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/apport/report.py", line 28, in <module>
        import problem_report
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/problem_report.py", line 16, in <module>
        from email.mime.multipart import MIMEMultipart
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3.6/email/mime/multipart.py", line 9, in <module>
        from email.mime.base import MIMEBase
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3.6/email/mime/base.py", line 9, in <module>
        import email.policy
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3.6/email/policy.py", line 26, in <module>
        class EmailPolicy(Policy):
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/__init__.py", line 721, in typechecked
        if callable(attr) and attr.__qualname__.startswith(prefix):
    AttributeError: 'HeaderRegistry' object has no attribute '__qualname__'
    
    Original exception was:
    Traceback (most recent call last):
      File "Test.py", line 5, in <module>
        import pkg_resources
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 77, in <module>
        __import__('pkg_resources.extern.packaging.requirements')
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/pkg_resources/_vendor/packaging/requirements.py", line 9, in <module>
        from pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 656, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 626, in _load_backward_compatible
      File "/usr/lib/python3/dist-packages/pkg_resources/extern/__init__.py", line 43, in load_module
        __import__(extant)
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/importhook.py", line 82, in exec_module
        return super().exec_module(module)
      File "/usr/lib/python3/dist-packages/pkg_resources/_vendor/pyparsing.py", line 5353, in <module>
        class pyparsing_common:
      File "/usr/local/lib/python3.6/dist-packages/typeguard-2.6.0.post5-py3.6.egg/typeguard/__init__.py", line 721, in typechecked
        if callable(attr) and attr.__qualname__.startswith(prefix):
    AttributeError: 'Combine' object has no attribute '__qualname__'
    
    bug 
    opened by jolaf 17
  • About performance

    About performance

    Hi!

    Thanks for the project, looks very good and interesting. I want to ask you some questions about performance: do you have any metrics (or thoughts) how usage of typechecked or TypeChecker affects on performance? And do you use your library in production or this just a prototype for fun?

    question 
    opened by Gr1N 15
  • Yield type inferred incorrectly in nested Generators

    Yield type inferred incorrectly in nested Generators

    The following code:

    from typing import Generator
    
    from typeguard import TypeChecker
    
    def a() -> Generator[str, None, None]:
        yield "OK"
    
    def b() -> Generator[Generator[str, None, None], None, None]:
        yield a()
        yield a()
    
    with TypeChecker('__main__'):
        for f in b():
            print(next(f))
    

    produces the following output:

    $ python3 Test.py 
    OK
    /usr/local/lib/python3.6/dist-packages/typeguard/__init__.py:932: TypeWarning: [MainThread] return from __main__.b() at Test.py:10: type of yielded value must be str; got generator instead
      warn(TypeWarning(memo, event, frame, exc))
    OK
    

    Note that the problem occurs only at the second yield, but not at the first one.

    This is an old issue that I'm observing for some time, but I thought it to be a consequence of #77, but #77 is fixed now in v2.5.1, but this issue still persists.

    opened by jolaf 13
  • Generator annotations are not interpreted according to PEP 484

    Generator annotations are not interpreted according to PEP 484

    Try this example:

    from typing import Generator, no_type_check
    from warnings import filterwarnings
    
    from typeguard import TypeChecker, TypeWarning
    
    
    def generator_example() -> Generator[int, None, None]:
        for i in range(3):
            yield i
    
    
    def main() -> None:
        filterwarnings("error", category=TypeWarning)
        checker = TypeChecker("__main__")
        checker.start()
        results = generator_example()
        for result in results:
            print(result)
    
    
    if __name__ == "__main__":
        main()
    

    I get: typeguard.TypeWarning: [MainThread] return from __main__.generator_example() at generator_fail.py:9: type of the return value must be collections.abc.Generator; got int instead

    As a workaround, I decorate generators with @no_type_check.

    enhancement 
    opened by mihaic 13
  • Handles type checks for Type[Protocol]

    Handles type checks for Type[Protocol]

    I noticed that typeguard wasn't able to correctly type check passed in classes when the type hint was a Type[Protocol]. You would receive an error like: TypeError: Protocols with non-method members don't support issubclass(). Using isinstance() in these situations would be able to correctly type check the passed in class. I also added a warning when a Protocol wasn't annotated with runtime_checkable to make it more explicit when typeguard was unable to perform type checking.

    Tests: Added a data protocol to improve coverage Added a test for checking Type[Protocol]

    opened by williamlw999-fb 12
  • Fixed an exception when a dict has mixed bytes and str keys

    Fixed an exception when a dict has mixed bytes and str keys

    The following code demonstrates the problem that is fixed by this PR:

    from typing import TypedDict
    
    from typeguard import typechecked
    
    class TestDict(TypedDict):
        a: str
    
    @typechecked
    def test() -> TestDict:
        return {
            'str': 'test',
            b'bytes': 'test'
        }
    
    test()
    
    $ ./test.py 
    Traceback (most recent call last):
      File "/home/ldef/typeguard/src/./test.py", line 16, in <module>
        test()
      File "/home/ldef/typeguard/src/typeguard/__init__.py", line 285, in wrapper
        check_return_type(retval, memo)
      File "/home/ldef/typeguard/src/typeguard/__init__.py", line 172, in check_return_type
        check_type_internal(retval, memo.type_hints["return"], memo)
      File "/home/ldef/typeguard/src/typeguard/_checkers.py", line 568, in check_type_internal
        checker(value, origin_type, args, memo)
      File "/home/ldef/typeguard/src/typeguard/_checkers.py", line 220, in check_typed_dict
        raise TypeCheckError(f"has unexpected extra key(s): {keys_formatted}")
    typeguard._exceptions.TypeCheckError: the return value has unexpected extra key(s): "b'bytes'", "str"
    
    opened by biolds 2
  • AttributeError: 'CPUDispatcher' object has no attribute '__globals__' with numba.njit decorated function

    AttributeError: 'CPUDispatcher' object has no attribute '__globals__' with numba.njit decorated function

    Describe the bug I am using the numba.njit decorator to decorate a function. When I execute pytest with typeguard, I get an error when this decorated function is called: AttributeError: 'CPUDispatcher' object has no attribute '__globals__'. When trying to narrow down the error and trying to reproduce with a minimal working example, I found out that the error only occurs when the decorated function is imported absolutely from a module. When the same function is imported with a relative import there is no error.

    To Reproduce I have three different files: two source files (one for absolute and one for relative import) and one pytest file: src/my_module/numba_typeguard.py (absolute import)

    from typing import TypeVar
    
    import numpy as np
    import numpy.typing as npt
    from numba import njit
    
    T = TypeVar("T", bound=np.generic)
    
    
    @njit
    def numba_sum(
        array: npt.NDArray[T],
    ) -> T:
        return np.sum(array)
    

    tests/numba_typeguard.py (relative import) same function as above but in tests directory.

    from typing import TypeVar
    
    import numpy as np
    import numpy.typing as npt
    from numba import njit
    
    T = TypeVar("T", bound=np.generic)
    
    
    @njit
    def numba_sum_local(
        array: npt.NDArray[T],
    ) -> T:
        return np.sum(array)
    

    tests/test_numba_typeguard.py

    import numpy as np
    from my_module.numba_typeguard import numba_sum
    from .numba_typeguard import numba_sum_local
    
    
    def test_numba_sum_njit() -> None:
        x = np.arange(4)
        s = numba_sum(x)
        assert s == np.sum(x)
    
    
    def test_numba_sum() -> None:
        x = np.arange(4)
        s = numba_sum.py_func(x)
        assert s == np.sum(x)
    
    
    def test_numba_sum_local_njit() -> None:
        x = np.arange(4)
        s = numba_sum_local(x)
        assert s == np.sum(x)
    
    
    def test_numba_sum_local() -> None:
        x = np.arange(4)
        s = numba_sum_local.py_func(x)
        assert s == np.sum(x)
    

    The following is the error I get:

    ======================================================================================================================================= FAILURES =======================================================================================================================================
    _________________________________________________________________________________________________________________________________ test_numba_sum_njit __________________________________________________________________________________________________________________________________
    
        def test_numba_sum_njit() -> None:
            x = np.arange(4)
    >       s = numba_sum(x)
    
    tests/test_numba_typeguard.py:8:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    .nox/typeguard-3-9/lib/python3.9/site-packages/typeguard/__init__.py:1031: in wrapper
        memo = _CallMemo(python_func, _localns, args=args, kwargs=kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <typeguard._CallMemo object at 0x7f9db523c880>, func = CPUDispatcher(<function numba_sum at 0x7f9db52fa5e0>)
    frame_locals = {'T': ~T, 'TypeVar': <class 'typing.TypeVar'>, '__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, 'Asserti...s/.nox/typeguard-3-9/lib/python3.9/site-packages/my_module/__pycache__/numba_typeguard.cpython-39.pyc', ...}
    args = (array([0, 1, 2, 3]),), kwargs = {}, forward_refs_policy = <ForwardRefPolicy.ERROR: 1>
    
        def __init__(self, func: Callable, frame_locals: Optional[Dict[str, Any]] = None,
                     args: tuple = None, kwargs: Dict[str, Any] = None,
                     forward_refs_policy=ForwardRefPolicy.ERROR):
    >       super().__init__(func.__globals__, frame_locals)
    E       AttributeError: 'CPUDispatcher' object has no attribute '__globals__'
    
    .nox/typeguard-3-9/lib/python3.9/site-packages/typeguard/__init__.py:191: AttributeError
    

    Expected behavior I expect the error not to depend on relative vs absolute import.

    Additional context As I do not know if this is related to typeguard alone or something else and as I am using the hypermodern python template, I raised also an issue there: https://github.com/cjolowicz/cookiecutter-hypermodern-python/issues/1271

    I tried to remove the py.typed file in the src/my_module directory, but this did not resolve the error.

    opened by gatoniel 0
  • typeguard doesn't check types like

    typeguard doesn't check types like "a | b"

    It seems typeguard doesn't support types like "a | b" that is introduced in PEP604.

    To Reproduce

    from typeguard import typechecked
    from typing import Union
    
    @typechecked
    def f(x: int | float):
      print(x)
    
    @typechecked
    def g(x: Union[int, float]):
      print(x)
    
    f("a")
    g("a")
    

    Expected behavior Both should raise TypeError, but in reality f("a") just passed without raising an exception.

    opened by jingfeijia-tsy 2
  • Add support for typing.Self

    Add support for typing.Self

    Python 3.11 was released now as stable version. It added some new typing features. The most important change is the addition of typing.Self. It would be nice if typeguard could have support for this!

    enhancement 
    opened by LostInDarkMath 1
  • optionally allow extra keys in typed dicts via check_type

    optionally allow extra keys in typed dicts via check_type

    What

    This PR:

    • adds an optional kwarg allow_extra to check_type
    • allow_extra defaults to False
    • if allow_extra is True, any TypedDict checks will allow extra keys over value, rather than raise a TypeCheckError

    Why

    After reading https://github.com/python/mypy/issues/4617, it does not appear that TypedDict will allow extra keys (fields) any time soon.

    I like to use typeguard to validate data coming from outside process bounds. I use check_type for that. This lets me re-use the Python type hints already specified in the code base. This is better (IMO) than specifying things a second time with, say, Pydantic, or Marshmallow. In most cases this data is JSON, and most of the time it's envelope'd into a dictionary.

    opened by jomido 1
Owner
Alex Grönholm
Alex Grönholm
A very minimalistic python module that lets you track the time your code snippets take to run.

Clock Keeper A very minimalistic python module that lets you track the time your code snippets take to run. This package is available on PyPI! Run the

Rajdeep Biswas 1 Jan 19, 2022
Inspects Python source files and provides information about type and location of classes, methods etc

prospector About Prospector is a tool to analyse Python code and output information about errors, potential problems, convention violations and comple

Python Code Quality Authority 1.7k Dec 31, 2022
Performant type-checking for python.

Pyre is a performant type checker for Python compliant with PEP 484. Pyre can analyze codebases with millions of lines of code incrementally – providi

Facebook 6.2k Jan 7, 2023
A system for Python that generates static type annotations by collecting runtime types

MonkeyType MonkeyType collects runtime types of function arguments and return values, and can automatically generate stub files or even add draft type

Instagram 4.1k Jan 2, 2023
A static type analyzer for Python code

pytype - ? ✔ Pytype checks and infers types for your Python code - without requiring type annotations. Pytype can: Lint plain Python code, flagging c

Google 4k Dec 31, 2022
Unbearably fast O(1) runtime type-checking in pure Python.

Look for the bare necessities, the simple bare necessities. Forget about your worries and your strife. — The Jungle Book.

null 1.4k Dec 29, 2022
Data parsing and validation using Python type hints

pydantic Data validation and settings management using Python type hinting. Fast and extensible, pydantic plays nicely with your linters/IDE/brain. De

Samuel Colvin 12.1k Jan 5, 2023
pycallgraph is a Python module that creates call graphs for Python programs.

Project Abandoned Many apologies. I've stopped maintaining this project due to personal time constraints. Blog post with more information. I'm happy t

gak 1.7k Jan 1, 2023
Turn your Python and Javascript code into DOT flowcharts

Notes from 2017 This is an older project which I am no longer working on. It was built before ES6 existed and before Python 3 had much usage. While it

Scott Rogowski 3k Jan 9, 2023
Find dead Python code

Vulture - Find dead code Vulture finds unused code in Python programs. This is useful for cleaning up and finding errors in large code bases. If you r

Jendrik Seipp 2.4k Jan 3, 2023
Code audit tool for python.

Pylama Code audit tool for Python and JavaScript. Pylama wraps these tools: pycodestyle (formerly pep8) © 2012-2013, Florent Xicluna; pydocstyle (form

Kirill Klenov 966 Dec 29, 2022
The strictest and most opinionated python linter ever!

wemake-python-styleguide Welcome to the strictest and most opinionated python linter ever. wemake-python-styleguide is actually a flake8 plugin with s

wemake.services 2.1k Jan 5, 2023
The uncompromising Python code formatter

The Uncompromising Code Formatter “Any color you like.” Black is the uncompromising Python code formatter. By using it, you agree to cede control over

Python Software Foundation 30.7k Dec 28, 2022
A Python utility / library to sort imports.

Read Latest Documentation - Browse GitHub Code Repository isort your imports, so you don't have to. isort is a Python utility / library to sort import

Python Code Quality Authority 5.5k Jan 6, 2023
A formatter for Python files

YAPF Introduction Most of the current formatters for Python --- e.g., autopep8, and pep8ify --- are made to remove lint errors from code. This has som

Google 13k Dec 31, 2022
Collection of library stubs for Python, with static types

typeshed About Typeshed contains external type annotations for the Python standard library and Python builtins, as well as third party packages as con

Python 3.3k Jan 2, 2023
Optional static typing for Python 3 and 2 (PEP 484)

Mypy: Optional Static Typing for Python Got a question? Join us on Gitter! We don't have a mailing list; but we are always happy to answer questions o

Python 14.4k Jan 5, 2023
A static analysis tool for Python

pyanalyze Pyanalyze is a tool for programmatically detecting common mistakes in Python code, such as references to undefined variables and some catego

Quora 212 Jan 7, 2023
Typing-toolbox for Python 3 _and_ 2.7 w.r.t. PEP 484.

Welcome to the pytypes project pytypes is a typing toolbox w.r.t. PEP 484 (PEP 526 on the road map, later also 544 if it gets accepted). Its main feat

Stefan Richthofer 188 Dec 29, 2022