From 12b6f8761402445e735c16d827df6fc2d8dce84d Mon Sep 17 00:00:00 2001 From: rechen Date: Wed, 31 May 2023 23:19:32 -0700 Subject: [PATCH] Don't report [not-instantiable] for fake classes constructed with NewType. PiperOrigin-RevId: 536927203 --- pytype/overlays/typing_overlay.py | 12 +++++++++--- pytype/tests/test_typing2.py | 10 ++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/pytype/overlays/typing_overlay.py b/pytype/overlays/typing_overlay.py index 4b7dd2132..ae4880783 100644 --- a/pytype/overlays/typing_overlay.py +++ b/pytype/overlays/typing_overlay.py @@ -391,19 +391,25 @@ def call(self, node, func, args, alias_map=None): # We need the type arg to be an atomic value. If not, we just # silently return unsolvable. return node, self.ctx.new_unsolvable(node) - value_arg_name = "val" + if isinstance(type_value, abstract.AnnotationContainer): + type_value = type_value.base_cls constructor = overlay_utils.make_method( self.ctx, node, name="__init__", - params=[Param(value_arg_name, type_value)]) + params=[Param("val", type_value)]) members = abstract.Dict(self.ctx) members.set_str_item(node, "__init__", constructor) props = class_mixin.ClassBuilderProperties( name_var=name_arg, bases=[type_arg], class_dict_var=members.to_variable(node)) - return self.ctx.make_class(node, props) + node, clsvar = self.ctx.make_class(node, props) + # At runtime, the 'class' created by NewType is simply an identity function, + # so it ignores abstract-ness. + for cls in clsvar.data: + cls.abstract_methods.clear() + return node, clsvar class Overload(abstract.PyTDFunction): diff --git a/pytype/tests/test_typing2.py b/pytype/tests/test_typing2.py index 5cb139aee..a3d570e75 100644 --- a/pytype/tests/test_typing2.py +++ b/pytype/tests/test_typing2.py @@ -427,6 +427,16 @@ def func3(s: MyStr) -> MyStr: "e2": r".*Expected: \(i: MyInt\)\nActually passed: \(i: int\)", "e3": r".*Expected:.*val: str\)\nActually passed:.*val: int\)"}) + def test_new_type_not_abstract(self): + # At runtime, the 'class' created by NewType is simply an identity function, + # so it ignores abstract-ness. + self.Check(""" + from typing import Mapping, NewType + X = NewType('X', Mapping) + def f() -> X: + return X({}) + """) + def test_maybe_return(self): self.Check(""" def f() -> int: