diff --git a/django-stubs/urls/converters.pyi b/django-stubs/urls/converters.pyi index b8fb3ad16..a8c07a601 100644 --- a/django-stubs/urls/converters.pyi +++ b/django-stubs/urls/converters.pyi @@ -1,6 +1,12 @@ -from typing import Any +from typing import Any, Protocol from uuid import UUID +class _Converter(Protocol): + regex: str + def __init__(self) -> None: ... + def to_python(self, value: str) -> Any: ... + def to_url(self, value: Any) -> str: ... + class IntConverter: regex: str def to_python(self, value: str) -> int: ... @@ -19,9 +25,9 @@ class UUIDConverter: class SlugConverter(StringConverter): ... class PathConverter(StringConverter): ... -DEFAULT_CONVERTERS: dict[str, Any] -REGISTERED_CONVERTERS: dict[str, Any] +DEFAULT_CONVERTERS: dict[str, _Converter] +REGISTERED_CONVERTERS: dict[str, _Converter] -def register_converter(converter: type[Any], type_name: str) -> None: ... -def get_converters() -> dict[str, Any]: ... -def get_converter(raw_converter: str) -> Any: ... +def register_converter(converter: type[_Converter], type_name: str) -> None: ... +def get_converters() -> dict[str, _Converter]: ... +def get_converter(raw_converter: str) -> _Converter: ... diff --git a/tests/typecheck/urls/test_converters.yml b/tests/typecheck/urls/test_converters.yml new file mode 100644 index 000000000..0c396dafe --- /dev/null +++ b/tests/typecheck/urls/test_converters.yml @@ -0,0 +1,36 @@ +- case: test_register_converter_builtin + main: | + from django.urls import register_converter + from django.urls.converters import IntConverter + + register_converter(IntConverter, "bigint") + +- case: test_register_converter_custom + main: | + from django.urls import register_converter + + class BigIntConverter: + regex = r"[0-9]+" + + def to_python(self, value: str) -> int: + return int(value) + + def to_url(self, value: int) -> str: + return str(value) + + register_converter(BigIntConverter, "bigint") + +- case: test_register_converter_incorrect_types + main: | + from django.urls import register_converter + + class BigIntConverter: + regex = r"[0-9]+" + + def to_python(self, value: int) -> str: + return str(value) + + def to_url(self, value: str) -> int: + return int(value) + + register_converter(BigIntConverter, "bigint") # E: Argument 1 to "register_converter" has incompatible type "Type[BigIntConverter]"; expected "Type[_Converter]" [arg-type]