def test_stringify_type_Literal(): from typing import Literal # type: ignore assert stringify(Literal[1, "2", "\r"]) == "Literal[1, '2', '\\r']" assert stringify(Literal[1, "2", "\r"], "fully-qualified") == "typing.Literal[1, '2', '\\r']" assert stringify(Literal[1, "2", "\r"], "smart") == "~typing.Literal[1, '2', '\\r']"
def test_stringify_mock(): with mock(['unknown']): import unknown assert stringify(unknown) == 'unknown' assert stringify(unknown.secret.Class) == 'unknown.secret.Class' assert stringify(unknown.secret.Class, "smart") == 'unknown.secret.Class'
def test_stringify(): assert stringify(int) == "int" assert stringify(str) == "str" assert stringify(None) == "None" assert stringify(Integral) == "numbers.Integral" assert restify(Struct) == ":class:`struct.Struct`" assert stringify(Any) == "Any"
def test_stringify_type_hints_Callable(): assert stringify(Callable) == "Callable" if sys.version_info >= (3, 7): assert stringify(Callable[[str], int]) == "Callable[[str], int]" assert stringify(Callable[..., int]) == "Callable[[...], int]" else: assert stringify(Callable[[str], int]) == "Callable[str, int]" assert stringify(Callable[..., int]) == "Callable[..., int]"
def test_stringify_type_hints_alias(): MyStr = str MyTuple = Tuple[str, str] assert stringify(MyStr) == "str" assert stringify(MyStr, "smart") == "str" assert stringify(MyTuple) == "Tuple[str, str]" # type: ignore assert stringify(MyTuple, "smart") == "~typing.Tuple[str, str]" # type: ignore
def test_stringify_type_hints_typevars(): T = TypeVar('T') T_co = TypeVar('T_co', covariant=True) T_contra = TypeVar('T_contra', contravariant=True) assert stringify(T) == "T" assert stringify(T_co) == "T_co" assert stringify(T_contra) == "T_contra" assert stringify(List[T]) == "List[T]"
def test_stringify_type_hints_alias(): MyStr = str MyTuple = Tuple[str, str] assert stringify(MyStr, False) == "str" assert stringify(MyStr, True) == "str" assert stringify(MyTuple, False) == "Tuple[str, str]" # type: ignore assert stringify(MyTuple, True) == "~typing.Tuple[str, str]" # type: ignore
def test_stringify_type_hints_containers(): assert stringify(List) == "List" assert stringify(Dict) == "Dict" assert stringify(List[int]) == "List[int]" assert stringify(List[str]) == "List[str]" assert stringify(Dict[str, float]) == "Dict[str, float]" assert stringify(Tuple[str, str, str]) == "Tuple[str, str, str]" assert stringify(Tuple[str, ...]) == "Tuple[str, ...]" assert stringify(List[Dict[str, Tuple]]) == "List[Dict[str, Tuple]]" assert stringify(MyList[Tuple[int, int]]) == "tests.test_util_typing.MyList[Tuple[int, int]]" assert stringify(Generator[None, None, None]) == "Generator[None, None, None]"
def test_stringify_type_hints_string(): assert stringify("int", False) == "int" assert stringify("int", True) == "int" assert stringify("str", False) == "str" assert stringify("str", True) == "str" assert stringify(List["int"], False) == "List[int]" assert stringify(List["int"], True) == "~typing.List[int]" assert stringify("Tuple[str]", False) == "Tuple[str]" assert stringify("Tuple[str]", True) == "Tuple[str]" assert stringify("unknown", False) == "unknown" assert stringify("unknown", True) == "unknown"
def test_stringify_type_hints_string(): assert stringify("int") == "int" assert stringify("int", "smart") == "int" assert stringify("str") == "str" assert stringify("str", "smart") == "str" assert stringify(List["int"]) == "List[int]" assert stringify(List["int"], "smart") == "~typing.List[int]" assert stringify("Tuple[str]") == "Tuple[str]" assert stringify("Tuple[str]", "smart") == "Tuple[str]" assert stringify("unknown") == "unknown" assert stringify("unknown", "smart") == "unknown"
def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any, options: Dict, args: str, retann: str) -> None: """Record type hints to env object.""" try: if callable(obj): annotations = app.env.temp_data.setdefault('annotations', {}) annotation = annotations.setdefault(name, OrderedDict()) sig = inspect.signature(obj) for param in sig.parameters.values(): if param.annotation is not param.empty: annotation[param.name] = typing.stringify(param.annotation) if sig.return_annotation is not sig.empty: annotation['return'] = typing.stringify(sig.return_annotation) except TypeError: pass
def test_stringify_type_hints_pep_585(): assert stringify(list[int]) == "list[int]" assert stringify(list[str]) == "list[str]" assert stringify(dict[str, float]) == "dict[str, float]" assert stringify(tuple[str, str, str]) == "tuple[str, str, str]" assert stringify(tuple[str, ...]) == "tuple[str, ...]" assert stringify(tuple[()]) == "tuple[()]" assert stringify(list[dict[str, tuple]]) == "list[dict[str, tuple]]" assert stringify(type[int]) == "type[int]"
def test_stringify_type_hints_containers(): assert stringify(List) == "List" assert stringify(Dict) == "Dict" assert stringify(List[int]) == "List[int]" assert stringify(List[str]) == "List[str]" assert stringify(Dict[str, float]) == "Dict[str, float]" assert stringify(Tuple[str, str, str]) == "Tuple[str, str, str]" assert stringify(Tuple[str, ...]) == "Tuple[str, ...]" assert stringify(List[Dict[str, Tuple]]) == "List[Dict[str, Tuple]]"
def ref_to_class(class_obj): """ Create the sphinx pending_xref for a class """ class_path = typing.stringify(class_obj) t_ref = pending_xref(refdomain='py', reftype='class', reftarget=class_path) t_ref += nodes.Text(class_path) return t_ref
def test_stringify(): assert stringify(int) == "int" assert stringify(str) == "str" assert stringify(None) == "None" assert stringify(Integral) == "numbers.Integral" assert stringify(Struct) == "struct.Struct" assert stringify(TracebackType) == "types.TracebackType" assert stringify(Any) == "Any"
def test_stringify_type_hints_Callable(): assert stringify(Callable) == "Callable" assert stringify(Callable, "fully-qualified") == "typing.Callable" assert stringify(Callable, "smart") == "~typing.Callable" assert stringify(Callable[[str], int]) == "Callable[[str], int]" assert stringify(Callable[[str], int], "fully-qualified") == "typing.Callable[[str], int]" assert stringify(Callable[[str], int], "smart") == "~typing.Callable[[str], int]" assert stringify(Callable[..., int]) == "Callable[[...], int]" assert stringify(Callable[..., int], "fully-qualified") == "typing.Callable[[...], int]" assert stringify(Callable[..., int], "smart") == "~typing.Callable[[...], int]"
def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any, options: Dict, args: str, retann: str) -> None: """Record type hints to env object.""" if app.config.autodoc_typehints_format == 'short': mode = 'smart' else: mode = 'fully-qualified' try: if callable(obj): annotations = app.env.temp_data.setdefault('annotations', {}) annotation = annotations.setdefault(name, OrderedDict()) sig = inspect.signature(obj, type_aliases=app.config.autodoc_type_aliases) for param in sig.parameters.values(): if param.annotation is not param.empty: annotation[param.name] = typing.stringify(param.annotation, mode) if sig.return_annotation is not sig.empty: annotation['return'] = typing.stringify(sig.return_annotation, mode) except (TypeError, ValueError): pass
def test_stringify_type_hints_typevars(): T = TypeVar('T') T_co = TypeVar('T_co', covariant=True) T_contra = TypeVar('T_contra', contravariant=True) if sys.version_info < (3, 7): assert stringify(T) == "T" assert stringify(T_co) == "T_co" assert stringify(T_contra) == "T_contra" assert stringify(List[T]) == "List[T]" else: assert stringify(T) == "tests.test_util_typing.T" assert stringify(T_co) == "tests.test_util_typing.T_co" assert stringify(T_contra) == "tests.test_util_typing.T_contra" assert stringify(List[T]) == "List[tests.test_util_typing.T]" if sys.version_info >= (3, 10): assert stringify(MyInt) == "tests.test_util_typing.MyInt" else: assert stringify(MyInt) == "MyInt"
def test_stringify_type_hints_Union(): assert stringify(Optional[int]) == "Optional[int]" assert stringify(Union[str, None]) == "Optional[str]" assert stringify(Union[int, str]) == "Union[int, str]" if sys.version_info >= (3, 7): assert stringify(Union[int, Integral]) == "Union[int, numbers.Integral]" assert (stringify(Union[MyClass1, MyClass2]) == "Union[test_util_typing.MyClass1, test_util_typing.<MyClass2>]") else: assert stringify(Union[int, Integral]) == "numbers.Integral" assert stringify(Union[MyClass1, MyClass2]) == "test_util_typing.MyClass1"
def format_as_markdown_list(section_body, types: dict = None, aliases: dict = None): section_body = re.sub(r'\n([^ ].*?):', r'\n- __\1__:', section_body) section_body = re.sub(r'^([^ ].*?):', r'- __\1__:', section_body) # Optionally add type annotations to docstring if types: for arg, arg_type in types.items(): type_hint_str = apply_aliases(stringify(arg_type), aliases) section_body = re.sub(rf"(- __{arg}__)", rf"\1 `{type_hint_str}`", section_body) return section_body
def test_stringify_type_union_operator(): assert stringify(int | None) == "int | None" # type: ignore assert stringify(int | None, "smart") == "int | None" # type: ignore assert stringify(int | str) == "int | str" # type: ignore assert stringify(int | str, "smart") == "int | str" # type: ignore assert stringify(int | str | None) == "int | str | None" # type: ignore assert stringify(int | str | None, "smart") == "int | str | None" # type: ignore
def test_stringify_type_union_operator(): assert stringify(int | None, False) == "int | None" # type: ignore assert stringify(int | None, True) == "int | None" # type: ignore assert stringify(int | str, False) == "int | str" # type: ignore assert stringify(int | str, True) == "int | str" # type: ignore assert stringify(int | str | None, False) == "int | str | None" # type: ignore assert stringify(int | str | None, True) == "int | str | None" # type: ignore
def add_content(self, more_content, no_docstring=False): # This is a modified version of autodoc.ClassDocumenter.add_content # that changes the module name for aliases no_docstring = False if self.doc_as_attr: fullname = stringify(self.object) modname = self.env.config["autoautosummary_change_modules"].get( fullname, ".".join(fullname.split(".")[:-1]) ) more_content = StringList( [_(f"alias of :class:`{modname}.{fullname.split('.')[-1]}`")], source="" ) no_docstring = True # no_docstring only needs to be specified in sphinx<3.4 # pylint: disable=bad-super-call super(autodoc.ClassDocumenter, self).add_content( more_content, no_docstring=no_docstring )
def test_stringify_broken_type_hints(): assert stringify(BrokenType) == 'tests.test_util_typing.BrokenType'
def test_stringify_type_union_operator(): assert stringify(int | None) == "Optional[int]" # type: ignore assert stringify(int | str) == "int | str" # type: ignore assert stringify(int | str | None) == "Optional[int | str]" # type: ignore
def test_stringify_type_hints_custom_class(): assert stringify(MyClass1) == "tests.test_util_typing.MyClass1" assert stringify(MyClass2) == "tests.test_util_typing.<MyClass2>"
def test_stringify_Annotated(): from typing import Annotated # type: ignore assert stringify(Annotated[str, "foo", "bar"]) == "str" # NOQA
def test_stringify_type_Literal(): from typing import Literal # type: ignore assert stringify(Literal[1, "2", "\r"]) == "Literal[1, '2', '\\r']"
def test_stringify_type_hints_custom_class(): assert stringify(MyClass1, False) == "tests.test_util_typing.MyClass1" assert stringify(MyClass1, True) == "~tests.test_util_typing.MyClass1" assert stringify(MyClass2, False) == "tests.test_util_typing.<MyClass2>" assert stringify(MyClass2, True) == "~tests.test_util_typing.<MyClass2>"
def test_stringify_mock(): with mock(['unknown']): import unknown assert stringify(unknown.secret.Class, False) == 'unknown.secret.Class' assert stringify(unknown.secret.Class, True) == 'unknown.secret.Class'