Skip to content

TYP: annotations in indexes #31181

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 24 commits into from
Jan 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
21ff7c6
annotations
jbrockmendel Jan 15, 2020
172a923
annotations
jbrockmendel Jan 15, 2020
e842524
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 15, 2020
9f8d03f
annotate
jbrockmendel Jan 15, 2020
6235606
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 15, 2020
294f625
annotations
jbrockmendel Jan 15, 2020
e352231
annotate
jbrockmendel Jan 15, 2020
964b7b1
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 15, 2020
06fde05
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 16, 2020
9e5ca95
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 16, 2020
2252c9f
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 17, 2020
6015551
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 17, 2020
585f1fb
rebase
jbrockmendel Jan 17, 2020
e49ebbd
rebase
jbrockmendel Jan 17, 2020
2f54a48
merge
jbrockmendel Jan 17, 2020
b2f195b
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 17, 2020
ac64bb0
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 19, 2020
d16a3a3
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 21, 2020
4288cd2
cln
jbrockmendel Jan 21, 2020
2ab8e3e
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 21, 2020
b85bea3
blackify
jbrockmendel Jan 21, 2020
87f5311
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 21, 2020
c15ca51
Merge branch 'master' of https://github.com/pandas-dev/pandas into cl…
jbrockmendel Jan 22, 2020
9f188ed
suggested edits
jbrockmendel Jan 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions pandas/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import builtins
import textwrap
from typing import Dict, FrozenSet, List, Optional
from typing import Dict, FrozenSet, List, Optional, Union

import numpy as np

Expand Down Expand Up @@ -112,7 +112,7 @@ def _freeze(self):
object.__setattr__(self, "__frozen", True)

# prevent adding any attribute via s.xxx.new_attribute = ...
def __setattr__(self, key, value):
def __setattr__(self, key: str, value):
# _cache is used by a decorator
# We need to check both 1.) cls.__dict__ and 2.) getattr(self, key)
# because
Expand Down Expand Up @@ -241,7 +241,7 @@ def __getitem__(self, key):
raise KeyError(f"Column not found: {key}")
return self._gotitem(key, ndim=1)

def _gotitem(self, key, ndim, subset=None):
def _gotitem(self, key, ndim: int, subset=None):
"""
sub-classes to define
return a sliced object
Expand Down Expand Up @@ -607,6 +607,11 @@ class IndexOpsMixin:
["tolist"] # tolist is not deprecated, just suppressed in the __dir__
)

@property
def _values(self) -> Union[ExtensionArray, np.ndarray]:
# must be defined here as a property for mypy
raise AbstractMethodError(self)

def transpose(self, *args, **kwargs):
"""
Return the transpose, which is by definition self.
Expand All @@ -632,6 +637,10 @@ def shape(self):
"""
return self._values.shape

def __len__(self) -> int:
Copy link
Member

Choose a reason for hiding this comment

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

What error was this throwing? Slightly hesitant to do something like this as it could interfere with Mixins that define this otherwise

Copy link
Member Author

Choose a reason for hiding this comment

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

pandas/core/base.py:1343: error: Argument 1 to "len" has incompatible type "IndexOpsMixin"; expected "Sized"

Copy link
Member

Choose a reason for hiding this comment

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

It might make sense to just ignore that line; I think mypy generally doesn't play nice with Mixins so may be a few things like this, but I would imagine the intent is for that to be defined by whatever gets composed with this class

Not a big deal for me either way maybe just a note for other reviewers. Otherwise this lgtm

Copy link
Member Author

Choose a reason for hiding this comment

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

@simonjayhawkins thoughts here?

Copy link
Member

Choose a reason for hiding this comment

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

perhaps for consistency with addition for _values above, __len__ could raise AbstractMethodError instead?

another alternative could be to add a type declaration at the top of the class instead,
__len__: Callable[..., int]

or ignore as @WillAyd suggested.

# We need this defined here for mypy
raise AbstractMethodError(self)

@property
def ndim(self) -> int:
"""
Expand Down Expand Up @@ -666,14 +675,14 @@ def item(self):
raise ValueError("can only convert an array of size 1 to a Python scalar")

@property
def nbytes(self):
def nbytes(self) -> int:
"""
Return the number of bytes in the underlying data.
"""
return self._values.nbytes

@property
def size(self):
def size(self) -> int:
"""
Return the number of elements in the underlying data.
"""
Expand Down Expand Up @@ -1079,7 +1088,14 @@ def hasnans(self):
return bool(isna(self).any())

def _reduce(
self, op, name, axis=0, skipna=True, numeric_only=None, filter_type=None, **kwds
self,
op,
name: str,
axis=0,
skipna=True,
numeric_only=None,
filter_type=None,
**kwds,
):
""" perform the reduction type operation if we can """
func = getattr(self, name, None)
Expand Down Expand Up @@ -1275,7 +1291,7 @@ def unique(self):

return result

def nunique(self, dropna=True):
def nunique(self, dropna: bool = True) -> int:
"""
Return number of unique elements in the object.

Expand Down Expand Up @@ -1316,7 +1332,7 @@ def nunique(self, dropna=True):
return n

@property
def is_unique(self):
def is_unique(self) -> bool:
"""
Return boolean if values in the object are unique.

Expand All @@ -1327,7 +1343,7 @@ def is_unique(self):
return self.nunique(dropna=False) == len(self)

@property
def is_monotonic(self):
def is_monotonic(self) -> bool:
"""
Return boolean if values in the object are
monotonic_increasing.
Expand All @@ -1340,7 +1356,11 @@ def is_monotonic(self):

return Index(self).is_monotonic

is_monotonic_increasing = is_monotonic
@property
def is_monotonic_increasing(self) -> bool:
"""alias for is_monotonic"""
# mypy complains if we alias directly
Copy link
Member

Choose a reason for hiding this comment

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

probably don't need the comment.

In Index, is_monotonic is an alias for is_monotonic_increasing, whereas here is_monotonic_increasing is an alias for is_monotonic. Would it make sense to make these consistent instead?

Although without going deeper, looks strange that is_monotonic returns Index(self).is_monotonic, maybe the code there, should be here.

Copy link
Member Author

Choose a reason for hiding this comment

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

maybe the code there, should be here.

it does seem a little weird, but its because this gets mixed in to Series, so Series.is_monotonic needs to wrap in Index so that it can use IndexEngine

return self.is_monotonic

@property
def is_monotonic_decreasing(self) -> bool:
Expand Down Expand Up @@ -1493,7 +1513,7 @@ def factorize(self, sort=False, na_sentinel=-1):

@Substitution(klass="Index")
@Appender(_shared_docs["searchsorted"])
def searchsorted(self, value, side="left", sorter=None):
def searchsorted(self, value, side="left", sorter=None) -> np.ndarray:
return algorithms.searchsorted(self._values, value, side=side, sorter=sorter)

def drop_duplicates(self, keep="first", inplace=False):
Expand Down
14 changes: 7 additions & 7 deletions pandas/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,35 +178,35 @@ def not_none(*args):
return (arg for arg in args if arg is not None)


def any_none(*args):
def any_none(*args) -> bool:
"""
Returns a boolean indicating if any argument is None.
"""
return any(arg is None for arg in args)


def all_none(*args):
def all_none(*args) -> bool:
"""
Returns a boolean indicating if all arguments are None.
"""
return all(arg is None for arg in args)


def any_not_none(*args):
def any_not_none(*args) -> bool:
"""
Returns a boolean indicating if any argument is not None.
"""
return any(arg is not None for arg in args)


def all_not_none(*args):
def all_not_none(*args) -> bool:
"""
Returns a boolean indicating if all arguments are not None.
"""
return all(arg is not None for arg in args)


def count_not_none(*args):
def count_not_none(*args) -> int:
"""
Returns the count of arguments that are not None.
"""
Expand Down Expand Up @@ -286,7 +286,7 @@ def maybe_iterable_to_list(obj: Union[Iterable[T], T]) -> Union[Collection[T], T
return obj


def is_null_slice(obj):
def is_null_slice(obj) -> bool:
"""
We have a null slice.
"""
Expand All @@ -306,7 +306,7 @@ def is_true_slices(l):


# TODO: used only once in indexing; belongs elsewhere?
def is_full_slice(obj, l):
def is_full_slice(obj, l) -> bool:
"""
We have a full length slice.
"""
Expand Down
Loading