Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/code-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
run: sudo apt-get update && sudo apt-get install -y libegl1 libopengl0

- name: Run doctests
run: cd ci && ./code_checks.sh doctests
run: cd ci && PANDAS_FUTURE_PYTHON_SCALARS="1" ./code_checks.sh doctests
if: ${{ steps.build.outcome == 'success' && always() }}

- name: Install pandas in editable mode
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
# Prevent the include jobs from overriding other jobs
pattern: [""]
pandas_future_infer_string: ["1"]
pandas_future_python_scalars: ["0"]
include:
- name: "Downstream Compat"
env_file: actions-313-downstream_compat.yaml
Expand Down Expand Up @@ -75,6 +76,10 @@ jobs:
env_file: actions-313.yaml
pandas_future_infer_string: "0"
platform: ubuntu-24.04
- name: "PANDAS_FUTURE_PYTHON_SCALARS=1"
env_file: actions-313.yaml
pandas_future_python_scalars: "1"
platform: ubuntu-24.04
- name: "Numpy Dev"
env_file: actions-313-numpydev.yaml
pattern: "not slow and not network and not single_cpu"
Expand All @@ -92,6 +97,7 @@ jobs:
LC_ALL: ${{ matrix.lc_all || '' }}
PANDAS_CI: '1'
PANDAS_FUTURE_INFER_STRING: ${{ matrix.pandas_future_infer_string || '1' }}
PANDAS_FUTURE_PYTHON_SCALARS: ${{ matrix.pandas_future_python_scalars || '0' }}
TEST_ARGS: ${{ matrix.test_args || '' }}
PYTEST_WORKERS: 'auto'
PYTEST_TARGET: ${{ matrix.pytest_target || 'pandas' }}
Expand Down
5 changes: 5 additions & 0 deletions pandas/_config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ def using_string_dtype() -> bool:
return _mode_options["infer_string"]


def using_python_scalars() -> bool:
_mode_options = _global_config["future"]
return _mode_options["python_scalars"]


def is_nan_na() -> bool:
_mode_options = _global_config["mode"]
return _mode_options["nan_is_na"]
1 change: 0 additions & 1 deletion pandas/_libs/interval.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,6 @@ cdef class Interval(IntervalMixin):
>>> interval.closed
'left'
"""
__module__ = "pandas"

def __init__(self, left, right, str closed="right"):
# note: it is faster to just do these checks than to use a special
Expand Down
1 change: 0 additions & 1 deletion pandas/_libs/missing.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,6 @@ class NAType(C_NAType):
True
"""
__module__ = "pandas.api.typing"

_instance = None

def __new__(cls, *args, **kwargs):
Expand Down
1 change: 0 additions & 1 deletion pandas/_libs/tslibs/nattype.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,6 @@ class NaTType(_NaT):
0 2023-01-01
1 NaT
"""

__module__ = "pandas.api.typing"

def __new__(cls):
Expand Down
4 changes: 1 addition & 3 deletions pandas/_libs/tslibs/np_datetime.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ class OutOfBoundsDatetime(ValueError):
at position 0
"""
__module__ = "pandas.errors"
pass


class OutOfBoundsTimedelta(ValueError):
Expand All @@ -213,9 +212,8 @@ class OutOfBoundsTimedelta(ValueError):
OutOfBoundsTimedelta: Cannot cast 139999 days 00:00:00
to unit='ns' without overflow.
"""
__module__ = "pandas.errors"
# Timedelta analogue to OutOfBoundsDatetime
pass
__module__ = "pandas.errors"


cdef get_implementation_bounds(
Expand Down
4 changes: 2 additions & 2 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ from pandas._libs.tslibs.ccalendar import (
int_to_weekday,
weekday_to_int,
)
from pandas.util._decorators import set_module
from pandas.util._exceptions import find_stack_level

from pandas._libs.tslibs.ccalendar cimport (
Expand Down Expand Up @@ -1695,6 +1696,7 @@ class OffsetMeta(type):


# TODO: figure out a way to use a metaclass with a cdef class
@set_module("pandas")
class DateOffset(RelativeDeltaOffset, metaclass=OffsetMeta):
"""
Standard kind of date increment used for a date range.
Expand Down Expand Up @@ -1822,8 +1824,6 @@ class DateOffset(RelativeDeltaOffset, metaclass=OffsetMeta):
>>> ts + pd.DateOffset(hour=8)
Timestamp('2017-01-01 08:10:11')
"""
__module__ = "pandas"

def __setattr__(self, name, value):
raise AttributeError("DateOffset objects are immutable.")

Expand Down
2 changes: 1 addition & 1 deletion pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1626,12 +1626,12 @@ DIFFERENT_FREQ = ("Input has different freq={other_freq} "
"from {cls}(freq={own_freq})")


@set_module("pandas.errors")
class IncompatibleFrequency(TypeError):
"""
Raised when trying to compare or operate between Periods with different
frequencies.
"""
__module__ = "pandas.errors"
pass


Expand Down
24 changes: 22 additions & 2 deletions pandas/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ def pytest_addoption(parser) -> None:
)


def pytest_sessionstart(session):
import doctest
import inspect

orig = doctest.DocTestFinder._from_module

def _from_module(self, module, object):
if inspect.isfunction(object) and "." in object.__qualname__:
return True
return orig(self, module, object)

doctest.DocTestFinder._from_module = _from_module


def ignore_doctest_warning(item: pytest.Item, path: str, message: str) -> None:
"""Ignore doctest warning.

Expand All @@ -135,14 +149,15 @@ def pytest_collection_modifyitems(items, config) -> None:
# Warnings from doctests that can be ignored; place reason in comment above.
# Each entry specifies (path, message) - see the ignore_doctest_warning function
ignored_doctest_warnings = [
("api.interchange.from_dataframe", ".*Interchange Protocol is deprecated"),
("api.interchange.from_dataframe", "The DataFrame Interchange Protocol"),
("is_int64_dtype", "is_int64_dtype is deprecated"),
("is_interval_dtype", "is_interval_dtype is deprecated"),
("is_period_dtype", "is_period_dtype is deprecated"),
("is_datetime64tz_dtype", "is_datetime64tz_dtype is deprecated"),
("is_categorical_dtype", "is_categorical_dtype is deprecated"),
("is_sparse", "is_sparse is deprecated"),
("DataFrame.__dataframe__", "Interchange Protocol is deprecated"),
("CategoricalDtype._from_values_or_dtype", "Constructing a Categorical"),
("DataFrame.__dataframe__", "The DataFrame Interchange Protocol"),
("DataFrameGroupBy.fillna", "DataFrameGroupBy.fillna is deprecated"),
("DataFrameGroupBy.corrwith", "DataFrameGroupBy.corrwith is deprecated"),
("NDFrame.replace", "Series.replace without 'value'"),
Expand Down Expand Up @@ -2094,6 +2109,11 @@ def using_infer_string() -> bool:
return pd.options.future.infer_string is True


@pytest.fixture
def using_python_scalars() -> bool:
return pd.options.future.python_scalars is True


_warsaws: list[Any] = ["Europe/Warsaw", "dateutil/Europe/Warsaw"]
if pytz is not None:
_warsaws.append(pytz.timezone("Europe/Warsaw"))
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ def register_dataframe_accessor(name: str) -> Callable[[TypeT], TypeT]:
AttributeError: The series must contain integer data only.
>>> df = pd.Series([1, 2, 3])
>>> df.int_accessor.sum()
np.int64(6)"""
6"""


@set_module("pandas.api.extensions")
Expand Down Expand Up @@ -481,7 +481,7 @@ def register_series_accessor(name: str) -> Callable[[TypeT], TypeT]:
AttributeError: The series must contain integer data only.
>>> df = pd.Series([1, 2, 3])
>>> df.int_accessor.sum()
np.int64(6)
6
"""
from pandas import Series

Expand Down
8 changes: 5 additions & 3 deletions pandas/core/apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
)
from pandas.compat._optional import import_optional_dependency
from pandas.errors import SpecificationError
from pandas.util._decorators import cache_readonly
from pandas.util._decorators import (
cache_readonly,
set_module,
)

from pandas.core.dtypes.cast import is_nested_object
from pandas.core.dtypes.common import (
Expand Down Expand Up @@ -75,6 +78,7 @@
ResType: TypeAlias = dict[int, Any]


@set_module("pandas.api.executors")
class BaseExecutionEngine(abc.ABC):
"""
Base class for execution engines for map and apply methods.
Expand All @@ -88,8 +92,6 @@ class BaseExecutionEngine(abc.ABC):
simply runs the code with the Python interpreter and pandas.
"""

__module__ = "pandas.api.executors"

@staticmethod
@abc.abstractmethod
def map(
Expand Down
5 changes: 4 additions & 1 deletion pandas/core/arraylike.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from pandas._libs import lib
from pandas._libs.ops_dispatch import maybe_dispatch_ufunc_to_dunder_op

from pandas.core.dtypes.cast import maybe_unbox_numpy_scalar
from pandas.core.dtypes.generic import ABCNDFrame

from pandas.core import roperator
Expand Down Expand Up @@ -529,4 +530,6 @@ def dispatch_reduction_ufunc(self, ufunc: np.ufunc, method: str, *inputs, **kwar

# By default, numpy's reductions do not skip NaNs, so we have to
# pass skipna=False
return getattr(self, method_name)(skipna=False, **kwargs)
result = getattr(self, method_name)(skipna=False, **kwargs)
result = maybe_unbox_numpy_scalar(result)
return result
8 changes: 5 additions & 3 deletions pandas/core/arrays/arrow/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@
PYARROW_MIN_VERSION,
)
from pandas.errors import Pandas4Warning
from pandas.util._decorators import doc
from pandas.util._decorators import (
doc,
set_module,
)
from pandas.util._exceptions import find_stack_level

from pandas.core.dtypes.cast import (
Expand Down Expand Up @@ -242,6 +245,7 @@ def to_pyarrow_type(
return None


@set_module("pandas.arrays")
class ArrowExtensionArray(
OpsMixin,
ExtensionArraySupportsAnyAll,
Expand Down Expand Up @@ -297,8 +301,6 @@ class ArrowExtensionArray(
Length: 3, dtype: int64[pyarrow]
""" # noqa: E501 (http link too long)

__module__ = "pandas.arrays"

_pa_array: pa.ChunkedArray
_dtype: ArrowDtype

Expand Down
7 changes: 3 additions & 4 deletions pandas/core/arrays/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from pandas.errors import AbstractMethodError
from pandas.util._decorators import (
cache_readonly,
set_module,
)
from pandas.util._validators import (
validate_bool_kwarg,
Expand Down Expand Up @@ -106,6 +107,7 @@
_extension_array_shared_docs: dict[str, str] = {}


@set_module("pandas.api.extensions")
class ExtensionArray:
"""
Abstract base class for custom 1-D array types.
Expand Down Expand Up @@ -257,8 +259,6 @@ class ExtensionArray:
https://github.com/pandas-dev/pandas/blob/main/pandas/tests/extension/list/array.py
"""

__module__ = "pandas.api.extensions"

# '_typ' is for pandas.core.dtypes.generic.ABCExtensionArray.
# Don't override this.
_typ = "extension"
Expand Down Expand Up @@ -2804,6 +2804,7 @@ def _add_logical_ops(cls) -> None:
setattr(cls, "__rxor__", cls._create_logical_method(roperator.rxor))


@set_module("pandas.api.extensions")
class ExtensionScalarOpsMixin(ExtensionOpsMixin):
"""
A mixin for defining ops on an ExtensionArray.
Expand All @@ -2830,8 +2831,6 @@ class ExtensionScalarOpsMixin(ExtensionOpsMixin):
with NumPy arrays.
"""

__module__ = "pandas.api.extensions"

@classmethod
def _create_method(cls, op, coerce_to_dtype: bool = True, result_dtype=None):
"""
Expand Down
3 changes: 1 addition & 2 deletions pandas/core/arrays/boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ def coerce_to_array(
return values, mask


@set_module("pandas.arrays")
class BooleanArray(BaseMaskedArray):
"""
Array of boolean (True/False) data with missing values.
Expand Down Expand Up @@ -321,8 +322,6 @@ class BooleanArray(BaseMaskedArray):
Length: 3, dtype: boolean
"""

__module__ = "pandas.arrays"

_TRUE_VALUES = {"True", "TRUE", "true", "1", "1.0"}
_FALSE_VALUES = {"False", "FALSE", "false", "0", "0.0"}

Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from pandas._libs.arrays import NDArrayBacked
from pandas.compat.numpy import function as nv
from pandas.errors import Pandas4Warning
from pandas.util._decorators import set_module
from pandas.util._exceptions import find_stack_level
from pandas.util._validators import validate_bool_kwarg

Expand Down Expand Up @@ -245,6 +246,7 @@ def contains(cat, key, container) -> bool:
return any(loc_ in container for loc_ in loc)


@set_module("pandas")
class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMixin):
"""
Represent a categorical variable in classic R / S-plus fashion.
Expand Down Expand Up @@ -361,8 +363,6 @@ class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMi
'c'
"""

__module__ = "pandas"

# For comparisons, so that numpy uses our implementation if the compare
# ops, which raise
__array_priority__ = 1000
Expand Down
8 changes: 4 additions & 4 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
)
from pandas._libs.tslibs.dtypes import abbrev_to_npy_unit
from pandas.errors import PerformanceWarning
from pandas.util._decorators import set_module
from pandas.util._exceptions import find_stack_level
from pandas.util._validators import validate_inclusive

Expand Down Expand Up @@ -171,6 +172,7 @@ def f(self):
return property(f)


@set_module("pandas.arrays")
class DatetimeArray(dtl.TimelikeOps, dtl.DatelikeOps):
"""
Pandas ExtensionArray for tz-naive or tz-aware datetime data.
Expand Down Expand Up @@ -223,8 +225,6 @@ class DatetimeArray(dtl.TimelikeOps, dtl.DatelikeOps):
Length: 2, dtype: datetime64[us]
"""

__module__ = "pandas.arrays"

_typ = "datetimearray"
_internal_fill_value = np.datetime64("NaT", "ns")
_recognized_scalars = (datetime, np.datetime64)
Expand Down Expand Up @@ -1046,7 +1046,7 @@ def tz_localize(
4 2018-10-28 02:30:00+01:00
5 2018-10-28 03:00:00+01:00
6 2018-10-28 03:30:00+01:00
dtype: datetime64[s, CET]
dtype: datetime64[us, CET]

In some cases, inferring the DST is impossible. In such cases, you can
pass an ndarray to the ambiguous parameter to set the DST explicitly
Expand All @@ -1058,7 +1058,7 @@ def tz_localize(
0 2018-10-28 01:20:00+02:00
1 2018-10-28 02:36:00+02:00
2 2018-10-28 03:46:00+01:00
dtype: datetime64[s, CET]
dtype: datetime64[us, CET]

If the DST transition causes nonexistent times, you can shift these
dates forward or backwards with a timedelta object or `'shift_forward'`
Expand Down
Loading
Loading