diff --git a/pandas/_typing.py b/pandas/_typing.py index a1224a609579e..45c43fa958caa 100644 --- a/pandas/_typing.py +++ b/pandas/_typing.py @@ -1,34 +1,29 @@ from pathlib import Path -from typing import IO, AnyStr, TypeVar, Union +from typing import IO, TYPE_CHECKING, AnyStr, TypeVar, Union import numpy as np -from pandas._libs import Timestamp -from pandas._libs.tslibs.period import Period -from pandas._libs.tslibs.timedeltas import Timedelta +# To prevent import cycles place any internal imports in the branch below +# and use a string literal forward reference to it in subsequent types +# https://mypy.readthedocs.io/en/latest/common_issues.html#import-cycles +if TYPE_CHECKING: + from pandas._libs import Period, Timedelta, Timestamp # noqa: F401 + from pandas.core.arrays.base import ExtensionArray # noqa: F401 + from pandas.core.dtypes.dtypes import ExtensionDtype # noqa: F401 + from pandas.core.indexes.base import Index # noqa: F401 + from pandas.core.frame import DataFrame # noqa: F401 + from pandas.core.series import Series # noqa: F401 + from pandas.core.sparse.series import SparseSeries # noqa: F401 -from pandas.core.dtypes.dtypes import ExtensionDtype -from pandas.core.dtypes.generic import ( - ABCDataFrame, - ABCExtensionArray, - ABCIndexClass, - ABCSeries, - ABCSparseSeries, -) AnyArrayLike = TypeVar( - "AnyArrayLike", - ABCExtensionArray, - ABCIndexClass, - ABCSeries, - ABCSparseSeries, - np.ndarray, + "AnyArrayLike", "ExtensionArray", "Index", "Series", "SparseSeries", np.ndarray ) -ArrayLike = TypeVar("ArrayLike", ABCExtensionArray, np.ndarray) -DatetimeLikeScalar = TypeVar("DatetimeLikeScalar", Period, Timestamp, Timedelta) -Dtype = Union[str, np.dtype, ExtensionDtype] +ArrayLike = TypeVar("ArrayLike", "ExtensionArray", np.ndarray) +DatetimeLikeScalar = TypeVar("DatetimeLikeScalar", "Period", "Timestamp", "Timedelta") +Dtype = Union[str, np.dtype, "ExtensionDtype"] FilePathOrBuffer = Union[str, Path, IO[AnyStr]] -FrameOrSeries = TypeVar("FrameOrSeries", ABCSeries, ABCDataFrame) +FrameOrSeries = TypeVar("FrameOrSeries", "Series", "DataFrame") Scalar = Union[str, int, float] Axis = Union[str, int] diff --git a/pandas/core/dtypes/common.py b/pandas/core/dtypes/common.py index f2571573bd1bc..054c97056a117 100644 --- a/pandas/core/dtypes/common.py +++ b/pandas/core/dtypes/common.py @@ -167,12 +167,13 @@ def ensure_int_or_float(arr: ArrayLike, copy=False) -> np.array: If the array is explicitly of type uint64 the type will remain unchanged. """ + # TODO: GH27506 potential bug with ExtensionArrays try: - return arr.astype("int64", copy=copy, casting="safe") + return arr.astype("int64", copy=copy, casting="safe") # type: ignore except TypeError: pass try: - return arr.astype("uint64", copy=copy, casting="safe") + return arr.astype("uint64", copy=copy, casting="safe") # type: ignore except TypeError: return arr.astype("float64", copy=copy) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 7372dada3b48a..66290ae54e626 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -906,35 +906,35 @@ def get_indexer( ) raise InvalidIndexError(msg) - target = ensure_index(target) + target_as_index = ensure_index(target) - if isinstance(target, IntervalIndex): + if isinstance(target_as_index, IntervalIndex): # equal indexes -> 1:1 positional match - if self.equals(target): + if self.equals(target_as_index): return np.arange(len(self), dtype="intp") # different closed or incompatible subtype -> no matches common_subtype = find_common_type( - [self.dtype.subtype, target.dtype.subtype] + [self.dtype.subtype, target_as_index.dtype.subtype] ) - if self.closed != target.closed or is_object_dtype(common_subtype): - return np.repeat(np.intp(-1), len(target)) + if self.closed != target_as_index.closed or is_object_dtype(common_subtype): + return np.repeat(np.intp(-1), len(target_as_index)) - # non-overlapping -> at most one match per interval in target + # non-overlapping -> at most one match per interval in target_as_index # want exact matches -> need both left/right to match, so defer to # left/right get_indexer, compare elementwise, equality -> match - left_indexer = self.left.get_indexer(target.left) - right_indexer = self.right.get_indexer(target.right) + left_indexer = self.left.get_indexer(target_as_index.left) + right_indexer = self.right.get_indexer(target_as_index.right) indexer = np.where(left_indexer == right_indexer, left_indexer, -1) - elif not is_object_dtype(target): + elif not is_object_dtype(target_as_index): # homogeneous scalar index: use IntervalTree - target = self._maybe_convert_i8(target) - indexer = self._engine.get_indexer(target.values) + target_as_index = self._maybe_convert_i8(target_as_index) + indexer = self._engine.get_indexer(target_as_index.values) else: # heterogeneous scalar index: defer elementwise to get_loc # (non-overlapping so get_loc guarantees scalar of KeyError) indexer = [] - for key in target: + for key in target_as_index: try: loc = self.get_loc(key) except KeyError: @@ -947,21 +947,26 @@ def get_indexer( def get_indexer_non_unique( self, target: AnyArrayLike ) -> Tuple[np.ndarray, np.ndarray]: - target = ensure_index(target) + target_as_index = ensure_index(target) - # check that target IntervalIndex is compatible - if isinstance(target, IntervalIndex): + # check that target_as_index IntervalIndex is compatible + if isinstance(target_as_index, IntervalIndex): common_subtype = find_common_type( - [self.dtype.subtype, target.dtype.subtype] + [self.dtype.subtype, target_as_index.dtype.subtype] ) - if self.closed != target.closed or is_object_dtype(common_subtype): + if self.closed != target_as_index.closed or is_object_dtype(common_subtype): # different closed or incompatible subtype -> no matches - return np.repeat(-1, len(target)), np.arange(len(target)) + return ( + np.repeat(-1, len(target_as_index)), + np.arange(len(target_as_index)), + ) - if is_object_dtype(target) or isinstance(target, IntervalIndex): - # target might contain intervals: defer elementwise to get_loc + if is_object_dtype(target_as_index) or isinstance( + target_as_index, IntervalIndex + ): + # target_as_index might contain intervals: defer elementwise to get_loc indexer, missing = [], [] - for i, key in enumerate(target): + for i, key in enumerate(target_as_index): try: locs = self.get_loc(key) if isinstance(locs, slice): @@ -973,8 +978,10 @@ def get_indexer_non_unique( indexer.append(locs) indexer = np.concatenate(indexer) else: - target = self._maybe_convert_i8(target) - indexer, missing = self._engine.get_indexer_non_unique(target.values) + target_as_index = self._maybe_convert_i8(target_as_index) + indexer, missing = self._engine.get_indexer_non_unique( + target_as_index.values + ) return ensure_platform_int(indexer), ensure_platform_int(missing) diff --git a/pandas/core/window.py b/pandas/core/window.py index 5098ab3c7220f..79a0f5f24af12 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -240,7 +240,7 @@ def _prep_values(self, values: Optional[np.ndarray] = None) -> np.ndarray: return values - def _wrap_result(self, result, block=None, obj=None) -> FrameOrSeries: + def _wrap_result(self, result, block=None, obj=None): """ Wrap a single result. """ diff --git a/setup.cfg b/setup.cfg index 7f0062428c442..716ff5d9d8853 100644 --- a/setup.cfg +++ b/setup.cfg @@ -77,7 +77,9 @@ filterwarnings = [coverage:run] branch = False -omit = */tests/* +omit = + */tests/* + pandas/_typing.py plugins = Cython.Coverage [coverage:report]