Exemplo n.º 1
0
  def testComplexCombinedType(self):
    """Test parsing a type with both union and intersection."""

    data1 = r"def foo(a: Foo or Bar and Zot) -> object"
    data2 = r"def foo(a: Foo or (Bar and Zot)) -> object"
    result1 = self.Parse(data1)
    result2 = self.Parse(data2)
    f = pytd.Function(
        name="foo",
        signatures=(pytd.Signature(
            params=(
                pytd.Parameter(
                    name="a",
                    type=pytd.UnionType(
                        type_list=(
                            pytd.NamedType("Foo"),
                            pytd.IntersectionType(
                                type_list=(
                                    pytd.NamedType("Bar"),
                                    pytd.NamedType("Zot"))))
                    )
                ),),
            return_type=pytd.NamedType("object"),
            template=(), has_optional=False,
            exceptions=()),))
    self.assertEqual(f, result1.Lookup("foo"))
    self.assertEqual(f, result2.Lookup("foo"))
Exemplo n.º 2
0
 def VisitUnionType(self, union):
     if len(union.type_list) > self.max_length:
         return pytd.NamedType("object")
     elif pytd.NamedType("object") in union.type_list:
         return pytd.NamedType("object")
     else:
         return union
Exemplo n.º 3
0
 def testNamed(self):
     m = type_match.TypeMatch({})
     eq = m.match_type_against_type(pytd.NamedType("A"),
                                    pytd.NamedType("A"), {})
     self.assertEquals(eq, booleq.TRUE)
     eq = m.match_type_against_type(pytd.NamedType("A"),
                                    pytd.NamedType("B"), {})
     self.assertNotEquals(eq, booleq.TRUE)
Exemplo n.º 4
0
def ClassAsType(cls):
    """Converts a pytd.Class to an instance of pytd.Type."""
    params = tuple(item.type_param for item in cls.template)
    if not params:
        return pytd.NamedType(cls.name)
    elif len(params) == 1:
        return pytd.HomogeneousContainerType(pytd.NamedType(cls.name), params)
    else:  # len(cls.template) >= 2
        return pytd.GenericType(pytd.NamedType(cls.name), params)
Exemplo n.º 5
0
 def p_type_homogeneous(self, p):
     """type : NAME LBRACKET parameters RBRACKET"""
     if len(p[3]) == 1:
         element_type, = p[3]
         p[0] = pytd.HomogeneousContainerType(base_type=pytd.NamedType(
             p[1]),
                                              parameters=(element_type, ))
     else:
         p[0] = pytd.GenericType(base_type=pytd.NamedType(p[1]),
                                 parameters=p[3])
Exemplo n.º 6
0
    def _HasSubClassInSet(self, cls, known):
        """Queries whether a subclass of a type is present in a given set."""

        # object is an implicit superclass of all types. So if we're being asked
        # whether object has a subclass in the set, we just need to find any
        # class that's not object itself.
        if (cls == pytd.NamedType("object") and known
                and any(k != pytd.NamedType("object") for k in known)):
            return True

        return any(
            pytd.NamedType(sub) in known for sub in self._subclasses[str(cls)])
Exemplo n.º 7
0
  def testTokens(self):
    """Test various token forms (int, float, n"...", etc.)."""
    # TODO: a test with '"' or "'" in a string
    data = textwrap.dedent("""
        def `interface`(abcde: "xyz", foo: 'a"b', b: -1.0, c: 666) -> int
        """)

    result = self.Parse(data)
    f1 = result.Lookup("interface")
    f2 = pytd.Function(
        name="interface",
        signatures=(pytd.Signature(
            params=(
                pytd.Parameter(name="abcde",
                               type=pytd.Scalar(value="xyz")),
                pytd.Parameter(name="foo",
                               type=pytd.Scalar(value='a"b')),
                pytd.Parameter(name="b",
                               type=pytd.Scalar(value=-1.0)),
                pytd.Parameter(name="c",
                               type=pytd.Scalar(value=666))),
            return_type=pytd.NamedType("int"),
            exceptions=(),
            template=(), has_optional=False),))
    self.assertEqual(f1, f2)
Exemplo n.º 8
0
 def testJoinNothingType(self):
     """Test that JoinTypes() removes or collapses 'nothing'."""
     a = pytd.NamedType("a")
     nothing = pytd.NothingType()
     self.assertEquals(utils.JoinTypes([a, nothing]), a)
     self.assertEquals(utils.JoinTypes([nothing]), nothing)
     self.assertEquals(utils.JoinTypes([nothing, nothing]), nothing)
Exemplo n.º 9
0
 def __init__(self, replace_unknown=False, force=False):
     self.class_types = []  # allow nested classes
     self.force = force
     self.replaced_self_types = (pytd.NamedType("object"),
                                 pytd.ClassType("object"))
     if replace_unknown:
         self.replaced_self_types += (pytd.AnythingType(), )
Exemplo n.º 10
0
    def p_classdef(self, p):
        """classdef : CLASS NAME template parents COLON INDENT class_funcs DEDENT"""
        #             1     2    3        4       5     6
        funcdefs = [x for x in p[7] if isinstance(x, NameAndSig)]
        constants = [x for x in p[7] if isinstance(x, pytd.Constant)]
        if (set(f.name for f in funcdefs) | set(c.name for c in constants) !=
                set(d.name for d in p[7])):
            # TODO: raise a syntax error right when the identifier is defined.
            raise make_syntax_error(self, 'Duplicate identifier(s)', p)
        # Check that template parameter names are unique:
        template_names = {t.name for t in p[3]}
        for _, sig in funcdefs:
            for t in sig.template:
                if t.name in template_names:
                    raise make_syntax_error(
                        self, 'Duplicate template parameter %s' % t.name, p)

        if p[4] == [pytd.NothingType()]:
            bases = ()
        else:
            # Everything implicitly subclasses "object"
            bases = tuple(p[4]) or (pytd.NamedType('object'), )
        cls = pytd.Class(name=p[2],
                         parents=bases,
                         methods=tuple(MergeSignatures(funcdefs)),
                         constants=tuple(constants),
                         template=tuple(p[3]))
        p[0] = cls.Visit(visitors.AdjustSelf())
Exemplo n.º 11
0
    def VisitClassType(self, node):
        """Converts a class type to a named type.

    Args:
      node: The ClassType.

    Returns:
      A NamedType.
    """
        return pytd.NamedType(node.name)
Exemplo n.º 12
0
 def testJoinTypes(self):
     """Test that JoinTypes() does recursive flattening."""
     n1, n2, n3, n4, n5, n6 = [pytd.NamedType("n%d" % i) for i in xrange(6)]
     # n1 or (n2 or (n3))
     nested1 = pytd.UnionType(
         (n1, pytd.UnionType((n2, pytd.UnionType((n3, ))))))
     # ((n4) or n5) or n6
     nested2 = pytd.UnionType((pytd.UnionType((pytd.UnionType(
         (n4, )), n5)), n6))
     joined = optimize.JoinTypes([nested1, nested2])
     self.assertEquals(joined.type_list, (n1, n2, n3, n4, n5, n6))
Exemplo n.º 13
0
    def _CollectSuperclasses(self, node, collect):
        """Recursively collect super classes for a type.

    Arguments:
      node: A type node.
      collect: A set(), modified to contain all superclasses.
    """
        collect.add(node)
        superclasses = [
            pytd.NamedType(name)
            for name in self._superclasses.get(str(node), [])
        ]

        # The superclasses might have superclasses of their own, so recurse.
        for superclass in superclasses:
            self._CollectSuperclasses(superclass, collect)

        if node != pytd.NamedType("object"):
            # Everything but object itself subclasses object. This is not explicitly
            # specified in _superclasses, so we add object manually.
            collect.add(pytd.NamedType("object"))
Exemplo n.º 14
0
 def testReplaceType(self):
     src = """
     class A:
       def a(self, a: A or B) -> A or B raises A, B
 """
     expected = """
     class A:
       def a(self, a: A2 or B) -> A2 or B raises A2, B
 """
     tree = self.Parse(src)
     new_tree = tree.Visit(visitors.ReplaceType({"A":
                                                 pytd.NamedType("A2")}))
     self.AssertSourceEquals(new_tree, expected)
Exemplo n.º 15
0
 def testReturnTypes(self):
   src = textwrap.dedent("""
       def a() -> ?  # TODO: remove "-> ?" if we allow implicit result
       def b() -> ?
       def c() -> object
       def d() -> None
       def e() -> a or b
       def f() -> a<x>
       def g() -> a<x,>
       def h() -> a<x,y>
       def i() -> nothing  # never returns
   """)
   result = self.Parse(src)
   ret = {f.name: f.signatures[0].return_type for f in result.functions}
   self.assertIsInstance(ret["a"], pytd.AnythingType)
   self.assertIsInstance(ret["b"], pytd.AnythingType)
   self.assertEquals(ret["c"], pytd.NamedType("object"))
   self.assertEquals(ret["d"], pytd.NamedType("None"))
   self.assertIsInstance(ret["e"], pytd.UnionType)
   self.assertIsInstance(ret["f"], pytd.HomogeneousContainerType)
   self.assertIsInstance(ret["g"], pytd.GenericType)
   self.assertIsInstance(ret["h"], pytd.GenericType)
   self.assertIsInstance(ret["i"], pytd.NothingType)
Exemplo n.º 16
0
    def _CollectSuperclasses(self, node, collect):
        """Recursively collect super classes for a type.

    Arguments:
      node: A type node.
      collect: A set(), modified to contain all superclasses.
    """
        collect.add(node)
        superclasses = [
            pytd.NamedType(name)
            for name in self._superclasses.get(str(node), [])
        ]

        # The superclasses might have superclasses of their own, so recurse.
        for superclass in superclasses:
            self._CollectSuperclasses(superclass, collect)
Exemplo n.º 17
0
    def VisitGenericType(self, node):
        """Converts a parameter-based template type (e.g. dict<str,int>) to a class.

    This works by looking up the actual Class (using the lookup table passed
    when initializing the visitor) and substituting the parameters of the
    template everywhere in its definition. The new class is appended to the
    list of classes of this module. (Later on, also all templates are removed.)

    Args:
      node: An instance of GenericType.

    Returns:
      A new NamedType pointing to an instantiation of the class.
    """
        name = pytd.Print(node)
        if name not in self.classes_to_instantiate:
            self.classes_to_instantiate[name] = node
        return pytd.NamedType(name)
Exemplo n.º 18
0
    def VisitHomogeneousContainerType(self, node):
        """Converts a template type (container type) to a concrete class.

    This works by looking up the actual Class (using the lookup table passed
    when initializing the visitor) and substituting the parameters of the
    template everywhere in its definition. The new class is appended to the
    list of classes of this module. (Later on, the template we used is removed.)

    Args:
      node: An instance of HomogeneousContainerType

    Returns:
      A new NamedType pointing to an instantiation of the class.
    """
        name = pytd.Print(node)
        if name not in self.classes_to_instantiate:
            self.classes_to_instantiate[name] = node
        return pytd.NamedType(name)
Exemplo n.º 19
0
 def testOrder(self):
     # pytd types' primary sort key is the class name, second sort key is
     # the contents when interpreted as a (named)tuple.
     nodes = [
         pytd.AnythingType(),
         pytd.GenericType(self.list, (self.int, )),
         pytd.NamedType("int"),
         pytd.NothingType(),
         pytd.UnionType(self.float),
         pytd.UnionType(self.int)
     ]
     for n1, n2 in zip(nodes[:-1], nodes[1:]):
         self.assertLess(n1, n2)
         self.assertLessEqual(n1, n2)
         self.assertGreater(n2, n1)
         self.assertGreaterEqual(n2, n1)
     for p in itertools.permutations(nodes):
         self.assertEquals(list(sorted(p)), nodes)
Exemplo n.º 20
0
  def testSelf(self):
    """Test handling of self."""

    data = textwrap.dedent("""
        class MyClass<U, V>:
          def f1(self) -> ?
        """)

    result = self.Parse(data)
    myclass = result.Lookup("MyClass")
    self.assertEquals([t.name for t in myclass.template], ["U", "V"])

    f = myclass.Lookup("f1").signatures[0]
    self_param = f.params[0]
    self.assertEquals(self_param.name, "self")
    u, v = myclass.template
    self.assertEquals(self_param.type,
                      pytd.GenericType(pytd.NamedType("MyClass"),
                                       (u.type_param, v.type_param)))
Exemplo n.º 21
0
 def p_funcdef(self, p):
     """funcdef : DEF NAME template LPAREN params RPAREN return raises signature maybe_body"""
     #            1   2    3        4      5      6      7      8      9         10
     # TODO: Output a warning if we already encountered a signature
     #              with these types (but potentially different argument names)
     if p[2] == '__init__' and isinstance(p[7], pytd.AnythingType):
         # for __init__, the default return value is None
         ret = pytd.NamedType('NoneType')
     else:
         ret = p[7]
     signature = pytd.Signature(params=tuple(p[5].required),
                                return_type=ret,
                                exceptions=tuple(p[8]),
                                template=tuple(p[3]),
                                has_optional=p[5].has_optional)
     for mutator in p[10]:
         signature = signature.Visit(mutator)
         if not mutator.successful:
             make_syntax_error(self, 'No parameter named %s' % mutator.name,
                               p)
     p[0] = NameAndSig(name=p[2], signature=signature)
Exemplo n.º 22
0
  def testDecorator(self):
    decorator = decorate.Decorator()

    # Change pytd.NamedType to also have a method called "Test1"
    @decorator  # pylint: disable=unused-variable
    class NamedType(pytd.NamedType):

      def Test1(self):
        pass

    # Change pytd.Scalar to also have a method called "Test2"
    @decorator  # pylint: disable=unused-variable
    class Scalar(pytd.Scalar):

      def Test2(self):
        pass

    tree = pytd.Scalar(pytd.NamedType("test"))
    tree = decorator.Visit(tree)
    # test that we now have the "test2" method on pytd.Scalar
    tree.Test2()
    # test that we now have the "test1" method on pytd.NamedType
    tree.value.Test1()
Exemplo n.º 23
0
 def testNamedAgainstGeneric(self):
     m = type_match.TypeMatch({})
     eq = m.match_type_against_type(
         pytd.GenericType(pytd.NamedType("A"), []), pytd.NamedType("A"), {})
     self.assertEquals(eq, booleq.TRUE)
Exemplo n.º 24
0
 def p_type_name(self, p):
     """type : NAME"""
     p[0] = pytd.NamedType(p[1])
Exemplo n.º 25
0
 def p_type_generic_1(self, p):
     """type : NAME LBRACKET parameters COMMA RBRACKET"""
     p[0] = pytd.GenericType(base_type=pytd.NamedType(p[1]),
                             parameters=p[3])
Exemplo n.º 26
0
 def p_param(self, p):
     """param : NAME"""
     # type is optional and defaults to "object"
     p[0] = pytd.Parameter(p[1], pytd.NamedType('object'))
Exemplo n.º 27
0
 def p_template_item(self, p):
     """template_item : NAME"""
     p[0] = pytd.TemplateItem(pytd.TypeParameter(p[1]),
                              pytd.NamedType('object'))
Exemplo n.º 28
0
 def p_template_item(self, p):
     """template_item : NAME"""
     p[0] = pytd.TemplateItem(p[1], pytd.NamedType('object'), 0)
Exemplo n.º 29
0
 def testNothing(self):
     m = type_match.TypeMatch({})
     eq = m.match_type_against_type(pytd.NothingType(), pytd.NamedType("A"),
                                    {})
     self.assertEquals(eq, booleq.FALSE)
Exemplo n.º 30
0
 def testHasObjectSuperClass(self):
     cls = self.builtins.Lookup("int")
     self.assertEquals(cls.parents, (pytd.NamedType("object"), ))
     cls = self.builtins.Lookup("object")
     self.assertEquals(cls.parents, ())