Esempio n. 1
0
  def testAdjustTypeParameters(self):
    ast = self.Parse("""
      T = TypeVar("T")
      T2 = TypeVar("T2")
      def f(x: T) -> T
      class A(Generic[T]):
        def a(self, x: T2) -> None:
          self = A[T or T2]
    """)

    f = ast.Lookup("f")
    sig, = f.signatures
    p_x, = sig.params
    self.assertEqual(sig.template,
                     (pytd.TemplateItem(pytd.TypeParameter("T", scope="f")),))
    self.assertEqual(p_x.type, pytd.TypeParameter("T", scope="f"))

    cls = ast.Lookup("A")
    f_cls, = cls.methods
    sig_cls, = f_cls.signatures
    p_self, p_x_cls = sig_cls.params
    self.assertEqual(cls.template,
                     (pytd.TemplateItem(pytd.TypeParameter("T", scope="A")),))
    self.assertEqual(sig_cls.template, (pytd.TemplateItem(
        pytd.TypeParameter("T2", scope="A.a")),))
    self.assertEqual(p_self.type.parameters,
                     (pytd.TypeParameter("T", scope="A"),))
    self.assertEqual(p_x_cls.type, pytd.TypeParameter("T2", scope="A.a"))
Esempio n. 2
0
 def testAdjustTypeParametersWithDuplicates(self):
     ast = self.ParseWithBuiltins("""
   T = TypeVar("T")
   class A(Dict[T, T], Generic[T]): pass
 """)
     a = ast.Lookup("A")
     self.assertEqual(
         (pytd.TemplateItem(pytd.TypeParameter("T", (), None, "A")),
          pytd.TemplateItem(pytd.TypeParameter("T",
                                               (), None, "A"))), a.template)
Esempio n. 3
0
def SplitParents(parser, p, parents):
    """Strip the special Generic[...] class out of the base classes."""
    template = ()
    other_parents = []
    for parent in parents:
        if (isinstance(parent, pytd.GenericType) and parent.base_type
                == pytd.ExternalType('Generic', 'typing')):
            if not all(
                    isinstance(param, pytd.NamedType)
                    for param in parent.parameters):
                make_syntax_error(
                    parser,
                    'Illegal template parameter %s' % pytd.Print(parent), p)
            if template:
                make_syntax_error(parser, 'Duplicate Template base class', p)
            template = tuple(
                pytd.TemplateItem(pytd.TypeParameter(param.name))
                for param in parent.parameters)
            all_names = [t.name for t in template]
            duplicates = [
                name for name, count in collections.Counter(all_names).items()
                if count >= 2
            ]
            if duplicates:
                make_syntax_error(
                    parser,
                    'Duplicate template parameters' + ', '.join(duplicates), p)
        else:
            if parent != pytd.NothingType():
                other_parents.append(parent)
    return template, tuple(other_parents)
Esempio n. 4
0
 def testAdjustTypeParametersWithBuiltins(self):
   ast = self.ParseWithBuiltins("""
     T = TypeVar("T")
     K = TypeVar("K")
     V = TypeVar("V")
     class Foo(List[int]): pass
     class Bar(Dict[T, int]): pass
     class Baz(Generic[K, V]): pass
     class Qux(Baz[str, int]): pass
   """)
   foo = ast.Lookup("Foo")
   bar = ast.Lookup("Bar")
   qux = ast.Lookup("Qux")
   foo_parent, = foo.parents
   bar_parent, = bar.parents
   qux_parent, = qux.parents
   # Expected:
   #  Class(Foo, parent=GenericType(List, parameters=(int,)), template=())
   #  Class(Bar, parent=GenericType(Dict, parameters=(T, int)), template=(T))
   #  Class(Qux, parent=GenericType(Baz, parameters=(str, int)), template=())
   self.assertEqual((pytd.ClassType("int"),), foo_parent.parameters)
   self.assertEqual((), foo.template)
   self.assertEqual(
       (pytd.TypeParameter("T", scope="Bar"), pytd.ClassType("int")),
       bar_parent.parameters)
   self.assertEqual(
       (pytd.TemplateItem(pytd.TypeParameter("T", scope="Bar")),),
       bar.template)
   self.assertEqual((pytd.ClassType("str"), pytd.ClassType("int")),
                    qux_parent.parameters)
   self.assertEqual((), qux.template)
Esempio n. 5
0
 def testVerifyHeterogeneousTuple(self):
   # Error: does not inherit from Generic
   base = pytd.ClassType("tuple")
   base.cls = pytd.Class("tuple", None, (), (), (), (), None, ())
   t1 = pytd.TupleType(base, (pytd.NamedType("str"), pytd.NamedType("float")))
   self.assertRaises(visitors.ContainerError,
                     lambda: t1.Visit(visitors.VerifyContainers()))
   # Error: Generic[str, float]
   gen = pytd.ClassType("typing.Generic")
   gen.cls = pytd.Class("typing.Generic", None, (), (), (), (), None, ())
   t2 = pytd.TupleType(gen, (pytd.NamedType("str"), pytd.NamedType("float")))
   self.assertRaises(visitors.ContainerError,
                     lambda: t2.Visit(visitors.VerifyContainers()))
   # Okay
   param = pytd.TypeParameter("T")
   parent = pytd.GenericType(gen, (param,))
   base.cls = pytd.Class(
       "tuple", None, (parent,), (), (), (), None, (pytd.TemplateItem(param),))
   t3 = pytd.TupleType(base, (pytd.NamedType("str"), pytd.NamedType("float")))
   t3.Visit(visitors.VerifyContainers())
Esempio n. 6
0
    def p_funcdef(self, p):
        """funcdef : DEF NAME LPAREN params RPAREN return raises signature maybe_body"""
        _, _, name, _, params, _, return_type, raises, _, body = p
        # TODO(kramm): Output a warning if we already encountered a signature
        #              with these types (but potentially different argument names)
        if name == '__init__' and isinstance(return_type, pytd.AnythingType):
            ret = pytd.NamedType('NoneType')
        else:
            ret = return_type
        signature = pytd.Signature(params=tuple(params.required),
                                   return_type=ret,
                                   exceptions=tuple(raises),
                                   template=(),
                                   has_optional=params.has_optional)

        typeparams = {
            name: pytd.TypeParameter(name)
            for name in self.context.typevars
        }
        used_typeparams = set()
        signature = signature.Visit(
            visitors.ReplaceTypes(typeparams, used_typeparams))
        if used_typeparams:
            signature = signature.Replace(template=tuple(
                pytd.TemplateItem(typeparams[name])
                for name in used_typeparams))

        for mutator in body:
            try:
                signature = signature.Visit(mutator)
            except NotImplementedError as e:
                make_syntax_error(self, e.message, p)
            if not mutator.successful:
                make_syntax_error(self, 'No parameter named %s' % mutator.name,
                                  p)
        p[0] = NameAndSig(name=name, signature=signature, external_code=False)