Skip to content

Commit fa4e26b

Browse files
authored
Merge branch 'main' into issue2
2 parents 8f67c9f + 56dc719 commit fa4e26b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+883
-202
lines changed

pandas/__init__.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# flake8: noqa
21
from __future__ import annotations
32

43
__docformat__ = "restructuredtext"
@@ -20,7 +19,7 @@
2019
del _hard_dependencies, _dependency, _missing_dependencies
2120

2221
# numpy compat
23-
from pandas.compat import is_numpy_dev as _is_numpy_dev
22+
from pandas.compat import is_numpy_dev as _is_numpy_dev # pyright: ignore # noqa:F401
2423

2524
try:
2625
from pandas._libs import hashtable as _hashtable, lib as _lib, tslib as _tslib
@@ -44,7 +43,7 @@
4443
)
4544

4645
# let init-time option registration happen
47-
import pandas.core.config_init
46+
import pandas.core.config_init # pyright: ignore # noqa:F401
4847

4948
from pandas.core.api import (
5049
# dtype
@@ -134,7 +133,8 @@
134133
qcut,
135134
)
136135

137-
from pandas import api, arrays, errors, io, plotting, testing, tseries
136+
from pandas import api, arrays, errors, io, plotting, tseries
137+
from pandas import testing # noqa:PDF015
138138
from pandas.util._print_versions import show_versions
139139

140140
from pandas.io.api import (

pandas/_config/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"options",
1717
]
1818
from pandas._config import config
19-
from pandas._config import dates # noqa:F401
19+
from pandas._config import dates # pyright: ignore # noqa:F401
2020
from pandas._config.config import (
2121
describe_option,
2222
get_option,

pandas/_libs/interval.pyi

+13-11
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import numpy.typing as npt
1212

1313
from pandas._libs import lib
1414
from pandas._typing import (
15-
IntervalClosedType,
15+
IntervalInclusiveType,
1616
Timedelta,
1717
Timestamp,
1818
)
1919

20-
VALID_CLOSED: frozenset[str]
20+
VALID_INCLUSIVE: frozenset[str]
2121

2222
_OrderableScalarT = TypeVar("_OrderableScalarT", int, float)
2323
_OrderableTimesT = TypeVar("_OrderableTimesT", Timestamp, Timedelta)
@@ -52,29 +52,31 @@ class IntervalMixin:
5252
def open_right(self) -> bool: ...
5353
@property
5454
def is_empty(self) -> bool: ...
55-
def _check_closed_matches(self, other: IntervalMixin, name: str = ...) -> None: ...
55+
def _check_inclusive_matches(
56+
self, other: IntervalMixin, name: str = ...
57+
) -> None: ...
5658

5759
def _warning_interval(
5860
inclusive, closed
59-
) -> tuple[IntervalClosedType, lib.NoDefault]: ...
61+
) -> tuple[IntervalInclusiveType, lib.NoDefault]: ...
6062

6163
class Interval(IntervalMixin, Generic[_OrderableT]):
6264
@property
6365
def left(self: Interval[_OrderableT]) -> _OrderableT: ...
6466
@property
6567
def right(self: Interval[_OrderableT]) -> _OrderableT: ...
6668
@property
67-
def inclusive(self) -> IntervalClosedType: ...
69+
def inclusive(self) -> IntervalInclusiveType: ...
6870
@property
69-
def closed(self) -> IntervalClosedType: ...
71+
def closed(self) -> IntervalInclusiveType: ...
7072
mid: _MidDescriptor
7173
length: _LengthDescriptor
7274
def __init__(
7375
self,
7476
left: _OrderableT,
7577
right: _OrderableT,
76-
inclusive: IntervalClosedType = ...,
77-
closed: IntervalClosedType = ...,
78+
inclusive: IntervalInclusiveType = ...,
79+
closed: IntervalInclusiveType = ...,
7880
) -> None: ...
7981
def __hash__(self) -> int: ...
8082
@overload
@@ -150,15 +152,15 @@ class Interval(IntervalMixin, Generic[_OrderableT]):
150152
def overlaps(self: Interval[_OrderableT], other: Interval[_OrderableT]) -> bool: ...
151153

152154
def intervals_to_interval_bounds(
153-
intervals: np.ndarray, validate_closed: bool = ...
154-
) -> tuple[np.ndarray, np.ndarray, str]: ...
155+
intervals: np.ndarray, validate_inclusive: bool = ...
156+
) -> tuple[np.ndarray, np.ndarray, IntervalInclusiveType]: ...
155157

156158
class IntervalTree(IntervalMixin):
157159
def __init__(
158160
self,
159161
left: np.ndarray,
160162
right: np.ndarray,
161-
inclusive: IntervalClosedType = ...,
163+
inclusive: IntervalInclusiveType = ...,
162164
leaf_size: int = ...,
163165
) -> None: ...
164166
@property

pandas/_libs/interval.pyx

+25-25
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ from pandas._libs.tslibs.util cimport (
5656
is_timedelta64_object,
5757
)
5858

59-
VALID_CLOSED = frozenset(['both', 'neither', 'left', 'right'])
59+
VALID_INCLUSIVE = frozenset(['both', 'neither', 'left', 'right'])
6060

6161

6262
cdef class IntervalMixin:
@@ -85,7 +85,7 @@ cdef class IntervalMixin:
8585
Returns
8686
-------
8787
bool
88-
True if the Interval is closed on the left-side.
88+
True if the Interval is closed on the right-side.
8989
"""
9090
return self.inclusive in ('right', 'both')
9191

@@ -99,7 +99,7 @@ cdef class IntervalMixin:
9999
Returns
100100
-------
101101
bool
102-
True if the Interval is closed on the left-side.
102+
True if the Interval is not closed on the left-side.
103103
"""
104104
return not self.closed_left
105105

@@ -113,7 +113,7 @@ cdef class IntervalMixin:
113113
Returns
114114
-------
115115
bool
116-
True if the Interval is closed on the left-side.
116+
True if the Interval is not closed on the right-side.
117117
"""
118118
return not self.closed_right
119119

@@ -188,7 +188,7 @@ cdef class IntervalMixin:
188188
"""
189189
return (self.right == self.left) & (self.inclusive != 'both')
190190

191-
def _check_closed_matches(self, other, name='other'):
191+
def _check_inclusive_matches(self, other, name='other'):
192192
"""
193193
Check if the inclusive attribute of `other` matches.
194194
@@ -203,7 +203,7 @@ cdef class IntervalMixin:
203203
Raises
204204
------
205205
ValueError
206-
When `other` is not closed exactly the same as self.
206+
When `other` is not inclusive exactly the same as self.
207207
"""
208208
if self.inclusive != other.inclusive:
209209
raise ValueError(f"'{name}.inclusive' is {repr(other.inclusive)}, "
@@ -259,14 +259,14 @@ cdef class Interval(IntervalMixin):
259259
.. deprecated:: 1.5.0
260260
261261
inclusive : {'both', 'neither', 'left', 'right'}, default 'both'
262-
Whether the interval is closed on the left-side, right-side, both or
262+
Whether the interval is inclusive on the left-side, right-side, both or
263263
neither. See the Notes for more detailed explanation.
264264
265265
.. versionadded:: 1.5.0
266266
267267
See Also
268268
--------
269-
IntervalIndex : An Index of Interval objects that are all closed on the
269+
IntervalIndex : An Index of Interval objects that are all inclusive on the
270270
same side.
271271
cut : Convert continuous data into discrete bins (Categorical
272272
of Interval objects).
@@ -279,13 +279,13 @@ cdef class Interval(IntervalMixin):
279279
The parameters `left` and `right` must be from the same type, you must be
280280
able to compare them and they must satisfy ``left <= right``.
281281
282-
A closed interval (in mathematics denoted by square brackets) contains
283-
its endpoints, i.e. the closed interval ``[0, 5]`` is characterized by the
282+
A inclusive interval (in mathematics denoted by square brackets) contains
283+
its endpoints, i.e. the inclusive interval ``[0, 5]`` is characterized by the
284284
conditions ``0 <= x <= 5``. This is what ``inclusive='both'`` stands for.
285285
An open interval (in mathematics denoted by parentheses) does not contain
286286
its endpoints, i.e. the open interval ``(0, 5)`` is characterized by the
287287
conditions ``0 < x < 5``. This is what ``inclusive='neither'`` stands for.
288-
Intervals can also be half-open or half-closed, i.e. ``[0, 5)`` is
288+
Intervals can also be half-open or half-inclusive, i.e. ``[0, 5)`` is
289289
described by ``0 <= x < 5`` (``inclusive='left'``) and ``(0, 5]`` is
290290
described by ``0 < x <= 5`` (``inclusive='right'``).
291291
@@ -352,7 +352,7 @@ cdef class Interval(IntervalMixin):
352352

353353
cdef readonly str inclusive
354354
"""
355-
Whether the interval is closed on the left-side, right-side, both or
355+
Whether the interval is inclusive on the left-side, right-side, both or
356356
neither.
357357
"""
358358

@@ -368,7 +368,7 @@ cdef class Interval(IntervalMixin):
368368
if inclusive is None:
369369
inclusive = "right"
370370

371-
if inclusive not in VALID_CLOSED:
371+
if inclusive not in VALID_INCLUSIVE:
372372
raise ValueError(f"invalid option for 'inclusive': {inclusive}")
373373
if not left <= right:
374374
raise ValueError("left side of interval must be <= right side")
@@ -522,7 +522,7 @@ cdef class Interval(IntervalMixin):
522522
"""
523523
Check whether two Interval objects overlap.
524524
525-
Two intervals overlap if they share a common point, including closed
525+
Two intervals overlap if they share a common point, including inclusive
526526
endpoints. Intervals that only have an open endpoint in common do not
527527
overlap.
528528
@@ -551,7 +551,7 @@ cdef class Interval(IntervalMixin):
551551
>>> i1.overlaps(i3)
552552
False
553553
554-
Intervals that share closed endpoints overlap:
554+
Intervals that share inclusive endpoints overlap:
555555
556556
>>> i4 = pd.Interval(0, 1, inclusive='both')
557557
>>> i5 = pd.Interval(1, 2, inclusive='both')
@@ -568,7 +568,7 @@ cdef class Interval(IntervalMixin):
568568
raise TypeError("`other` must be an Interval, "
569569
f"got {type(other).__name__}")
570570

571-
# equality is okay if both endpoints are closed (overlap at a point)
571+
# equality is okay if both endpoints are inclusive (overlap at a point)
572572
op1 = le if (self.closed_left and other.closed_right) else lt
573573
op2 = le if (other.closed_left and self.closed_right) else lt
574574

@@ -580,16 +580,16 @@ cdef class Interval(IntervalMixin):
580580

581581
@cython.wraparound(False)
582582
@cython.boundscheck(False)
583-
def intervals_to_interval_bounds(ndarray intervals, bint validate_closed=True):
583+
def intervals_to_interval_bounds(ndarray intervals, bint validate_inclusive=True):
584584
"""
585585
Parameters
586586
----------
587587
intervals : ndarray
588588
Object array of Intervals / nulls.
589589
590-
validate_closed: bool, default True
591-
Boolean indicating if all intervals must be closed on the same side.
592-
Mismatching closed will raise if True, else return None for closed.
590+
validate_inclusive: bool, default True
591+
Boolean indicating if all intervals must be inclusive on the same side.
592+
Mismatching inclusive will raise if True, else return None for inclusive.
593593
594594
Returns
595595
-------
@@ -602,7 +602,7 @@ def intervals_to_interval_bounds(ndarray intervals, bint validate_closed=True):
602602
object inclusive = None, interval
603603
Py_ssize_t i, n = len(intervals)
604604
ndarray left, right
605-
bint seen_closed = False
605+
bint seen_inclusive = False
606606

607607
left = np.empty(n, dtype=intervals.dtype)
608608
right = np.empty(n, dtype=intervals.dtype)
@@ -620,13 +620,13 @@ def intervals_to_interval_bounds(ndarray intervals, bint validate_closed=True):
620620

621621
left[i] = interval.left
622622
right[i] = interval.right
623-
if not seen_closed:
624-
seen_closed = True
623+
if not seen_inclusive:
624+
seen_inclusive = True
625625
inclusive = interval.inclusive
626626
elif inclusive != interval.inclusive:
627627
inclusive = None
628-
if validate_closed:
629-
raise ValueError("intervals must all be closed on the same side")
628+
if validate_inclusive:
629+
raise ValueError("intervals must all be inclusive on the same side")
630630

631631
return left, right, inclusive
632632

pandas/_libs/lib.pyx

+23-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ from cpython.number cimport PyNumber_Check
1717
from cpython.object cimport (
1818
Py_EQ,
1919
PyObject_RichCompareBool,
20+
PyTypeObject,
2021
)
2122
from cpython.ref cimport Py_INCREF
2223
from cpython.sequence cimport PySequence_Check
@@ -54,6 +55,11 @@ from numpy cimport (
5455

5556
cnp.import_array()
5657

58+
cdef extern from "Python.h":
59+
# Note: importing extern-style allows us to declare these as nogil
60+
# functions, whereas `from cpython cimport` does not.
61+
bint PyObject_TypeCheck(object obj, PyTypeObject* type) nogil
62+
5763
cdef extern from "numpy/arrayobject.h":
5864
# cython's numpy.dtype specification is incorrect, which leads to
5965
# errors in issubclass(self.dtype.type, np.bool_), so we directly
@@ -71,6 +77,9 @@ cdef extern from "numpy/arrayobject.h":
7177
object fields
7278
tuple names
7379

80+
PyTypeObject PySignedIntegerArrType_Type
81+
PyTypeObject PyUnsignedIntegerArrType_Type
82+
7483
cdef extern from "numpy/ndarrayobject.h":
7584
bint PyArray_CheckScalar(obj) nogil
7685

@@ -1283,9 +1292,9 @@ cdef class Seen:
12831292
In addition to setting a flag that an integer was seen, we
12841293
also set two flags depending on the type of integer seen:
12851294
1286-
1) sint_ : a negative (signed) number in the
1295+
1) sint_ : a signed numpy integer type or a negative (signed) number in the
12871296
range of [-2**63, 0) was encountered
1288-
2) uint_ : a positive number in the range of
1297+
2) uint_ : an unsigned numpy integer type or a positive number in the range of
12891298
[2**63, 2**64) was encountered
12901299
12911300
Parameters
@@ -1294,8 +1303,18 @@ cdef class Seen:
12941303
Value with which to set the flags.
12951304
"""
12961305
self.int_ = True
1297-
self.sint_ = self.sint_ or (oINT64_MIN <= val < 0)
1298-
self.uint_ = self.uint_ or (oINT64_MAX < val <= oUINT64_MAX)
1306+
self.sint_ = (
1307+
self.sint_
1308+
or (oINT64_MIN <= val < 0)
1309+
# Cython equivalent of `isinstance(val, np.signedinteger)`
1310+
or PyObject_TypeCheck(val, &PySignedIntegerArrType_Type)
1311+
)
1312+
self.uint_ = (
1313+
self.uint_
1314+
or (oINT64_MAX < val <= oUINT64_MAX)
1315+
# Cython equivalent of `isinstance(val, np.unsignedinteger)`
1316+
or PyObject_TypeCheck(val, &PyUnsignedIntegerArrType_Type)
1317+
)
12991318

13001319
@property
13011320
def numeric_(self):
@@ -2542,7 +2561,6 @@ def maybe_convert_objects(ndarray[object] objects,
25422561
floats[i] = <float64_t>val
25432562
complexes[i] = <double complex>val
25442563
if not seen.null_:
2545-
val = int(val)
25462564
seen.saw_int(val)
25472565

25482566
if ((seen.uint_ and seen.sint_) or

0 commit comments

Comments
 (0)