def _new_named_tuple(self, class_name: str, fields: List[Tuple[str, Any]]) -> pytd.Class: """Generates a pytd class for a named tuple. Args: class_name: The name of the generated class fields: A list of (name, type) tuples. Returns: A generated class that describes the named tuple. """ class_base = pytdgen.heterogeneous_tuple(pytd.NamedType("tuple"), tuple(t for _, t in fields)) class_constants = tuple(pytd.Constant(n, t) for n, t in fields) # Since the user-defined fields are the only namedtuple attributes commonly # used, we define all the other attributes as Any for simplicity. class_constants += tuple( pytd.Constant(name, pytd.AnythingType()) for name in _NAMEDTUPLE_MEMBERS) methods = function.merge_method_signatures( [self._make_new(class_name, fields), self._make_init()]) return pytd.Class(name=class_name, metaclass=None, bases=(class_base, ), methods=tuple(methods), constants=class_constants, decorators=(), classes=(), slots=tuple(n for n, _ in fields), template=())
def _parameterized_type(self, base_type, parameters): """Return a parameterized type.""" if self._is_literal_base_type(base_type): return types.pytd_literal(parameters) elif any(isinstance(p, types.Constant) for p in parameters): parameters = ", ".join( p.repr_str() if isinstance(p, types.Constant) else "_" for p in parameters) raise ParseError("%s[%s] not supported" % (pytd_utils.Print(base_type), parameters)) elif pytdgen.is_any(base_type): return pytd.AnythingType() elif len(parameters) == 2 and parameters[-1] is self.ELLIPSIS and ( not self._is_callable_base_type(base_type)): element_type = parameters[0] if element_type is self.ELLIPSIS: raise ParseError("[..., ...] not supported") return pytd.GenericType(base_type=base_type, parameters=(element_type, )) else: parameters = tuple(pytd.AnythingType() if p is self.ELLIPSIS else p for p in parameters) if self._is_tuple_base_type(base_type): return pytdgen.heterogeneous_tuple(base_type, parameters) elif self._is_callable_base_type(base_type): return pytdgen.pytd_callable(base_type, parameters) else: assert parameters return pytd.GenericType(base_type=base_type, parameters=parameters)
def _parameterized_type(self, base_type: Any, parameters): """Return a parameterized type.""" if self._matches_named_type(base_type, _LITERAL_TYPES): return pytd_literal(parameters) elif self._matches_named_type(base_type, _ANNOTATED_TYPES): return pytd_annotated(parameters) elif self._matches_named_type(base_type, _FINAL_TYPES): typ, = parameters return pytd.GenericType(pytd.NamedType("typing.Final"), (typ, )) elif self._matches_named_type(base_type, _TYPEGUARD_TYPES): # We do not yet support PEP 647, User-Defined Type Guards. To avoid # blocking typeshed, convert type guards to plain bools. return pytd.NamedType("bool") elif any(isinstance(p, types.Pyval) for p in parameters): parameters = ", ".join( p.repr_str() if isinstance(p, types.Pyval) else "_" for p in parameters) raise ParseError("%s[%s] not supported" % (pytd_utils.Print(base_type), parameters)) elif pytdgen.is_any(base_type): return pytd.AnythingType() elif len(parameters) == 2 and parameters[-1] is self.ELLIPSIS and ( not self._matches_named_type(base_type, _CALLABLE_TYPES)): element_type = parameters[0] if element_type is self.ELLIPSIS: raise ParseError("[..., ...] not supported") return pytd.GenericType(base_type=base_type, parameters=(element_type, )) else: processed_parameters = [] # We do not yet support PEP 612, Parameter Specification Variables. # To avoid blocking typeshed from adopting this PEP, we convert new # features to approximations that only use supported features. for p in parameters: if p is self.ELLIPSIS: processed = pytd.AnythingType() elif (p in self.param_specs and self._matches_full_name( base_type, "typing.Generic")): # Replacing a ParamSpec with a TypeVar isn't correct, but it'll work # for simple cases in which the filled value is also a ParamSpec. if not any(t.name == p.name for t in self.type_params): self.type_params.append(pytd.TypeParameter(p.name)) processed = p elif (p in self.param_specs or (isinstance(p, pytd.GenericType) and self._matches_full_name(p, _CONCATENATE_TYPES))): processed = pytd.AnythingType() else: processed = p processed_parameters.append(processed) parameters = tuple(processed_parameters) if self._matches_named_type(base_type, _TUPLE_TYPES): return pytdgen.heterogeneous_tuple(base_type, parameters) elif self._matches_named_type(base_type, _CALLABLE_TYPES): return pytdgen.pytd_callable(base_type, parameters) else: assert parameters return pytd.GenericType(base_type=base_type, parameters=parameters)
def _parameterized_type(self, base_type, parameters): """Return a parameterized type.""" if self._matches_named_type(base_type, _LITERAL_TYPES): return types.pytd_literal(parameters) elif self._matches_named_type(base_type, _ANNOTATED_TYPES): return types.pytd_annotated(parameters) elif self._matches_named_type(base_type, _TYPEGUARD_TYPES): # We do not yet support PEP 647, User-Defined Type Guards. To avoid # blocking typeshed, convert type guards to plain bools. return pytd.NamedType("bool") elif any(isinstance(p, types.Constant) for p in parameters): parameters = ", ".join( p.repr_str() if isinstance(p, types.Constant) else "_" for p in parameters) raise ParseError("%s[%s] not supported" % (pytd_utils.Print(base_type), parameters)) elif pytdgen.is_any(base_type): return pytd.AnythingType() elif len(parameters) == 2 and parameters[-1] is self.ELLIPSIS and ( not self._matches_named_type(base_type, _CALLABLE_TYPES)): element_type = parameters[0] if element_type is self.ELLIPSIS: raise ParseError("[..., ...] not supported") return pytd.GenericType(base_type=base_type, parameters=(element_type, )) else: parameters = tuple(pytd.AnythingType() if p is self.ELLIPSIS else p for p in parameters) if self._matches_named_type(base_type, _TUPLE_TYPES): return pytdgen.heterogeneous_tuple(base_type, parameters) elif self._matches_named_type(base_type, _CALLABLE_TYPES): callable_parameters = [] for p in parameters: # We do not yet support PEP 612, Parameter Specification Variables. # To avoid blocking typeshed from adopting this PEP, we convert new # features to Any. if p in self.param_specs or (isinstance( p, pytd.GenericType) and self._matches_full_name( p, _CONCATENATE_TYPES)): callable_parameters.append(pytd.AnythingType()) else: callable_parameters.append(p) return pytdgen.pytd_callable(base_type, tuple(callable_parameters)) else: assert parameters return pytd.GenericType(base_type=base_type, parameters=parameters)
def _parameterized_type(self, base_type, parameters): """Return a parameterized type.""" if self._is_literal_base_type(base_type): return types.pytd_literal(parameters) elif any(isinstance(p, types.Constant) for p in parameters): parameters = ", ".join( p.repr_str() if isinstance(p, types.Constant) else "_" for p in parameters) raise ParseError("%s[%s] not supported" % (pytd_utils.Print(base_type), parameters)) elif pytdgen.is_any(base_type): return pytd.AnythingType() elif len(parameters) == 2 and parameters[-1] is self.ELLIPSIS and ( not self._is_callable_base_type(base_type)): element_type = parameters[0] if element_type is self.ELLIPSIS: raise ParseError("[..., ...] not supported") return pytd.GenericType(base_type=base_type, parameters=(element_type, )) else: parameters = tuple(pytd.AnythingType() if p is self.ELLIPSIS else p for p in parameters) if self._is_tuple_base_type(base_type): return pytdgen.heterogeneous_tuple(base_type, parameters) elif self._is_callable_base_type(base_type): callable_parameters = [] for p in parameters: # We do not yet support PEP 612, Parameter Specification Variables. # To avoid blocking typeshed from adopting this PEP, we convert new # features to Any. if p in self.param_specs or (isinstance( p, pytd.GenericType) and self._matches_full_name( p, ("typing.Concatenate", "typing_extensions.Concatenate"))): callable_parameters.append(pytd.AnythingType()) else: callable_parameters.append(p) return pytdgen.pytd_callable(base_type, tuple(callable_parameters)) else: assert parameters return pytd.GenericType(base_type=base_type, parameters=parameters)