-
Notifications
You must be signed in to change notification settings - Fork 233
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
make wrapt a PEP561 typed package. #225
base: develop
Are you sure you want to change the base?
Conversation
not sure if the name have to be "wrapt.pyi" or "py.typed" - that needs to be tested.
correction : not sure if the name have to be "wrapt.pyi" or "wrappers.pyi" - that needs to be tested. |
Is the |
oh, sorry, yes, the |
Kind poke! |
I think you're correct. Typically, there's 1-1 for .py and .pyi file (technically one for each module), like in At the same time, I think (but I can't find the reference) that stub package can be shipped in a form of a single file, and that would be |
For a very matured project like wrapt I think its better to work with *.pyi files, because signatures dont change that frequently.
I never worked with pylance , I use pycharm - I am almost sure with pycharm that is not the case, but i did not try.
I would guess that 99% of the users only use the wrapt decorator and nothing else. So, to type check that, the signature of the wrapt decorator would be enough, and You can add signatures gradually as needed. Besides the "offline" type checkers, there is also a wonderful runtime type checker : https://github.com/beartype/beartype maybe You can team up with @leycec - he is a "Runtime type-checking aficionado. " |
stubs can be marked as |
💪 🐻 @leycec has been summoned to the chat. The chat proceeds to descend into chaos. Actually, I humbly agree with everything @bitranox has wisely spouted above – except this:
Yes. I strongly agree with this. In 2023, I see vanishingly few Pure-Python
Actually, it's probably the opposite; well-annotated That said, your mileage may vary (YMMV). This has been a public service announcement from the @beartype Broadcasting Service. Please do let me know if there is anything @beartype can explicitly do for |
@leycec , always funny and precise comments, love it. |
T = TypeVar("T", bound=Any) | ||
|
||
def decorator(wrapper: F, enabled: Optional[bool] = None, adapter: Optional[A] = None) -> F: ... | ||
|
||
class ObjectProxy(Generic[T]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that pyi files should also follow pep-8, which means 2 blank lines between functions and classes declared at the module scope.
Maybe just run ruff
or black
to auto-format this file?
A = TypeVar('A', bound=Callable[..., Any]) | ||
T = TypeVar("T", bound=Any) | ||
|
||
def decorator(wrapper: F, enabled: Optional[bool] = None, adapter: Optional[A] = None) -> F: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to microsoft/pyright#5929 the re-export in __init__.py
needs to be updated too.
For example, from .decorators import decorator as decorator
The issue affects pyright
but not mypy
.
You can test this by e.g.
poetry add git+https://github.com/GrahamDumpleton/wrapt.git#a2dddf6e10536f4cd4bfc96ff1a706cd71b0694c
poetry add pyright
poetry add mypy
pyright some_test_file.py
mypy some_test_file.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative to from ... import A as A
would be to provide explicit __all__
in wrapt/__init__.py
.
Latest version of wrapt requires Python 3.6+ and in #261 someone recently suggested requiring Python 3.8+. So maybe someone wants to have a go at a separate PR now which embeds annotations in the code. Would appreciate it starting with core functionality first so I can follow along, learn, and verify myself since am not knowledgeable about using type annotations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This did not work for me, so I managed to type the wrapt.decorator
in a different way, I think it's Py 3.7+
from typing import Any, Callable, Optional, TypeVar, Tuple, Dict, Protocol
R = TypeVar('R', covariant=True) # Return type of the function
T = TypeVar('T') # Type of instance (for methods)
class FuncProtocol(Protocol[R]):
def __call__(self, *args: Any, **kwargs: Any) -> R: ...
def decorator(
wrapper: Callable[
[
FuncProtocol[R],
Optional[T],
Tuple[Any, ...],
Dict[str, Any]],
R],
enabled: Optional[bool] = None
) -> FuncProtocol[R]: ...
https://gist.github.com/dimaqq/e4b418e1b9ce6a3cd874ba9540fe42c6
not sure if the name have to be "wrapt.pyi" or "py.typed" - that needs to be tested.