Improve type hints of URL conf & include() (#949)

* Improve type hints of URL conf & include()

The type of `urlpatterns` list is `List[Union[URLPattern, URLResolver]]`.

* https://docs.djangoproject.com/en/dev/ref/urls/#django.urls.include
* https://docs.djangoproject.com/en/4.0/ref/urls/

* Alias _AnyURL = Union[URLPattern, URLResolver]

* Fix extract_views_from_urlpatterns
This commit is contained in:
Marti Raudsepp
2022-05-06 09:00:21 +03:00
committed by GitHub
parent 4a5d330228
commit 1a36c6c379
11 changed files with 72 additions and 28 deletions

View File

@@ -1,10 +1,8 @@
from typing import Callable, List, Tuple, Union
from typing import List, Tuple
from django.urls.resolvers import URLPattern, URLResolver
from django.urls import _AnyURL
def i18n_patterns(
*urls: Union[URLPattern, URLResolver], prefix_default_language: bool = ...
) -> List[Union[URLPattern, URLResolver]]: ...
def i18n_patterns(*urls: _AnyURL, prefix_default_language: bool = ...) -> List[_AnyURL]: ...
def is_language_prefix_patterns_used(urlconf: str) -> Tuple[bool, bool]: ...
urlpatterns: List[Callable]
urlpatterns: List[_AnyURL]

View File

@@ -1,3 +1,5 @@
from typing import Any, List
from typing import List
urlpatterns: List[Any] = ...
from django.urls import _AnyURL
urlpatterns: List[_AnyURL] = ...

View File

@@ -1,6 +1,7 @@
from typing import Any, Optional, Union
from typing import Any, Callable, Iterable, List, Optional, Pattern, Tuple, Union
from django.db.models.fields import Field
from django.urls import _AnyURL
from django.views.generic import TemplateView
MODEL_METHODS_EXCLUDE: Any
@@ -17,5 +18,7 @@ class TemplateDetailView(BaseAdminDocsView): ...
def get_return_data_type(func_name: Any): ...
def get_readable_field_data_type(field: Union[Field, str]) -> str: ...
def extract_views_from_urlpatterns(urlpatterns: Any, base: str = ..., namespace: Optional[Any] = ...): ...
def extract_views_from_urlpatterns(
urlpatterns: Iterable[_AnyURL], base: str = ..., namespace: Optional[str] = ...
) -> List[Tuple[Callable, Pattern[str], Optional[str], Optional[str]]]: ...
def simplify_regex(pattern: str) -> str: ...

View File

@@ -1,3 +1,5 @@
from typing import Any, List
from typing import List
urlpatterns: List[Any] = ...
from django.urls import _AnyURL
urlpatterns: List[_AnyURL] = ...

View File

@@ -1,3 +1,5 @@
from typing import Any, List
from typing import List
urlpatterns: List[Any] = ...
from django.urls import _AnyURL
urlpatterns: List[_AnyURL] = ...

View File

@@ -1,7 +1,7 @@
from typing import Any, List, Optional
from typing import List, Optional
from django.urls.resolvers import URLPattern
from django.urls import URLPattern, _AnyURL
urlpatterns: List[Any] = ...
urlpatterns: List[_AnyURL] = ...
def staticfiles_urlpatterns(prefix: Optional[str] = ...) -> List[URLPattern]: ...

View File

@@ -1,11 +1,11 @@
from typing import Any, Optional, Sequence, Union
from typing import Any, Optional, Sequence
from django.apps.config import AppConfig
from django.core.checks.messages import CheckMessage, Error, Warning
from django.urls.resolvers import URLPattern, URLResolver
from django.urls import _AnyURL
def check_url_config(app_configs: Optional[Sequence[AppConfig]], **kwargs: Any) -> Sequence[CheckMessage]: ...
def check_resolver(resolver: Union[URLPattern, URLResolver]) -> Sequence[CheckMessage]: ...
def check_resolver(resolver: _AnyURL) -> Sequence[CheckMessage]: ...
def check_url_namespaces_unique(app_configs: Optional[Sequence[AppConfig]], **kwargs: Any) -> Sequence[Warning]: ...
def get_warning_for_invalid_pattern(pattern: Any) -> Sequence[Error]: ...
def check_url_settings(app_configs: Optional[Sequence[AppConfig]], **kwargs: Any) -> Sequence[Error]: ...

View File

@@ -1,3 +1,5 @@
from typing import Union
# noinspection PyUnresolvedReferences
from .base import clear_script_prefix as clear_script_prefix
from .base import clear_url_caches as clear_url_caches
@@ -34,3 +36,5 @@ from .resolvers import get_resolver as get_resolver
# noinspection PyUnresolvedReferences
from .utils import get_callable as get_callable
from .utils import get_mod_func as get_mod_func
_AnyURL = Union[URLPattern, URLResolver]

View File

@@ -1,11 +1,15 @@
from types import ModuleType
from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union, overload
from django.urls import URLPattern, URLResolver, _AnyURL
from ..conf.urls import IncludedURLConf
from ..http.response import HttpResponseBase
from .resolvers import URLPattern, URLResolver
_URLConf = Union[str, ModuleType, Sequence[_AnyURL]]
def include(
arg: Any, namespace: Optional[str] = ...
arg: Union[_URLConf, tuple[_URLConf, str]], namespace: Optional[str] = ...
) -> Tuple[Sequence[Union[URLResolver, URLPattern]], Optional[str], Optional[str]]: ...
# path()

View File

@@ -2,6 +2,7 @@ from types import ModuleType
from typing import Any, Callable, Dict, List, Optional, Pattern, Sequence, Tuple, Type, Union, overload
from django.core.checks.messages import CheckMessage
from django.urls import _AnyURL
from django.urls.converters import UUIDConverter
from django.utils.datastructures import MultiValueDict
@@ -96,7 +97,7 @@ class URLPattern:
class URLResolver:
pattern: _Pattern = ...
urlconf_name: Union[str, None, Sequence[Union[URLPattern, URLResolver]]] = ...
urlconf_name: Union[str, None, Sequence[_AnyURL]] = ...
callback: None = ...
default_kwargs: Dict[str, Any] = ...
namespace: Optional[str] = ...
@@ -106,7 +107,7 @@ class URLResolver:
def __init__(
self,
pattern: _Pattern,
urlconf_name: Union[str, None, Sequence[Union[URLPattern, URLResolver]]],
urlconf_name: Union[str, None, Sequence[_AnyURL]],
default_kwargs: Optional[Dict[str, Any]] = ...,
app_name: Optional[str] = ...,
namespace: Optional[str] = ...,
@@ -118,9 +119,9 @@ class URLResolver:
@property
def app_dict(self) -> Dict[str, List[str]]: ...
@property
def urlconf_module(self) -> Union[ModuleType, None, Sequence[Union[URLPattern, URLResolver]]]: ...
def urlconf_module(self) -> Union[ModuleType, None, Sequence[_AnyURL]]: ...
@property
def url_patterns(self) -> List[Union[URLPattern, URLResolver]]: ...
def url_patterns(self) -> List[_AnyURL]: ...
def resolve(self, path: str) -> ResolverMatch: ...
def resolve_error_handler(self, view_type: int) -> Callable: ...
def reverse(self, lookup_view: str, *args: Any, **kwargs: Any) -> str: ...

View File

@@ -1,9 +1,9 @@
- case: test_path_accepts_mix_of_pattern_and_resolver_output
main: |
from typing import List, Tuple, Union
from django.urls import path, URLPattern, URLResolver
from django.urls import path, _AnyURL
def include() -> Tuple[List[Union[URLPattern, URLResolver]], None, None]: ...
def include() -> Tuple[List[_AnyURL], None, None]: ...
path('test/', include())
@@ -16,3 +16,31 @@
def include() -> Tuple[List[URLPattern], None, None]: ...
path('test/', include())
- case: test_urlconf_include
main: |
from typing import List
from django.conf.urls.i18n import urlpatterns as i18n_urlpatterns
from django.contrib.auth.views import LoginView
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import admin
from django.contrib.flatpages import urls as flatpages_urls
from django.urls import _AnyURL, re_path, include, path
foo_patterns: List[_AnyURL] = []
urlpatterns: List[_AnyURL] = [
path('login/', LoginView.as_view(), name='login'),
path('admin/', admin.site.urls),
re_path('^foo/', include(foo_patterns, namespace='foo')),
re_path('^foo/', include((foo_patterns, 'foo'), namespace='foo')),
re_path('^foo/', include(foo_patterns, 'foo')),
path('flat/', include(flatpages_urls)),
path('flat/', include((flatpages_urls, 'static'))),
path('i18n/', include(i18n_urlpatterns)),
path('i18n/', include((i18n_urlpatterns, 'i18n'))),
path('admindocs/', include('django.contrib.admindocs.urls')),
path('admindocs/', include(('django.contrib.admindocs.urls', 'i18n'))),
path('', include(staticfiles_urlpatterns(prefix='static/')))
]