Use Sequence instead of List for path param (#659)

Unlike `List`, which is invariant, `Sequence` is covariant, which lets
`path` accept lists of subsets of the `Union` as well.

I believe this is safe, as django doesn't mutate this input. I found
[this
comment](https://github.com/python/mypy/issues/3351#issuecomment-300447832)
helpful
This commit is contained in:
David Szotten
2021-07-03 11:46:29 +01:00
committed by GitHub
parent cf6952c9df
commit 739b1711a9
3 changed files with 17 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
# Stubs for django.conf.urls (Python 3.5) # Stubs for django.conf.urls (Python 3.5)
from typing import Any, Callable, Dict, List, Optional, overload, Tuple, Union from typing import Any, Callable, Dict, Optional, overload, Sequence, Tuple, Union
from django.http.response import HttpResponse, HttpResponseBase from django.http.response import HttpResponse, HttpResponseBase
@@ -10,7 +10,7 @@ handler403: Union[str, Callable[..., HttpResponse]] = ...
handler404: Union[str, Callable[..., HttpResponse]] = ... handler404: Union[str, Callable[..., HttpResponse]] = ...
handler500: Union[str, Callable[..., HttpResponse]] = ... handler500: Union[str, Callable[..., HttpResponse]] = ...
IncludedURLConf = Tuple[List[Union[URLResolver, URLPattern]], Optional[str], Optional[str]] IncludedURLConf = Tuple[Sequence[Union[URLResolver, URLPattern]], Optional[str], Optional[str]]
def include(arg: Any, namespace: str = ..., app_name: str = ...) -> IncludedURLConf: ... def include(arg: Any, namespace: str = ..., app_name: str = ...) -> IncludedURLConf: ...
@overload @overload
@@ -21,5 +21,5 @@ def url(
def url(regex: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ... def url(regex: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ...
@overload @overload
def url( def url(
regex: str, view: List[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ... regex: str, view: Sequence[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ...
) -> URLResolver: ... ) -> URLResolver: ...

View File

@@ -1,4 +1,4 @@
from typing import Any, List, Optional, Tuple, overload, Callable, Dict, Union from typing import Any, Optional, Sequence, Tuple, overload, Callable, Dict, Union
from .resolvers import URLResolver, URLPattern from .resolvers import URLResolver, URLPattern
from ..conf.urls import IncludedURLConf from ..conf.urls import IncludedURLConf
@@ -6,7 +6,7 @@ from ..http.response import HttpResponseBase
def include( def include(
arg: Any, namespace: Optional[str] = ... arg: Any, namespace: Optional[str] = ...
) -> Tuple[List[Union[URLResolver, URLPattern]], Optional[str], Optional[str]]: ... ) -> Tuple[Sequence[Union[URLResolver, URLPattern]], Optional[str], Optional[str]]: ...
# path() # path()
@overload @overload
@@ -17,7 +17,7 @@ def path(
def path(route: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ... def path(route: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ...
@overload @overload
def path( def path(
route: str, view: List[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ... route: str, view: Sequence[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ...
) -> URLResolver: ... ) -> URLResolver: ...
# re_path() # re_path()
@@ -29,5 +29,5 @@ def re_path(
def re_path(route: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ... def re_path(route: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ...
@overload @overload
def re_path( def re_path(
route: str, view: List[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ... route: str, view: Sequence[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ...
) -> URLResolver: ... ) -> URLResolver: ...

View File

@@ -6,3 +6,13 @@
def include() -> Tuple[List[Union[URLPattern, URLResolver]], None, None]: ... def include() -> Tuple[List[Union[URLPattern, URLResolver]], None, None]: ...
path('test/', include()) path('test/', include())
- case: test_path_accepts_pattern_resolver_union_subset
main: |
from typing import List, Tuple
from django.urls import path, URLPattern
def include() -> Tuple[List[URLPattern], None, None]: ...
path('test/', include())