diff options
author | Nikita Sobolev <mail@sobolevn.me> | 2022-02-19 01:53:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-19 01:53:29 (GMT) |
commit | 395029b0bd343648b4da8044c7509672ea768775 (patch) | |
tree | cdbf8b86c5bead4d8315c100a7f732f92902b817 /Lib/typing.py | |
parent | f80a97b492f41afd3c42bb2bd6da7b2828dca215 (diff) | |
download | cpython-395029b0bd343648b4da8044c7509672ea768775.zip cpython-395029b0bd343648b4da8044c7509672ea768775.tar.gz cpython-395029b0bd343648b4da8044c7509672ea768775.tar.bz2 |
bpo-46571: improve `typing.no_type_check` to skip foreign objects (GH-31042)
There are several changes:
1. We now don't explicitly check for any base / sub types, because new name check covers it
2. I've also checked that `no_type_check` do not modify foreign functions. It was the same as with `type`s
3. I've also covered `except TypeError` in `no_type_check` with a simple test case, it was not covered at all
4. I also felt like adding `lambda` test is a good idea: because `lambda` is a bit of both in class bodies: a function and an assignment
<!-- issue-number: [bpo-46571](https://bugs.python.org/issue46571) -->
https://bugs.python.org/issue46571
<!-- /issue-number -->
Diffstat (limited to 'Lib/typing.py')
-rw-r--r-- | Lib/typing.py | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/Lib/typing.py b/Lib/typing.py index 8f923fa..ad1435e 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -2131,13 +2131,23 @@ def no_type_check(arg): This mutates the function(s) or class(es) in place. """ if isinstance(arg, type): - arg_attrs = arg.__dict__.copy() - for attr, val in arg.__dict__.items(): - if val in arg.__bases__ + (arg,): - arg_attrs.pop(attr) - for obj in arg_attrs.values(): + for key in dir(arg): + obj = getattr(arg, key) + if ( + not hasattr(obj, '__qualname__') + or obj.__qualname__ != f'{arg.__qualname__}.{obj.__name__}' + or getattr(obj, '__module__', None) != arg.__module__ + ): + # We only modify objects that are defined in this type directly. + # If classes / methods are nested in multiple layers, + # we will modify them when processing their direct holders. + continue + # Instance, class, and static methods: if isinstance(obj, types.FunctionType): obj.__no_type_check__ = True + if isinstance(obj, types.MethodType): + obj.__func__.__no_type_check__ = True + # Nested types: if isinstance(obj, type): no_type_check(obj) try: |