Skip to content

Commit b64a372

Browse files
Merge branch 'main' into bug-json-normalize
2 parents 55d1419 + 29193c9 commit b64a372

File tree

17 files changed

+542
-345
lines changed

17 files changed

+542
-345
lines changed

.github/workflows/docbuild-and-upload.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ jobs:
9393
run: mv doc/build/html web/build/docs
9494

9595
- name: Save website as an artifact
96-
uses: actions/upload-artifact@v4
96+
uses: actions/upload-artifact@v5
9797
with:
9898
name: website
9999
path: web/build

.github/workflows/wheels.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
python -m pip install build
6565
python -m build --sdist
6666
67-
- uses: actions/upload-artifact@v4
67+
- uses: actions/upload-artifact@v5
6868
with:
6969
name: sdist
7070
path: ./dist/*
@@ -138,7 +138,7 @@ jobs:
138138
# removes unnecessary files from the release
139139
- name: Download sdist (not macOS)
140140
#if: ${{ matrix.buildplat[1] != 'macosx_*' }}
141-
uses: actions/download-artifact@v5
141+
uses: actions/download-artifact@v6
142142
with:
143143
name: sdist
144144
path: ./dist
@@ -196,7 +196,7 @@ jobs:
196196
shell: bash -el {0}
197197
run: for whl in $(ls wheelhouse); do wheel unpack wheelhouse/$whl -d /tmp; done
198198

199-
- uses: actions/upload-artifact@v4
199+
- uses: actions/upload-artifact@v5
200200
with:
201201
name: ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}
202202
path: ./wheelhouse/*.whl
@@ -238,11 +238,11 @@ jobs:
238238

239239
steps:
240240
- name: Download all artefacts
241-
uses: actions/download-artifact@v5
241+
uses: actions/download-artifact@v6
242242
with:
243243
path: dist # everything lands in ./dist/**
244244

245-
# TODO: This step can be probably be achieved by actions/download-artifact@v5
245+
# TODO: This step can be probably be achieved by actions/download-artifact@v6
246246
# by specifying merge-multiple: true, and a glob pattern
247247
- name: Collect files
248248
run: |

doc/source/user_guide/io.rst

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2366,52 +2366,7 @@ Read a URL with no options:
23662366

23672367
The data from the above URL changes every Monday so the resulting data above may be slightly different.
23682368

2369-
Read a URL while passing headers alongside the HTTP request:
2370-
2371-
.. code-block:: ipython
2372-
2373-
In [322]: url = 'https://www.sump.org/notes/request/' # HTTP request reflector
2374-
2375-
In [323]: pd.read_html(url)
2376-
Out[323]:
2377-
[ 0 1
2378-
0 Remote Socket: 51.15.105.256:51760
2379-
1 Protocol Version: HTTP/1.1
2380-
2 Request Method: GET
2381-
3 Request URI: /notes/request/
2382-
4 Request Query: NaN,
2383-
0 Accept-Encoding: identity
2384-
1 Host: www.sump.org
2385-
2 User-Agent: Python-urllib/3.8
2386-
3 Connection: close]
2387-
2388-
In [324]: headers = {
2389-
.....: 'User-Agent':'Mozilla Firefox v14.0',
2390-
.....: 'Accept':'application/json',
2391-
.....: 'Connection':'keep-alive',
2392-
.....: 'Auth':'Bearer 2*/f3+fe68df*4'
2393-
.....: }
2394-
2395-
In [325]: pd.read_html(url, storage_options=headers)
2396-
Out[325]:
2397-
[ 0 1
2398-
0 Remote Socket: 51.15.105.256:51760
2399-
1 Protocol Version: HTTP/1.1
2400-
2 Request Method: GET
2401-
3 Request URI: /notes/request/
2402-
4 Request Query: NaN,
2403-
0 User-Agent: Mozilla Firefox v14.0
2404-
1 AcceptEncoding: gzip, deflate, br
2405-
2 Accept: application/json
2406-
3 Connection: keep-alive
2407-
4 Auth: Bearer 2*/f3+fe68df*4]
2408-
2409-
.. note::
2410-
2411-
We see above that the headers we passed are reflected in the HTTP request.
2412-
2413-
Read in the content of the file from the above URL and pass it to ``read_html``
2414-
as a string:
2369+
Read in HTML content from a file using ``read_html``:
24152370

24162371
.. ipython:: python
24172372

doc/source/whatsnew/v3.0.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,7 @@ Conversion
10351035

10361036
Strings
10371037
^^^^^^^
1038+
- Bug in :meth:`Series.str.replace` raising an error on valid group references (``\1``, ``\2``, etc.) on series converted to PyArrow backend dtype (:issue:`62653`)
10381039
- Bug in :meth:`Series.str.zfill` raising ``AttributeError`` for :class:`ArrowDtype` (:issue:`61485`)
10391040
- Bug in :meth:`Series.value_counts` would not respect ``sort=False`` for series having ``string`` dtype (:issue:`55224`)
10401041
- Bug in multiplication with a :class:`StringDtype` incorrectly allowing multiplying by bools; explicitly cast to integers instead (:issue:`62595`)
@@ -1208,6 +1209,7 @@ ExtensionArray
12081209
- Bug in comparison between object with :class:`ArrowDtype` and incompatible-dtyped (e.g. string vs bool) incorrectly raising instead of returning all-``False`` (for ``==``) or all-``True`` (for ``!=``) (:issue:`59505`)
12091210
- Bug in constructing pandas data structures when passing into ``dtype`` a string of the type followed by ``[pyarrow]`` while PyArrow is not installed would raise ``NameError`` rather than ``ImportError`` (:issue:`57928`)
12101211
- Bug in various :class:`DataFrame` reductions for pyarrow temporal dtypes returning incorrect dtype when result was null (:issue:`59234`)
1212+
- Fixed flex arithmetic with :class:`ExtensionArray` operands raising when ``fill_value`` was passed. (:issue:`62467`)
12111213

12121214
Styler
12131215
^^^^^^

pandas/conftest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,6 +1447,9 @@ def any_string_dtype(request):
14471447
return pd.StringDtype(storage, na_value)
14481448

14491449

1450+
any_string_dtype2 = any_string_dtype
1451+
1452+
14501453
@pytest.fixture(params=tm.DATETIME64_DTYPES)
14511454
def datetime64_dtype(request):
14521455
"""

pandas/core/arrays/_arrow_string_mixins.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,15 +173,12 @@ def _str_replace(
173173
or callable(repl)
174174
or not case
175175
or flags
176-
or (
177-
isinstance(repl, str)
178-
and (r"\g<" in repl or re.search(r"\\\d", repl) is not None)
179-
)
176+
or (isinstance(repl, str) and r"\g<" in repl)
180177
):
181178
raise NotImplementedError(
182179
"replace is not supported with a re.Pattern, callable repl, "
183180
"case=False, flags!=0, or when the replacement string contains "
184-
"named group references (\\g<...>, \\d+)"
181+
"named group references (\\g<...>)"
185182
)
186183

187184
func = pc.replace_substring_regex if regex else pc.replace_substring

pandas/core/arrays/string_arrow.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,7 @@ def _str_replace(
425425
or flags
426426
or ( # substitution contains a named group pattern
427427
# https://docs.python.org/3/library/re.html
428-
isinstance(repl, str)
429-
and (r"\g<" in repl or re.search(r"\\\d", repl) is not None)
428+
isinstance(repl, str) and r"\g<" in repl
430429
)
431430
):
432431
return super()._str_replace(pat, repl, n, case, flags, regex)

pandas/core/indexes/range.py

Lines changed: 108 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
from pandas.compat.numpy import function as nv
2828
from pandas.util._decorators import (
2929
cache_readonly,
30-
doc,
3130
set_module,
3231
)
3332

@@ -473,8 +472,51 @@ def inferred_type(self) -> str:
473472
# --------------------------------------------------------------------
474473
# Indexing Methods
475474

476-
@doc(Index.get_loc)
477475
def get_loc(self, key) -> int:
476+
"""
477+
Get integer location for requested label.
478+
479+
Parameters
480+
----------
481+
key : int or float
482+
Label to locate. Integer-like floats (e.g. 3.0) are accepted and
483+
treated as the corresponding integer. Non-integer floats and other
484+
non-integer labels are not valid and will raise KeyError or
485+
InvalidIndexError.
486+
487+
Returns
488+
-------
489+
int
490+
Integer location of the label within the RangeIndex.
491+
492+
Raises
493+
------
494+
KeyError
495+
If the label is not present in the RangeIndex or the label is a
496+
non-integer value.
497+
InvalidIndexError
498+
If the label is of an invalid type for the RangeIndex.
499+
500+
See Also
501+
--------
502+
RangeIndex.get_slice_bound : Calculate slice bound that corresponds to
503+
given label.
504+
RangeIndex.get_indexer : Computes indexer and mask for new index given
505+
the current index.
506+
RangeIndex.get_non_unique : Returns indexer and masks for new index given
507+
the current index.
508+
RangeIndex.get_indexer_for : Returns an indexer even when non-unique.
509+
510+
Examples
511+
--------
512+
>>> idx = pd.RangeIndex(5)
513+
>>> idx.get_loc(3)
514+
3
515+
516+
>>> idx = pd.RangeIndex(2, 10, 2) # values [2, 4, 6, 8]
517+
>>> idx.get_loc(6)
518+
2
519+
"""
478520
if is_integer(key) or (is_float(key) and key.is_integer()):
479521
new_key = int(key)
480522
try:
@@ -528,12 +570,39 @@ def _should_fallback_to_positional(self) -> bool:
528570
def tolist(self) -> list[int]:
529571
return list(self._range)
530572

531-
@doc(Index.__iter__)
532573
def __iter__(self) -> Iterator[int]:
574+
"""
575+
Return an iterator of the values.
576+
577+
Returns
578+
-------
579+
iterator
580+
An iterator yielding ints from the RangeIndex.
581+
582+
Examples
583+
--------
584+
>>> idx = pd.RangeIndex(3)
585+
>>> for x in idx:
586+
... print(x)
587+
0
588+
1
589+
2
590+
"""
533591
yield from self._range
534592

535-
@doc(Index._shallow_copy)
536593
def _shallow_copy(self, values, name: Hashable = no_default):
594+
"""
595+
Create a new RangeIndex with the same class as the caller, don't copy the
596+
data, use the same object attributes with passed in attributes taking
597+
precedence.
598+
599+
*this is an internal non-public method*
600+
601+
Parameters
602+
----------
603+
values : the values to create the new RangeIndex, optional
604+
name : Label, defaults to self.name
605+
"""
537606
name = self._name if name is no_default else name
538607

539608
if values.dtype.kind == "f":
@@ -560,8 +629,42 @@ def _wrap_reindex_result(self, target, indexer, preserve_names: bool):
560629
target = self._shallow_copy(target._values, name=target.name)
561630
return super()._wrap_reindex_result(target, indexer, preserve_names)
562631

563-
@doc(Index.copy)
564632
def copy(self, name: Hashable | None = None, deep: bool = False) -> Self:
633+
"""
634+
Make a copy of this object.
635+
636+
Name is set on the new object.
637+
638+
Parameters
639+
----------
640+
name : Label, optional
641+
Set name for new object.
642+
deep : bool, default False
643+
If True attempts to make a deep copy of the RangeIndex.
644+
Else makes a shallow copy.
645+
646+
Returns
647+
-------
648+
RangeIndex
649+
RangeIndex refer to new object which is a copy of this object.
650+
651+
See Also
652+
--------
653+
RangeIndex.delete: Make new RangeIndex with passed location(-s) deleted.
654+
RangeIndex.drop: Make new RangeIndex with passed list of labels deleted.
655+
656+
Notes
657+
-----
658+
In most cases, there should be no functional difference from using
659+
``deep``, but if ``deep`` is passed it will attempt to deepcopy.
660+
661+
Examples
662+
--------
663+
>>> idx = pd.RangeIndex(3)
664+
>>> new_idx = idx.copy()
665+
>>> idx is new_idx
666+
False
667+
"""
565668
name = self._validate_names(name=name, deep=deep)[0]
566669
new_index = self._rename(name=name)
567670
return new_index

pandas/core/resample.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,6 @@ def interpolate(
850850
inplace: bool = False,
851851
limit_direction: Literal["forward", "backward", "both"] = "forward",
852852
limit_area=None,
853-
downcast=lib.no_default,
854853
**kwargs,
855854
):
856855
"""
@@ -907,11 +906,6 @@ def interpolate(
907906
(interpolate).
908907
* 'outside': Only fill NaNs outside valid values (extrapolate).
909908
910-
downcast : optional, 'infer' or None, defaults to None
911-
Downcast dtypes if possible.
912-
913-
.. deprecated:: 2.1.0
914-
915909
**kwargs : optional
916910
Keyword arguments to pass on to the interpolating function.
917911
@@ -993,7 +987,6 @@ def interpolate(
993987
Note that the series correctly decreases between two anchors
994988
``07:00:00`` and ``07:00:02``.
995989
"""
996-
assert downcast is lib.no_default # just checking coverage
997990
result = self._upsample("asfreq")
998991

999992
# If the original data has timestamps which are not aligned with the
@@ -1030,7 +1023,6 @@ def interpolate(
10301023
inplace=inplace,
10311024
limit_direction=limit_direction,
10321025
limit_area=limit_area,
1033-
downcast=downcast,
10341026
**kwargs,
10351027
)
10361028

pandas/core/series.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6738,7 +6738,7 @@ def _flex_method(self, other, op, *, level=None, fill_value=None, axis: Axis = 0
67386738

67396739
if isinstance(other, Series):
67406740
return self._binop(other, op, level=level, fill_value=fill_value)
6741-
elif isinstance(other, (np.ndarray, list, tuple)):
6741+
elif isinstance(other, (np.ndarray, list, tuple, ExtensionArray)):
67426742
if len(other) != len(self):
67436743
raise ValueError("Lengths must be equal")
67446744
other = self._constructor(other, self.index, copy=False)

0 commit comments

Comments
 (0)