From 4668fb82856eeb82f4638f372db7f2b13a9bb04d Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 17 Oct 2020 17:33:58 -0700 Subject: [PATCH 1/7] TYP: plotting._matplotlib.converter --- pandas/core/indexes/period.py | 15 +++++++++++++++ pandas/io/parsers.py | 2 +- setup.cfg | 3 --- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index ce2839ab9a8e1..e4fd095ba57e1 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -161,6 +161,21 @@ def to_timestamp(self, freq=None, how="start") -> DatetimeIndex: arr = self._data.to_timestamp(freq, how) return DatetimeIndex._simple_new(arr, name=self.name) + # TODO: use @doc(PeriodArray.hour) once mypy supports + @property + def hour(self) -> Int64Index: + return Int64Index(self._data.hour, name=self.name) + + # TODO: use @doc(PeriodArray.minute) once mypy supports + @property + def minute(self) -> Int64Index: + return Int64Index(self._data.minute, name=self.name) + + # TODO: use @doc(PeriodArray.second) once mypy supports + @property + def second(self) -> Int64Index: + return Int64Index(self._data.second, name=self.name) + # ------------------------------------------------------------------------ # Index Constructors diff --git a/pandas/io/parsers.py b/pandas/io/parsers.py index 538c15b707761..c8ab845df6881 100644 --- a/pandas/io/parsers.py +++ b/pandas/io/parsers.py @@ -2179,7 +2179,7 @@ def TextParser(*args, **kwds): return TextFileReader(*args, **kwds) -def count_empty_vals(vals): +def count_empty_vals(vals) -> int: return sum(1 for v in vals if v == "" or v is None) diff --git a/setup.cfg b/setup.cfg index 9f8776262268a..ee1519440a876 100644 --- a/setup.cfg +++ b/setup.cfg @@ -223,9 +223,6 @@ check_untyped_defs=False [mypy-pandas.io.parsers] check_untyped_defs=False -[mypy-pandas.plotting._matplotlib.converter] -check_untyped_defs=False - [mypy-pandas.plotting._matplotlib.core] check_untyped_defs=False From 0e2c353fa2bf67b20b85e446b6fd3f9d7669c773 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 18 Oct 2020 11:14:40 -0700 Subject: [PATCH 2/7] TYP: indexes --- pandas/core/indexes/category.py | 10 +++++++--- pandas/core/indexes/datetimelike.py | 5 ++++- pandas/core/indexes/interval.py | 6 ++---- pandas/core/reshape/concat.py | 3 +++ setup.cfg | 6 ------ 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index a5e8edca80873..ff014ac249fc3 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -235,20 +235,23 @@ def _shallow_copy(self, values=None, name: Label = no_default): return super()._shallow_copy(values=values, name=name) - def _is_dtype_compat(self, other) -> bool: + def _is_dtype_compat(self, other) -> Categorical: """ *this is an internal non-public method* provide a comparison between the dtype of self and other (coercing if needed) + Returns + ------- + Categorical + Raises ------ TypeError if the dtypes are not compatible """ if is_categorical_dtype(other): - if isinstance(other, CategoricalIndex): - other = other._values + other = extract_array(other) if not other.is_dtype_equal(self): raise TypeError( "categories must match existing categories when appending" @@ -263,6 +266,7 @@ def _is_dtype_compat(self, other) -> bool: raise TypeError( "cannot append a non-category item to a CategoricalIndex" ) + other = other._values return other diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 017dc6527944a..0ab9a540316f3 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -43,7 +43,7 @@ from pandas.core.tools.timedeltas import to_timedelta if TYPE_CHECKING: - from pandas import CategoricalIndex + from pandas import CategoricalIndex, DatetimeIndex _index_doc_kwargs = dict(ibase._index_doc_kwargs) @@ -953,6 +953,9 @@ def _maybe_utc_convert(self, other): raise TypeError("Cannot join tz-naive with tz-aware DatetimeIndex") if not timezones.tz_compare(self.tz, other.tz): + self = cast("DatetimeIndex", self) + other = cast("DatetimeIndex", other) + this = self.tz_convert("UTC") other = other.tz_convert("UTC") return this, other diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index cb25ef1241ce0..68177b4331717 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -1302,10 +1302,8 @@ def interval_range( else: # delegate to the appropriate range function if isinstance(endpoint, Timestamp): - range_func = date_range + breaks = date_range(start=start, end=end, periods=periods, freq=freq) else: - range_func = timedelta_range - - breaks = range_func(start=start, end=end, periods=periods, freq=freq) + breaks = timedelta_range(start=start, end=end, periods=periods, freq=freq) return IntervalIndex.from_breaks(breaks, name=name, closed=closed) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 13052c23a9f11..e54ad177b3996 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -455,6 +455,7 @@ def __init__( self.new_axes = self._get_new_axes() def get_result(self): + from pandas import DataFrame, Series # series only if self._is_series: @@ -463,6 +464,7 @@ def get_result(self): if self.bm_axis == 0: name = com.consensus_name_attr(self.objs) cons = self.objs[0]._constructor + assert issubclass(cons, Series) # for mypy arrs = [ser._values for ser in self.objs] @@ -476,6 +478,7 @@ def get_result(self): # GH28330 Preserves subclassed objects through concat cons = self.objs[0]._constructor_expanddim + assert issubclass(cons, DataFrame) # for mypy index, columns = self.new_axes df = cons(data, index=index) diff --git a/setup.cfg b/setup.cfg index 925173fb7c6d1..d8525c12cf13e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -181,18 +181,12 @@ check_untyped_defs=False [mypy-pandas.core.indexes.extension] check_untyped_defs=False -[mypy-pandas.core.indexes.interval] -check_untyped_defs=False - [mypy-pandas.core.indexes.multi] check_untyped_defs=False [mypy-pandas.core.resample] check_untyped_defs=False -[mypy-pandas.core.reshape.concat] -check_untyped_defs=False - [mypy-pandas.core.reshape.merge] check_untyped_defs=False From 7ef7c56784725eacc4c335b89cd057aed213dc01 Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 24 Oct 2020 11:10:55 -0700 Subject: [PATCH 3/7] use @doc for PeriodIndex props --- pandas/core/indexes/period.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 2d65e3f674a9f..9c1858a7e3224 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -161,18 +161,21 @@ def to_timestamp(self, freq=None, how="start") -> DatetimeIndex: arr = self._data.to_timestamp(freq, how) return DatetimeIndex._simple_new(arr, name=self.name) - # TODO: use @doc(PeriodArray.hour) once mypy supports - @property + # error: Decorated property not supported [misc] + @property # type:ignore[misc] + @doc(PeriodArray.hour.fget) def hour(self) -> Int64Index: return Int64Index(self._data.hour, name=self.name) - # TODO: use @doc(PeriodArray.minute) once mypy supports - @property + # error: Decorated property not supported [misc] + @property # type:ignore[misc] + @doc(PeriodArray.minute.fget) def minute(self) -> Int64Index: return Int64Index(self._data.minute, name=self.name) - # TODO: use @doc(PeriodArray.second) once mypy supports - @property + # error: Decorated property not supported [misc] + @property # type:ignore[misc] + @doc(PeriodArray.second.fget) def second(self) -> Int64Index: return Int64Index(self._data.second, name=self.name) From 96ed502a3eb9c7ba81bcc1c6d3ed2bf8e42cbe73 Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 24 Oct 2020 11:11:24 -0700 Subject: [PATCH 4/7] revert --- pandas/core/indexes/datetimelike.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index ceab75691a5ef..863880e222b5d 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -43,7 +43,7 @@ from pandas.core.tools.timedeltas import to_timedelta if TYPE_CHECKING: - from pandas import CategoricalIndex, DatetimeIndex + from pandas import CategoricalIndex _index_doc_kwargs = dict(ibase._index_doc_kwargs) @@ -944,9 +944,6 @@ def _maybe_utc_convert(self, other): raise TypeError("Cannot join tz-naive with tz-aware DatetimeIndex") if not timezones.tz_compare(self.tz, other.tz): - self = cast("DatetimeIndex", self) - other = cast("DatetimeIndex", other) - this = self.tz_convert("UTC") other = other.tz_convert("UTC") return this, other From ff2bccac4050b883548b59fbc217969dc30dded5 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 25 Oct 2020 08:20:56 -0700 Subject: [PATCH 5/7] dummy commit to force CI From a3c4b9936334a56c26209cbb6bf3ab7fea27f684 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 26 Oct 2020 18:08:01 -0700 Subject: [PATCH 6/7] update comment --- pandas/core/indexes/period.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 9c1858a7e3224..590b711d6d45a 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -148,7 +148,7 @@ class PeriodIndex(DatetimeIndexOpsMixin, Int64Index): _supports_partial_string_indexing = True # -------------------------------------------------------------------- - # methods that dispatch to array and wrap result in PeriodIndex + # methods that dispatch to array and wrap result in Index # These are defined here instead of via inherit_names for mypy @doc(PeriodArray.asfreq) From 3ca562c4e3cd6d40c6e26b458c2e1f4e6710946d Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 27 Oct 2020 11:04:00 -0700 Subject: [PATCH 7/7] suggested updates --- pandas/core/reshape/concat.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index e54ad177b3996..77b1076920f20 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -3,7 +3,7 @@ """ from collections import abc -from typing import TYPE_CHECKING, Iterable, List, Mapping, Union, overload +from typing import TYPE_CHECKING, Iterable, List, Mapping, Type, Union, cast, overload import numpy as np @@ -30,7 +30,7 @@ from pandas.core.internals import concatenate_block_managers if TYPE_CHECKING: - from pandas import DataFrame + from pandas import DataFrame, Series from pandas.core.generic import NDFrame # --------------------------------------------------------------------- @@ -455,16 +455,17 @@ def __init__( self.new_axes = self._get_new_axes() def get_result(self): - from pandas import DataFrame, Series + cons: Type[FrameOrSeriesUnion] + sample: FrameOrSeriesUnion # series only if self._is_series: + sample = cast("Series", self.objs[0]) # stack blocks if self.bm_axis == 0: name = com.consensus_name_attr(self.objs) - cons = self.objs[0]._constructor - assert issubclass(cons, Series) # for mypy + cons = sample._constructor arrs = [ser._values for ser in self.objs] @@ -477,8 +478,7 @@ def get_result(self): data = dict(zip(range(len(self.objs)), self.objs)) # GH28330 Preserves subclassed objects through concat - cons = self.objs[0]._constructor_expanddim - assert issubclass(cons, DataFrame) # for mypy + cons = sample._constructor_expanddim index, columns = self.new_axes df = cons(data, index=index) @@ -487,6 +487,8 @@ def get_result(self): # combine block managers else: + sample = cast("DataFrame", self.objs[0]) + mgrs_indexers = [] for obj in self.objs: indexers = {} @@ -509,7 +511,7 @@ def get_result(self): if not self.copy: new_data._consolidate_inplace() - cons = self.objs[0]._constructor + cons = sample._constructor return cons(new_data).__finalize__(self, method="concat") def _get_result_dim(self) -> int: