Repository: pandas-dev/pandas
Pull request #57108 (2024-01-27 23:42:09)

TYP: misc return values


Patch:
diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml
index 841559c8e9..6d3b9048a2 100644
--- a/.github/workflows/wheels.yml
+++ b/.github/workflows/wheels.yml
@@ -139,7 +139,7 @@ jobs:
 
       - name: Build normal wheels
         if: ${{ (env.IS_SCHEDULE_DISPATCH != 'true' || env.IS_PUSH == 'true') }}
-        uses: pypa/cibuildwheel@v2.16.2
+        uses: pypa/cibuildwheel@v2.16.4
         with:
          package-dir: ./dist/${{ matrix.buildplat[1] == 'macosx_*' && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
         env:
@@ -148,7 +148,7 @@ jobs:
 
       - name: Build nightly wheels (with NumPy pre-release)
         if: ${{ (env.IS_SCHEDULE_DISPATCH == 'true' && env.IS_PUSH != 'true') }}
-        uses: pypa/cibuildwheel@v2.16.2
+        uses: pypa/cibuildwheel@v2.16.4
         with:
          package-dir: ./dist/${{ matrix.buildplat[1] == 'macosx_*' && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
         env:
diff --git a/ci/code_checks.sh b/ci/code_checks.sh
index c0a26edd23..a1ca16cfa4 100755
--- a/ci/code_checks.sh
+++ b/ci/code_checks.sh
@@ -95,7 +95,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
         pandas.PeriodIndex.strftime\
         pandas.Series.clip\
         pandas.Series.rename_axis\
-        pandas.Series.interpolate\
         pandas.Series.dt.to_period\
         pandas.Series.dt.tz_localize\
         pandas.Series.dt.tz_convert\
@@ -186,8 +185,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
         pandas.core.groupby.DataFrameGroupBy.hist\
         pandas.core.groupby.DataFrameGroupBy.plot\
         pandas.core.groupby.SeriesGroupBy.plot\
-        pandas.read_hdf\
-        pandas.HDFStore.append\
         pandas.core.window.rolling.Rolling.quantile\
         pandas.core.window.expanding.Expanding.quantile\
         pandas.api.extensions.ExtensionArray.argsort # There should be no backslash in the final line, please keep this comment in the last ignored function
diff --git a/doc/source/user_guide/missing_data.rst b/doc/source/user_guide/missing_data.rst
index 4a2aa565dd..7ee77b7648 100644
--- a/doc/source/user_guide/missing_data.rst
+++ b/doc/source/user_guide/missing_data.rst
@@ -30,7 +30,7 @@ use :class:`api.types.NaTType`.
    pd.Series(["2020", "2020"], dtype=pd.PeriodDtype("D")).reindex([0, 1, 2])
 
 :class:`NA` for :class:`StringDtype`, :class:`Int64Dtype` (and other bit widths),
-:class:`Float64Dtype`(and other bit widths), :class:`BooleanDtype` and :class:`ArrowDtype`.
+:class:`Float64Dtype` (and other bit widths), :class:`BooleanDtype` and :class:`ArrowDtype`.
 These types will maintain the original data type of the data.
 For typing applications, use :class:`api.types.NAType`.
 
diff --git a/doc/source/whatsnew/v2.2.1.rst b/doc/source/whatsnew/v2.2.1.rst
index b9b2821ebc..660594c98e 100644
--- a/doc/source/whatsnew/v2.2.1.rst
+++ b/doc/source/whatsnew/v2.2.1.rst
@@ -16,6 +16,7 @@ Fixed regressions
 - Fixed memory leak in :func:`read_csv` (:issue:`57039`)
 - Fixed performance regression in :meth:`Series.combine_first` (:issue:`55845`)
 - Fixed regression in :func:`merge_ordered` raising ``TypeError`` for ``fill_method="ffill"`` and ``how="left"`` (:issue:`57010`)
+- Fixed regression in :func:`wide_to_long` raising an ``AttributeError`` for string columns (:issue:`57066`)
 - Fixed regression in :meth:`DataFrameGroupBy.idxmin`, :meth:`DataFrameGroupBy.idxmax`, :meth:`SeriesGroupBy.idxmin`, :meth:`SeriesGroupBy.idxmax` ignoring the ``skipna`` argument (:issue:`57040`)
 - Fixed regression in :meth:`DataFrameGroupBy.idxmin`, :meth:`DataFrameGroupBy.idxmax`, :meth:`SeriesGroupBy.idxmin`, :meth:`SeriesGroupBy.idxmax` where values containing the minimum or maximum value for the dtype could produce incorrect results (:issue:`57040`)
 - Fixed regression in :meth:`Series.pct_change` raising a ``ValueError`` for an empty :class:`Series` (:issue:`57056`)
diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst
index 73201fa93a..6d41c29a6c 100644
--- a/doc/source/whatsnew/v3.0.0.rst
+++ b/doc/source/whatsnew/v3.0.0.rst
@@ -142,7 +142,7 @@ Timezones
 
 Numeric
 ^^^^^^^
--
+- Bug in ``np.matmul`` with :class:`Index` inputs raising a ``TypeError`` (:issue:`57079`)
 -
 
 Conversion
@@ -152,7 +152,7 @@ Conversion
 
 Strings
 ^^^^^^^
--
+- Bug in :meth:`Series.value_counts` would not respect ``sort=False`` for series having ``string`` dtype (:issue:`55224`)
 -
 
 Interval
diff --git a/pandas/_config/config.py b/pandas/_config/config.py
index b74883dbe5..6a0e544afa 100644
--- a/pandas/_config/config.py
+++ b/pandas/_config/config.py
@@ -60,8 +60,10 @@ from typing import (
     Any,
     Callable,
     Generic,
+    Literal,
     NamedTuple,
     cast,
+    overload,
 )
 import warnings
 
@@ -740,7 +742,23 @@ def _build_option_description(k: str) -> str:
     return s
 
 
-def pp_options_list(keys: Iterable[str], width: int = 80, _print: bool = False):
+@overload
+def pp_options_list(
+    keys: Iterable[str], *, width: int = ..., _print: Literal[False] = ...
+) -> str:
+    ...
+
+
+@overload
+def pp_options_list(
+    keys: Iterable[str], *, width: int = ..., _print: Literal[True]
+) -> None:
+    ...
+
+
+def pp_options_list(
+    keys: Iterable[str], *, width: int = 80, _print: bool = False
+) -> str | None:
     """Builds a concise listing of available options, grouped by prefix"""
     from itertools import groupby
     from textwrap import wrap
@@ -770,8 +788,7 @@ def pp_options_list(keys: Iterable[str], width: int = 80, _print: bool = False):
     s = "\n".join(ls)
     if _print:
         print(s)
-    else:
-        return s
+    return s
 
 
 #
diff --git a/pandas/_libs/arrays.pyi b/pandas/_libs/arrays.pyi
index 86f69c3cdf..dda23d9dec 100644
--- a/pandas/_libs/arrays.pyi
+++ b/pandas/_libs/arrays.pyi
@@ -14,9 +14,9 @@ class NDArrayBacked:
     _ndarray: np.ndarray
     def __init__(self, values: np.ndarray, dtype: DtypeObj) -> None: ...
     @classmethod
-    def _simple_new(cls, values: np.ndarray, dtype: DtypeObj): ...
-    def _from_backing_data(self, values: np.ndarray): ...
-    def __setstate__(self, state): ...
+    def _simple_new(cls, values: np.ndarray, dtype: DtypeObj) -> Self: ...
+    def _from_backing_data(self, values: np.ndarray) -> Self: ...
+    def __setstate__(self, state) -> None: ...
     def __len__(self) -> int: ...
     @property
     def shape(self) -> Shape: ...
@@ -26,14 +26,14 @@ class NDArrayBacked:
     def size(self) -> int: ...
     @property
     def nbytes(self) -> int: ...
-    def copy(self, order=...): ...
-    def delete(self, loc, axis=...): ...
-    def swapaxes(self, axis1, axis2): ...
-    def repeat(self, repeats: int | Sequence[int], axis: int | None = ...): ...
-    def reshape(self, *args, **kwargs): ...
-    def ravel(self, order=...): ...
+    def copy(self, order=...) -> Self: ...
+    def delete(self, loc, axis=...) -> Self: ...
+    def swapaxes(self, axis1, axis2) -> Self: ...
+    def repeat(self, repeats: int | Sequence[int], axis: int | None = ...) -> Self: ...
+    def reshape(self, *args, **kwargs) -> Self: ...
+    def ravel(self, order=...) -> Self: ...
     @property
-    def T(self): ...
+    def T(self) -> Self: ...
     @classmethod
     def _concat_same_type(
         cls, to_concat: Sequence[Self], axis: AxisInt = ...
diff --git a/pandas/_libs/tslibs/dtypes.pyi b/pandas/_libs/tslibs/dtypes.pyi
index 7fdeb88d49..dc2855cbec 100644
--- a/pandas/_libs/tslibs/dtypes.pyi
+++ b/pandas/_libs/tslibs/dtypes.pyi
@@ -1,5 +1,7 @@
 from enum import Enum
 
+from pandas._typing import Self
+
 OFFSET_TO_PERIOD_FREQSTR: dict[str, str]
 
 def periods_per_day(reso: int = ...) -> int: ...
@@ -12,7 +14,7 @@ class PeriodDtypeBase:
     _n: int
 
     # actually __cinit__
-    def __new__(cls, code: int, n: int): ...
+    def __new__(cls, code: int, n: int) -> Self: ...
     @property
     def _freq_group_code(self) -> int: ...
     @property
diff --git a/pandas/_libs/tslibs/offsets.pyi b/pandas/_libs/tslibs/offsets.pyi
index 7eb8dc0813..434f10a007 100644
--- a/pandas/_libs/tslibs/offsets.pyi
+++ b/pandas/_libs/tslibs/offsets.pyi
@@ -64,7 +64,7 @@ class BaseOffset:
     @overload
     def __rsub__(self, other: npt.NDArray[np.object_]) -> npt.NDArray[np.object_]: ...
     @overload
-    def __rsub__(self, other: BaseOffset): ...
+    def __rsub__(self, other: BaseOffset) -> Self: ...
     @overload
     def __rsub__(self, other: _DatetimeT) -> _DatetimeT: ...
     @overload
@@ -72,7 +72,7 @@ class BaseOffset:
     @overload
     def __mul__(self, other: np.ndarray) -> np.ndarray: ...
     @overload
-    def __mul__(self, other: int): ...
+    def __mul__(self, other: int) -> Self: ...
     @overload
     def __rmul__(self, other: np.ndarray) -> np.ndarray: ...
     @overload
@@ -100,7 +100,7 @@ def _get_offset(name: str) -> BaseOffset: ...
 
 class SingleConstructorOffset(BaseOffset):
     @classmethod
-    def _from_name(cls, suffix: None = ...): ...
+    def _from_name(cls, suffix: None = ...) -> Self: ...
     def __reduce__(self): ...
 
 @overload
diff --git a/pandas/core/arrays/_mixins.py b/pandas/core/arrays/_mixins.py
index 560845d375..adbb971f77 100644
--- a/pandas/core/arrays/_mixins.py
+++ b/pandas/core/arrays/_mixins.py
@@ -89,7 +89,9 @@ def ravel_compat(meth: F) -> F:
     return cast(F, method)
 
 
-class NDArrayBackedExtensionArray(NDArrayBacked, ExtensionArray):
+# error: Definition of "delete/ravel/T/repeat/copy" in base class "NDArrayBacked"
+# is incompatible with definition in base class "ExtensionArray"
+class NDArrayBackedExtensionArray(NDArrayBacked, ExtensionArray):  # type: ignore[misc]
     """
     ExtensionArray that is backed by a single NumPy ndarray.
     """
@@ -386,7 +388,7 @@ class NDArrayBackedExtensionArray(NDArrayBacked, ExtensionArray):
     # ------------------------------------------------------------------------
     # Reductions
 
-    def _wrap_reduction_result(self, axis: AxisInt | None, result):
+    def _wrap_reduction_result(self, axis: AxisInt | None, result) -> Any:
         if axis is None or self.ndim == 1:
             return self._box_func(result)
         return self._from_backing_data(result)
diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py
index 58264f2aef..b5946594fc 100644
--- a/pandas/core/arrays/base.py
+++ b/pandas/core/arrays/base.py
@@ -1781,7 +1781,7 @@ class ExtensionArray:
     # Reshaping
     # ------------------------------------------------------------------------
 
-    def transpose(self, *axes: int) -> ExtensionArray:
+    def transpose(self, *axes: int) -> Self:
         """
         Return a transposed view on this array.
 
@@ -1802,10 +1802,10 @@ class ExtensionArray:
         return self[:]
 
     @property
-    def T(self) -> ExtensionArray:
+    def T(self) -> Self:
         return self.transpose()
 
-    def ravel(self, order: Literal["C", "F", "A", "K"] | None = "C") -> ExtensionArray:
+    def ravel(self, order: Literal["C", "F", "A", "K"] | None = "C") -> Self:
         """
         Return a flattened view on this array.
 
diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py
index 9d94cbbc57..09f506e117 100644
--- a/pandas/core/arrays/categorical.py
+++ b/pandas/core/arrays/categorical.py
@@ -243,7 +243,9 @@ def contains(cat, key, container) -> bool:
         return any(loc_ in container for loc_ in loc)
 
 
-class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMixin):
+# error: Definition of "delete/ravel/T/repeat/copy" in base class "NDArrayBacked"
+# is incompatible with definition in base class "ExtensionArray"
+class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMixin):  # type: ignore[misc]
     """
     Represent a categorical variable in classic R / S-plus fashion.
 
@@ -561,6 +563,7 @@ class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMi
             object is returned.
         """
         dtype = pandas_dtype(dtype)
+        result: Categorical | np.ndarray
         if self.dtype is dtype:
             result = self.copy() if copy else self
 
@@ -1818,10 +1821,14 @@ class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMi
             ix = np.append(ix, -1)
 
         ix = coerce_indexer_dtype(ix, self.dtype.categories)
-        ix = self._from_backing_data(ix)
+        ix_categorical = self._from_backing_data(ix)
 
         return Series(
-            count, index=CategoricalIndex(ix), dtype="int64", name="count", copy=False
+            count,
+            index=CategoricalIndex(ix_categorical),
+            dtype="int64",
+            name="count",
+            copy=False,
         )
 
     # error: Argument 2 of "_empty" is incompatible with supertype
@@ -2526,7 +2533,9 @@ class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMi
             result = res_flat.reshape(len(first), -1, order="F")
             return result
 
-        result = union_categoricals(to_concat)
+        # error: Incompatible types in assignment (expression has type "Categorical",
+        # variable has type "Self")
+        result = union_categoricals(to_concat)  # type: ignore[assignment]
         return result
 
     # ------------------------------------------------------------------
@@ -2666,11 +2675,11 @@ class Categorical(NDArrayBackedExtensionArray, PandasObject, ObjectStringArrayMi
 
         new_categories = ser.take(locs)
         new_categories = new_categories.drop_duplicates(keep="first")
-        new_categories = Index(new_categories)
+        index_categories = Index(new_categories)
         new_codes = recode_for_categories(
-            cat._codes, all_values, new_categories, copy=False
+            cat._codes, all_values, index_categories, copy=False
         )
-        new_dtype = CategoricalDtype(new_categories, ordered=self.dtype.ordered)
+        new_dtype = CategoricalDtype(index_categories, ordered=self.dtype.ordered)
         NDArrayBacked.__init__(cat, new_codes, new_dtype)
 
         if new_dtype != orig_dtype:
diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py
index 2dbc2a663c..05e8b981f4 100644
--- a/pandas/core/arrays/interval.py
+++ b/pandas/core/arrays/interval.py
@@ -1727,6 +1727,8 @@ class IntervalArray(IntervalMixin, ExtensionArray):
         return self._shallow_copy(new_left, new_right)
 
     def delete(self, loc) -> Self:
+        new_left: np.ndarray | DatetimeArray | TimedeltaArray
+        new_right: np.ndarray | DatetimeArray | TimedeltaArray
         if isinstance(self._left, np.ndarray):
             new_left = np.delete(self._left, loc)
             assert isinstance(self._right, np.ndarray)
diff --git a/pandas/core/arrays/string_.py b/pandas/core/arrays/string_.py
index b73b49eca3..ecad5b481f 100644
--- a/pandas/core/arrays/string_.py
+++ b/pandas/core/arrays/string_.py
@@ -499,10 +499,10 @@ class StringArray(BaseStringArray, NumpyExtensionArray):  # type: ignore[misc]
             values = arr.astype(dtype.numpy_dtype)
             return IntegerArray(values, mask, copy=False)
         elif isinstance(dtype, FloatingDtype):
-            arr = self.copy()
+            arr_ea = self.copy()
             mask = self.isna()
-            arr[mask] = "0"
-            values = arr.astype(dtype.numpy_dtype)
+            arr_ea[mask] = "0"
+            values = arr_ea.astype(dtype.numpy_dtype)
             return FloatingArray(values, mask, copy=False)
         elif isinstance(dtype, ExtensionDtype):
             # Skip the NumpyExtensionArray.astype method
@@ -542,7 +542,7 @@ class StringArray(BaseStringArray, NumpyExtensionArray):  # type: ignore[misc]
     def value_counts(self, dropna: bool = True) -> Series:
         from pandas.core.algorithms import value_counts_internal as value_counts
 
-        result = value_counts(self._ndarray, dropna=dropna).astype("Int64")
+        result = value_counts(self._ndarray, sort=False, dropna=dropna).astype("Int64")
         result.index = result.index.astype(self.dtype)
         return result
 
diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py
index bf20525e2c..4b200c447c 100644
--- a/pandas/core/indexes/base.py
+++ b/pandas/core/indexes/base.py
@@ -951,6 +951,9 @@ class Index(IndexOpsMixin, PandasObject):
         elif method == "reduce":
             result = lib.item_from_zerodim(result)
             return result
+        elif is_scalar(result):
+            # e.g. matmul
+            return result
 
         if result.dtype == np.float16:
             result = result.astype(np.float32)
diff --git a/pandas/core/reshape/melt.py b/pandas/core/reshape/melt.py
index 1ae7000f56..4bf1742a83 100644
--- a/pandas/core/reshape/melt.py
+++ b/pandas/core/reshape/melt.py
@@ -458,8 +458,7 @@ def wide_to_long(
 
     def get_var_names(df, stub: str, sep: str, suffix: str):
         regex = rf"^{re.escape(stub)}{re.escape(sep)}{suffix}$"
-        pattern = re.compile(regex)
-        return df.columns[df.columns.str.match(pattern)]
+        return df.columns[df.columns.str.match(regex)]
 
     def melt_stub(df, stub: str, i, j, value_vars, sep: str):
         newdf = melt(
diff --git a/pandas/core/strings/accessor.py b/pandas/core/strings/accessor.py
index f0ad5b662d..804beb44bd 100644
--- a/pandas/core/strings/accessor.py
+++ b/pandas/core/strings/accessor.py
@@ -1332,14 +1332,14 @@ class StringMethods(NoNewAttributesMixin):
         return self._wrap_result(result, fill_value=na, returns_string=False)
 
     @forbid_nonstring_types(["bytes"])
-    def match(self, pat, case: bool = True, flags: int = 0, na=None):
+    def match(self, pat: str, case: bool = True, flags: int = 0, na=None):
         """
         Determine if each string starts with a match of a regular expression.
 
         Parameters
         ----------
         pat : str
-            Character sequence or regular expression.
+            Character sequence.
         case : bool, default True
             If True, case sensitive.
         flags : int, default 0 (no flags)
diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py
index 36c9b66f2b..3d6d1c213e 100644
--- a/pandas/io/pytables.py
+++ b/pandas/io/pytables.py
@@ -365,7 +365,7 @@ def read_hdf(
         A list of Term (or convertible) objects.
     start : int, optional
         Row number to start selection.
-    stop  : int, optional
+    stop : int, optional
         Row number to stop selection.
     columns : list, optional
         A list of columns names to return.
@@ -1269,7 +1269,7 @@ class HDFStore:
                 subsets of the data.
         index : bool, default True
             Write DataFrame index as a column.
-        append       : bool, default True
+        append : bool, default True
             Append the input data to the existing.
         data_columns : list of columns, or True, default None
             List of columns to create as indexed data columns for on-disk
@@ -1277,10 +1277,10 @@ class HDFStore:
             of the object are indexed. See `here
             <https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html#query-via-data-columns>`__.
         min_itemsize : dict of columns that specify minimum str sizes
-        nan_rep      : str to use as str nan representation
-        chunksize    : size to chunk the writing
+        nan_rep : str to use as str nan representation
+        chunksize : size to chunk the writing
         expectedrows : expected TOTAL row size of this table
-        encoding     : default None, provide an encoding for str
+        encoding : default None, provide an encoding for str
         dropna : bool, default False, optional
             Do not write an ALL nan row to the store settable
             by the option 'io.hdf.dropna_table'.
diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py
index 0f15b2edc0..e8675a6d74 100644
--- a/pandas/plotting/_core.py
+++ b/pandas/plotting/_core.py
@@ -98,7 +98,7 @@ def hist_series(
 
     Returns
     -------
-    matplotlib.Axes
+    matplotlib.axes.Axes
         A histogram plot.
 
     See Also
diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py
index 136056e3ff..6fa75ba5fb 100644
--- a/pandas/plotting/_matplotlib/core.py
+++ b/pandas/plotting/_matplotlib/core.py
@@ -1021,7 +1021,7 @@ class MPLPlot(ABC):
             return col_idx
 
     @final
-    def _get_ax(self, i: int):
+    def _get_ax(self, i: int) -> Axes:
         # get the twinx ax if appropriate
         if self.subplots:
             i = self._col_idx_to_axis_idx(i)
@@ -1037,7 +1037,7 @@ class MPLPlot(ABC):
         return ax
 
     @final
-    def on_right(self, i: int):
+    def on_right(self, i: int) -> bool:
         if isinstance(self.secondary_y, bool):
             return self.secondary_y
 
@@ -1210,7 +1210,7 @@ class MPLPlot(ABC):
         return errors
 
     @final
-    def _get_subplots(self, fig: Figure):
+    def _get_subplots(self, fig: Figure) -> list[Axes]:
         if Version(mpl.__version__) < Version("3.8"):
             from matplotlib.axes import Subplot as Klass
         else:
@@ -2100,9 +2100,11 @@ class PiePlot(MPLPlot):
             results = ax.pie(y, labels=blabels, **kwds)
 
             if kwds.get("autopct", None) is not None:
-                patches, texts, autotexts = results
+                # error: Need more than 2 values to unpack (3 expected)
+                patches, texts, autotexts = results  # type: ignore[misc]
             else:
-                patches, texts = results
+                # error: Too many values to unpack (2 expected, 3 provided)
+                patches, texts = results  # type: ignore[misc]
                 autotexts = []
 
             if self.fontsize is not None:
diff --git a/pandas/tseries/holiday.py b/pandas/tseries/holiday.py
index 646284c79a..650e77b264 100644
--- a/pandas/tseries/holiday.py
+++ b/pandas/tseries/holiday.py
@@ -384,7 +384,7 @@ def register(cls) -> None:
     holiday_calendars[name] = cls
 
 
-def get_calendar(name: str):
+def get_calendar(name: str) -> AbstractHolidayCalendar:
     """
     Return an instance of a calendar based on its name.
 
@@ -433,7 +433,7 @@ class AbstractHolidayCalendar(metaclass=HolidayCalendarMetaClass):
         if rules is not None:
             self.rules = rules
 
-    def rule_from_name(self, name: str):
+    def rule_from_name(self, name: str) -> Holiday | None:
         for rule in self.rules:
             if rule.name == name:
                 return rule
diff --git a/pandas/util/_doctools.py b/pandas/util/_doctools.py
index 12619abf4b..828b7a4591 100644
--- a/pandas/util/_doctools.py
+++ b/pandas/util/_doctools.py
@@ -9,6 +9,8 @@ import pandas as pd
 if TYPE_CHECKING:
     from collections.abc import Iterable
 
+    from matplotlib.figure import Figure
+
 
 class TablePlotter:
     """
@@ -46,7 +48,9 @@ class TablePlotter:
             hcells = sum([self._shape(df)[1] for df in left] + [self._shape(right)[1]])
         return hcells, vcells
 
-    def plot(self, left, right, labels: Iterable[str] = (), vertical: bool = True):
+    def plot(
+        self, left, right, labels: Iterable[str] = (), vertical: bool = True
+    ) -> Figure:
         """
         Plot left / right DataFrames in specified layout.
 


Test patch:
diff --git a/pandas/_libs/testing.pyi b/pandas/_libs/testing.pyi
index 01da496975..ab87e58eba 100644
--- a/pandas/_libs/testing.pyi
+++ b/pandas/_libs/testing.pyi
@@ -1,4 +1,6 @@
-def assert_dict_equal(a, b, compare_keys: bool = ...): ...
+from typing import Mapping
+
+def assert_dict_equal(a: Mapping, b: Mapping, compare_keys: bool = ...) -> bool: ...
 def assert_almost_equal(
     a,
     b,
@@ -9,4 +11,4 @@ def assert_almost_equal(
     lobj=...,
     robj=...,
     index_values=...,
-): ...
+) -> bool: ...
diff --git a/pandas/_testing/__init__.py b/pandas/_testing/__init__.py
index 3f5fd2e61b..274de33738 100644
--- a/pandas/_testing/__init__.py
+++ b/pandas/_testing/__init__.py
@@ -482,7 +482,7 @@ def iat(x):
 _UNITS = ["s", "ms", "us", "ns"]
 
 
-def get_finest_unit(left: str, right: str):
+def get_finest_unit(left: str, right: str) -> str:
     """
     Find the higher of two datetime64 units.
     """
diff --git a/pandas/tests/arrays/string_/test_string.py b/pandas/tests/arrays/string_/test_string.py
index f67268616a..cb324d2925 100644
--- a/pandas/tests/arrays/string_/test_string.py
+++ b/pandas/tests/arrays/string_/test_string.py
@@ -584,6 +584,19 @@ def test_value_counts_with_normalize(dtype):
     tm.assert_series_equal(result, expected)
 
 
+def test_value_counts_sort_false(dtype):
+    if getattr(dtype, "storage", "") == "pyarrow":
+        exp_dtype = "int64[pyarrow]"
+    elif getattr(dtype, "storage", "") == "pyarrow_numpy":
+        exp_dtype = "int64"
+    else:
+        exp_dtype = "Int64"
+    ser = pd.Series(["a", "b", "c", "b"], dtype=dtype)
+    result = ser.value_counts(sort=False)
+    expected = pd.Series([1, 2, 1], index=ser[:3], dtype=exp_dtype, name="count")
+    tm.assert_series_equal(result, expected)
+
+
 @pytest.mark.parametrize(
     "values, expected",
     [
diff --git a/pandas/tests/interchange/test_impl.py b/pandas/tests/interchange/test_impl.py
index 96a239b89d..aeee98f5a1 100644
--- a/pandas/tests/interchange/test_impl.py
+++ b/pandas/tests/interchange/test_impl.py
@@ -293,6 +293,30 @@ def test_multi_chunk_pyarrow() -> None:
         pd.api.interchange.from_dataframe(table, allow_copy=False)
 
 
+def test_timestamp_ns_pyarrow():
+    # GH 56712
+    pytest.importorskip("pyarrow", "11.0.0")
+    timestamp_args = {
+        "year": 2000,
+        "month": 1,
+        "day": 1,
+        "hour": 1,
+        "minute": 1,
+        "second": 1,
+    }
+    df = pd.Series(
+        [datetime(**timestamp_args)],
+        dtype="timestamp[ns][pyarrow]",
+        name="col0",
+    ).to_frame()
+
+    dfi = df.__dataframe__()
+    result = pd.api.interchange.from_dataframe(dfi)["col0"].item()
+
+    expected = pd.Timestamp(**timestamp_args)
+    assert result == expected
+
+
 @pytest.mark.parametrize("tz", ["UTC", "US/Pacific"])
 def test_datetimetzdtype(tz, unit):
     # GH 54239
diff --git a/pandas/tests/reshape/test_melt.py b/pandas/tests/reshape/test_melt.py
index eeba7f441d..f224a45ca3 100644
--- a/pandas/tests/reshape/test_melt.py
+++ b/pandas/tests/reshape/test_melt.py
@@ -1217,3 +1217,33 @@ class TestWideToLong:
         new_level = expected.index.levels[0].astype(dtype)
         expected.index = expected.index.set_levels(new_level, level=0)
         tm.assert_frame_equal(result, expected)
+
+
+def test_wide_to_long_pyarrow_string_columns():
+    # GH 57066
+    pytest.importorskip("pyarrow")
+    df = DataFrame(
+        {
+            "ID": {0: 1},
+            "R_test1": {0: 1},
+            "R_test2": {0: 1},
+            "R_test3": {0: 2},
+            "D": {0: 1},
+        }
+    )
+    df.columns = df.columns.astype("string[pyarrow_numpy]")
+    result = wide_to_long(
+        df, stubnames="R", i="ID", j="UNPIVOTED", sep="_", suffix=".*"
+    )
+    expected = DataFrame(
+        [[1, 1], [1, 1], [1, 2]],
+        columns=Index(["D", "R"], dtype=object),
+        index=pd.MultiIndex.from_arrays(
+            [
+                [1, 1, 1],
+                Index(["test1", "test2", "test3"], dtype="string[pyarrow_numpy]"),
+            ],
+            names=["ID", "UNPIVOTED"],
+        ),
+    )
+    tm.assert_frame_equal(result, expected)
diff --git a/pandas/tests/series/test_ufunc.py b/pandas/tests/series/test_ufunc.py
index 9d13ebf740..3ef3191743 100644
--- a/pandas/tests/series/test_ufunc.py
+++ b/pandas/tests/series/test_ufunc.py
@@ -427,6 +427,13 @@ def test_np_matmul():
     tm.assert_frame_equal(expected, result)
 
 
+@pytest.mark.parametrize("box", [pd.Index, pd.Series])
+def test_np_matmul_1D(box):
+    result = np.matmul(box([1, 2]), box([2, 3]))
+    assert result == 8
+    assert isinstance(result, np.int64)
+
+
 def test_array_ufuncs_for_many_arguments():
     # GH39853
     def add3(x, y, z):