From 92834f4379eeae23ef939afde403cb4145c0f87b Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Sat, 10 Aug 2024 18:45:50 -0400 Subject: [PATCH 01/13] DOC: Enforce Numpy Docstring Validation for freqstr, nanos, and rule_code methods of pandas.tseries.offsets Week, WeekOfMonth, YearBegin, and YearEnd classes. --- ci/code_checks.sh | 12 ---- pandas/_libs/tslibs/offsets.pyx | 103 ++++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 17 deletions(-) diff --git a/ci/code_checks.sh b/ci/code_checks.sh index 692b86ec731c9..e961cf98fc7a0 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -685,36 +685,24 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.Tick.normalize GL08" \ -i "pandas.tseries.offsets.Tick.rule_code GL08" \ -i "pandas.tseries.offsets.Week PR02" \ - -i "pandas.tseries.offsets.Week.freqstr SA01" \ -i "pandas.tseries.offsets.Week.is_on_offset GL08" \ -i "pandas.tseries.offsets.Week.n GL08" \ - -i "pandas.tseries.offsets.Week.nanos GL08" \ -i "pandas.tseries.offsets.Week.normalize GL08" \ - -i "pandas.tseries.offsets.Week.rule_code GL08" \ -i "pandas.tseries.offsets.Week.weekday GL08" \ -i "pandas.tseries.offsets.WeekOfMonth PR02,SA01" \ - -i "pandas.tseries.offsets.WeekOfMonth.freqstr SA01" \ -i "pandas.tseries.offsets.WeekOfMonth.is_on_offset GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.n GL08" \ - -i "pandas.tseries.offsets.WeekOfMonth.nanos GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.normalize GL08" \ - -i "pandas.tseries.offsets.WeekOfMonth.rule_code GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.week GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.weekday GL08" \ - -i "pandas.tseries.offsets.YearBegin.freqstr SA01" \ -i "pandas.tseries.offsets.YearBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.YearBegin.month GL08" \ -i "pandas.tseries.offsets.YearBegin.n GL08" \ - -i "pandas.tseries.offsets.YearBegin.nanos GL08" \ -i "pandas.tseries.offsets.YearBegin.normalize GL08" \ - -i "pandas.tseries.offsets.YearBegin.rule_code GL08" \ - -i "pandas.tseries.offsets.YearEnd.freqstr SA01" \ -i "pandas.tseries.offsets.YearEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.YearEnd.month GL08" \ -i "pandas.tseries.offsets.YearEnd.n GL08" \ - -i "pandas.tseries.offsets.YearEnd.nanos GL08" \ -i "pandas.tseries.offsets.YearEnd.normalize GL08" \ - -i "pandas.tseries.offsets.YearEnd.rule_code GL08" \ -i "pandas.util.hash_pandas_object PR07,SA01" # There should be no backslash in the final line, please keep this comment in the last ignored function RET=$(($RET + $?)) ; echo $MSG "DONE" diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index fd1bb3fe3e173..2a46aa05055ec 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -589,6 +589,22 @@ cdef class BaseOffset: @property def rule_code(self) -> str: + """ + Return a string representing the base frequency. + + See Also + -------- + tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. + + Examples + -------- + >>> pd.offsets.Hour().rule_code + 'h' + + >>> pd.offsets.Week(5).rule_code + 'W' + """ return self._prefix @cache_readonly @@ -596,6 +612,13 @@ cdef class BaseOffset: """ Return a string representing the frequency. + See Also + -------- + tseries.offsets.BusinessDay.freqstr : Return a string representing an offset frequency in Business Days. + tseries.offsets.BusinessHour.freqstr : Return a string representing an offset frequency in Business Hours. + tseries.offsets.Week.freqstr : Return a string representing an offset frequency in Weeks. + tseries.offsets.Hour.freqstr : Return a string representing an offset frequency in Hours. + Examples -------- >>> pd.DateOffset(5).freqstr @@ -773,6 +796,26 @@ cdef class BaseOffset: @property def nanos(self): + """ + Returns a ValueError becuase the frequency is non-fixed. + + Raises + ------ + ValueError + If the frequency is non-fixed. + + See Also + -------- + tseries.offsets.WeekOfMonth.nanos : Raises a ValueError becuase the frequency is non-fixed. + tseries.offsets.YearBegin.nanos : Raises a ValueError becuase the frequency is non-fixed. + tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. + tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. + + Examples + -------- + >>> pd.offsets.Week(n=1).nanos + ValueError: <5 * Weeks: weekday=None> is a non-fixed frequency + """ raise ValueError(f"{self} is a non-fixed frequency") # ------------------------------------------------------------------ @@ -980,12 +1023,14 @@ cdef class Tick(SingleConstructorOffset): @property def nanos(self) -> int64_t: """ - Return an integer of the total number of nanoseconds. + Returns an integer of the total number of nanoseconds. - Raises - ------ - ValueError - If the frequency is non-fixed. + See Also + -------- + tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. + tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. + tseries.offsets.WeekOfMonth.nanos : Raises a ValueError becuase the frequency is non-fixed. + tseries.offsets.YearBegin.nanos : Raises a ValueError becuase the frequency is non-fixed. Examples -------- @@ -2420,6 +2465,22 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset): @property def rule_code(self) -> str: + """ + Return a string representing the base frequency. + + See Also + -------- + tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. + + Examples + -------- + >>> pd.offsets.Week(5).rule_code + 'W' + + >>> pd.offsets.WeekOfMonth(n=1, week=0, weekday=0).rule_code + 'WOM-1MON' + """ weekday = int_to_weekday.get(self.weekday, "") if self.week == -1: # LastWeekOfMonth @@ -2466,6 +2527,22 @@ cdef class YearOffset(SingleConstructorOffset): @property def rule_code(self) -> str: + """ + Return a string representing the base frequency. + + See Also + -------- + tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. + + Examples + -------- + >>> pd.tseries.offsets.YearBegin(n=1, month=2).rule_code + 'YS-FEB' + + >>> pd.tseries.offsets.YearEnd(n=1, month=6).rule_code + 'YE-JUN' + """ month = MONTH_ALIASES[self.month] return f"{self._prefix}-{month}" @@ -3452,6 +3529,22 @@ cdef class Week(SingleConstructorOffset): @property def rule_code(self) -> str: + """ + Return a string representing the base frequency. + + See Also + -------- + tseries.offsets.Hour.name : Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.name : Returns a string representing the base frequency of 'D'. + + Examples + -------- + >>> pd.offsets.Hour().rule_code + 'h' + + >>> pd.offsets.Week(5).rule_code + 'W' + """ suffix = "" if self.weekday is not None: weekday = int_to_weekday[self.weekday] From 756fbd44c0c8a02e0bb31f90b3d5fdfdd851f246 Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Sat, 10 Aug 2024 22:50:11 -0400 Subject: [PATCH 02/13] DOC: Enforce Numpy Docstring Validation for freqstr, nanos, and rule_code methods of pandas.tseries.offsets Week, WeekOfMonth, YearBegin, and YearEnd classes. --- .devcontainer.json | 1 - .github/actions/setup-conda/action.yml | 6 + .github/workflows/unit-tests.yml | 7 +- .gitpod.yml | 2 +- Dockerfile | 4 +- ci/code_checks.sh | 2 - doc/source/whatsnew/v3.0.0.rst | 3 + pandas/_libs/tslibs/offsets.pyx | 34 ++-- pandas/core/array_algos/quantile.py | 20 +- pandas/core/arrays/string_.py | 182 +++++++++--------- pandas/core/arrays/string_arrow.py | 96 +-------- pandas/core/reshape/concat.py | 5 + pandas/core/reshape/tile.py | 11 +- pandas/core/strings/accessor.py | 2 + pandas/tests/apply/test_frame_apply.py | 5 + pandas/tests/apply/test_invalid_arg.py | 11 ++ pandas/tests/apply/test_numba.py | 1 + pandas/tests/arithmetic/test_object.py | 6 + .../tests/arrays/boolean/test_arithmetic.py | 7 + .../arrays/categorical/test_analytics.py | 9 +- .../arrays/categorical/test_constructors.py | 6 +- pandas/tests/arrays/integer/test_reduction.py | 9 +- pandas/tests/base/test_conversion.py | 12 +- pandas/tests/copy_view/test_astype.py | 5 +- pandas/tests/copy_view/test_functions.py | 12 +- pandas/tests/copy_view/test_interp_fillna.py | 4 +- pandas/tests/copy_view/test_methods.py | 9 +- pandas/tests/copy_view/test_replace.py | 6 +- pandas/tests/extension/base/ops.py | 24 +++ pandas/tests/extension/test_categorical.py | 2 + pandas/tests/extension/test_numpy.py | 7 + pandas/tests/frame/indexing/test_indexing.py | 5 +- pandas/tests/frame/indexing/test_where.py | 8 + pandas/tests/frame/methods/test_info.py | 3 +- pandas/tests/frame/methods/test_rank.py | 14 +- .../tests/frame/methods/test_value_counts.py | 7 + pandas/tests/frame/test_api.py | 6 +- pandas/tests/frame/test_arithmetic.py | 6 +- pandas/tests/frame/test_constructors.py | 3 +- pandas/tests/frame/test_logical_ops.py | 7 + pandas/tests/frame/test_reductions.py | 11 +- pandas/tests/frame/test_unary.py | 10 +- .../groupby/methods/test_value_counts.py | 4 + pandas/tests/groupby/test_groupby.py | 5 + pandas/tests/groupby/test_groupby_dropna.py | 19 ++ pandas/tests/indexes/object/test_indexing.py | 6 + pandas/tests/indexes/test_base.py | 20 +- pandas/tests/indexes/test_old_base.py | 6 + pandas/tests/indexing/test_loc.py | 4 + pandas/tests/io/formats/style/test_bar.py | 1 + pandas/tests/io/parser/conftest.py | 22 ++- pandas/tests/reductions/test_reductions.py | 5 + pandas/tests/reshape/concat/test_concat.py | 11 ++ pandas/tests/reshape/test_qcut.py | 12 ++ pandas/tests/series/indexing/test_setitem.py | 6 + pandas/tests/series/test_api.py | 7 + pandas/tests/series/test_logical_ops.py | 5 + pandas/tests/series/test_reductions.py | 13 ++ pandas/tests/tseries/offsets/test_offsets.py | 7 + pandas/tests/window/test_rolling.py | 6 + 60 files changed, 501 insertions(+), 248 deletions(-) diff --git a/.devcontainer.json b/.devcontainer.json index 7c5d009260c64..54ddfa1a130f8 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -8,7 +8,6 @@ // Use 'settings' to set *default* container specific settings.json values on container create. // You can edit these settings after create using File > Preferences > Settings > Remote. "settings": { - "terminal.integrated.shell.linux": "/bin/bash", "python.pythonPath": "/usr/local/bin/python", "python.formatting.provider": "black", "python.linting.enabled": true, diff --git a/.github/actions/setup-conda/action.yml b/.github/actions/setup-conda/action.yml index ceeebfcd1c90c..3eb68bdd2a15c 100644 --- a/.github/actions/setup-conda/action.yml +++ b/.github/actions/setup-conda/action.yml @@ -14,3 +14,9 @@ runs: condarc-file: ci/.condarc cache-environment: true cache-downloads: true + + - name: Uninstall pyarrow + if: ${{ env.REMOVE_PYARROW == '1' }} + run: | + micromamba remove -y pyarrow + shell: bash -el {0} diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index a085d0265a1a5..166c06acccc49 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -29,6 +29,7 @@ jobs: env_file: [actions-310.yaml, actions-311.yaml, actions-312.yaml] # Prevent the include jobs from overriding other jobs pattern: [""] + pandas_future_infer_string: ["0"] include: - name: "Downstream Compat" env_file: actions-311-downstream_compat.yaml @@ -58,6 +59,9 @@ jobs: # It will be temporarily activated during tests with locale.setlocale extra_loc: "zh_CN" - name: "Future infer strings" + env_file: actions-312.yaml + pandas_future_infer_string: "1" + - name: "Future infer strings (without pyarrow)" env_file: actions-311.yaml pandas_future_infer_string: "1" - name: "Pypy" @@ -85,9 +89,10 @@ jobs: NPY_PROMOTION_STATE: ${{ matrix.env_file == 'actions-311-numpydev.yaml' && 'weak' || 'legacy' }} # Clipboard tests QT_QPA_PLATFORM: offscreen + REMOVE_PYARROW: ${{ matrix.name == 'Future infer strings (without pyarrow)' && '1' || '0' }} concurrency: # https://github.community/t/concurrecy-not-work-for-push/183068/7 - group: ${{ github.event_name == 'push' && github.run_number || github.ref }}-${{ matrix.env_file }}-${{ matrix.pattern }}-${{ matrix.extra_apt || '' }}} + group: ${{ github.event_name == 'push' && github.run_number || github.ref }}-${{ matrix.env_file }}-${{ matrix.pattern }}-${{ matrix.extra_apt || '' }}-${{ matrix.pandas_future_infer_string }} cancel-in-progress: true services: diff --git a/.gitpod.yml b/.gitpod.yml index 9222639136a17..9ff349747a33e 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -14,7 +14,7 @@ tasks: cp gitpod/settings.json .vscode/settings.json git fetch --tags python -m pip install -ve . --no-build-isolation --config-settings editable-verbose=true - pre-commit install + pre-commit install --install-hooks command: | python -m pip install -ve . --no-build-isolation --config-settings editable-verbose=true echo "✨ Pre-build complete! You can close this terminal ✨ " diff --git a/Dockerfile b/Dockerfile index 0fcbcee92295c..dead3a494e52d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.10.8 WORKDIR /home/pandas RUN apt-get update && apt-get -y upgrade -RUN apt-get install -y build-essential +RUN apt-get install -y build-essential bash-completion # hdf5 needed for pytables installation # libgles2-mesa needed for pytest-qt @@ -12,4 +12,6 @@ RUN python -m pip install --upgrade pip COPY requirements-dev.txt /tmp RUN python -m pip install -r /tmp/requirements-dev.txt RUN git config --global --add safe.directory /home/pandas + +ENV SHELL "/bin/bash" CMD ["/bin/bash"] diff --git a/ci/code_checks.sh b/ci/code_checks.sh index e961cf98fc7a0..2956f8a3f6836 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -163,7 +163,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.Series.str.center RT03,SA01" \ -i "pandas.Series.str.decode PR07,RT03,SA01" \ -i "pandas.Series.str.encode PR07,RT03,SA01" \ - -i "pandas.Series.str.index RT03" \ -i "pandas.Series.str.ljust RT03,SA01" \ -i "pandas.Series.str.lower RT03" \ -i "pandas.Series.str.lstrip RT03" \ @@ -172,7 +171,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.Series.str.partition RT03" \ -i "pandas.Series.str.repeat SA01" \ -i "pandas.Series.str.replace SA01" \ - -i "pandas.Series.str.rindex RT03" \ -i "pandas.Series.str.rjust RT03,SA01" \ -i "pandas.Series.str.rpartition RT03" \ -i "pandas.Series.str.rstrip RT03" \ diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 32c98fbf9d655..ee9d18d0c7ce2 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -50,6 +50,8 @@ Other enhancements - :meth:`DataFrame.pivot_table` and :func:`pivot_table` now allow the passing of keyword arguments to ``aggfunc`` through ``**kwargs`` (:issue:`57884`) - :meth:`Series.cummin` and :meth:`Series.cummax` now supports :class:`CategoricalDtype` (:issue:`52335`) - :meth:`Series.plot` now correctly handle the ``ylabel`` parameter for pie charts, allowing for explicit control over the y-axis label (:issue:`58239`) +- :meth:`pandas.concat` will raise a ``ValueError`` when ``ignore_index=True`` and ``keys`` is not ``None`` (:issue:`59274`) +- Multiplying two :class:`DateOffset` objects will now raise a ``TypeError`` instead of a ``RecursionError`` (:issue:`59442`) - Restore support for reading Stata 104-format and enable reading 103-format dta files (:issue:`58554`) - Support reading Stata 102-format (Stata 1) dta files (:issue:`58978`) - Support reading Stata 110-format (Stata 7) dta files (:issue:`47176`) @@ -617,6 +619,7 @@ Groupby/resample/rolling Reshaping ^^^^^^^^^ +- Bug in :func:`qcut` where values at the quantile boundaries could be incorrectly assigned (:issue:`59355`) - Bug in :meth:`DataFrame.join` inconsistently setting result index name (:issue:`55815`) - Bug in :meth:`DataFrame.unstack` producing incorrect results when ``sort=False`` (:issue:`54987`, :issue:`55516`) - Bug in :meth:`DataFrame.unstack` producing incorrect results when manipulating empty :class:`DataFrame` with an :class:`ExtentionDtype` (:issue:`59123`) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 2a46aa05055ec..5c6b734d99cc8 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -491,6 +491,12 @@ cdef class BaseOffset: elif is_integer_object(other): return type(self)(n=other * self.n, normalize=self.normalize, **self.kwds) + elif isinstance(other, BaseOffset): + # Otherwise raises RecurrsionError due to __rmul__ + raise TypeError( + f"Cannot multiply {type(self).__name__} with " + f"{type(other).__name__}." + ) return NotImplemented def __rmul__(self, other): @@ -604,7 +610,7 @@ cdef class BaseOffset: >>> pd.offsets.Week(5).rule_code 'W' - """ + """ # noqa return self._prefix @cache_readonly @@ -632,7 +638,7 @@ cdef class BaseOffset: >>> pd.offsets.Nano(-3).freqstr '-3ns' - """ + """ # noqa try: code = self.rule_code except NotImplementedError: @@ -797,8 +803,8 @@ cdef class BaseOffset: @property def nanos(self): """ - Returns a ValueError becuase the frequency is non-fixed. - + Returns a ValueError because the frequency is non-fixed. + Raises ------ ValueError @@ -806,16 +812,16 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.WeekOfMonth.nanos : Raises a ValueError becuase the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : Raises a ValueError becuase the frequency is non-fixed. + tseries.offsets.WeekOfMonth.nanos : Raises a ValueError because the frequency is non-fixed. + tseries.offsets.YearBegin.nanos : Raises a ValueError because the frequency is non-fixed. tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. Examples -------- >>> pd.offsets.Week(n=1).nanos - ValueError: <5 * Weeks: weekday=None> is a non-fixed frequency - """ + ValueError: is a non-fixed frequency + """ # noqa raise ValueError(f"{self} is a non-fixed frequency") # ------------------------------------------------------------------ @@ -1029,14 +1035,14 @@ cdef class Tick(SingleConstructorOffset): -------- tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.WeekOfMonth.nanos : Raises a ValueError becuase the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : Raises a ValueError becuase the frequency is non-fixed. + tseries.offsets.WeekOfMonth.nanos : Raises a ValueError because the frequency is non-fixed. + tseries.offsets.YearBegin.nanos : Raises a ValueError because the frequency is non-fixed. Examples -------- >>> pd.offsets.Hour(5).nanos 18000000000000 - """ + """ # noqa return self.n * self._nanos_inc def is_on_offset(self, dt: datetime) -> bool: @@ -2480,7 +2486,7 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset): >>> pd.offsets.WeekOfMonth(n=1, week=0, weekday=0).rule_code 'WOM-1MON' - """ + """ # noqa weekday = int_to_weekday.get(self.weekday, "") if self.week == -1: # LastWeekOfMonth @@ -2542,7 +2548,7 @@ cdef class YearOffset(SingleConstructorOffset): >>> pd.tseries.offsets.YearEnd(n=1, month=6).rule_code 'YE-JUN' - """ + """ # noqa month = MONTH_ALIASES[self.month] return f"{self._prefix}-{month}" @@ -3544,7 +3550,7 @@ cdef class Week(SingleConstructorOffset): >>> pd.offsets.Week(5).rule_code 'W' - """ + """ # noqa suffix = "" if self.weekday is not None: weekday = int_to_weekday[self.weekday] diff --git a/pandas/core/array_algos/quantile.py b/pandas/core/array_algos/quantile.py index 5c933294fb944..b2f78182b9bf0 100644 --- a/pandas/core/array_algos/quantile.py +++ b/pandas/core/array_algos/quantile.py @@ -94,9 +94,9 @@ def quantile_with_mask( flat = np.array([fill_value] * len(qs)) result = np.repeat(flat, len(values)).reshape(len(values), len(qs)) else: - result = _nanpercentile( + result = _nanquantile( values, - qs * 100.0, + qs, na_value=fill_value, mask=mask, interpolation=interpolation, @@ -108,7 +108,7 @@ def quantile_with_mask( return result -def _nanpercentile_1d( +def _nanquantile_1d( values: np.ndarray, mask: npt.NDArray[np.bool_], qs: npt.NDArray[np.float64], @@ -116,7 +116,7 @@ def _nanpercentile_1d( interpolation: str, ) -> Scalar | np.ndarray: """ - Wrapper for np.percentile that skips missing values, specialized to + Wrapper for np.quantile that skips missing values, specialized to 1-dimensional case. Parameters @@ -142,7 +142,7 @@ def _nanpercentile_1d( # equiv: 'np.array([na_value] * len(qs))' but much faster return np.full(len(qs), na_value) - return np.percentile( + return np.quantile( values, qs, # error: No overload variant of "percentile" matches argument @@ -152,7 +152,7 @@ def _nanpercentile_1d( ) -def _nanpercentile( +def _nanquantile( values: np.ndarray, qs: npt.NDArray[np.float64], *, @@ -161,7 +161,7 @@ def _nanpercentile( interpolation: str, ): """ - Wrapper for np.percentile that skips missing values. + Wrapper for np.quantile that skips missing values. Parameters ---------- @@ -180,7 +180,7 @@ def _nanpercentile( if values.dtype.kind in "mM": # need to cast to integer to avoid rounding errors in numpy - result = _nanpercentile( + result = _nanquantile( values.view("i8"), qs=qs, na_value=na_value.view("i8"), @@ -196,7 +196,7 @@ def _nanpercentile( # Caller is responsible for ensuring mask shape match assert mask.shape == values.shape result = [ - _nanpercentile_1d(val, m, qs, na_value, interpolation=interpolation) + _nanquantile_1d(val, m, qs, na_value, interpolation=interpolation) for (val, m) in zip(list(values), list(mask)) ] if values.dtype.kind == "f": @@ -215,7 +215,7 @@ def _nanpercentile( result = result.astype(values.dtype, copy=False) return result else: - return np.percentile( + return np.quantile( values, qs, axis=1, diff --git a/pandas/core/arrays/string_.py b/pandas/core/arrays/string_.py index 8a4fd9fc1b34d..2ba7c9fccbfce 100644 --- a/pandas/core/arrays/string_.py +++ b/pandas/core/arrays/string_.py @@ -346,6 +346,57 @@ def _from_scalars(cls, scalars, dtype: DtypeObj) -> Self: raise ValueError return cls._from_sequence(scalars, dtype=dtype) + def _str_map( + self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True + ): + if self.dtype.na_value is np.nan: + return self._str_map_nan_semantics( + f, na_value=na_value, dtype=dtype, convert=convert + ) + + from pandas.arrays import BooleanArray + + if dtype is None: + dtype = self.dtype + if na_value is None: + na_value = self.dtype.na_value + + mask = isna(self) + arr = np.asarray(self) + + if is_integer_dtype(dtype) or is_bool_dtype(dtype): + constructor: type[IntegerArray | BooleanArray] + if is_integer_dtype(dtype): + constructor = IntegerArray + else: + constructor = BooleanArray + + na_value_is_na = isna(na_value) + if na_value_is_na: + na_value = 1 + elif dtype == np.dtype("bool"): + # GH#55736 + na_value = bool(na_value) + result = lib.map_infer_mask( + arr, + f, + mask.view("uint8"), + convert=False, + na_value=na_value, + # error: Argument 1 to "dtype" has incompatible type + # "Union[ExtensionDtype, str, dtype[Any], Type[object]]"; expected + # "Type[object]" + dtype=np.dtype(cast(type, dtype)), + ) + + if not na_value_is_na: + mask[:] = False + + return constructor(result, mask) + + else: + return self._str_map_str_or_object(dtype, na_value, arr, f, mask) + def _str_map_str_or_object( self, dtype, @@ -353,7 +404,6 @@ def _str_map_str_or_object( arr: np.ndarray, f, mask: npt.NDArray[np.bool_], - convert: bool, ): # _str_map helper for case where dtype is either string dtype or object if is_string_dtype(dtype) and not is_object_dtype(dtype): @@ -377,6 +427,47 @@ def _str_map_str_or_object( # -> We don't know the result type. E.g. `.get` can return anything. return lib.map_infer_mask(arr, f, mask.view("uint8")) + def _str_map_nan_semantics( + self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True + ): + if dtype is None: + dtype = self.dtype + if na_value is None: + na_value = self.dtype.na_value + + mask = isna(self) + arr = np.asarray(self) + + if is_integer_dtype(dtype) or is_bool_dtype(dtype): + na_value_is_na = isna(na_value) + if na_value_is_na: + if is_integer_dtype(dtype): + na_value = 0 + else: + na_value = True + + result = lib.map_infer_mask( + arr, + f, + mask.view("uint8"), + convert=False, + na_value=na_value, + dtype=np.dtype(cast(type, dtype)), + ) + if na_value_is_na and mask.any(): + # TODO: we could alternatively do this check before map_infer_mask + # and adjust the dtype/na_value we pass there. Which is more + # performant? + if is_integer_dtype(dtype): + result = result.astype("float64") + else: + result = result.astype("object") + result[mask] = np.nan + return result + + else: + return self._str_map_str_or_object(dtype, na_value, arr, f, mask) + # error: Definition of "_concat_same_type" in base class "NDArrayBacked" is # incompatible with definition in base class "ExtensionArray" @@ -742,95 +833,6 @@ def _cmp_method(self, other, op): # base class "NumpyExtensionArray" defined the type as "float") _str_na_value = libmissing.NA # type: ignore[assignment] - def _str_map_nan_semantics( - self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True - ): - if dtype is None: - dtype = self.dtype - if na_value is None: - na_value = self.dtype.na_value - - mask = isna(self) - arr = np.asarray(self) - convert = convert and not np.all(mask) - - if is_integer_dtype(dtype) or is_bool_dtype(dtype): - na_value_is_na = isna(na_value) - if na_value_is_na: - if is_integer_dtype(dtype): - na_value = 0 - else: - na_value = True - - result = lib.map_infer_mask( - arr, - f, - mask.view("uint8"), - convert=False, - na_value=na_value, - dtype=np.dtype(cast(type, dtype)), - ) - if na_value_is_na and mask.any(): - if is_integer_dtype(dtype): - result = result.astype("float64") - else: - result = result.astype("object") - result[mask] = np.nan - return result - - else: - return self._str_map_str_or_object(dtype, na_value, arr, f, mask, convert) - - def _str_map( - self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True - ): - if self.dtype.na_value is np.nan: - return self._str_map_nan_semantics( - f, na_value=na_value, dtype=dtype, convert=convert - ) - - from pandas.arrays import BooleanArray - - if dtype is None: - dtype = StringDtype(storage="python") - if na_value is None: - na_value = self.dtype.na_value - - mask = isna(self) - arr = np.asarray(self) - - if is_integer_dtype(dtype) or is_bool_dtype(dtype): - constructor: type[IntegerArray | BooleanArray] - if is_integer_dtype(dtype): - constructor = IntegerArray - else: - constructor = BooleanArray - - na_value_is_na = isna(na_value) - if na_value_is_na: - na_value = 1 - elif dtype == np.dtype("bool"): - na_value = bool(na_value) - result = lib.map_infer_mask( - arr, - f, - mask.view("uint8"), - convert=False, - na_value=na_value, - # error: Argument 1 to "dtype" has incompatible type - # "Union[ExtensionDtype, str, dtype[Any], Type[object]]"; expected - # "Type[object]" - dtype=np.dtype(cast(type, dtype)), - ) - - if not na_value_is_na: - mask[:] = False - - return constructor(result, mask) - - else: - return self._str_map_str_or_object(dtype, na_value, arr, f, mask, convert) - class StringArrayNumpySemantics(StringArray): _storage = "python" diff --git a/pandas/core/arrays/string_arrow.py b/pandas/core/arrays/string_arrow.py index 4893883d3ad12..cc37995969f0a 100644 --- a/pandas/core/arrays/string_arrow.py +++ b/pandas/core/arrays/string_arrow.py @@ -6,7 +6,6 @@ from typing import ( TYPE_CHECKING, Union, - cast, ) import numpy as np @@ -23,8 +22,6 @@ ) from pandas.core.dtypes.common import ( - is_bool_dtype, - is_integer_dtype, is_scalar, pandas_dtype, ) @@ -279,98 +276,7 @@ def astype(self, dtype, copy: bool = True): # base class "ObjectStringArrayMixin" defined the type as "float") _str_na_value = libmissing.NA # type: ignore[assignment] - def _str_map_nan_semantics( - self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True - ): - if dtype is None: - dtype = self.dtype - if na_value is None: - na_value = self.dtype.na_value - - mask = isna(self) - arr = np.asarray(self) - - if is_integer_dtype(dtype) or is_bool_dtype(dtype): - if is_integer_dtype(dtype): - na_value = np.nan - else: - na_value = False - - dtype = np.dtype(cast(type, dtype)) - if mask.any(): - # numpy int/bool dtypes cannot hold NaNs so we must convert to - # float64 for int (to match maybe_convert_objects) or - # object for bool (again to match maybe_convert_objects) - if is_integer_dtype(dtype): - dtype = np.dtype("float64") - else: - dtype = np.dtype(object) - result = lib.map_infer_mask( - arr, - f, - mask.view("uint8"), - convert=False, - na_value=na_value, - dtype=dtype, - ) - return result - - else: - return self._str_map_str_or_object(dtype, na_value, arr, f, mask, convert) - - def _str_map( - self, f, na_value=None, dtype: Dtype | None = None, convert: bool = True - ): - if self.dtype.na_value is np.nan: - return self._str_map_nan_semantics( - f, na_value=na_value, dtype=dtype, convert=convert - ) - - # TODO: de-duplicate with StringArray method. This method is moreless copy and - # paste. - - from pandas.arrays import ( - BooleanArray, - IntegerArray, - ) - - if dtype is None: - dtype = self.dtype - if na_value is None: - na_value = self.dtype.na_value - - mask = isna(self) - arr = np.asarray(self) - - if is_integer_dtype(dtype) or is_bool_dtype(dtype): - constructor: type[IntegerArray | BooleanArray] - if is_integer_dtype(dtype): - constructor = IntegerArray - else: - constructor = BooleanArray - - na_value_is_na = isna(na_value) - if na_value_is_na: - na_value = 1 - result = lib.map_infer_mask( - arr, - f, - mask.view("uint8"), - convert=False, - na_value=na_value, - # error: Argument 1 to "dtype" has incompatible type - # "Union[ExtensionDtype, str, dtype[Any], Type[object]]"; expected - # "Type[object]" - dtype=np.dtype(cast(type, dtype)), - ) - - if not na_value_is_na: - mask[:] = False - - return constructor(result, mask) - - else: - return self._str_map_str_or_object(dtype, na_value, arr, f, mask, convert) + _str_map = BaseStringArray._str_map def _str_contains( self, pat, case: bool = True, flags: int = 0, na=np.nan, regex: bool = True diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py index 6836ba3f65691..c005a1ce26e4b 100644 --- a/pandas/core/reshape/concat.py +++ b/pandas/core/reshape/concat.py @@ -379,6 +379,11 @@ def concat( 0 1 2 1 3 4 """ + if ignore_index and keys is not None: + raise ValueError( + f"Cannot set {ignore_index=} and specify keys. Either should be used." + ) + if copy is not lib.no_default: warnings.warn( "The copy keyword is deprecated and will be removed in a future " diff --git a/pandas/core/reshape/tile.py b/pandas/core/reshape/tile.py index 18517199f073c..b3f946f289891 100644 --- a/pandas/core/reshape/tile.py +++ b/pandas/core/reshape/tile.py @@ -358,7 +358,16 @@ def qcut( x_idx = _preprocess_for_cut(x) x_idx, _ = _coerce_to_type(x_idx) - quantiles = np.linspace(0, 1, q + 1) if is_integer(q) else q + if is_integer(q): + quantiles = np.linspace(0, 1, q + 1) + # Round up rather than to nearest if not representable in base 2 + np.putmask( + quantiles, + q * quantiles != np.arange(q + 1), + np.nextafter(quantiles, 1), + ) + else: + quantiles = q bins = x_idx.to_series().dropna().quantile(quantiles) diff --git a/pandas/core/strings/accessor.py b/pandas/core/strings/accessor.py index 8e6183c43480f..25fdafa9b8354 100644 --- a/pandas/core/strings/accessor.py +++ b/pandas/core/strings/accessor.py @@ -3092,6 +3092,8 @@ def normalize(self, form): Returns ------- Series or Index of object + Returns a Series or an Index of the %(side)s indexes + in each string of the input. See Also -------- diff --git a/pandas/tests/apply/test_frame_apply.py b/pandas/tests/apply/test_frame_apply.py index b0475b64a844e..3be3562d23cd6 100644 --- a/pandas/tests/apply/test_frame_apply.py +++ b/pandas/tests/apply/test_frame_apply.py @@ -6,6 +6,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas.core.dtypes.dtypes import CategoricalDtype import pandas as pd @@ -1245,6 +1247,9 @@ def test_agg_multiple_mixed(): tm.assert_frame_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_agg_multiple_mixed_raises(): # GH 20909 mdf = DataFrame( diff --git a/pandas/tests/apply/test_invalid_arg.py b/pandas/tests/apply/test_invalid_arg.py index 3137d3ff50954..ba970e328ae40 100644 --- a/pandas/tests/apply/test_invalid_arg.py +++ b/pandas/tests/apply/test_invalid_arg.py @@ -12,6 +12,9 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW from pandas.errors import SpecificationError from pandas import ( @@ -209,6 +212,10 @@ def transform(row): data.apply(transform, axis=1) +# we should raise a proper TypeError instead of propagating the pyarrow error +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) @pytest.mark.parametrize( "df, func, expected", tm.get_cython_table_params( @@ -229,6 +236,10 @@ def test_agg_cython_table_raises_frame(df, func, expected, axis, using_infer_str df.agg(func, axis=axis) +# we should raise a proper TypeError instead of propagating the pyarrow error +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) @pytest.mark.parametrize( "series, func, expected", chain( diff --git a/pandas/tests/apply/test_numba.py b/pandas/tests/apply/test_numba.py index 6ac0b49f0e4e7..6bbe5100e8826 100644 --- a/pandas/tests/apply/test_numba.py +++ b/pandas/tests/apply/test_numba.py @@ -104,6 +104,7 @@ def test_numba_nonunique_unsupported(apply_axis): def test_numba_unsupported_dtypes(apply_axis): + pytest.importorskip("pyarrow") f = lambda x: x df = DataFrame({"a": [1, 2], "b": ["a", "b"], "c": [4, 5]}) df["c"] = df["c"].astype("double[pyarrow]") diff --git a/pandas/tests/arithmetic/test_object.py b/pandas/tests/arithmetic/test_object.py index 4b5156d0007bb..899ea1910d055 100644 --- a/pandas/tests/arithmetic/test_object.py +++ b/pandas/tests/arithmetic/test_object.py @@ -8,6 +8,9 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW import pandas.util._test_decorators as td import pandas as pd @@ -315,6 +318,9 @@ def test_add(self): expected = pd.Index(["1a", "1b", "1c"]) tm.assert_index_equal("1" + index, expected) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_sub_fail(self, using_infer_string): index = pd.Index([str(i) for i in range(10)]) diff --git a/pandas/tests/arrays/boolean/test_arithmetic.py b/pandas/tests/arrays/boolean/test_arithmetic.py index 0c4fcf149eb20..4dbd8eb9f5ca7 100644 --- a/pandas/tests/arrays/boolean/test_arithmetic.py +++ b/pandas/tests/arrays/boolean/test_arithmetic.py @@ -3,6 +3,10 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW + import pandas as pd import pandas._testing as tm @@ -90,6 +94,9 @@ def test_op_int8(left_array, right_array, opname): # ----------------------------------------------------------------------------- +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_error_invalid_values(data, all_arithmetic_operators, using_infer_string): # invalid ops diff --git a/pandas/tests/arrays/categorical/test_analytics.py b/pandas/tests/arrays/categorical/test_analytics.py index dca33dffa3996..52fd80cd196e0 100644 --- a/pandas/tests/arrays/categorical/test_analytics.py +++ b/pandas/tests/arrays/categorical/test_analytics.py @@ -6,7 +6,10 @@ from pandas._config import using_string_dtype -from pandas.compat import PYPY +from pandas.compat import ( + HAS_PYARROW, + PYPY, +) from pandas import ( Categorical, @@ -296,7 +299,9 @@ def test_nbytes(self): exp = 3 + 3 * 8 # 3 int8s for values + 3 int64s for categories assert cat.nbytes == exp - @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") + @pytest.mark.xfail( + using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)" + ) def test_memory_usage(self): cat = Categorical([1, 2, 3]) diff --git a/pandas/tests/arrays/categorical/test_constructors.py b/pandas/tests/arrays/categorical/test_constructors.py index 6752a503016f8..d7eb6800e5d07 100644 --- a/pandas/tests/arrays/categorical/test_constructors.py +++ b/pandas/tests/arrays/categorical/test_constructors.py @@ -8,6 +8,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas.core.dtypes.common import ( is_float_dtype, is_integer_dtype, @@ -442,7 +444,9 @@ def test_constructor_str_unknown(self): with pytest.raises(ValueError, match="Unknown dtype"): Categorical([1, 2], dtype="foo") - @pytest.mark.xfail(using_string_dtype(), reason="Can't be NumPy strings") + @pytest.mark.xfail( + using_string_dtype() and HAS_PYARROW, reason="Can't be NumPy strings" + ) def test_constructor_np_strs(self): # GH#31499 Hashtable.map_locations needs to work on np.str_ objects cat = Categorical(["1", "0", "1"], [np.str_("0"), np.str_("1")]) diff --git a/pandas/tests/arrays/integer/test_reduction.py b/pandas/tests/arrays/integer/test_reduction.py index db04862e4ea07..e485c7f79b475 100644 --- a/pandas/tests/arrays/integer/test_reduction.py +++ b/pandas/tests/arrays/integer/test_reduction.py @@ -1,6 +1,8 @@ import numpy as np import pytest +from pandas.compat import HAS_PYARROW + import pandas as pd from pandas import ( DataFrame, @@ -102,9 +104,10 @@ def test_groupby_reductions(op, expected): ["all", Series([True, True, True], index=["A", "B", "C"], dtype="boolean")], ], ) -def test_mixed_reductions(op, expected, using_infer_string): - if op in ["any", "all"] and using_infer_string: - expected = expected.astype("bool") +def test_mixed_reductions(request, op, expected, using_infer_string): + if op in ["any", "all"] and using_infer_string and HAS_PYARROW: + # TODO(infer_string) inconsistent result type + request.applymarker(pytest.mark.xfail(reason="TODO(infer_string)")) df = DataFrame( { "A": ["a", "b", "b"], diff --git a/pandas/tests/base/test_conversion.py b/pandas/tests/base/test_conversion.py index dd6bf3c7521f8..13a3ff048c79e 100644 --- a/pandas/tests/base/test_conversion.py +++ b/pandas/tests/base/test_conversion.py @@ -1,6 +1,10 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW + from pandas.core.dtypes.dtypes import DatetimeTZDtype import pandas as pd @@ -20,6 +24,7 @@ SparseArray, TimedeltaArray, ) +from pandas.core.arrays.string_ import StringArrayNumpySemantics from pandas.core.arrays.string_arrow import ArrowStringArrayNumpySemantics @@ -218,7 +223,9 @@ def test_iter_box_period(self): ) def test_values_consistent(arr, expected_type, dtype, using_infer_string): if using_infer_string and dtype == "object": - expected_type = ArrowStringArrayNumpySemantics + expected_type = ( + ArrowStringArrayNumpySemantics if HAS_PYARROW else StringArrayNumpySemantics + ) l_values = Series(arr)._values r_values = pd.Index(arr)._values assert type(l_values) is expected_type @@ -355,6 +362,9 @@ def test_to_numpy(arr, expected, index_or_series_or_array, request): tm.assert_numpy_array_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize("as_series", [True, False]) @pytest.mark.parametrize( "arr", [np.array([1, 2, 3], dtype="int64"), np.array(["a", "b", "c"], dtype=object)] diff --git a/pandas/tests/copy_view/test_astype.py b/pandas/tests/copy_view/test_astype.py index 8724f62de1534..de56d5e4a07ee 100644 --- a/pandas/tests/copy_view/test_astype.py +++ b/pandas/tests/copy_view/test_astype.py @@ -5,6 +5,7 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW from pandas.compat.pyarrow import pa_version_under12p0 import pandas.util._test_decorators as td @@ -197,7 +198,7 @@ def test_astype_arrow_timestamp(): assert np.shares_memory(get_array(df, "a"), get_array(result, "a")._pa_array) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_convert_dtypes_infer_objects(): ser = Series(["a", "b", "c"]) ser_orig = ser.copy() @@ -213,7 +214,7 @@ def test_convert_dtypes_infer_objects(): tm.assert_series_equal(ser, ser_orig) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_convert_dtypes(): df = DataFrame({"a": ["a", "b"], "b": [1, 2], "c": [1.5, 2.5], "d": [True, False]}) df_orig = df.copy() diff --git a/pandas/tests/copy_view/test_functions.py b/pandas/tests/copy_view/test_functions.py index d2e2d43b0a42b..dd4dd154f74b0 100644 --- a/pandas/tests/copy_view/test_functions.py +++ b/pandas/tests/copy_view/test_functions.py @@ -3,6 +3,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas import ( DataFrame, Index, @@ -14,7 +16,7 @@ from pandas.tests.copy_view.util import get_array -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_concat_frames(): df = DataFrame({"b": ["a"] * 3}) df2 = DataFrame({"a": ["a"] * 3}) @@ -33,7 +35,7 @@ def test_concat_frames(): tm.assert_frame_equal(df, df_orig) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_concat_frames_updating_input(): df = DataFrame({"b": ["a"] * 3}) df2 = DataFrame({"a": ["a"] * 3}) @@ -153,7 +155,7 @@ def test_concat_copy_keyword(): assert np.shares_memory(get_array(df2, "b"), get_array(result, "b")) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") @pytest.mark.parametrize( "func", [ @@ -249,7 +251,7 @@ def test_merge_copy_keyword(): assert np.shares_memory(get_array(df2, "b"), get_array(result, "b")) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_join_on_key(): df_index = Index(["a", "b", "c"], name="key") @@ -277,7 +279,7 @@ def test_join_on_key(): tm.assert_frame_equal(df2, df2_orig) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_join_multiple_dataframes_on_key(): df_index = Index(["a", "b", "c"], name="key") diff --git a/pandas/tests/copy_view/test_interp_fillna.py b/pandas/tests/copy_view/test_interp_fillna.py index f80e9b7dcf838..fc57178b897b9 100644 --- a/pandas/tests/copy_view/test_interp_fillna.py +++ b/pandas/tests/copy_view/test_interp_fillna.py @@ -3,6 +3,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas import ( NA, DataFrame, @@ -121,7 +123,7 @@ def test_interpolate_cannot_with_object_dtype(): df.interpolate() -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_interpolate_object_convert_no_op(): df = DataFrame({"a": ["a", "b", "c"], "b": 1}) arr_a = get_array(df, "a") diff --git a/pandas/tests/copy_view/test_methods.py b/pandas/tests/copy_view/test_methods.py index 3716df8fbf855..92e1ba750fae2 100644 --- a/pandas/tests/copy_view/test_methods.py +++ b/pandas/tests/copy_view/test_methods.py @@ -3,6 +3,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + import pandas as pd from pandas import ( DataFrame, @@ -714,7 +716,7 @@ def test_head_tail(method): tm.assert_frame_equal(df, df_orig) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_infer_objects(): df = DataFrame({"a": [1, 2], "b": "c", "c": 1, "d": "x"}) df_orig = df.copy() @@ -730,6 +732,9 @@ def test_infer_objects(): tm.assert_frame_equal(df, df_orig) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_infer_objects_no_reference(): df = DataFrame( { @@ -899,7 +904,7 @@ def test_sort_values_inplace(obj, kwargs): tm.assert_equal(view, obj_orig) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") @pytest.mark.parametrize("decimals", [-1, 0, 1]) def test_round(decimals): df = DataFrame({"a": [1, 2], "b": "c"}) diff --git a/pandas/tests/copy_view/test_replace.py b/pandas/tests/copy_view/test_replace.py index c1120ccfea635..58c979fb05089 100644 --- a/pandas/tests/copy_view/test_replace.py +++ b/pandas/tests/copy_view/test_replace.py @@ -3,6 +3,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas import ( Categorical, DataFrame, @@ -59,7 +61,7 @@ def test_replace_regex_inplace_refs(): tm.assert_frame_equal(view, df_orig) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_replace_regex_inplace(): df = DataFrame({"a": ["aaa", "bbb"]}) arr = get_array(df, "a") @@ -257,7 +259,7 @@ def test_replace_empty_list(): assert not df2._mgr._has_no_reference(0) -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") @pytest.mark.parametrize("value", ["d", None]) def test_replace_object_list_inplace(value): df = DataFrame({"a": ["a", "b", "c"]}) diff --git a/pandas/tests/extension/base/ops.py b/pandas/tests/extension/base/ops.py index fad2560265d21..ff9f3cbed64a2 100644 --- a/pandas/tests/extension/base/ops.py +++ b/pandas/tests/extension/base/ops.py @@ -7,6 +7,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas.core.dtypes.common import is_string_dtype import pandas as pd @@ -140,6 +142,12 @@ class BaseArithmeticOpsTests(BaseOpsUtil): series_array_exc: type[Exception] | None = TypeError divmod_exc: type[Exception] | None = TypeError + # TODO(infer_string) need to remove import of pyarrow + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) def test_arith_series_with_scalar(self, data, all_arithmetic_operators): # series & scalar if all_arithmetic_operators == "__rmod__" and is_string_dtype(data.dtype): @@ -149,6 +157,11 @@ def test_arith_series_with_scalar(self, data, all_arithmetic_operators): ser = pd.Series(data) self.check_opname(ser, op_name, ser.iloc[0]) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) def test_arith_frame_with_scalar(self, data, all_arithmetic_operators): # frame & scalar if all_arithmetic_operators == "__rmod__" and is_string_dtype(data.dtype): @@ -158,12 +171,22 @@ def test_arith_frame_with_scalar(self, data, all_arithmetic_operators): df = pd.DataFrame({"A": data}) self.check_opname(df, op_name, data[0]) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) def test_arith_series_with_array(self, data, all_arithmetic_operators): # ndarray & other series op_name = all_arithmetic_operators ser = pd.Series(data) self.check_opname(ser, op_name, pd.Series([ser.iloc[0]] * len(ser))) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) def test_divmod(self, data): ser = pd.Series(data) self._check_divmod_op(ser, divmod, 1) @@ -179,6 +202,7 @@ def test_divmod_series_array(self, data, data_for_twos): other = pd.Series(other) self._check_divmod_op(other, ops.rdivmod, ser) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_add_series_with_extension_array(self, data): # Check adding an ExtensionArray to a Series of the same dtype matches # the behavior of adding the arrays directly and then wrapping in a diff --git a/pandas/tests/extension/test_categorical.py b/pandas/tests/extension/test_categorical.py index 8f8af607585df..c3d4b83f731a3 100644 --- a/pandas/tests/extension/test_categorical.py +++ b/pandas/tests/extension/test_categorical.py @@ -140,6 +140,7 @@ def test_map(self, data, na_action): result = data.map(lambda x: x, na_action=na_action) tm.assert_extension_array_equal(result, data) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): # frame & scalar op_name = all_arithmetic_operators @@ -151,6 +152,7 @@ def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): ) super().test_arith_frame_with_scalar(data, op_name) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_arith_series_with_scalar(self, data, all_arithmetic_operators, request): op_name = all_arithmetic_operators if op_name == "__rmod__": diff --git a/pandas/tests/extension/test_numpy.py b/pandas/tests/extension/test_numpy.py index 79cfb736941d6..1b251a5118681 100644 --- a/pandas/tests/extension/test_numpy.py +++ b/pandas/tests/extension/test_numpy.py @@ -19,6 +19,8 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + from pandas.core.dtypes.dtypes import NumpyEADtype import pandas as pd @@ -255,6 +257,7 @@ def test_insert_invalid(self, data, invalid_scalar): frame_scalar_exc = None series_array_exc = None + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_divmod(self, data): divmod_exc = None if data.dtype.kind == "O": @@ -262,6 +265,7 @@ def test_divmod(self, data): self.divmod_exc = divmod_exc super().test_divmod(data) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_divmod_series_array(self, data): ser = pd.Series(data) exc = None @@ -270,6 +274,7 @@ def test_divmod_series_array(self, data): self.divmod_exc = exc self._check_divmod_op(ser, divmod, data) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_arith_series_with_scalar(self, data, all_arithmetic_operators, request): opname = all_arithmetic_operators series_scalar_exc = None @@ -283,6 +288,7 @@ def test_arith_series_with_scalar(self, data, all_arithmetic_operators, request) self.series_scalar_exc = series_scalar_exc super().test_arith_series_with_scalar(data, all_arithmetic_operators) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_arith_series_with_array(self, data, all_arithmetic_operators): opname = all_arithmetic_operators series_array_exc = None @@ -291,6 +297,7 @@ def test_arith_series_with_array(self, data, all_arithmetic_operators): self.series_array_exc = series_array_exc super().test_arith_series_with_array(data, all_arithmetic_operators) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_arith_frame_with_scalar(self, data, all_arithmetic_operators, request): opname = all_arithmetic_operators frame_scalar_exc = None diff --git a/pandas/tests/frame/indexing/test_indexing.py b/pandas/tests/frame/indexing/test_indexing.py index 826ac2be3339b..8ce4e8725d632 100644 --- a/pandas/tests/frame/indexing/test_indexing.py +++ b/pandas/tests/frame/indexing/test_indexing.py @@ -12,6 +12,7 @@ from pandas._config import using_string_dtype from pandas._libs import iNaT +from pandas.compat import HAS_PYARROW from pandas.errors import InvalidIndexError from pandas.core.dtypes.common import is_integer @@ -1148,7 +1149,9 @@ def test_loc_setitem_datetimelike_with_inference(self): ) tm.assert_series_equal(result, expected) - @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") + @pytest.mark.xfail( + using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)" + ) def test_getitem_boolean_indexing_mixed(self): df = DataFrame( { diff --git a/pandas/tests/frame/indexing/test_where.py b/pandas/tests/frame/indexing/test_where.py index 1d7b3e12b2e86..32a827c25c77a 100644 --- a/pandas/tests/frame/indexing/test_where.py +++ b/pandas/tests/frame/indexing/test_where.py @@ -6,6 +6,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas.core.dtypes.common import is_scalar import pandas as pd @@ -938,6 +940,9 @@ def test_where_nullable_invalid_na(frame_or_series, any_numeric_ea_dtype): obj.mask(mask, null) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) @given(data=OPTIONAL_ONE_OF_ALL) def test_where_inplace_casting(data): # GH 22051 @@ -1018,6 +1023,9 @@ def test_where_producing_ea_cond_for_np_dtype(): tm.assert_frame_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize( "replacement", [0.001, True, "snake", None, datetime(2022, 5, 4)] ) diff --git a/pandas/tests/frame/methods/test_info.py b/pandas/tests/frame/methods/test_info.py index a4319f8a8ae7f..aad43b7a77ac7 100644 --- a/pandas/tests/frame/methods/test_info.py +++ b/pandas/tests/frame/methods/test_info.py @@ -10,6 +10,7 @@ from pandas._config import using_string_dtype from pandas.compat import ( + HAS_PYARROW, IS64, PYPY, ) @@ -520,7 +521,7 @@ def test_info_int_columns(): assert result == expected -@pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") +@pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)") def test_memory_usage_empty_no_warning(): # GH#50066 df = DataFrame(index=["a", "b"]) diff --git a/pandas/tests/frame/methods/test_rank.py b/pandas/tests/frame/methods/test_rank.py index 79aabbcc83bbf..4e8e267523439 100644 --- a/pandas/tests/frame/methods/test_rank.py +++ b/pandas/tests/frame/methods/test_rank.py @@ -6,10 +6,13 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + from pandas._libs.algos import ( Infinity, NegInfinity, ) +from pandas.compat import HAS_PYARROW from pandas import ( DataFrame, @@ -464,9 +467,18 @@ def test_rank_inf_nans_na_option( ], ) def test_rank_object_first( - self, frame_or_series, na_option, ascending, expected, using_infer_string + self, + request, + frame_or_series, + na_option, + ascending, + expected, + using_infer_string, ): obj = frame_or_series(["foo", "foo", None, "foo"]) + if using_string_dtype() and not HAS_PYARROW and isinstance(obj, Series): + request.applymarker(pytest.mark.xfail(reason="TODO(infer_string)")) + result = obj.rank(method="first", na_option=na_option, ascending=ascending) expected = frame_or_series(expected) if using_infer_string and isinstance(obj, Series): diff --git a/pandas/tests/frame/methods/test_value_counts.py b/pandas/tests/frame/methods/test_value_counts.py index 4136d641ef67f..7670b53f23173 100644 --- a/pandas/tests/frame/methods/test_value_counts.py +++ b/pandas/tests/frame/methods/test_value_counts.py @@ -1,6 +1,10 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW + import pandas as pd import pandas._testing as tm @@ -132,6 +136,9 @@ def test_data_frame_value_counts_dropna_true(nulls_fixture): tm.assert_series_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) def test_data_frame_value_counts_dropna_false(nulls_fixture): # GH 41334 df = pd.DataFrame( diff --git a/pandas/tests/frame/test_api.py b/pandas/tests/frame/test_api.py index e8ef0592ac432..f8219e68a72da 100644 --- a/pandas/tests/frame/test_api.py +++ b/pandas/tests/frame/test_api.py @@ -8,6 +8,8 @@ from pandas._config import using_string_dtype from pandas._config.config import option_context +from pandas.compat import HAS_PYARROW + import pandas as pd from pandas import ( DataFrame, @@ -113,7 +115,9 @@ def test_not_hashable(self): with pytest.raises(TypeError, match=msg): hash(empty_frame) - @pytest.mark.xfail(using_string_dtype(), reason="surrogates not allowed") + @pytest.mark.xfail( + using_string_dtype() and HAS_PYARROW, reason="surrogates not allowed" + ) def test_column_name_contains_unicode_surrogate(self): # GH 25509 colname = "\ud83d" diff --git a/pandas/tests/frame/test_arithmetic.py b/pandas/tests/frame/test_arithmetic.py index 734bfc8b30053..e41a3b27e592c 100644 --- a/pandas/tests/frame/test_arithmetic.py +++ b/pandas/tests/frame/test_arithmetic.py @@ -13,6 +13,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + import pandas as pd from pandas import ( DataFrame, @@ -1542,7 +1544,9 @@ def test_comparisons(self, simple_frame, float_frame, func): with pytest.raises(ValueError, match=msg): func(simple_frame, simple_frame[:2]) - @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") + @pytest.mark.xfail( + using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)" + ) def test_strings_to_numbers_comparisons_raises(self, compare_operators_no_eq_ne): # GH 11565 df = DataFrame( diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py index a210af94561f9..0176a36fe78d7 100644 --- a/pandas/tests/frame/test_constructors.py +++ b/pandas/tests/frame/test_constructors.py @@ -24,6 +24,7 @@ from pandas._config import using_string_dtype from pandas._libs import lib +from pandas.compat import HAS_PYARROW from pandas.compat.numpy import np_version_gt2 from pandas.errors import IntCastingNaNError @@ -299,7 +300,7 @@ def test_constructor_dtype_nocast_view_2d_array(self): df2 = DataFrame(df.values, dtype=df[0].dtype) assert df2._mgr.blocks[0].values.flags.c_contiguous - @pytest.mark.xfail(using_string_dtype(), reason="conversion copies") + @pytest.mark.xfail(using_string_dtype() and HAS_PYARROW, reason="conversion copies") def test_1d_object_array_does_not_copy(self): # https://github.com/pandas-dev/pandas/issues/39272 arr = np.array(["a", "b"], dtype="object") diff --git a/pandas/tests/frame/test_logical_ops.py b/pandas/tests/frame/test_logical_ops.py index ad54cfaf9d927..6788721e8a72e 100644 --- a/pandas/tests/frame/test_logical_ops.py +++ b/pandas/tests/frame/test_logical_ops.py @@ -4,6 +4,10 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW + from pandas import ( CategoricalIndex, DataFrame, @@ -96,6 +100,9 @@ def test_logical_ops_int_frame(self): res_ser = df1a_int["A"] | df1a_bool["A"] tm.assert_series_equal(res_ser, df1a_bool["A"]) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_logical_ops_invalid(self, using_infer_string): # GH#5808 diff --git a/pandas/tests/frame/test_reductions.py b/pandas/tests/frame/test_reductions.py index 4c355ed92b6c3..1d667d35db253 100644 --- a/pandas/tests/frame/test_reductions.py +++ b/pandas/tests/frame/test_reductions.py @@ -226,6 +226,7 @@ def float_frame_with_na(): class TestDataFrameAnalytics: # --------------------------------------------------------------------- # Reductions + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) @pytest.mark.parametrize("axis", [0, 1]) @pytest.mark.parametrize( "opname", @@ -431,6 +432,7 @@ def test_stat_operators_attempt_obj_array(self, method, df, axis): expected[expected.isna()] = None tm.assert_series_equal(result, expected) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) @pytest.mark.parametrize("op", ["mean", "std", "var", "skew", "kurt", "sem"]) def test_mixed_ops(self, op): # GH#16116 @@ -532,7 +534,7 @@ def test_mean_mixed_string_decimal(self): df = DataFrame(d) with pytest.raises( - TypeError, match="unsupported operand type|does not support" + TypeError, match="unsupported operand type|does not support|Cannot perform" ): df.mean() result = df[["A", "C"]].mean() @@ -690,6 +692,7 @@ def test_mode_dropna(self, dropna, expected): expected = DataFrame(expected) tm.assert_frame_equal(result, expected) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) def test_mode_sortwarning(self, using_infer_string): # Check for the warning that is raised when the mode # results cannot be sorted @@ -979,7 +982,7 @@ def test_sum_mixed_datetime(self): def test_mean_corner(self, float_frame, float_string_frame): # unit test when have object data - msg = "Could not convert|does not support" + msg = "Could not convert|does not support|Cannot perform" with pytest.raises(TypeError, match=msg): float_string_frame.mean(axis=0) @@ -1093,6 +1096,7 @@ def test_idxmin_empty(self, index, skipna, axis): expected = Series(dtype=index.dtype) tm.assert_series_equal(result, expected) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) @pytest.mark.parametrize("numeric_only", [True, False]) def test_idxmin_numeric_only(self, numeric_only): df = DataFrame({"a": [2, 3, 1], "b": [2, 1, 1], "c": list("xyx")}) @@ -1143,6 +1147,7 @@ def test_idxmax_empty(self, index, skipna, axis): expected = Series(dtype=index.dtype) tm.assert_series_equal(result, expected) + @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)", strict=False) @pytest.mark.parametrize("numeric_only", [True, False]) def test_idxmax_numeric_only(self, numeric_only): df = DataFrame({"a": [2, 3, 1], "b": [2, 1, 1], "c": list("xyx")}) @@ -1964,7 +1969,7 @@ def test_minmax_extensionarray(method, numeric_only): def test_frame_mixed_numeric_object_with_timestamp(ts_value): # GH 13912 df = DataFrame({"a": [1], "b": [1.1], "c": ["foo"], "d": [ts_value]}) - with pytest.raises(TypeError, match="does not support operation"): + with pytest.raises(TypeError, match="does not support operation|Cannot perform"): df.sum() diff --git a/pandas/tests/frame/test_unary.py b/pandas/tests/frame/test_unary.py index 1887fa61ad081..5bbe047078c6e 100644 --- a/pandas/tests/frame/test_unary.py +++ b/pandas/tests/frame/test_unary.py @@ -5,6 +5,7 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW from pandas.compat.numpy import np_version_gte1p25 import pandas as pd @@ -42,6 +43,11 @@ def test_neg_object(self, df, expected): tm.assert_frame_equal(-df, expected) tm.assert_series_equal(-df["a"], expected["a"]) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) @pytest.mark.parametrize( "df_data", [ @@ -130,7 +136,9 @@ def test_pos_object(self, df_data): tm.assert_frame_equal(+df, df) tm.assert_series_equal(+df["a"], df["a"]) - @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)") + @pytest.mark.xfail( + using_string_dtype() and HAS_PYARROW, reason="TODO(infer_string)" + ) @pytest.mark.filterwarnings("ignore:Applying:DeprecationWarning") def test_pos_object_raises(self): # GH#21380 diff --git a/pandas/tests/groupby/methods/test_value_counts.py b/pandas/tests/groupby/methods/test_value_counts.py index 14d3dbd6fa496..18802ebd002fc 100644 --- a/pandas/tests/groupby/methods/test_value_counts.py +++ b/pandas/tests/groupby/methods/test_value_counts.py @@ -9,6 +9,7 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW import pandas.util._test_decorators as td from pandas import ( @@ -500,6 +501,9 @@ def test_dropna_combinations( tm.assert_series_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize( "dropna, expected_data, expected_index", [ diff --git a/pandas/tests/groupby/test_groupby.py b/pandas/tests/groupby/test_groupby.py index 791f279bffc94..11b874d0b1608 100644 --- a/pandas/tests/groupby/test_groupby.py +++ b/pandas/tests/groupby/test_groupby.py @@ -8,6 +8,7 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW from pandas.errors import SpecificationError import pandas.util._test_decorators as td @@ -1407,6 +1408,10 @@ def g(group): tm.assert_series_equal(result, expected) +# TODO harmonize error messages +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize("grouper", ["A", ["A", "B"]]) def test_set_group_name(df, grouper, using_infer_string): def f(group): diff --git a/pandas/tests/groupby/test_groupby_dropna.py b/pandas/tests/groupby/test_groupby_dropna.py index d42aa06d6bbfe..02071acf378dd 100644 --- a/pandas/tests/groupby/test_groupby_dropna.py +++ b/pandas/tests/groupby/test_groupby_dropna.py @@ -3,6 +3,7 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW from pandas.compat.pyarrow import pa_version_under10p1 from pandas.core.dtypes.missing import na_value_for_dtype @@ -12,6 +13,9 @@ from pandas.tests.groupby import get_groupby_method_args +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize( "dropna, tuples, outputs", [ @@ -55,6 +59,9 @@ def test_groupby_dropna_multi_index_dataframe_nan_in_one_group( tm.assert_frame_equal(grouped, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize( "dropna, tuples, outputs", [ @@ -131,6 +138,9 @@ def test_groupby_dropna_normal_index_dataframe(dropna, idx, outputs): tm.assert_frame_equal(grouped, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize( "dropna, idx, expected", [ @@ -205,6 +215,9 @@ def test_groupby_dataframe_slice_then_transform(dropna, index): tm.assert_series_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize( "dropna, tuples, outputs", [ @@ -286,6 +299,9 @@ def test_groupby_dropna_datetime_like_data( tm.assert_frame_equal(grouped, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)", strict=False +) @pytest.mark.parametrize( "dropna, data, selected_data, levels", [ @@ -371,6 +387,9 @@ def test_groupby_dropna_with_multiindex_input(input_index, keys, series): tm.assert_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_groupby_nan_included(): # GH 35646 data = {"group": ["g1", np.nan, "g1", "g2", np.nan], "B": [0, 1, 2, 3, 4]} diff --git a/pandas/tests/indexes/object/test_indexing.py b/pandas/tests/indexes/object/test_indexing.py index 1eeeebd6b8ca9..e3428d1060dbe 100644 --- a/pandas/tests/indexes/object/test_indexing.py +++ b/pandas/tests/indexes/object/test_indexing.py @@ -3,10 +3,13 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + from pandas._libs.missing import ( NA, is_matching_na, ) +from pandas.compat import HAS_PYARROW import pandas.util._test_decorators as td import pandas as pd @@ -29,6 +32,9 @@ def test_get_indexer_strings(self, method, expected): tm.assert_numpy_array_equal(actual, expected) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_get_indexer_strings_raises(self, using_infer_string): index = Index(["b", "c"]) diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index 0911f2aec74d6..7ec66100b7291 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -8,7 +8,12 @@ import numpy as np import pytest -from pandas.compat import IS64 +from pandas._config import using_string_dtype + +from pandas.compat import ( + HAS_PYARROW, + IS64, +) from pandas.errors import InvalidIndexError import pandas.util._test_decorators as td @@ -71,6 +76,9 @@ def test_constructor_casting(self, index): tm.assert_contains_all(arr, new_index) tm.assert_index_equal(index, new_index) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_constructor_copy(self, using_infer_string): index = Index(list("abc"), name="name") arr = np.array(index) @@ -335,6 +343,11 @@ def test_constructor_empty_special(self, empty, klass): def test_view_with_args(self, index): index.view("i8") + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) @pytest.mark.parametrize( "index", [ @@ -817,6 +830,11 @@ def test_isin(self, values, index, expected): expected = np.array(expected, dtype=bool) tm.assert_numpy_array_equal(result, expected) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) def test_isin_nan_common_object( self, nulls_fixture, nulls_fixture2, using_infer_string ): diff --git a/pandas/tests/indexes/test_old_base.py b/pandas/tests/indexes/test_old_base.py index 6d01ba6adc87a..9993a21d93f12 100644 --- a/pandas/tests/indexes/test_old_base.py +++ b/pandas/tests/indexes/test_old_base.py @@ -9,6 +9,7 @@ from pandas._config import using_string_dtype from pandas._libs.tslibs import Timestamp +from pandas.compat import HAS_PYARROW from pandas.core.dtypes.common import ( is_integer_dtype, @@ -245,6 +246,11 @@ def test_repr_max_seq_item_setting(self, simple_index): repr(idx) assert "..." not in str(idx) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) @pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning") def test_ensure_copied_data(self, index): # Check the "copy" argument of each Index.__new__ is honoured diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index 247501f1504e7..e007b8c4e97ac 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -16,6 +16,7 @@ from pandas._config import using_string_dtype from pandas._libs import index as libindex +from pandas.compat import HAS_PYARROW from pandas.errors import IndexingError import pandas as pd @@ -1388,6 +1389,9 @@ def test_loc_setitem_categorical_values_partial_column_slice(self): df.loc[1:2, "a"] = Categorical(["b", "b"], categories=["a", "b"]) df.loc[2:3, "b"] = Categorical(["b", "b"], categories=["a", "b"]) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_loc_setitem_single_row_categorical(self, using_infer_string): # GH#25495 df = DataFrame({"Alpha": ["a"], "Numeric": [0]}) diff --git a/pandas/tests/io/formats/style/test_bar.py b/pandas/tests/io/formats/style/test_bar.py index b0e4712e8bb3d..d28c7c566d851 100644 --- a/pandas/tests/io/formats/style/test_bar.py +++ b/pandas/tests/io/formats/style/test_bar.py @@ -347,6 +347,7 @@ def test_styler_bar_with_NA_values(): def test_style_bar_with_pyarrow_NA_values(): + pytest.importorskip("pyarrow") data = """name,age,test1,test2,teacher Adam,15,95.0,80,Ashby Bob,16,81.0,82,Ashby diff --git a/pandas/tests/io/parser/conftest.py b/pandas/tests/io/parser/conftest.py index 6d5f870f07206..90f77a7024235 100644 --- a/pandas/tests/io/parser/conftest.py +++ b/pandas/tests/io/parser/conftest.py @@ -4,6 +4,7 @@ import pytest +from pandas.compat import HAS_PYARROW from pandas.compat._optional import VERSIONS from pandas import ( @@ -117,7 +118,15 @@ def csv1(datapath): _py_parsers_only = [_pythonParser] _c_parsers_only = [_cParserHighMemory, _cParserLowMemory] -_pyarrow_parsers_only = [pytest.param(_pyarrowParser, marks=pytest.mark.single_cpu)] +_pyarrow_parsers_only = [ + pytest.param( + _pyarrowParser, + marks=[ + pytest.mark.single_cpu, + pytest.mark.skipif(not HAS_PYARROW, reason="pyarrow is not installed"), + ], + ) +] _all_parsers = [*_c_parsers_only, *_py_parsers_only, *_pyarrow_parsers_only] @@ -181,7 +190,16 @@ def _get_all_parser_float_precision_combinations(): parser = parser.values[0] for precision in parser.float_precision_choices: # Re-wrap in pytest.param for pyarrow - mark = pytest.mark.single_cpu if parser.engine == "pyarrow" else () + mark = ( + [ + pytest.mark.single_cpu, + pytest.mark.skipif( + not HAS_PYARROW, reason="pyarrow is not installed" + ), + ] + if parser.engine == "pyarrow" + else () + ) param = pytest.param((parser(), precision), marks=mark) params.append(param) ids.append(f"{parser_id}-{precision}") diff --git a/pandas/tests/reductions/test_reductions.py b/pandas/tests/reductions/test_reductions.py index 66799732be064..26fecef6ed0e6 100644 --- a/pandas/tests/reductions/test_reductions.py +++ b/pandas/tests/reductions/test_reductions.py @@ -9,6 +9,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + import pandas as pd from pandas import ( Categorical, @@ -1204,6 +1206,9 @@ def test_idxminmax_object_dtype(self, using_infer_string): with pytest.raises(TypeError, match=msg): ser3.idxmin(skipna=False) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_idxminmax_object_frame(self): # GH#4279 df = DataFrame([["zimm", 2.5], ["biff", 1.0], ["bid", 12.0]]) diff --git a/pandas/tests/reshape/concat/test_concat.py b/pandas/tests/reshape/concat/test_concat.py index b2caa1fadd1a5..8af224f1ad64f 100644 --- a/pandas/tests/reshape/concat/test_concat.py +++ b/pandas/tests/reshape/concat/test_concat.py @@ -939,3 +939,14 @@ def test_concat_with_series_and_frame_returns_rangeindex_columns(): result = concat([ser, df]) expected = DataFrame([0, 1, 2], index=[0, 0, 1]) tm.assert_frame_equal(result, expected, check_column_type=True) + + +def test_concat_with_moot_ignore_index_and_keys(): + df1 = DataFrame([[0]]) + df2 = DataFrame([[42]]) + + ignore_index = True + keys = ["df1", "df2"] + msg = f"Cannot set {ignore_index=} and specify keys. Either should be used." + with pytest.raises(ValueError, match=msg): + concat([df1, df2], keys=keys, ignore_index=ignore_index) diff --git a/pandas/tests/reshape/test_qcut.py b/pandas/tests/reshape/test_qcut.py index 5f769db7f8acf..b2e9f26e1c407 100644 --- a/pandas/tests/reshape/test_qcut.py +++ b/pandas/tests/reshape/test_qcut.py @@ -307,3 +307,15 @@ def test_qcut_nullable_integer(q, any_numeric_ea_dtype): expected = qcut(arr.astype(float), q) tm.assert_categorical_equal(result, expected) + + +@pytest.mark.parametrize("scale", [1.0, 1 / 3, 17.0]) +@pytest.mark.parametrize("q", [3, 7, 9]) +@pytest.mark.parametrize("precision", [1, 3, 16]) +def test_qcut_contains(scale, q, precision): + # GH-59355 + arr = (scale * np.arange(q + 1)).round(precision) + result = qcut(arr, q, precision=precision) + + for value, bucket in zip(arr, result): + assert value in bucket diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index 742091d761d62..71ba2dab671ef 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -10,6 +10,7 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW from pandas.compat.numpy import np_version_gte1p24 from pandas.errors import IndexingError @@ -822,6 +823,11 @@ def test_mask_key(self, obj, key, expected, raises, val, indexer_sli): else: indexer_sli(obj)[mask] = val + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, + reason="TODO(infer_string)", + strict=False, + ) def test_series_where(self, obj, key, expected, raises, val, is_inplace): mask = np.zeros(obj.shape, dtype=bool) mask[key] = True diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index a63ffbbd3a5a1..79a55eb357f87 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -4,6 +4,10 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW + import pandas as pd from pandas import ( DataFrame, @@ -160,6 +164,9 @@ def test_attrs(self): result = s + 1 assert result.attrs == {"version": 1} + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_inspect_getmembers(self): # GH38782 pytest.importorskip("jinja2") diff --git a/pandas/tests/series/test_logical_ops.py b/pandas/tests/series/test_logical_ops.py index 939bf888fd61b..262ec35b472ad 100644 --- a/pandas/tests/series/test_logical_ops.py +++ b/pandas/tests/series/test_logical_ops.py @@ -6,6 +6,8 @@ from pandas._config import using_string_dtype +from pandas.compat import HAS_PYARROW + from pandas import ( DataFrame, Index, @@ -143,6 +145,9 @@ def test_logical_operators_int_dtype_with_bool(self): expected = Series([False, True, True, True]) tm.assert_series_equal(result, expected) + @pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" + ) def test_logical_operators_int_dtype_with_object(self, using_infer_string): # GH#9016: support bitwise op for integer types s_0123 = Series(range(4), dtype="int64") diff --git a/pandas/tests/series/test_reductions.py b/pandas/tests/series/test_reductions.py index 0bc3092d30b43..7bbb902e14a36 100644 --- a/pandas/tests/series/test_reductions.py +++ b/pandas/tests/series/test_reductions.py @@ -1,6 +1,10 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + +from pandas.compat import HAS_PYARROW + import pandas as pd from pandas import Series import pandas._testing as tm @@ -162,6 +166,9 @@ def test_validate_stat_keepdims(): np.sum(ser, keepdims=True) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_mean_with_convertible_string_raises(using_infer_string): # GH#44008 ser = Series(["1", "2"]) @@ -181,6 +188,9 @@ def test_mean_with_convertible_string_raises(using_infer_string): df.mean() +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_mean_dont_convert_j_to_complex(): # GH#36703 df = pd.DataFrame([{"db": "J", "numeric": 123}]) @@ -199,6 +209,9 @@ def test_mean_dont_convert_j_to_complex(): np.mean(df["db"].astype("string").array) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_median_with_convertible_string_raises(): # GH#34671 this _could_ return a string "2", but definitely not float 2.0 msg = r"Cannot convert \['1' '2' '3'\] to numeric|does not support" diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index d19717e87c7d2..d0192c12f9518 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -1182,3 +1182,10 @@ def test_is_yqm_start_end(): for ts, value in tests: assert ts == value + + +@pytest.mark.parametrize("left", [DateOffset(1), Nano(1)]) +@pytest.mark.parametrize("right", [DateOffset(1), Nano(1)]) +def test_multiply_dateoffset_typeerror(left, right): + with pytest.raises(TypeError, match="Cannot multiply"): + left * right diff --git a/pandas/tests/window/test_rolling.py b/pandas/tests/window/test_rolling.py index af3194b5085c4..17b92427f0d5d 100644 --- a/pandas/tests/window/test_rolling.py +++ b/pandas/tests/window/test_rolling.py @@ -6,7 +6,10 @@ import numpy as np import pytest +from pandas._config import using_string_dtype + from pandas.compat import ( + HAS_PYARROW, IS64, is_platform_arm, is_platform_power, @@ -1326,6 +1329,9 @@ def test_rolling_corr_timedelta_index(index, window): tm.assert_almost_equal(result, expected) +@pytest.mark.xfail( + using_string_dtype() and not HAS_PYARROW, reason="TODO(infer_string)" +) def test_groupby_rolling_nan_included(): # GH 35542 data = {"group": ["g1", np.nan, "g1", "g2", np.nan], "B": [0, 1, 2, 3, 4]} From b3a4070c94193debb9c127319624481d8bb46e68 Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Sat, 10 Aug 2024 22:58:35 -0400 Subject: [PATCH 03/13] Fix precommit errors - Add 2 spaces before inline comment --- pandas/_libs/tslibs/offsets.pyx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 5c6b734d99cc8..f392736343f88 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -610,7 +610,7 @@ cdef class BaseOffset: >>> pd.offsets.Week(5).rule_code 'W' - """ # noqa + """ # noqa return self._prefix @cache_readonly @@ -638,7 +638,7 @@ cdef class BaseOffset: >>> pd.offsets.Nano(-3).freqstr '-3ns' - """ # noqa + """ # noqa try: code = self.rule_code except NotImplementedError: @@ -821,7 +821,7 @@ cdef class BaseOffset: -------- >>> pd.offsets.Week(n=1).nanos ValueError: is a non-fixed frequency - """ # noqa + """ # noqa raise ValueError(f"{self} is a non-fixed frequency") # ------------------------------------------------------------------ @@ -1042,7 +1042,7 @@ cdef class Tick(SingleConstructorOffset): -------- >>> pd.offsets.Hour(5).nanos 18000000000000 - """ # noqa + """ # noqa return self.n * self._nanos_inc def is_on_offset(self, dt: datetime) -> bool: @@ -2486,7 +2486,7 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset): >>> pd.offsets.WeekOfMonth(n=1, week=0, weekday=0).rule_code 'WOM-1MON' - """ # noqa + """ # noqa weekday = int_to_weekday.get(self.weekday, "") if self.week == -1: # LastWeekOfMonth @@ -2548,7 +2548,7 @@ cdef class YearOffset(SingleConstructorOffset): >>> pd.tseries.offsets.YearEnd(n=1, month=6).rule_code 'YE-JUN' - """ # noqa + """ # noqa month = MONTH_ALIASES[self.month] return f"{self._prefix}-{month}" @@ -3550,7 +3550,7 @@ cdef class Week(SingleConstructorOffset): >>> pd.offsets.Week(5).rule_code 'W' - """ # noqa + """ # noqa suffix = "" if self.weekday is not None: weekday = int_to_weekday[self.weekday] From 53c709695b0a72c724e1d2e8f352c8fb15027f89 Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Sat, 10 Aug 2024 23:05:37 -0400 Subject: [PATCH 04/13] Fix precommit errors - Remove unwanted language --- pandas/_libs/tslibs/offsets.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index f392736343f88..b5b8013dbdf06 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -820,7 +820,7 @@ cdef class BaseOffset: Examples -------- >>> pd.offsets.Week(n=1).nanos - ValueError: is a non-fixed frequency + ValueError: Week: weekday=None is a non-fixed frequency """ # noqa raise ValueError(f"{self} is a non-fixed frequency") From 72b141f940666eb2a9c4ff82a0f4baa5d747b38c Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:27:06 -0400 Subject: [PATCH 05/13] Update code_checks.sh to remove methods that don't fail anymore. --- ci/code_checks.sh | 85 ----------------------------------------------- 1 file changed, 85 deletions(-) diff --git a/ci/code_checks.sh b/ci/code_checks.sh index 2956f8a3f6836..da33134854bd2 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -424,155 +424,108 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.testing.assert_extension_array_equal SA01" \ -i "pandas.tseries.offsets.BDay PR02,SA01" \ -i "pandas.tseries.offsets.BQuarterBegin PR02" \ - -i "pandas.tseries.offsets.BQuarterBegin.freqstr SA01" \ -i "pandas.tseries.offsets.BQuarterBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.BQuarterBegin.n GL08" \ - -i "pandas.tseries.offsets.BQuarterBegin.nanos GL08" \ -i "pandas.tseries.offsets.BQuarterBegin.normalize GL08" \ -i "pandas.tseries.offsets.BQuarterBegin.rule_code GL08" \ -i "pandas.tseries.offsets.BQuarterBegin.startingMonth GL08" \ - -i "pandas.tseries.offsets.BQuarterEnd.freqstr SA01" \ -i "pandas.tseries.offsets.BQuarterEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.BQuarterEnd.n GL08" \ - -i "pandas.tseries.offsets.BQuarterEnd.nanos GL08" \ -i "pandas.tseries.offsets.BQuarterEnd.normalize GL08" \ -i "pandas.tseries.offsets.BQuarterEnd.rule_code GL08" \ -i "pandas.tseries.offsets.BQuarterEnd.startingMonth GL08" \ - -i "pandas.tseries.offsets.BYearBegin.freqstr SA01" \ -i "pandas.tseries.offsets.BYearBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.BYearBegin.month GL08" \ -i "pandas.tseries.offsets.BYearBegin.n GL08" \ - -i "pandas.tseries.offsets.BYearBegin.nanos GL08" \ -i "pandas.tseries.offsets.BYearBegin.normalize GL08" \ - -i "pandas.tseries.offsets.BYearBegin.rule_code GL08" \ -i "pandas.tseries.offsets.BYearEnd PR02" \ - -i "pandas.tseries.offsets.BYearEnd.freqstr SA01" \ -i "pandas.tseries.offsets.BYearEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.BYearEnd.month GL08" \ -i "pandas.tseries.offsets.BYearEnd.n GL08" \ - -i "pandas.tseries.offsets.BYearEnd.nanos GL08" \ -i "pandas.tseries.offsets.BYearEnd.normalize GL08" \ - -i "pandas.tseries.offsets.BYearEnd.rule_code GL08" \ -i "pandas.tseries.offsets.BusinessDay PR02,SA01" \ -i "pandas.tseries.offsets.BusinessDay.calendar GL08" \ - -i "pandas.tseries.offsets.BusinessDay.freqstr SA01" \ -i "pandas.tseries.offsets.BusinessDay.holidays GL08" \ -i "pandas.tseries.offsets.BusinessDay.is_on_offset GL08" \ -i "pandas.tseries.offsets.BusinessDay.n GL08" \ - -i "pandas.tseries.offsets.BusinessDay.nanos GL08" \ -i "pandas.tseries.offsets.BusinessDay.normalize GL08" \ - -i "pandas.tseries.offsets.BusinessDay.rule_code GL08" \ -i "pandas.tseries.offsets.BusinessDay.weekmask GL08" \ -i "pandas.tseries.offsets.BusinessHour PR02,SA01" \ -i "pandas.tseries.offsets.BusinessHour.calendar GL08" \ -i "pandas.tseries.offsets.BusinessHour.end GL08" \ - -i "pandas.tseries.offsets.BusinessHour.freqstr SA01" \ -i "pandas.tseries.offsets.BusinessHour.holidays GL08" \ -i "pandas.tseries.offsets.BusinessHour.is_on_offset GL08" \ -i "pandas.tseries.offsets.BusinessHour.n GL08" \ - -i "pandas.tseries.offsets.BusinessHour.nanos GL08" \ -i "pandas.tseries.offsets.BusinessHour.normalize GL08" \ - -i "pandas.tseries.offsets.BusinessHour.rule_code GL08" \ -i "pandas.tseries.offsets.BusinessHour.start GL08" \ -i "pandas.tseries.offsets.BusinessHour.weekmask GL08" \ - -i "pandas.tseries.offsets.BusinessMonthBegin.freqstr SA01" \ -i "pandas.tseries.offsets.BusinessMonthBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.BusinessMonthBegin.n GL08" \ - -i "pandas.tseries.offsets.BusinessMonthBegin.nanos GL08" \ -i "pandas.tseries.offsets.BusinessMonthBegin.normalize GL08" \ - -i "pandas.tseries.offsets.BusinessMonthBegin.rule_code GL08" \ - -i "pandas.tseries.offsets.BusinessMonthEnd.freqstr SA01" \ -i "pandas.tseries.offsets.BusinessMonthEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.BusinessMonthEnd.n GL08" \ - -i "pandas.tseries.offsets.BusinessMonthEnd.nanos GL08" \ -i "pandas.tseries.offsets.BusinessMonthEnd.normalize GL08" \ - -i "pandas.tseries.offsets.BusinessMonthEnd.rule_code GL08" \ -i "pandas.tseries.offsets.CBMonthBegin PR02" \ -i "pandas.tseries.offsets.CBMonthEnd PR02" \ -i "pandas.tseries.offsets.CDay PR02,SA01" \ -i "pandas.tseries.offsets.CustomBusinessDay PR02,SA01" \ -i "pandas.tseries.offsets.CustomBusinessDay.calendar GL08" \ - -i "pandas.tseries.offsets.CustomBusinessDay.freqstr SA01" \ -i "pandas.tseries.offsets.CustomBusinessDay.holidays GL08" \ -i "pandas.tseries.offsets.CustomBusinessDay.is_on_offset GL08" \ -i "pandas.tseries.offsets.CustomBusinessDay.n GL08" \ - -i "pandas.tseries.offsets.CustomBusinessDay.nanos GL08" \ -i "pandas.tseries.offsets.CustomBusinessDay.normalize GL08" \ - -i "pandas.tseries.offsets.CustomBusinessDay.rule_code GL08" \ -i "pandas.tseries.offsets.CustomBusinessDay.weekmask GL08" \ -i "pandas.tseries.offsets.CustomBusinessHour PR02,SA01" \ -i "pandas.tseries.offsets.CustomBusinessHour.calendar GL08" \ -i "pandas.tseries.offsets.CustomBusinessHour.end GL08" \ - -i "pandas.tseries.offsets.CustomBusinessHour.freqstr SA01" \ -i "pandas.tseries.offsets.CustomBusinessHour.holidays GL08" \ -i "pandas.tseries.offsets.CustomBusinessHour.is_on_offset GL08" \ -i "pandas.tseries.offsets.CustomBusinessHour.n GL08" \ - -i "pandas.tseries.offsets.CustomBusinessHour.nanos GL08" \ -i "pandas.tseries.offsets.CustomBusinessHour.normalize GL08" \ - -i "pandas.tseries.offsets.CustomBusinessHour.rule_code GL08" \ -i "pandas.tseries.offsets.CustomBusinessHour.start GL08" \ -i "pandas.tseries.offsets.CustomBusinessHour.weekmask GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin PR02" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin.calendar GL08" \ - -i "pandas.tseries.offsets.CustomBusinessMonthBegin.freqstr SA01" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin.holidays GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin.is_on_offset SA01" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin.m_offset GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin.n GL08" \ - -i "pandas.tseries.offsets.CustomBusinessMonthBegin.nanos GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin.normalize GL08" \ - -i "pandas.tseries.offsets.CustomBusinessMonthBegin.rule_code GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthBegin.weekmask GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd PR02" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.calendar GL08" \ - -i "pandas.tseries.offsets.CustomBusinessMonthEnd.freqstr SA01" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.holidays GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.is_on_offset SA01" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.m_offset GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.n GL08" \ - -i "pandas.tseries.offsets.CustomBusinessMonthEnd.nanos GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.normalize GL08" \ - -i "pandas.tseries.offsets.CustomBusinessMonthEnd.rule_code GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.weekmask GL08" \ -i "pandas.tseries.offsets.DateOffset PR02" \ - -i "pandas.tseries.offsets.DateOffset.freqstr SA01" \ -i "pandas.tseries.offsets.DateOffset.is_on_offset GL08" \ -i "pandas.tseries.offsets.DateOffset.n GL08" \ - -i "pandas.tseries.offsets.DateOffset.nanos GL08" \ -i "pandas.tseries.offsets.DateOffset.normalize GL08" \ - -i "pandas.tseries.offsets.DateOffset.rule_code GL08" \ - -i "pandas.tseries.offsets.Day.freqstr SA01" \ -i "pandas.tseries.offsets.Day.is_on_offset GL08" \ -i "pandas.tseries.offsets.Day.n GL08" \ - -i "pandas.tseries.offsets.Day.nanos SA01" \ -i "pandas.tseries.offsets.Day.normalize GL08" \ - -i "pandas.tseries.offsets.Day.rule_code GL08" \ -i "pandas.tseries.offsets.Easter PR02" \ - -i "pandas.tseries.offsets.Easter.freqstr SA01" \ -i "pandas.tseries.offsets.Easter.is_on_offset GL08" \ -i "pandas.tseries.offsets.Easter.n GL08" \ - -i "pandas.tseries.offsets.Easter.nanos GL08" \ -i "pandas.tseries.offsets.Easter.normalize GL08" \ - -i "pandas.tseries.offsets.Easter.rule_code GL08" \ -i "pandas.tseries.offsets.FY5253 PR02" \ - -i "pandas.tseries.offsets.FY5253.freqstr SA01" \ -i "pandas.tseries.offsets.FY5253.get_rule_code_suffix GL08" \ -i "pandas.tseries.offsets.FY5253.get_year_end GL08" \ -i "pandas.tseries.offsets.FY5253.is_on_offset GL08" \ -i "pandas.tseries.offsets.FY5253.n GL08" \ - -i "pandas.tseries.offsets.FY5253.nanos GL08" \ -i "pandas.tseries.offsets.FY5253.normalize GL08" \ -i "pandas.tseries.offsets.FY5253.rule_code GL08" \ -i "pandas.tseries.offsets.FY5253.startingMonth GL08" \ -i "pandas.tseries.offsets.FY5253.variation GL08" \ -i "pandas.tseries.offsets.FY5253.weekday GL08" \ -i "pandas.tseries.offsets.FY5253Quarter PR02" \ - -i "pandas.tseries.offsets.FY5253Quarter.freqstr SA01" \ -i "pandas.tseries.offsets.FY5253Quarter.get_rule_code_suffix GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.get_weeks GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.is_on_offset GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.n GL08" \ - -i "pandas.tseries.offsets.FY5253Quarter.nanos GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.normalize GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.qtr_with_extra_week GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.rule_code GL08" \ @@ -581,107 +534,69 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.FY5253Quarter.weekday GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.year_has_extra_week GL08" \ -i "pandas.tseries.offsets.Hour PR02" \ - -i "pandas.tseries.offsets.Hour.freqstr SA01" \ -i "pandas.tseries.offsets.Hour.is_on_offset GL08" \ -i "pandas.tseries.offsets.Hour.n GL08" \ - -i "pandas.tseries.offsets.Hour.nanos SA01" \ -i "pandas.tseries.offsets.Hour.normalize GL08" \ - -i "pandas.tseries.offsets.Hour.rule_code GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth PR02,SA01" \ - -i "pandas.tseries.offsets.LastWeekOfMonth.freqstr SA01" \ -i "pandas.tseries.offsets.LastWeekOfMonth.is_on_offset GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.n GL08" \ - -i "pandas.tseries.offsets.LastWeekOfMonth.nanos GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.normalize GL08" \ - -i "pandas.tseries.offsets.LastWeekOfMonth.rule_code GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.week GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.weekday GL08" \ -i "pandas.tseries.offsets.Micro PR02" \ - -i "pandas.tseries.offsets.Micro.freqstr SA01" \ -i "pandas.tseries.offsets.Micro.is_on_offset GL08" \ -i "pandas.tseries.offsets.Micro.n GL08" \ - -i "pandas.tseries.offsets.Micro.nanos SA01" \ -i "pandas.tseries.offsets.Micro.normalize GL08" \ - -i "pandas.tseries.offsets.Micro.rule_code GL08" \ -i "pandas.tseries.offsets.Milli PR02" \ - -i "pandas.tseries.offsets.Milli.freqstr SA01" \ -i "pandas.tseries.offsets.Milli.is_on_offset GL08" \ -i "pandas.tseries.offsets.Milli.n GL08" \ - -i "pandas.tseries.offsets.Milli.nanos SA01" \ -i "pandas.tseries.offsets.Milli.normalize GL08" \ - -i "pandas.tseries.offsets.Milli.rule_code GL08" \ -i "pandas.tseries.offsets.Minute PR02" \ - -i "pandas.tseries.offsets.Minute.freqstr SA01" \ -i "pandas.tseries.offsets.Minute.is_on_offset GL08" \ -i "pandas.tseries.offsets.Minute.n GL08" \ - -i "pandas.tseries.offsets.Minute.nanos SA01" \ -i "pandas.tseries.offsets.Minute.normalize GL08" \ - -i "pandas.tseries.offsets.Minute.rule_code GL08" \ -i "pandas.tseries.offsets.MonthBegin PR02" \ - -i "pandas.tseries.offsets.MonthBegin.freqstr SA01" \ -i "pandas.tseries.offsets.MonthBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.MonthBegin.n GL08" \ - -i "pandas.tseries.offsets.MonthBegin.nanos GL08" \ -i "pandas.tseries.offsets.MonthBegin.normalize GL08" \ - -i "pandas.tseries.offsets.MonthBegin.rule_code GL08" \ - -i "pandas.tseries.offsets.MonthEnd.freqstr SA01" \ -i "pandas.tseries.offsets.MonthEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.MonthEnd.n GL08" \ - -i "pandas.tseries.offsets.MonthEnd.nanos GL08" \ -i "pandas.tseries.offsets.MonthEnd.normalize GL08" \ - -i "pandas.tseries.offsets.MonthEnd.rule_code GL08" \ -i "pandas.tseries.offsets.Nano PR02" \ - -i "pandas.tseries.offsets.Nano.freqstr SA01" \ -i "pandas.tseries.offsets.Nano.is_on_offset GL08" \ -i "pandas.tseries.offsets.Nano.n GL08" \ - -i "pandas.tseries.offsets.Nano.nanos SA01" \ -i "pandas.tseries.offsets.Nano.normalize GL08" \ - -i "pandas.tseries.offsets.Nano.rule_code GL08" \ -i "pandas.tseries.offsets.QuarterBegin PR02" \ - -i "pandas.tseries.offsets.QuarterBegin.freqstr SA01" \ -i "pandas.tseries.offsets.QuarterBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.QuarterBegin.n GL08" \ - -i "pandas.tseries.offsets.QuarterBegin.nanos GL08" \ -i "pandas.tseries.offsets.QuarterBegin.normalize GL08" \ -i "pandas.tseries.offsets.QuarterBegin.rule_code GL08" \ -i "pandas.tseries.offsets.QuarterBegin.startingMonth GL08" \ - -i "pandas.tseries.offsets.QuarterEnd.freqstr SA01" \ -i "pandas.tseries.offsets.QuarterEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.QuarterEnd.n GL08" \ - -i "pandas.tseries.offsets.QuarterEnd.nanos GL08" \ -i "pandas.tseries.offsets.QuarterEnd.normalize GL08" \ -i "pandas.tseries.offsets.QuarterEnd.rule_code GL08" \ -i "pandas.tseries.offsets.QuarterEnd.startingMonth GL08" \ -i "pandas.tseries.offsets.Second PR02" \ - -i "pandas.tseries.offsets.Second.freqstr SA01" \ -i "pandas.tseries.offsets.Second.is_on_offset GL08" \ -i "pandas.tseries.offsets.Second.n GL08" \ - -i "pandas.tseries.offsets.Second.nanos SA01" \ -i "pandas.tseries.offsets.Second.normalize GL08" \ - -i "pandas.tseries.offsets.Second.rule_code GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin PR02,SA01" \ -i "pandas.tseries.offsets.SemiMonthBegin.day_of_month GL08" \ - -i "pandas.tseries.offsets.SemiMonthBegin.freqstr SA01" \ -i "pandas.tseries.offsets.SemiMonthBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin.n GL08" \ - -i "pandas.tseries.offsets.SemiMonthBegin.nanos GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin.normalize GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin.rule_code GL08" \ -i "pandas.tseries.offsets.SemiMonthEnd SA01" \ -i "pandas.tseries.offsets.SemiMonthEnd.day_of_month GL08" \ - -i "pandas.tseries.offsets.SemiMonthEnd.freqstr SA01" \ -i "pandas.tseries.offsets.SemiMonthEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.SemiMonthEnd.n GL08" \ - -i "pandas.tseries.offsets.SemiMonthEnd.nanos GL08" \ -i "pandas.tseries.offsets.SemiMonthEnd.normalize GL08" \ -i "pandas.tseries.offsets.SemiMonthEnd.rule_code GL08" \ -i "pandas.tseries.offsets.Tick GL08" \ - -i "pandas.tseries.offsets.Tick.freqstr SA01" \ -i "pandas.tseries.offsets.Tick.is_on_offset GL08" \ -i "pandas.tseries.offsets.Tick.n GL08" \ - -i "pandas.tseries.offsets.Tick.nanos SA01" \ -i "pandas.tseries.offsets.Tick.normalize GL08" \ - -i "pandas.tseries.offsets.Tick.rule_code GL08" \ -i "pandas.tseries.offsets.Week PR02" \ -i "pandas.tseries.offsets.Week.is_on_offset GL08" \ -i "pandas.tseries.offsets.Week.n GL08" \ From 5633f8d5634db4d66365b4145d609638672cc24c Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:28:23 -0400 Subject: [PATCH 06/13] Indented See Also strings to avoid using # noqa --- pandas/_libs/tslibs/offsets.pyx | 74 +++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index b5b8013dbdf06..ccb8942f27175 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -600,8 +600,10 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. + tseries.offsets.Hour.rule_code : + Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.rule_code : + Returns a string representing the base frequency of 'D'. Examples -------- @@ -610,7 +612,7 @@ cdef class BaseOffset: >>> pd.offsets.Week(5).rule_code 'W' - """ # noqa + """ return self._prefix @cache_readonly @@ -620,10 +622,14 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.BusinessDay.freqstr : Return a string representing an offset frequency in Business Days. - tseries.offsets.BusinessHour.freqstr : Return a string representing an offset frequency in Business Hours. - tseries.offsets.Week.freqstr : Return a string representing an offset frequency in Weeks. - tseries.offsets.Hour.freqstr : Return a string representing an offset frequency in Hours. + tseries.offsets.BusinessDay.freqstr : + Return a string representing an offset frequency in Business Days. + tseries.offsets.BusinessHour.freqstr : + Return a string representing an offset frequency in Business Hours. + tseries.offsets.Week.freqstr : + Return a string representing an offset frequency in Weeks. + tseries.offsets.Hour.freqstr : + Return a string representing an offset frequency in Hours. Examples -------- @@ -638,7 +644,7 @@ cdef class BaseOffset: >>> pd.offsets.Nano(-3).freqstr '-3ns' - """ # noqa + """ try: code = self.rule_code except NotImplementedError: @@ -812,16 +818,20 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.WeekOfMonth.nanos : Raises a ValueError because the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : Raises a ValueError because the frequency is non-fixed. - tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. + tseries.offsets.WeekOfMonth.nanos : + Raises a ValueError because the frequency is non-fixed. + tseries.offsets.YearBegin.nanos : + Raises a ValueError because the frequency is non-fixed. + tseries.offsets.Hour.nanos : + Returns an integer of the total number of nanoseconds. + tseries.offsets.Day.nanos : + Returns an integer of the total number of nanoseconds. Examples -------- >>> pd.offsets.Week(n=1).nanos ValueError: Week: weekday=None is a non-fixed frequency - """ # noqa + """ raise ValueError(f"{self} is a non-fixed frequency") # ------------------------------------------------------------------ @@ -1033,16 +1043,20 @@ cdef class Tick(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.WeekOfMonth.nanos : Raises a ValueError because the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : Raises a ValueError because the frequency is non-fixed. + tseries.offsets.Hour.nanos : + Returns an integer of the total number of nanoseconds. + tseries.offsets.Day.nanos : + Returns an integer of the total number of nanoseconds. + tseries.offsets.WeekOfMonth.nanos : + Raises a ValueError because the frequency is non-fixed. + tseries.offsets.YearBegin.nanos : + Raises a ValueError because the frequency is non-fixed. Examples -------- >>> pd.offsets.Hour(5).nanos 18000000000000 - """ # noqa + """ return self.n * self._nanos_inc def is_on_offset(self, dt: datetime) -> bool: @@ -2476,8 +2490,10 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. + tseries.offsets.Hour.rule_code : + Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.rule_code : + Returns a string representing the base frequency of 'D'. Examples -------- @@ -2486,7 +2502,7 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset): >>> pd.offsets.WeekOfMonth(n=1, week=0, weekday=0).rule_code 'WOM-1MON' - """ # noqa + """ weekday = int_to_weekday.get(self.weekday, "") if self.week == -1: # LastWeekOfMonth @@ -2538,8 +2554,10 @@ cdef class YearOffset(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. + tseries.offsets.Hour.rule_code : + Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.rule_code : + Returns a string representing the base frequency of 'D'. Examples -------- @@ -2548,7 +2566,7 @@ cdef class YearOffset(SingleConstructorOffset): >>> pd.tseries.offsets.YearEnd(n=1, month=6).rule_code 'YE-JUN' - """ # noqa + """ month = MONTH_ALIASES[self.month] return f"{self._prefix}-{month}" @@ -3540,8 +3558,10 @@ cdef class Week(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.name : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.name : Returns a string representing the base frequency of 'D'. + tseries.offsets.Hour.name : + Returns a string representing the base frequency of 'h'. + tseries.offsets.Day.name : + Returns a string representing the base frequency of 'D'. Examples -------- @@ -3550,7 +3570,7 @@ cdef class Week(SingleConstructorOffset): >>> pd.offsets.Week(5).rule_code 'W' - """ # noqa + """ suffix = "" if self.weekday is not None: weekday = int_to_weekday[self.weekday] From 367a1647cb75196836b5a20a4b2c33fa9a327cb0 Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Tue, 13 Aug 2024 22:01:12 -0400 Subject: [PATCH 07/13] Correct for code check error. --- pandas/_libs/tslibs/offsets.pyx | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 78d74104f6572..300c9d6ab1105 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -600,9 +600,9 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.Hour.rule_code : + tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.rule_code : + tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. Examples @@ -622,13 +622,13 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.BusinessDay.freqstr : + tseries.offsets.BusinessDay.freqstr : Return a string representing an offset frequency in Business Days. - tseries.offsets.BusinessHour.freqstr : + tseries.offsets.BusinessHour.freqstr : Return a string representing an offset frequency in Business Hours. - tseries.offsets.Week.freqstr : + tseries.offsets.Week.freqstr : Return a string representing an offset frequency in Weeks. - tseries.offsets.Hour.freqstr : + tseries.offsets.Hour.freqstr : Return a string representing an offset frequency in Hours. Examples @@ -818,13 +818,13 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.WeekOfMonth.nanos : + tseries.offsets.WeekOfMonth.nanos : Raises a ValueError because the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : + tseries.offsets.YearBegin.nanos : Raises a ValueError because the frequency is non-fixed. - tseries.offsets.Hour.nanos : + tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.Day.nanos : + tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. Examples @@ -1043,13 +1043,13 @@ cdef class Tick(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.nanos : + tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.Day.nanos : + tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.WeekOfMonth.nanos : + tseries.offsets.WeekOfMonth.nanos : Raises a ValueError because the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : + tseries.offsets.YearBegin.nanos : Raises a ValueError because the frequency is non-fixed. Examples @@ -2490,9 +2490,9 @@ cdef class WeekOfMonthMixin(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.rule_code : + tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.rule_code : + tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. Examples @@ -2554,9 +2554,9 @@ cdef class YearOffset(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.rule_code : + tseries.offsets.Hour.rule_code : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.rule_code : + tseries.offsets.Day.rule_code : Returns a string representing the base frequency of 'D'. Examples @@ -3558,9 +3558,9 @@ cdef class Week(SingleConstructorOffset): See Also -------- - tseries.offsets.Hour.name : + tseries.offsets.Hour.name : Returns a string representing the base frequency of 'h'. - tseries.offsets.Day.name : + tseries.offsets.Day.name : Returns a string representing the base frequency of 'D'. Examples From dedcd830029883c93b6467948c235bd011b9740f Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Tue, 13 Aug 2024 22:16:15 -0400 Subject: [PATCH 08/13] Removed duplicate from code_checks.sh. --- ci/code_checks.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/code_checks.sh b/ci/code_checks.sh index 6457a993b5c47..d8c4dc4c8ee73 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -526,7 +526,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.Hour.is_on_offset GL08" \ -i "pandas.tseries.offsets.Hour.n GL08" \ -i "pandas.tseries.offsets.Hour.normalize GL08" \ - -i "pandas.tseries.offsets.LastWeekOfMonth PR02,SA01" \ -i "pandas.tseries.offsets.Hour.rule_code GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth SA01" \ -i "pandas.tseries.offsets.LastWeekOfMonth.freqstr SA01" \ From ec59485ef43aa23dce0a07a9d94bbd93dc0a5f6a Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:06:46 -0400 Subject: [PATCH 09/13] Correct code_checks.sh. --- ci/code_checks.sh | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/ci/code_checks.sh b/ci/code_checks.sh index d8c4dc4c8ee73..a7ac6acce0c61 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -406,7 +406,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.set_eng_float_format RT03,SA01" \ -i "pandas.testing.assert_extension_array_equal SA01" \ -i "pandas.tseries.offsets.BDay PR02,SA01" \ - -i "pandas.tseries.offsets.BQuarterBegin PR02" \ -i "pandas.tseries.offsets.BQuarterBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.BQuarterBegin.n GL08" \ -i "pandas.tseries.offsets.BQuarterBegin.normalize GL08" \ @@ -421,7 +420,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.BYearBegin.month GL08" \ -i "pandas.tseries.offsets.BYearBegin.n GL08" \ -i "pandas.tseries.offsets.BYearBegin.normalize GL08" \ - -i "pandas.tseries.offsets.BYearEnd PR02" \ -i "pandas.tseries.offsets.BYearEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.BYearEnd.month GL08" \ -i "pandas.tseries.offsets.BYearEnd.n GL08" \ @@ -483,22 +481,16 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.CustomBusinessMonthEnd.n GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.normalize GL08" \ -i "pandas.tseries.offsets.CustomBusinessMonthEnd.weekmask GL08" \ - -i "pandas.tseries.offsets.DateOffset PR02" \ -i "pandas.tseries.offsets.DateOffset.is_on_offset GL08" \ -i "pandas.tseries.offsets.DateOffset.n GL08" \ -i "pandas.tseries.offsets.DateOffset.normalize GL08" \ -i "pandas.tseries.offsets.Day.is_on_offset GL08" \ -i "pandas.tseries.offsets.Day.n GL08" \ -i "pandas.tseries.offsets.Day.normalize GL08" \ - -i "pandas.tseries.offsets.Easter PR02" \ - -i "pandas.tseries.offsets.Day.rule_code GL08" \ - -i "pandas.tseries.offsets.Easter.freqstr SA01" \ -i "pandas.tseries.offsets.Easter.is_on_offset GL08" \ -i "pandas.tseries.offsets.Easter.n GL08" \ -i "pandas.tseries.offsets.Easter.normalize GL08" \ - -i "pandas.tseries.offsets.FY5253 PR02" \ -i "pandas.tseries.offsets.Easter.rule_code GL08" \ - -i "pandas.tseries.offsets.FY5253.freqstr SA01" \ -i "pandas.tseries.offsets.FY5253.get_rule_code_suffix GL08" \ -i "pandas.tseries.offsets.FY5253.get_year_end GL08" \ -i "pandas.tseries.offsets.FY5253.is_on_offset GL08" \ @@ -508,8 +500,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.FY5253.startingMonth GL08" \ -i "pandas.tseries.offsets.FY5253.variation GL08" \ -i "pandas.tseries.offsets.FY5253.weekday GL08" \ - -i "pandas.tseries.offsets.FY5253Quarter PR02" \ - -i "pandas.tseries.offsets.FY5253Quarter.freqstr SA01" \ -i "pandas.tseries.offsets.FY5253Quarter.get_rule_code_suffix GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.get_weeks GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.is_on_offset GL08" \ @@ -521,36 +511,24 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.FY5253Quarter.variation GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.weekday GL08" \ -i "pandas.tseries.offsets.FY5253Quarter.year_has_extra_week GL08" \ - -i "pandas.tseries.offsets.Hour PR02" \ - -i "pandas.tseries.offsets.Hour.freqstr SA01" \ -i "pandas.tseries.offsets.Hour.is_on_offset GL08" \ -i "pandas.tseries.offsets.Hour.n GL08" \ -i "pandas.tseries.offsets.Hour.normalize GL08" \ - -i "pandas.tseries.offsets.Hour.rule_code GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth SA01" \ - -i "pandas.tseries.offsets.LastWeekOfMonth.freqstr SA01" \ -i "pandas.tseries.offsets.LastWeekOfMonth.is_on_offset GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.n GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.normalize GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.week GL08" \ -i "pandas.tseries.offsets.LastWeekOfMonth.weekday GL08" \ - -i "pandas.tseries.offsets.Micro PR02" \ - -i "pandas.tseries.offsets.Micro.freqstr SA01" \ -i "pandas.tseries.offsets.Micro.is_on_offset GL08" \ -i "pandas.tseries.offsets.Micro.n GL08" \ -i "pandas.tseries.offsets.Micro.normalize GL08" \ - -i "pandas.tseries.offsets.Milli PR02" \ - -i "pandas.tseries.offsets.Micro.rule_code GL08" \ - -i "pandas.tseries.offsets.Milli.freqstr SA01" \ -i "pandas.tseries.offsets.Milli.is_on_offset GL08" \ -i "pandas.tseries.offsets.Milli.n GL08" \ -i "pandas.tseries.offsets.Milli.normalize GL08" \ - -i "pandas.tseries.offsets.Milli.rule_code GL08" \ - -i "pandas.tseries.offsets.Minute.freqstr SA01" \ -i "pandas.tseries.offsets.Minute.is_on_offset GL08" \ -i "pandas.tseries.offsets.Minute.n GL08" \ -i "pandas.tseries.offsets.Minute.normalize GL08" \ - -i "pandas.tseries.offsets.MonthBegin PR02" \ -i "pandas.tseries.offsets.MonthBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.MonthBegin.n GL08" \ -i "pandas.tseries.offsets.MonthBegin.normalize GL08" \ @@ -559,9 +537,7 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.MonthEnd.normalize GL08" \ -i "pandas.tseries.offsets.Nano PR02" \ -i "pandas.tseries.offsets.Nano.is_on_offset GL08" \ - -i "pandas.tseries.offsets.Nano.n GL08" \ -i "pandas.tseries.offsets.Nano.normalize GL08" \ - -i "pandas.tseries.offsets.QuarterBegin PR02" \ -i "pandas.tseries.offsets.QuarterBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.QuarterBegin.n GL08" \ -i "pandas.tseries.offsets.QuarterBegin.normalize GL08" \ @@ -572,11 +548,9 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.QuarterEnd.normalize GL08" \ -i "pandas.tseries.offsets.QuarterEnd.rule_code GL08" \ -i "pandas.tseries.offsets.QuarterEnd.startingMonth GL08" \ - -i "pandas.tseries.offsets.Second PR02" \ -i "pandas.tseries.offsets.Second.is_on_offset GL08" \ -i "pandas.tseries.offsets.Second.n GL08" \ -i "pandas.tseries.offsets.Second.normalize GL08" \ - -i "pandas.tseries.offsets.SemiMonthBegin PR02,SA01" \ -i "pandas.tseries.offsets.SemiMonthBegin.day_of_month GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin.n GL08" \ @@ -592,12 +566,10 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.Tick.is_on_offset GL08" \ -i "pandas.tseries.offsets.Tick.n GL08" \ -i "pandas.tseries.offsets.Tick.normalize GL08" \ - -i "pandas.tseries.offsets.Week PR02" \ -i "pandas.tseries.offsets.Week.is_on_offset GL08" \ -i "pandas.tseries.offsets.Week.n GL08" \ -i "pandas.tseries.offsets.Week.normalize GL08" \ -i "pandas.tseries.offsets.Week.weekday GL08" \ - -i "pandas.tseries.offsets.WeekOfMonth PR02,SA01" \ -i "pandas.tseries.offsets.WeekOfMonth.is_on_offset GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.n GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.normalize GL08" \ From e1c2879cbbaece45f8224a2daaa58716d3eb2a24 Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Wed, 14 Aug 2024 00:07:11 -0400 Subject: [PATCH 10/13] Correct code_checks.sh. --- ci/code_checks.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ci/code_checks.sh b/ci/code_checks.sh index a7ac6acce0c61..4b4d665059e89 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -490,7 +490,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.Easter.is_on_offset GL08" \ -i "pandas.tseries.offsets.Easter.n GL08" \ -i "pandas.tseries.offsets.Easter.normalize GL08" \ - -i "pandas.tseries.offsets.Easter.rule_code GL08" \ -i "pandas.tseries.offsets.FY5253.get_rule_code_suffix GL08" \ -i "pandas.tseries.offsets.FY5253.get_year_end GL08" \ -i "pandas.tseries.offsets.FY5253.is_on_offset GL08" \ @@ -535,9 +534,9 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.MonthEnd.is_on_offset GL08" \ -i "pandas.tseries.offsets.MonthEnd.n GL08" \ -i "pandas.tseries.offsets.MonthEnd.normalize GL08" \ - -i "pandas.tseries.offsets.Nano PR02" \ -i "pandas.tseries.offsets.Nano.is_on_offset GL08" \ -i "pandas.tseries.offsets.Nano.normalize GL08" \ + -i "pandas.tseries.offsets.Nano.n GL08" \ -i "pandas.tseries.offsets.QuarterBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.QuarterBegin.n GL08" \ -i "pandas.tseries.offsets.QuarterBegin.normalize GL08" \ @@ -551,6 +550,7 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.Second.is_on_offset GL08" \ -i "pandas.tseries.offsets.Second.n GL08" \ -i "pandas.tseries.offsets.Second.normalize GL08" \ + -i "pandas.tseries.offsets.SemiMonthBegin SA01" \ -i "pandas.tseries.offsets.SemiMonthBegin.day_of_month GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin.is_on_offset GL08" \ -i "pandas.tseries.offsets.SemiMonthBegin.n GL08" \ @@ -570,6 +570,7 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then -i "pandas.tseries.offsets.Week.n GL08" \ -i "pandas.tseries.offsets.Week.normalize GL08" \ -i "pandas.tseries.offsets.Week.weekday GL08" \ + -i "pandas.tseries.offsets.WeekOfMonth SA01" \ -i "pandas.tseries.offsets.WeekOfMonth.is_on_offset GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.n GL08" \ -i "pandas.tseries.offsets.WeekOfMonth.normalize GL08" \ From 2455161081fc7522f82b843c8da79f88d0b9c892 Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Wed, 14 Aug 2024 18:18:48 -0400 Subject: [PATCH 11/13] Update pandas/_libs/tslibs/offsets.pyx Delete two examples from See Also for nanos Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> --- pandas/_libs/tslibs/offsets.pyx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 300c9d6ab1105..d376d43d5d3e4 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -1047,10 +1047,6 @@ cdef class Tick(SingleConstructorOffset): Returns an integer of the total number of nanoseconds. tseries.offsets.Day.nanos : Returns an integer of the total number of nanoseconds. - tseries.offsets.WeekOfMonth.nanos : - Raises a ValueError because the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : - Raises a ValueError because the frequency is non-fixed. Examples -------- From c02646d95f2c5e0a1fc55ba51a162ed9208db03b Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Wed, 14 Aug 2024 18:19:24 -0400 Subject: [PATCH 12/13] Update pandas/_libs/tslibs/offsets.pyx Update nanos summary Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> --- pandas/_libs/tslibs/offsets.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index d376d43d5d3e4..e8bc38481e00b 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -809,7 +809,7 @@ cdef class BaseOffset: @property def nanos(self): """ - Returns a ValueError because the frequency is non-fixed. + Returns a integer of the total number of nanoseconds for fixed frequencies. Raises ------ From 5a53c07530576f22b57fc76ffd8d02f779505330 Mon Sep 17 00:00:00 2001 From: SanchitD <79684090+Siniade@users.noreply.github.com> Date: Wed, 14 Aug 2024 18:19:36 -0400 Subject: [PATCH 13/13] Update pandas/_libs/tslibs/offsets.pyx Delete two examples from See Also for nanos Co-authored-by: Matthew Roeschke <10647082+mroeschke@users.noreply.github.com> --- pandas/_libs/tslibs/offsets.pyx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index e8bc38481e00b..c48acc07b34db 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -818,10 +818,6 @@ cdef class BaseOffset: See Also -------- - tseries.offsets.WeekOfMonth.nanos : - Raises a ValueError because the frequency is non-fixed. - tseries.offsets.YearBegin.nanos : - Raises a ValueError because the frequency is non-fixed. tseries.offsets.Hour.nanos : Returns an integer of the total number of nanoseconds. tseries.offsets.Day.nanos :