mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 14:35:27 +00:00
docs: Add documentation on mypy @overload.
We only use this in a few places, but they're really important places for understanding the types in the codebase, and so it's worth having a bit of expository documentation explaining how we use it. (And I expect we'll add more with time).
This commit is contained in:
@@ -148,6 +148,42 @@ because a list can have many elements, which would make the output too large.
|
|||||||
Similarly in dicts, one key's type and the corresponding value's type are printed.
|
Similarly in dicts, one key's type and the corresponding value's type are printed.
|
||||||
So `{1: 'a', 2: 'b', 3: 'c'}` will be printed as `{int: str, ...}`.
|
So `{1: 'a', 2: 'b', 3: 'c'}` will be printed as `{int: str, ...}`.
|
||||||
|
|
||||||
|
## Using @overload to accurately describe variations
|
||||||
|
|
||||||
|
Sometimes, a function's type is most precisely expressed as a few
|
||||||
|
possibilites, and which possibility can be determined by looking at
|
||||||
|
the arguments. You can express that idea in a way mypy understands
|
||||||
|
using `@overload`. For example, `check_list` returns a `Validator`
|
||||||
|
function that verifies that an object is a list, raising an exception
|
||||||
|
if it isn't.
|
||||||
|
|
||||||
|
It supports being passed a `sub_validator`, which will verify that
|
||||||
|
each element in the list has a given type as well. One can express
|
||||||
|
the idea "If `sub_validator` validates that something is a `ResultT`,
|
||||||
|
`check_list(sub_validator)` validators that something is a
|
||||||
|
`List[ResultT]` as follows:
|
||||||
|
|
||||||
|
~~~ py
|
||||||
|
@overload
|
||||||
|
def check_list(sub_validator: None, length: Optional[int]=None) -> Validator[List[object]]:
|
||||||
|
...
|
||||||
|
@overload
|
||||||
|
def check_list(sub_validator: Validator[ResultT],
|
||||||
|
length: Optional[int]=None) -> Validator[List[ResultT]]:
|
||||||
|
...
|
||||||
|
def check_list(sub_validator: Optional[Validator[ResultT]]=None,
|
||||||
|
length: Optional[int]=None) -> Validator[List[ResultT]]:
|
||||||
|
~~~
|
||||||
|
|
||||||
|
The first overload expresses the types for the case where no
|
||||||
|
`sub_validator` is passed, in which case all we know is that it
|
||||||
|
returns a `Validator[List[object]]`; whereas the second defines the
|
||||||
|
type logic for the case where we are passed a `sub_validator`.
|
||||||
|
|
||||||
|
See the [mypy overloading documentation][mypy-overloads] for more details.
|
||||||
|
|
||||||
|
[mypy-overloads]: https://mypy.readthedocs.io/en/stable/more_types.html#function-overloading
|
||||||
|
|
||||||
## Troubleshooting advice
|
## Troubleshooting advice
|
||||||
|
|
||||||
All of our linters, including mypy, are designed to only check files
|
All of our linters, including mypy, are designed to only check files
|
||||||
|
|||||||
@@ -137,7 +137,10 @@ class _REQ(Generic[ResultT]):
|
|||||||
# functions using has_request_variables. In reality, REQ returns an
|
# functions using has_request_variables. In reality, REQ returns an
|
||||||
# instance of class _REQ to enable the decorator to scan the parameter
|
# instance of class _REQ to enable the decorator to scan the parameter
|
||||||
# list for _REQ objects and patch the parameters as the true types.
|
# list for _REQ objects and patch the parameters as the true types.
|
||||||
|
#
|
||||||
|
# See also this documentation to learn how @overload helps here.
|
||||||
|
# https://zulip.readthedocs.io/en/latest/testing/mypy.html#using-overload-to-accurately-describe-variations
|
||||||
|
#
|
||||||
# Overload 1: converter
|
# Overload 1: converter
|
||||||
@overload
|
@overload
|
||||||
def REQ(
|
def REQ(
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ def check_none_or(sub_validator: Validator[ResultT]) -> Validator[ResultT]:
|
|||||||
return sub_validator(var_name, val)
|
return sub_validator(var_name, val)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
# https://zulip.readthedocs.io/en/latest/testing/mypy.html#using-overload-to-accurately-describe-variations
|
||||||
@overload
|
@overload
|
||||||
def check_list(sub_validator: None, length: Optional[int]=None) -> Validator[List[object]]:
|
def check_list(sub_validator: None, length: Optional[int]=None) -> Validator[List[object]]:
|
||||||
...
|
...
|
||||||
@@ -220,6 +221,7 @@ def check_list(sub_validator: Optional[Validator[ResultT]]=None, length: Optiona
|
|||||||
return cast(List[ResultT], val)
|
return cast(List[ResultT], val)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
# https://zulip.readthedocs.io/en/latest/testing/mypy.html#using-overload-to-accurately-describe-variations
|
||||||
@overload
|
@overload
|
||||||
def check_dict(required_keys: Iterable[Tuple[str, Validator[object]]]=[],
|
def check_dict(required_keys: Iterable[Tuple[str, Validator[object]]]=[],
|
||||||
optional_keys: Iterable[Tuple[str, Validator[object]]]=[],
|
optional_keys: Iterable[Tuple[str, Validator[object]]]=[],
|
||||||
|
|||||||
Reference in New Issue
Block a user