ATM we vendor typing_extensions but mypy doesnt recognize it, so we can't actually use it. We should either remove it or make it a dependency.
Comment From: TomAugspurger
So if I do mypy pandas
on a file using something from our vendored typing extensions, mypy will error? Or ignore the types?
Comment From: jorisvandenbossche
Can you also explain what it means to "make it a dependency"? Is that only a developer dependency for when you want to do type checking? Or would it actually be a runtime dependency?
Comment From: jbrockmendel
So if I do mypy pandas on a file using something from our vendored typing extensions, mypy will error? Or ignore the types?
If I import from pandas._vendored.typing_extensions import final
and then incorrectly decorate Index.get_loc
with @final
, mypy will fail to alert me that this is incorrect.
Comment From: jbrockmendel
Can you also explain what it means to "make it a dependency"? Is that only a developer dependency for when you want to do type checking? Or would it actually be a runtime dependency?
I'm not aware of any way to make it a dev-only dependency. AFAIK it would have to be runtime-importable.
Comment From: jorisvandenbossche
And the import can't be hidden behind a if TYPE_CHECKING
clause as we do for other cases, because it are actual functions used as decorators and such, I suppose?
We could have a no-op version of the items we want to use, which we import at runtime, and override them with the actual working versions from typing_extensions behind if TYPE_CHECKING
?
Comment From: jbrockmendel
And the import can't be hidden behind a if TYPE_CHECKING
That's a neat idea, but doesn't do it.
Comment From: jorisvandenbossche
And can you explain why it doesn't do it? (see also my second sentence in the comment above)
(I don't know much about typing, just asking questions)
Comment From: simonjayhawkins
And can you explain why it doesn't do it? (see also my second sentence in the comment above)
i did this in https://github.com/pandas-dev/pandas/pull/27646/files/9aa69fe5491e0b161e679c8f54cbb8f13a48b85a
didn't get any support at the time follow conversation from https://github.com/pandas-dev/pandas/pull/27646#issuecomment-518290328 onwards
Comment From: simonjayhawkins
see also https://github.com/pandas-dev/pandas/issues/34869#issuecomment-669075742 for more discussion and a reference to similar workaround used by pytest for Protocol.
Comment From: jorisvandenbossche
So that seems certainly doable then to have mypy_extensions as a dev dependency, without having it as a runtime dependency
Comment From: simonjayhawkins
and we no longer need to add it explicitly to environment.yaml see https://github.com/pandas-dev/pandas/pull/27646#issuecomment-530970654
Comment From: jbrockmendel
And can you explain why it doesn't do it?
I don't know, can only confirm that I tried it and it didn't work.
see also #34869 (comment) for more discussion and a reference to similar workaround used by pytest for Protocol.
@simonjayhawkins this looks really similar to Joris's suggestion which I was not able to implement succesfully. My prior has nonzero weight on "me messing up", can you confirm whether or not this is viable for us?
Comment From: simonjayhawkins
I'm not sure if we could do everything that we could do if having typing_extensions as a runtime dependency would allow. but if having a runtime dependency is a definite no-no, then some more investigation of possible workarounds is worthwhile.
as a start, have opened #37137 as a POC for Literal in function signatures.
Comment From: MarcoGorelli
if having a runtime dependency is a definite no-no
Is it definitely a no-no? Not that this is a definite reason to include it, but for reference, black
use it:
https://github.com/psf/black/blob/df4dd38a9a2b44c14485948fe8209fa19db2383a/setup.py
install_requires=[
"click>=7.1.2",
"appdirs",
"toml>=0.10.1",
"typed-ast>=1.4.2",
"regex>=2020.1.8",
"pathspec>=0.6, <1",
"dataclasses>=0.6; python_version < '3.7'",
"typing_extensions>=3.7.4; python_version < '3.8'",
"mypy_extensions>=0.4.3",
],
Comment From: simonjayhawkins
re-opening as discussion about having typing_extensions as a dev only dependency or using other workarounds is ongoing.
Comment From: MarcoGorelli
Hi @simonjayhawkins - why not make it a runtime dependency? Wouldn't that be needed to be able to access Literal
and Protocol
in Python3.7?
I realise that there needs to be a really high bar for adding an extra runtime dependency, and this is one case where I think it would really be worth it:
- it means being able to overload functions with inplace: bool
so that we know what the return type is
- tighter typing potentially uncovers bugs
- typing-extensions
is really light - we're talking about a handful of kilobytes https://pypi.org/project/typing-extensions/#files . It has no requirements itself and so won't conflict with anything
- PyTorch and black have it as a non-optional dependency. I'm not advocating for cargo-culting, just pointing out that there's already a precedent for including it as a requirement
Perhaps this is best discussed in the next dev meeting? tagging @pandas-dev/pandas-core @pandas-dev/pandas-triage in case anyone hasn't seen this and has input
EDIT: just saw #37137, which Literal
is indeed used successfully, so my first point no longer stands
Comment From: bashtage
You can just dummy these for Python < 3.8
Something like
from __future__ import annotations
import sys
from typing import TYPE_CHECKING, List
if sys.version_info >= (3,8):
from typing import Literal
if TYPE_CHECKING:
from typing_extensions import Literal
Edit: Soft dependency only needed if developing/type checking on Python 3.7
Comment From: MarcoGorelli
@bashtage from #37137 it seems that this is even simpler if you have from __future__ import annotations
, so...perhaps this can be closed for now? Can reopen if some limitation of this approach comes up
Comment From: bashtage
@MarcoGorelli I don't think annotations
fixes the missing Literal
, at least if you want to be able to type check in Python 3.7.
Comment From: MarcoGorelli
See #37137 though, it seems to work fine there
e.g.
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Literal
def foo(a: Literal[True]) -> None: ...
runs fine in Python3.7, but fails if you remove from __future__ import annotations
Comment From: simonjayhawkins
Hi @simonjayhawkins - why not make it a runtime dependency? Wouldn't that be needed to be able to access
Literal
andProtocol
in Python3.7?
This has been discussed many times before. I have no objection, but others do.
by all means we can discuss again, but would need to get @TomAugspurger and @WillAyd to agree
Comment From: bashtage
Does it type check in Python 3.7?
Comment From: TomAugspurger
Since we're a central part of the scientific python ecosystem, we should have a high bar for taking on dependencies. IMO this doesn't meet that bar.
Comment From: MarcoGorelli
Does it type check in Python 3.7?
As in, can you run mypy
? typing_extensions
is a required dependency of mypy
, so yes, it should be fine.
Anyway, it seems that
if TYPE_CHECKING:
from typing import Literal
works for both running the code, and for type checking it, so it should be OK to avoid adding this as a requirement.
If all that needs to be done until Python3.7 is dropped is to place some imports under if TYPE_CHECKING
, then we don't need this.
I think this can be closed then - if placing these imports under TYPE_CHECKING
has some limitation, then we can reopen and reevaluate whether this meets the bar for inclusion
Comment From: topper-123
My experince in using import typing_extensions
inside if TYPE_CHECKING
in #51480 and #51309 is that everything works as expected, i.e. mypy used the relevant typing_extensions
classes for typing and did catch a lot of things when used.
Maybe someone could corroborate my experiece and see if they see something I didn't?
Comment From: topper-123
typing_extensions
as a dev dependency has been merged into main in #51480, so closing this issue.