Пример #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"))
Пример #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
Пример #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)
Пример #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)
Пример #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])
Пример #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)])
Пример #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)
Пример #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)
Пример #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(), )
Пример #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())
Пример #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)
Пример #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))
Пример #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"))
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)))
Пример #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)
Пример #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()
Пример #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)
Пример #24
0
 def p_type_name(self, p):
     """type : NAME"""
     p[0] = pytd.NamedType(p[1])
Пример #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])
Пример #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'))
Пример #27
0
 def p_template_item(self, p):
     """template_item : NAME"""
     p[0] = pytd.TemplateItem(pytd.TypeParameter(p[1]),
                              pytd.NamedType('object'))
Пример #28
0
 def p_template_item(self, p):
     """template_item : NAME"""
     p[0] = pytd.TemplateItem(p[1], pytd.NamedType('object'), 0)
Пример #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)
Пример #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, ())