-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typing changes in 8.1.4 cause failure of mypy check #2558
Comments
To anyone seeing or voting on this issue: Happy to review a PR. |
We ran into this as well. Unfortunately I won't be able to work on a fix for several hours at least, but I'm happy to try things out and submit a PR if I can. If someone else gets to it first, I'd also be happy to help review and check the fix against our codebase if that would be useful. I think the issue stems from the definition of the I put together a reproducer for the import typing as t
from click import Command
T = t.TypeVar("T")
_AnyCallable: t.TypeAlias = t.Callable[..., t.Any]
_Decorator: t.TypeAlias = t.Callable[[T], T]
FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command])
def option() -> _Decorator[FC]:
def decorator(f: FC) -> FC:
return f
return decorator
FC2: t.TypeAlias = t.Union[_AnyCallable, Command]
FC2_Decorator: t.TypeAlias = t.Callable[[FC2], FC2]
def option2() -> FC2_Decorator:
def decorator(f: FC) -> FC:
return f
return decorator
def foo() -> None:
pass
reveal_type(option)
reveal_type(option2)
foo = option()(foo)
foo2 = option2()(foo) |
There is a typing issue with click decorators: pallets/click#2558 [ghstack-poisoned]
There is a typing issue with click decorators: pallets/click#2558 ghstack-source-id: 26c468f16e6e67dc4aed70ee7d65e1696ea1755a Pull Request resolved: #339
There is a typing issue with click decorators: pallets/click#2558 [ghstack-poisoned]
There is a typing issue with click decorators: pallets/click#2558 ghstack-source-id: 26c468f16e6e67dc4aed70ee7d65e1696ea1755a Pull Request resolved: #339
A minor note: I'm now fairly certain that my "solution" above is incorrect. If It might be okay to use |
I'm guessing the right way to type these decorators is to use the facilities described here, which are intended to deal with exactly this problem of decorating functions that may have arbitrary signatures: https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators |
That was what I used originally. It was apparently lacking, because we continue to get reports from users saying that their type checker doesn't like something, then we add more complexity to the type, then something else isn't correct, etc. Python's and mypy's implementation of typing can be a huge mess sometimes. Whoever is going to change this, be sure to follow |
Taking a quick look at this. Would you consider changing the signature of def option(
*param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any
) -> t.Callable[[FC], FC]: ? This syntax is equivalent to what we have today. The current implementation with a generic type alias might be a little too much for Mypy at this time (I'm getting After that, I think this overload is the issue: # variant: name omitted, cls _must_ be a keyword argument, @command(cmd=CommandCls, ...)
# The correct way to spell this overload is to use keyword-only argument syntax:
# def command(*, cls: t.Type[CmdType], **attrs: t.Any) -> ...
# However, mypy thinks this doesn't fit the overloaded function. Pyright does
# accept that spelling, and the following work-around makes pyright issue a
# warning that CmdType could be left unsolved, but mypy sees it as fine. *shrug*
@t.overload
def command(
name: None = None,
cls: t.Type[CmdType] = ...,
**attrs: t.Any,
) -> t.Callable[[_AnyCallable], CmdType]:
... If I comment it out, the example type-checks. So we need to figure out how to fix it. Given the comment, it might not be super easy. |
Like the @t.overload
def command(
name: None = None,
*,
cls: t.Type[CmdType],
**attrs: t.Any,
) -> t.Callable[[_AnyCallable], CmdType]:
... The comment also mentions this doesn't actually pass Mypy. Now I haven't really used custom command in click, so I googled and found this example from the official docs: https://click.palletsprojects.com/en/8.1.x/advanced/#command-aliases. It looks like this example might be exercising the problematic overload? If I try pasting the first part of the example into a file, Mypy seems to work fine with it: import click
class AliasedGroup(click.Group):
def get_command(self, ctx, cmd_name):
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv
matches = [x for x in self.list_commands(ctx) if x.startswith(cmd_name)]
if not matches:
return None
elif len(matches) == 1:
return click.Group.get_command(self, ctx, matches[0])
ctx.fail(f"Too many matches: {', '.join(sorted(matches))}")
def resolve_command(self, ctx, args):
# always return the full command name
_, cmd, args = super().resolve_command(ctx, args)
return cmd.name if cmd is not None else None, cmd, args
@click.command(cls=AliasedGroup)
def cli():
pass
reveal_type(cli) # note: Revealed type is "a02.AliasedGroup" So maybe Mypy fixed this in the meantime and we can use the proper overload variant? |
I'm fine with changing signatures. I'm also fine with writing the "right" type for people using Click, even if mypy doesn't like it when checking Click itself; we can just add ignores and comments. Another wrinkle in this, as shown by that comment, is that people want both mypy and pyright to work, and they have different behaviors regarding decorators. |
I can put together a PR over the weekend. How about I set up some typing tests too (by stealing them from @hynek in attrs)? |
That would be great! We added some typing tests to Flask after talking with Hynek at PyCon. The |
Happy to review a PR. |
…ompatible Fiona, temporarily pin click to <8.1.4 to avoid mypy type check failures (pallets/click#2558), and pin pandas to 1.5.3 until pandas 2.0 is more thoroughly tested.
I think this is still broken but maybe I'm doing something incorrectly:
import click
@click.group(context_settings={'help_option_names': ['-h', '--help']}, invoke_without_command=True)
@click.version_option(version='0.1.0', prog_name='ddev')
@click.pass_context
def ddev(ctx: click.Context):
print('ddev')
@click.command(name='ci')
@click.pass_context
def ci(ctx: click.Context):
print('ci')
ddev.add_command(ci)
def main():
return ddev(prog_name='ddev', windows_expand_args=False)
if __name__ == '__main__':
main() |
…orarily pin click to <8.1.4 to avoid mypy type check failure (pallets/click#2558), and pin pandas to 1.5.3 until pandas 2.x has been more thoroughly tested.'
Oh indeed that fixes it:
|
…nd add github actions CI (#7) * use functools.lru_cache to please python 3.8 fixes #6 * ignore mypy huggingface-hub * add basic tests for ci * limit click versions to please mypy related to pallets/click#2558
* use pytorch 2.0.0 as base image * install g++ * do not remove gcc * import torch to please jit compiler * move custom model impls to custom_models namespace * refactor to use wsinfer-zoo * run isort and then black * rm modeldefs + make modellib and patchlib public (no underscore) * do not use torch.compile on torchscript models * Fix/issue 131 (#133) * use tifffile in lieu of large_image * run isort * make outputs float or None * changes to please mypy * add newline at end of document * add openslide-python and tifffile to core deps * add back roi support and mps device caps * black formatting * rm unused file * add wsinfer-zoo to deps * predownload registry JSON + install system deps in early layer * scale step size and print info Fixes #135 * add patchlib presets to package data and rm modeldefs * set default step_size to None * only allow step-size=patch-size * allow custom step sizes * update mpp print logs to slide mpp * add tiff mpp via openslide * resize patches to prescribed patch size and spacing * add model config schema * add schemas to package data * fix error messages Replace `--model-name` with `--model`. * create OpenSlide obj in worker_init func Fixes #137 The OpenSlide object is no longer created in `__init__`. Previously the openslide object was shared across workers. Now each worker creates its own OpenSlide object. I hypothesize that this will allow multi-worker data loading on Windows. * handle num_workers=0 * ADD choice of backends (tiffslide or openslide) (#139) * replace openslide with tiffslide * patch zarr to avoid decoding tiles in duplicate This implements the change proposed in zarr-developers/zarr-python#1454 * rm openslide-python and add tiffslide * do not stitch because it imposes a performance penalty * ignore types in vis_params * add isort and tiffslide to dev deps * add NoBackendException * run isort * use wsinfer.wsi module instead of slide_utils and add tiffslide and openslide backends * use wsinfer.wsi.WSI as generic entrypoint for whole slides * replace PathType with "str | Path" * add logging and backend selection to cli * add "from __future__ import annotations" * TST: update tests for dev branch (#143) * begin to update tests * do not resize images prior to transform This introduces subtle differences from the current stable version of wsinfer. * fix for issue #125 * do not save slide path in model outputs csv * add test_cli_run_with_registered_models * add reference model outputs These reference outputs were created using a patched version of 0.3.6 wsinfer. The patches involved padding the patches from large-image to be the expected patch size. Large image does not pad images by default, whereas openslide and tiffslide pad with black. * skip jit tests and cli with custom config * deprecate python 3.7 * install openslide and tiffslide * remove WSIType object * remove dense grid creation fixes #138 * remove timm and custom models We will focus on using TorchScript models only. In the future, we can also look into using ONNX as a backend. fixes #140 * limit click versions to please mypy related to pallets/click#2558 * satisfy mypy * fix cli args for wsinfer run * fail loudly with dev pytorch + fix jit compile tests * fix test of issue 89 * move wsinfer imports to beginning of file * add test of mutually exclusive cli args * use -p shorthand for model-path * mark that we support typing * add py.typed to package data * run test-package on windows, macos, and linux * fix test of patching * install openslide differently on different systems * close the case statement * fix the way we install openslide on different envs * fix matrix.os test * get line length with python for cross-platform * test "wsinfer run" differently for unix and windows * fix windows test * fix path to csv * skip windows tests for now because tissue segmentation is different * run "wsinfer run" on windows but do not test file length * add test of local model with config
I'm still experiencing this issue, the examples in https://click.palletsprojects.com/en/8.1.x/quickstart/#nesting-commands fail to typecheck under MyPy 1.4.1. I imagine whatever type adjustments were done to import click
@click.group()
def cli():
pass
@cli.command()
def initdb():
click.echo('Initialized the database')
@cli.command()
def dropdb():
click.echo('Dropped the database') ❯ python3 -m pip list
Package Version
----------------- -------
click 8.1.5
mypy 1.4.1
mypy-extensions 1.0.0
pip 23.1.2
setuptools 68.0.0
typing_extensions 4.7.1
❯ mypy --pretty example.py
example.py:7: error: <nothing> has no attribute "command" [attr-defined]
@cli.command()
^~~~~~~~~~~
example.py:11: error: <nothing> has no attribute "command" [attr-defined]
@cli.command()
^~~~~~~~~~~
Found 2 errors in 1 file (checked 1 source file) |
Can you try #2565? |
Can confirm #2565 resolves this issue for me. Thanks! Now to wait for 8.1.6... |
This comment was marked as off-topic.
This comment was marked as off-topic.
Locking to avoid "me too" comments. |
These type: pragmas can be removed when click 8.1.6 is out, to fix pallets/click#2558.
Click 8.1.6 is available on PyPI. |
For anyone that runs mypy with pre-commit, make sure to add |
For more context, see Click issue: pallets/click#2558 At this point, click 8.1.6 is released and fixes can be reverted.
Click's simple example https://github.com/pallets/click#a-simple-example doesn't pass mypy 1.4.1 since 8.1.4. With click 8.1.3 the example did pass. This affects not only the simple example but also existing projects that use click. I ran mypy on one of my projects and everything passed, ran it 30 minutes later and saw failures out of the blue. Click 8.1.4 was published to PyPI between my checks.
To reproduce:
pip install mypy==1.4.1 click==8.1.3
mypy click.py
This is the output:
Environment:
The text was updated successfully, but these errors were encountered: