class Constant(node.Node('name: str', 'type: {Type}')): __slots__ = ()
class NamedType(node.Node('name: str'), Type): """A type specified by name and, optionally, the module it is in.""" __slots__ = () def __str__(self): return self.name
class Node1(node.Node("a", "b")): """Simple node for equality testing. Not equal to anything else."""
class TypeDeclUnit( node.Node('name: str or None', 'is_package: bool', 'constants: tuple[Constant]', 'type_params: tuple[TypeParameter]', 'classes: tuple[Class]', 'functions: tuple[Function]', 'aliases: tuple[Alias]', 'modules: tuple[Module]')): """Module node. Holds module contents (constants / classes / functions). Attributes: name: Name of this module, or None for the top-level module. is_package: True for, e.g., 'foo/__init__.pyi', False for 'foo.pyi' (though self.name is 'foo' for both) constants: Iterable of module-level constants. type_params: Iterable of module-level type parameters. functions: Iterable of functions defined in this type decl unit. classes: Iterable of classes defined in this type decl unit. aliases: Iterable of aliases (or imports) for types in other modules. modules: Iterable of imported modules. """ def __new__(cls, name, is_package, constants, type_params, classes, functions, aliases, modules=()): return super(TypeDeclUnit, cls).__new__(cls, name, is_package, constants, type_params, classes, functions, aliases, modules) def Lookup(self, name): """Convenience function: Look up a given name in the global namespace. Tries to find a constant, function or class by this name. Args: name: Name to look up. Returns: A Constant, Function or Class. Raises: KeyError: if this identifier doesn't exist. """ # TODO(kramm): Put constants, functions, classes and aliases into a # combined dict. try: return self._name2item[name] except AttributeError: self._name2item = {} for x in self.type_params: self._name2item[x.full_name] = x # We store imported names as modules too in case they don't resolve as # anything else, but that should have lower priority, so put modules # first and let them be overwritten if we find the same name later. for x in (self.modules + self.constants + self.functions + self.classes + self.aliases): self._name2item[x.name] = x return self._name2item[name] @property def package_name(self): if self.is_package: return self.name else: parts = self.name.split('.') return '.'.join(parts[:-1]) # The hash/eq/ne values are used for caching and speed things up quite a bit. def __hash__(self): return id(self) def __eq__(self, other): return id(self) == id(other) def __ne__(self, other): return id(self) != id(other) def ASTeq(self, other): # Used in tests. return (self.constants == other.constants and self.type_params == other.type_params and self.classes == other.classes and self.functions == other.functions and self.aliases == other.aliases)
class X(node.Node("a", "b")): """Inner node 'X', with two children. See testVisitor[...]() below."""
class XY(node.Node("x", "y")): """Inner node 'XY', with two children. See testVisitor[...]() below."""
class FunctionType(node.Node('name: str', 'function: Function'), Type): """The type of a function. E.g. the type of 'x' in 'x = lambda y: y'.""" __slots__ = ()
class Data(node.Node("d1", "d2", "d3")): """'Data' node. Visitor tests use this to store numbers in leafs."""
class Constant(node.Node('name', 'type')): __slots__ = ()
class NativeType(node.Node('python_type'), Type): """DEPRECATED; Please use NamedType instead. A type specified by a native Python type. Used during runtime checking. """ __slots__ = ()
class NativeType(node.Node('python_type')): """A type specified by a native Python type. Used during runtime checking.""" __slots__ = ()
class Literal(node.Node('value: int or str or {Type}'), Type): __slots__ = () @property def name(self): return None
class AnythingType(node.Node(), Type): """A type we know nothing about yet ('?' in pytd).""" __slots__ = () def __nonzero__(self): return True
class TypeDeclUnit( node.Node('name: str or None', 'constants: tuple[Constant]', 'type_params: tuple[TypeParameter]', 'classes: tuple[Class]', 'functions: tuple[Function]', 'aliases: tuple[Alias]')): """Module node. Holds module contents (constants / classes / functions). Attributes: name: Name of this module, or None for the top-level module. constants: Iterable of module-level constants. type_params: Iterable of module-level type parameters. functions: Iterable of functions defined in this type decl unit. classes: Iterable of classes defined in this type decl unit. aliases: Iterable of aliases (or imports) for types in other modules. """ def Lookup(self, name): """Convenience function: Look up a given name in the global namespace. Tries to find a constant, function or class by this name. Args: name: Name to look up. Returns: A Constant, Function or Class. Raises: KeyError: if this identifier doesn't exist. """ # TODO(kramm): Put constants, functions, classes and aliases into a # combined dict. try: return self._name2item[name] except AttributeError: self._name2item = {} for x in self.type_params: self._name2item[x.full_name] = x for x in self.constants + self.functions + self.classes + self.aliases: self._name2item[x.name] = x return self._name2item[name] # The hash/eq/ne values are used for caching and speed things up quite a bit. def __hash__(self): return id(self) def __eq__(self, other): return id(self) == id(other) def __ne__(self, other): return id(self) != id(other) def ASTeq(self, other): return (self.constants == other.constants and self.type_params == other.type_params and self.classes == other.classes and self.functions == other.functions and self.aliases == other.aliases) def ASTdiff(self, other): return difflib.ndiff( Print(self).splitlines(), Print(other).splitlines())
class AnythingType(node.Node(), Type): """A type we know nothing about yet ('?' in pytd).""" __slots__ = ()
class LateType(node.Node('name: str'), Type): """A type we have yet to resolve.""" def __str__(self): return self.name
class Scalar(node.Node('value'), Type): __slots__ = ()
class V(node.Node("x")): """Inner node 'V', with one child. See testVisitor[...]() below."""
class TypeDeclUnit( node.Node('name: str or None', 'constants: tuple[Constant]', 'type_params: tuple[TypeParameter]', 'classes: tuple[Class]', 'functions: tuple[Function or ExternalFunction]', 'aliases: tuple[Alias]')): """Module node. Holds module contents (constants / classes / functions). Attributes: name: Name of this module, or None for the top-level module. constants: Iterable of module-level constants. type_params: Iterable of module-level type parameters. functions: Iterable of functions defined in this type decl unit. classes: Iterable of classes defined in this type decl unit. aliases: Iterable of aliases (or imports) for types in other modules. """ __slots__ = () def Lookup(self, name): """Convenience function: Look up a given name in the global namespace. Tries to find a constant, function or class by this name. Args: name: Name to look up. Returns: A Constant, Function or Class. Raises: KeyError: if this identifier doesn't exist. """ # TODO(kramm): Put constants, functions, classes and aliases into a # combined dict. try: return self._name2item[name] except AttributeError: self._name2item = {} module_name, _, _ = name.rpartition('.') if module_name == self.name: # The names in this module are fully qualified prefix = self.name + '.' else: prefix = '' for x in self.type_params: # There are hard-coded type parameters in the code (e.g., T for # sequences), so the module prefix must be added here rather than # directly to the parameter names. self._name2item[prefix + x.name] = x for x in self.constants + self.functions + self.classes + self.aliases: if x.name in self._name2item: raise AttributeError( 'Duplicate name %s found: %s and %s' % (x.name, type(self._name2item[x.name]), type(x))) self._name2item[x.name] = x return self._name2item[name] # The hash/eq/ne values are used for caching and speed things up quite a bit. def __hash__(self): return id(self) def __eq__(self, other): return id(self) == id(other) def __ne__(self, other): return id(self) != id(other) def ASTeq(self, other): # Used in tests. return (self.constants == other.constants and self.type_params == other.type_params and self.classes == other.classes and self.functions == other.functions and self.aliases == other.aliases)
class Y(node.Node("c", "d")): """Inner node 'Y', with two children. See testVisitor[...]() below."""
class Node2(node.Node("x", "y")): """For equality testing. Same attributes as Node3.""" pass
class MyNode(node.Node("s: str")): pass
class Literal(node.Node('value: int or str or {Type}'), Type): __slots__ = ()
class Node3(node.Node("x", "y")): """For equality testing: Same attributes as Node2."""
class FunctionType(node.Node('name: str'), Type): """The type of a function. E.g. the type of 'x' in 'x = lambda y: y'.""" def __new__(cls, name, function): self = super(FunctionType, cls).__new__(cls, name) self.function = function return self