def get_imports_for_annotation(anno: Any) -> ImportMap: """Return the imports (module, name) needed for the type in the annotation""" imports = ImportMap() if ( anno is inspect.Parameter.empty or anno is inspect.Signature.empty or not (isinstance(anno, type) or is_any(anno) or is_union(anno) or is_generic(anno)) or anno.__module__ == 'builtins' ): return imports if is_any(anno): imports['typing'].add('Any') elif _is_optional(anno): imports['typing'].add('Optional') elem_type = _get_optional_elem(anno) elem_imports = get_imports_for_annotation(elem_type) imports.merge(elem_imports) elif is_generic(anno): if is_union(anno): imports['typing'].add('Union') else: imports[anno.__module__].add( _get_import_for_qualname(qualname_of_generic(anno))) elem_types = anno.__args__ or [] for et in elem_types: elem_imports = get_imports_for_annotation(et) imports.merge(elem_imports) else: name = _get_import_for_qualname(anno.__qualname__) imports[anno.__module__].add(name) return imports
def type_to_dict(typ: type) -> TypeDict: """Convert a type into a dictionary representation that we can store. The dictionary must: 1. Be encodable as JSON 2. Contain enough information to let us reify the type """ if is_typed_dict(typ): return typed_dict_to_dict(typ) # Union and Any are special cases that aren't actually types. if is_union(typ): qualname = 'Union' elif is_any(typ): qualname = 'Any' elif is_generic(typ): qualname = qualname_of_generic(typ) else: qualname = typ.__qualname__ d: TypeDict = { 'module': typ.__module__, 'qualname': qualname, } elem_types = getattr(typ, '__args__', None) if elem_types and is_generic(typ): # empty typing.Tuple is weird; the spec says it should be Tuple[()], # which results in __args__ of `((),)` if elem_types == ((),): elem_types = () d['elem_types'] = [type_to_dict(t) for t in elem_types] return d
def _is_optional(anno: Any) -> bool: """Is the supplied annotation an instance of the 'virtual' Optional type? Optional isn't really a type. It's an alias to Union[T, NoneType] """ return ( is_union(anno) and NoneType in anno.__args__ )
def get_type_str(t): mod = t.__module__ if mod == 'typing': if is_union(t): s = _get_union_type_str(t) else: s = str(t) return s elif mod == 'builtins': return t.__qualname__ return mod + '.' + t.__qualname__
def rewrite(self, typ): if is_any(typ): typname = 'Any' elif is_union(typ): typname = 'Union' elif is_generic(typ): typname = name_of_generic(typ) else: typname = getattr(typ, '__name__', None) rewriter = getattr(self, 'rewrite_' + typname, None) if typname else None if rewriter: return rewriter(typ) return self.generic_rewrite(typ)
def rewrite(self, typ): if is_any(typ): typname = 'Any' elif is_union(typ): typname = 'Union' elif is_typed_dict(typ): typname = 'TypedDict' elif is_generic(typ): typname = name_of_generic(typ) else: typname = getattr(typ, '__name__', None) rewriter = getattr(self, 'rewrite_' + typname, None) if typname else None if rewriter: return rewriter(typ) if isinstance(typ, TypeVar): return self.rewrite_type_variable(typ) return self.generic_rewrite(typ)
def type_to_dict(typ: type) -> TypeDict: """Convert a type into a dictionary representation that we can store. The dictionary must: 1. Be encodable as JSON 2. Contain enough information to let us reify the type """ # Union and Any are special cases that aren't actually types. if is_union(typ): qualname = 'Union' elif is_any(typ): qualname = 'Any' elif is_generic(typ): qualname = qualname_of_generic(typ) else: qualname = typ.__qualname__ d: TypeDict = { 'module': typ.__module__, 'qualname': qualname, } elem_types = getattr(typ, '__args__', None) if elem_types and is_generic(typ): d['elem_types'] = [type_to_dict(t) for t in elem_types] return d