def testStrict(self): ast = parser.parse_string( textwrap.dedent(""" T = TypeVar('T') class list(typing.Generic[T], object): pass class A(): pass class B(A): pass class `~unknown0`(): pass a = ... # type: A def left() -> `~unknown0` def right() -> list[A] """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) left, right = ast.Lookup("left"), ast.Lookup("right") self.assertEquals( m.match(left, right, {}), booleq.And((booleq.Eq("~unknown0", "list"), booleq.Eq("~unknown0.list.T", "A"))))
def ParsePyTD(src=None, filename=None, python_version=None, module=None): """Parse pytd sourcecode and do name lookup for builtins. This loads a pytd and also makes sure that all names are resolved (i.e., that all primitive types in the AST are ClassType, and not NameType). Args: src: PyTD source code. filename: The filename the source code is from. python_version: The Python version to parse the pytd for. module: The name of the module we're parsing. Returns: A pytd.TypeDeclUnit. """ assert python_version if src is None: with open(filename, "rb") as fi: src = fi.read() ast = parser.parse_string(src, filename=filename, name=module, python_version=python_version) if module is not None: # Allow "" as module name ast = ast.Visit(visitors.AddNamePrefix(ast.name + ".")) ast = visitors.LookupClasses(ast, builtins.GetBuiltinsPyTD()) return ast
def ParsePyTD(src=None, filename=None, python_version=None, module=None, lookup_classes=False): """Parse pytd sourcecode and do name lookup for builtins. This loads a pytd and also makes sure that all names are resolved (i.e., that all primitive types in the AST are ClassType, and not NameType). Args: src: PyTD source code. filename: The filename the source code is from. python_version: The Python version to parse the pytd for. module: The name of the module we're parsing. lookup_classes: If we should also lookup the class of every ClassType. Returns: A pytd.TypeDeclUnit. """ assert python_version if src is None: with open(filename, "rb") as fi: src = fi.read() ast = parser.parse_string(src, filename=filename, name=module, python_version=python_version) if module is not None: # Allow "" as module name ast = ast.Visit(visitors.AddNamePrefix(ast.name + ".")) if lookup_classes: ast = visitors.LookupClasses(ast, builtins.GetBuiltinsPyTD()) return ast
def testOptional(self): ast = parser.parse_string(textwrap.dedent(""" def left(a: int) -> int def right(a: int, ...) -> int """)) m = type_match.TypeMatch() self.assertEquals(m.match(ast.Lookup("left"), ast.Lookup("right"), {}), booleq.TRUE)
def testOptional(self): ast = parser.parse_string( textwrap.dedent(""" def left(a: int) -> int def right(a: int, ...) -> int """)) m = type_match.TypeMatch() self.assertEquals(m.match(ast.Lookup("left"), ast.Lookup("right"), {}), booleq.TRUE)
def testGeneric(self): ast = parser.parse_string(textwrap.dedent(""" class A<T>(nothing): pass left: A<?> right: A<?> """)) ast = visitors.LookupClasses(ast) m = type_match.TypeMatch() self.assertEquals(m.match_type_against_type( ast.Lookup("left").type, ast.Lookup("right").type, {}), booleq.TRUE)
def testClassMatch(self): ast = parser.parse_string(textwrap.dedent(""" class Left(): def method(self) -> ? class Right(): def method(self) -> ? def method2(self) -> ? """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch() left, right = ast.Lookup("Left"), ast.Lookup("Right") self.assertEquals(m.match(left, right, {}), booleq.TRUE) self.assertNotEquals(m.match(right, left, {}), booleq.TRUE)
def testGeneric(self): ast = parser.parse_string(textwrap.dedent(""" T = TypeVar('T') class A(typing.Generic[T], object): pass left = ... # type: A[?] right = ... # type: A[?] """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch() self.assertEquals(m.match_type_against_type( ast.Lookup("left").type, ast.Lookup("right").type, {}), booleq.TRUE)
def testExternal(self): ast = parser.parse_string(textwrap.dedent(""" class Base(): pass class Foo(Base): pass base = ... # type: Base """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) mod1_foo = pytd.ExternalType("Foo", module="mod1", cls=ast.Lookup("Foo")) eq = m.match_type_against_type(mod1_foo, ast.Lookup("base").type, {}) self.assertEquals(eq, booleq.TRUE)
def test_isinstance(self): sourcecode = textwrap.dedent(""" x = ... # type: `~unknown1` def `~isinstance`(object: int, class_or_type_or_tuple: tuple[nothing]) -> `~unknown1` class `~unknown1`(object): pass """) expected = textwrap.dedent(""" x = ... # type: bool """).strip() ast = parser.parse_string(sourcecode) ast = convert_structural.convert_pytd(ast, self.builtins_pytd) self.assertMultiLineEqual(pytd.Print(ast), expected)
def testExternal(self): ast = parser.parse_string(textwrap.dedent(""" class Base(nothing): pass class Foo(Base): pass base: Foo foo: Foo """)) ast = visitors.LookupClasses(ast) m = type_match.TypeMatch({ast.Lookup("foo").type: [ast.Lookup("Base")]}) mod1_foo = pytd.ExternalType("Foo", module="mod1", cls=ast.Lookup("Foo")) eq = m.match_type_against_type(mod1_foo, ast.Lookup("base").type, {}) self.assertEquals(eq, booleq.TRUE)
def testConvertTypingToNativeOnBuiltins(self): """Test typing to native conversion in parsing builtins.""" builtins_src = textwrap.dedent(""" class object(): __dict__ = ... # type: Dict[str, Any] class list(List): ... """) typing_src = textwrap.dedent(""" class Pattern(object): def split(self) -> List """) builtins = parser.parse_string(builtins_src, name="__builtin__") typing = parser.parse_string(typing_src, name="typing") constant = builtins.Lookup("object").Lookup("__dict__") self.assertEquals(pytd.NamedType("dict"), constant.type.base_type) parent, = builtins.Lookup("list").parents self.assertEquals(pytd.NamedType("typing.List"), parent) method, = typing.Lookup("Pattern").Lookup("split").signatures self.assertEquals(pytd.NamedType("list"), method.return_type)
def testClassMatch(self): ast = parser.parse_string( textwrap.dedent(""" class Left(): def method(self) -> ? class Right(): def method(self) -> ? def method2(self) -> ? """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch() left, right = ast.Lookup("Left"), ast.Lookup("Right") self.assertEquals(m.match(left, right, {}), booleq.TRUE) self.assertNotEquals(m.match(right, left, {}), booleq.TRUE)
def testBaseClass(self): ast = parser.parse_string(textwrap.dedent(""" class Base(): def f(self, x:Base) -> Base class Foo(Base): pass class Match(): def f(self, x:Base) -> Base """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) eq = m.match_Class_against_Class(ast.Lookup("Match"), ast.Lookup("Foo"), {}) self.assertEquals(eq, booleq.TRUE)
def testGeneric(self): ast = parser.parse_string( textwrap.dedent(""" T = TypeVar('T') class A(typing.Generic[T], object): pass left = ... # type: A[?] right = ... # type: A[?] """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch() self.assertEquals( m.match_type_against_type( ast.Lookup("left").type, ast.Lookup("right").type, {}), booleq.TRUE)
def testSubclasses(self): ast = parser.parse_string(textwrap.dedent(""" class A(nothing): pass class B(A): pass a : A def left(a: B) -> B def right(a: A) -> A """)) ast = visitors.LookupClasses(ast) m = type_match.TypeMatch({ast.Lookup("a").type: [ast.Lookup("B")]}) left, right = ast.Lookup("left"), ast.Lookup("right") self.assertEquals(m.match(left, right, {}), booleq.TRUE) self.assertNotEquals(m.match(right, left, {}), booleq.TRUE)
def testSubclasses(self): ast = parser.parse_string(textwrap.dedent(""" class A(): pass class B(A): pass a = ... # type: A def left(a: B) -> B def right(a: A) -> A """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) left, right = ast.Lookup("left"), ast.Lookup("right") self.assertEquals(m.match(left, right, {}), booleq.TRUE) self.assertNotEquals(m.match(right, left, {}), booleq.TRUE)
def testBaseClass(self): ast = parser.parse_string( textwrap.dedent(""" class Base(): def f(self, x:Base) -> Base class Foo(Base): pass class Match(): def f(self, x:Base) -> Base """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) eq = m.match_Class_against_Class(ast.Lookup("Match"), ast.Lookup("Foo"), {}) self.assertEquals(eq, booleq.TRUE)
def testSubclasses(self): ast = parser.parse_string( textwrap.dedent(""" class A(): pass class B(A): pass a = ... # type: A def left(a: B) -> B def right(a: A) -> A """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) left, right = ast.Lookup("left"), ast.Lookup("right") self.assertEquals(m.match(left, right, {}), booleq.TRUE) self.assertNotEquals(m.match(right, left, {}), booleq.TRUE)
def testExternal(self): ast = parser.parse_string( textwrap.dedent(""" class Base(): pass class Foo(Base): pass base = ... # type: Base """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) mod1_foo = pytd.ExternalType("Foo", module="mod1", cls=ast.Lookup("Foo")) eq = m.match_type_against_type(mod1_foo, ast.Lookup("base").type, {}) self.assertEquals(eq, booleq.TRUE)
def test_convert(self): sourcecode = textwrap.dedent(""" class A(object): def foo(self, x: `~unknown1`) -> ? def foobaz(self, x: int) -> int class `~unknown1`(object): def foobaz(self, x: int) -> int """) expected = textwrap.dedent(""" class A(object): def foo(self, x: A) -> Any: ... def foobaz(self, x: int) -> int: ... """).lstrip() ast = parser.parse_string(sourcecode) ast = convert_structural.convert_pytd(ast, self.builtins_pytd) self.assertMultiLineEqual(pytd.Print(ast), expected)
def _TestTypeParameters(self, reverse=False): ast = parser.parse_string(textwrap.dedent(""" class `~unknown0`(nothing): def next(self) -> ? class A<T>(nothing): def next(self) -> ? class B(nothing): pass def left(x: `~unknown0`) -> ? def right(x: A<B>) -> ? """)) ast = visitors.LookupClasses(ast) m = type_match.TypeMatch() left, right = ast.Lookup("left"), ast.Lookup("right") match = m.match(right, left, {}) if reverse else m.match(left, right, {}) self.assertEquals(match, booleq.And((booleq.Eq("~unknown0", "A"), booleq.Eq("~unknown0.A.T", "B")))) self.assertIn("~unknown0.A.T", m.solver.variables)
def test_convert_with_type_params(self): sourcecode = textwrap.dedent(""" class A(object): def foo(self, x: `~unknown1`) -> bool class `~unknown1`(): def __setitem__(self, _1: str, _2: `~unknown2`) -> ? def update(self, _1: NoneType or Dict[nothing, nothing]) -> ? class `~unknown2`(): def append(self, v:NoneType) -> NoneType """) expected = textwrap.dedent(""" class A(object): def foo(self, x: Dict[str, List[Any]]) -> bool: ... """).lstrip() ast = parser.parse_string(sourcecode) ast = convert_structural.convert_pytd(ast, self.builtins_pytd) self.assertMultiLineEqual(pytd.Print(ast), expected)
def _TestTypeParameters(self, reverse=False): ast = parser.parse_string(textwrap.dedent(""" class `~unknown0`(): def next(self) -> ? T = TypeVar('T') class A(typing.Generic[T], object): def next(self) -> ? class B(): pass def left(x: `~unknown0`) -> ? def right(x: A[B]) -> ? """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch() left, right = ast.Lookup("left"), ast.Lookup("right") match = m.match(right, left, {}) if reverse else m.match(left, right, {}) self.assertEquals(match, booleq.And((booleq.Eq("~unknown0", "A"), booleq.Eq("~unknown0.A.T", "B")))) self.assertIn("~unknown0.A.T", m.solver.variables)
def testStrict(self): ast = parser.parse_string(textwrap.dedent(""" class list<T>(nothing): pass class A(nothing): pass class B(A): pass class `~unknown0`(nothing): pass a : A def left() -> `~unknown0` def right() -> list<A> """)) ast = visitors.LookupClasses(ast) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) left, right = ast.Lookup("left"), ast.Lookup("right") self.assertEquals(m.match(left, right, {}), booleq.And((booleq.Eq("~unknown0", "list"), booleq.Eq("~unknown0.list.T", "A"))))
def testStrict(self): ast = parser.parse_string(textwrap.dedent(""" T = TypeVar('T') class list(typing.Generic[T], object): pass class A(): pass class B(A): pass class `~unknown0`(): pass a = ... # type: A def left() -> `~unknown0` def right() -> list[A] """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch(type_match.get_all_subclasses([ast])) left, right = ast.Lookup("left"), ast.Lookup("right") self.assertEquals(m.match(left, right, {}), booleq.And((booleq.Eq("~unknown0", "list"), booleq.Eq("~unknown0.list.T", "A"))))
def _TestTypeParameters(self, reverse=False): ast = parser.parse_string( textwrap.dedent(""" class `~unknown0`(): def next(self) -> ? T = TypeVar('T') class A(typing.Generic[T], object): def next(self) -> ? class B(): pass def left(x: `~unknown0`) -> ? def right(x: A[B]) -> ? """)) ast = visitors.LookupClasses(ast, self.mini_builtins) m = type_match.TypeMatch() left, right = ast.Lookup("left"), ast.Lookup("right") match = m.match(right, left, {}) if reverse else m.match( left, right, {}) self.assertEquals( match, booleq.And((booleq.Eq("~unknown0", "A"), booleq.Eq("~unknown0.A.T", "B")))) self.assertIn("~unknown0.A.T", m.solver.variables)
def setUp(self): self.mini_builtins = parser.parse_string(textwrap.dedent(""" class object: # implicitly added by Generic pass """))
def parse(self, src): return parser.parse_string(textwrap.dedent(src))
def parse(self, src): ast = parser.parse_string(textwrap.dedent(src)) ast = ast.Visit( visitors.LookupBuiltins(builtins.GetBuiltinsAndTyping()[0])) return ast
def setUp(self): builtins = parser.parse_string(textwrap.dedent(_BUILTINS)).Replace( name="__builtin__").Visit(visitors.AddNamePrefix()) typing = parser.parse_string("class Generic: ...").Replace( name="typing").Visit(visitors.AddNamePrefix()) self.mini_builtins = pytd_utils.Concat(builtins, typing)
def setUp(self): self.mini_builtins = parser.parse_string( textwrap.dedent(""" class object: # implicitly added by Generic pass """))