Issue
I am using the yarl
library's URL
object.
It has a quasi-private attribute, ._val
, which is a urllib.parse.SplitResult
object but has no type annotation in yarl/__init__.pyi
. (Understandably so, if the developer does not want to formally make it part of the public API.)
However, I have chosen to use URL._val
at my own risk. A dummy example:
# urltest.py
from urllib.parse import SplitResult
from typing import Tuple
from yarl import URL
def foo(u: URL) -> Tuple[str, str, str]:
sr: SplitResult = u._val
return sr[:3]
But mypy
doesn't like this, because it complains:
$ mypy urltest.py
"URL" has no attribute "_val"
So, how can I, within my own project, "tack on" (or extend) an instance attribute annotation to URL
so that it can be used through the rest of my project? I.e.
from yarl import URL
URL._val: SplitResult
# ...
(mypy does not like this either; "Type cannot be declared in assignment to non-self attribute.")
Update
I've tried creating a new stub file, in stubs/yarl/__init__.pyi
:
from urllib.parse import SplitResult
class URL:
_val: SplitResult
And then setting export MYPYPATH='.../stubs'
as described in stub files. However, this overrides, not extends, the existing annotations, so everything but ._val
throws and error:
error: "URL" has no attribute "with_scheme"
error: "URL" has no attribute "host"
error: "URL" has no attribute "fragment"
...and so on.
Solution
Unfortunately, I don't think there's really a way of making "partial" changes to the type hints for some 3rd party library -- at least, not with mypy.
I would instead try one of the following three options:
Just
# type: ignore
the attribute access:def foo(u: URL) -> Tuple[str, str, str]: sr: SplitResult = u._val # type: ignore return sr[:3]
This type-ignore will suppress any error messages that are generated on that line. If you're going to take this approach, I'd also recommend running mypy with the
--warn-unused-ignores
flag, which will report any redundant and unused# type: ignore
statements. It's unlikely this particular# type: ignore
will become redundant as mypy updates/as the stubs for your third party library updates, but it's a nice flag to enable just in general.Talk to the maintainer of this library and see if they're willing to either add a type hint for this attribute (even if it's private), or to expose this information via some new API.
If it helps, there is some precedent for adding type hints even for private or undocumented attributes in Typeshed, the repository of types for the standard library -- see the "What to include" section in their contribution guidelines.
If the library maintainer isn't willing to add this attribute, you could always just fork the stubs for this library, make the change to the forked stubs, and start using that.
I would personally try solution 2 first, followed by solution 1, but that's just me.
Answered By - Michael0x2a
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.