click
click copied to clipboard
Make ProgressBar type available in public interface
mypy
considers function click.progressbar()
as generic with type parameter V
: https://github.com/pallets/click/blob/ca5e1c3d75e95cbc70fa6ed51ef263592e9ac0d0/src/click/termui.py#L287-L303
In most cases type parameter V
will be inferred from iterable
function parameter:
from typing import reveal_type
import click
with click.progressbar([1, 2, 3]) as bar:
reveal_type(bar) # Revealed type is "click._termui_impl.ProgressBar[builtins.int]"
However, if iterable
parameter is not specified (or if it's empty list), type parameter V
cannot be inferred:
import click
with click.progressbar(length=1) as bar:
pass
$ mypy mypy_click/__init__.py
mypy_click/__init__.py:3: error: Need type annotation for "bar" [var-annotated]
This issue can be solved with manually specified type parameter:
import click
with click.progressbar[int](length=1) as bar:
pass
Unfortunately, this doesn't work for functions:
$ mypy mypy_click/
mypy_click/__init__.py:3: error: Type application is only supported for generic classes [misc]
Another way to fix this is specify type for variable bar
:
from typing import cast
import click
from click._termui_impl import ProgressBar
with cast(ProgressBar[int], click.progressbar(length=1)) as bar:
pass
# or
with click.progressbar(length=1) as bar: # type: ProgressBar[int]
pass
But in this case ProgressBar
is imported as not a part of public interface.
So, I think ProgressBar
type should be a part of the public interface. Maybe it should not
be exported directly like class, because users should use click.progressbar()
function instead.
Public ProgressBar
type can be defined as protocol and click.progressbar()
just returns its implementation.
Environment:
- Python version: 3.11.5
- Click version: 8.1.7
- Mypy version: 1.6.1
Also possible to use function overloading to solve the problem above with inference of type parameter V
:
@overload
def progressbar(iterable: Optional[Iterable[V]], ...) -> ProgressBar[V]: ...
@overload
def progressbar(length: int, ...) -> ProgressBar[int]: ...
Anyway, return type of the function should be public.