Skip to content

TYP: Mypy workaround for NoDefault #47045

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

Merged
merged 15 commits into from
May 25, 2022
Merged

TYP: Mypy workaround for NoDefault #47045

merged 15 commits into from
May 25, 2022

Conversation

twoertwein
Copy link
Member

@twoertwein twoertwein commented May 17, 2022

This uses the mypy-workaround from https://github.com/python/typeshed/pull/7127/files for NoDefault (works also for pyright).

no_default is public but NoDefault is luckily not public, so it should be fine to do the following:

  • rename the existing NoDefault to _NoDefault (implementation and typing)
  • define NoDefault as NoDefault = Literal[_NoDefault.no_default] (implementation and typing; isinstance checks need to be re-written to use is no_default but all other type annotations can stay the same)
  • no_default "remains" no_default = _NoDefault.no_default (just replacing NoDefault with _NoDefault)

@simonjayhawkins @jreback @Dr-Irv

edit:

Some context: The following will work without mypy errors afterwards:

def foo(x: NoDefault | int) -> int:
    if x is no_default:
        return -1
    return x + 1

@simonjayhawkins simonjayhawkins added the Typing type annotations, mypy/pyright type checking label May 18, 2022
@twoertwein
Copy link
Member Author

Something similar could also be done for NaT and NaTType

@twoertwein twoertwein marked this pull request as ready for review May 18, 2022 16:33
@@ -1082,7 +1082,7 @@ def bdate_range(
name: Hashable = None,
weekmask=None,
holidays=None,
closed: lib.NoDefault = lib.no_default,
closed: Literal["left", "right"] | lib.NoDefault | None = lib.no_default,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the closed annotations seem unrelated but they are a result of this line

@@ -2802,7 +2803,8 @@ class NoDefault(Enum):


# Note: no_default is exported to the public API in pandas.api.extensions
no_default = NoDefault.no_default # Sentinel indicating the default value.
no_default = _NoDefault.no_default # Sentinel indicating the default value.
NoDefault = Literal[_NoDefault.no_default]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of defining NoDefault in lib.pyx and lib.pyi it could be defined in _typing.py (would require changing a lot of import statements)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its actually better where it is as we avoid circular deps this way

Copy link
Contributor

@Dr-Irv Dr-Irv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two comments:

  1. There is a PEP for sentinel values: https://peps.python.org/pep-0661/ so if that PEP is approved, maybe we should use a pattern here that makes it easy for us to switch to using that feature if it gets approved.
  2. There is a lot of usage of Literal["left", "right"] in this PR, so maybe we should create a type for that in _typing.py and use that instead.

@twoertwein
Copy link
Member Author

1. There is a PEP for sentinel values:  https://peps.python.org/pep-0661/ so if that PEP is approved, maybe we should use a pattern here that makes it easy for us to switch to using that feature if it gets approved.

Once we can use this PEP (might take a long time, especially without typing_extensions), we simply need to change the two lines that define NoDefault and no_default on top of this PR (the PEP also encourages is for comparison, not isinstance). Technically, we would then need to change no_default when switching to this PEP which would technically break the API as it is a public symbol.

2. There is a lot of usage of `Literal["left", "right"]` in this PR,  so maybe we should create a type for that in `_typing.py` and use that instead.

Will do

@Dr-Irv
Copy link
Contributor

Dr-Irv commented May 24, 2022

Once we can use this PEP (might take a long time, especially without typing_extensions), we simply need to change the two lines that define NoDefault and no_default on top of this PR (the PEP also encourages is for comparison, not isinstance). Technically, we would then need to change no_default when switching to this PEP which would technically break the API as it is a public symbol.

OK, I see the path forward. However, while no_default is a public symbol, we don't document what it does, so I don't think changing it to be a sentinel will break anything. In any case, that is something that wouldn't need to be done for a few years.

Copy link
Contributor

@Dr-Irv Dr-Irv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this, although I think others should approve as well.

@jreback jreback added this to the 1.5 milestone May 25, 2022
Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mroeschke mroeschke merged commit 1c82694 into pandas-dev:main May 25, 2022
@mroeschke
Copy link
Member

Thanks @twoertwein

@twoertwein twoertwein deleted the NoDefault branch May 26, 2022 01:58
yehoshuadimarsky pushed a commit to yehoshuadimarsky/pandas that referenced this pull request Jul 13, 2022
* TYP: NoDefault

* ix mypy issues; re-write isinstance(..., NoDefault)

* remove two more casts

* ENH: DatetimeArray fields support non-nano (pandas-dev#47044)

* DEPR: groupby numeric_only default (pandas-dev#47025)

* DOC: Clarify decay argument validation in ewm when times is provided (pandas-dev#47026)

* DOC: Fix some typos in pandas/. (pandas-dev#47022)

* remove two more casts

* avoid cast-like annotation

* left/right

* cannot use |

Co-authored-by: jbrockmendel <[email protected]>
Co-authored-by: Richard Shadrach <[email protected]>
Co-authored-by: Matthew Roeschke <[email protected]>
Co-authored-by: Shuangchi He <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Typing type annotations, mypy/pyright type checking
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants