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)
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"))
def p_funcdef(self, p): """funcdef : DEF template NAME LPAREN params RPAREN return raises signature maybe_body""" # 1 2 3 4 5 6 7 8 9 10 # TODO: do name lookups for template within params, return, raises # TODO: Output a warning if we already encountered a signature # with these types (but potentially different argument names) signature = pytd.Signature(params=tuple(p[5].required), return_type=p[7], exceptions=tuple(p[8]), template=tuple(p[2]), has_optional=p[5].has_optional) for mutator in p[10]: signature = signature.Visit(mutator) p[0] = NameAndSig(name=p[3], signature=signature)
def testTypeMatcher(self): """Test for the TypeMatcher class.""" class MyTypeMatcher(utils.TypeMatcher): def default_match(self, t1, t2, mykeyword): assert mykeyword == "foobar" return t1 == t2 def match_function_against_function(self, f1, f2, mykeyword): assert mykeyword == "foobar" return all( self.match(sig1, sig2, mykeyword) for sig1, sig2 in zip(f1.signatures, f2.signatures)) s1 = pytd.Signature((), pytd.NothingType(), (), (), False) s2 = pytd.Signature((), pytd.AnythingType(), (), (), False) match1 = MyTypeMatcher().match(pytd.Function("f1", (s1, s2)), pytd.Function("f2", (s1, s2)), mykeyword="foobar") self.assertEquals(match1, True) match2 = MyTypeMatcher().match(pytd.Function("f1", (s1, s2)), pytd.Function("f2", (s2, s2)), mykeyword="foobar") self.assertEquals(match2, False)
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)