Repository: pandas-dev/pandas
Pull request #57201 (2024-02-02 00:42:31)

CLN: pyproject.toml


Patch:
diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml
index 6d3b9048a2..f79b2c51b5 100644
--- a/.github/workflows/wheels.yml
+++ b/.github/workflows/wheels.yml
@@ -94,7 +94,9 @@ jobs:
         buildplat:
         - [ubuntu-22.04, manylinux_x86_64]
         - [ubuntu-22.04, musllinux_x86_64]
-        - [macos-12, macosx_*]
+        - [macos-12, macosx_x86_64]
+        # Note: M1 images on Github Actions start from macOS 14
+        - [macos-14, macosx_arm64]
         - [windows-2022, win_amd64]
         # TODO: support PyPy?
         python: [["cp39", "3.9"], ["cp310", "3.10"], ["cp311", "3.11"], ["cp312", "3.12"]]
@@ -128,7 +130,7 @@ jobs:
       # Python version used to build sdist doesn't matter
       # wheel will be built from sdist with the correct version
       - name: Unzip sdist (macOS)
-        if: ${{ matrix.buildplat[1] == 'macosx_*' }}
+        if: ${{ startsWith(matrix.buildplat[1], 'macosx') }}
         run: |
           tar -xzf ./dist/${{ env.sdist_name }} -C ./dist
 
@@ -139,18 +141,18 @@ jobs:
 
       - name: Build normal wheels
         if: ${{ (env.IS_SCHEDULE_DISPATCH != 'true' || env.IS_PUSH == 'true') }}
-        uses: pypa/cibuildwheel@v2.16.4
+        uses: pypa/cibuildwheel@v2.16.5
         with:
-         package-dir: ./dist/${{ matrix.buildplat[1] == 'macosx_*' && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
+         package-dir: ./dist/${{ startsWith(matrix.buildplat[1], 'macosx') && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
         env:
           CIBW_PRERELEASE_PYTHONS: True
           CIBW_BUILD: ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}
 
       - name: Build nightly wheels (with NumPy pre-release)
         if: ${{ (env.IS_SCHEDULE_DISPATCH == 'true' && env.IS_PUSH != 'true') }}
-        uses: pypa/cibuildwheel@v2.16.4
+        uses: pypa/cibuildwheel@v2.16.5
         with:
-         package-dir: ./dist/${{ matrix.buildplat[1] == 'macosx_*' && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
+         package-dir: ./dist/${{ startsWith(matrix.buildplat[1], 'macosx') && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
         env:
           # The nightly wheels should be build witht he NumPy 2.0 pre-releases
           # which requires the additional URL.
@@ -183,7 +185,7 @@ jobs:
           $TST_CMD = @"
           python -m pip install hypothesis>=6.46.1 pytest>=7.3.2 pytest-xdist>=2.2.0;
           python -m pip install `$(Get-Item pandas\wheelhouse\*.whl);
-          python -c `'import pandas as pd; pd.test(extra_args=[\"`\"--no-strict-data-files`\"\", \"`\"-m not clipboard and not single_cpu and not slow and not network and not db`\"\"])`';
+          python -c `'import pandas as pd; pd.test(extra_args=[`\"--no-strict-data-files`\", `\"-m not clipboard and not single_cpu and not slow and not network and not db`\"])`';
           "@
           # add rc to the end of the image name if the Python version is unreleased
           docker pull python:${{ matrix.python[1] == '3.12' && '3.12-rc' || format('{0}-windowsservercore', matrix.python[1]) }}
@@ -191,7 +193,7 @@ jobs:
 
       - uses: actions/upload-artifact@v4
         with:
-          name: ${{ matrix.python[0] }}-${{ startsWith(matrix.buildplat[1], 'macosx') && 'macosx' || matrix.buildplat[1] }}
+          name: ${{ matrix.python[0] }}-${{ matrix.buildplat[1] }}
           path: ./wheelhouse/*.whl
 
       - name: Upload wheels & sdist
diff --git a/ci/code_checks.sh b/ci/code_checks.sh
index 50baa1cb0b..a09c4662a1 100755
--- a/ci/code_checks.sh
+++ b/ci/code_checks.sh
@@ -169,8 +169,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
         pandas.Interval\
         pandas.Grouper\
         pandas.core.groupby.SeriesGroupBy.apply\
-        pandas.core.groupby.SeriesGroupBy.transform\
-        pandas.core.groupby.DataFrameGroupBy.transform\
         pandas.core.groupby.DataFrameGroupBy.nth\
         pandas.core.groupby.DataFrameGroupBy.rolling\
         pandas.core.groupby.SeriesGroupBy.nth\
@@ -178,9 +176,7 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
         pandas.core.groupby.DataFrameGroupBy.hist\
         pandas.core.groupby.DataFrameGroupBy.plot\
         pandas.core.groupby.DataFrameGroupBy.corrwith\
-        pandas.core.groupby.SeriesGroupBy.plot\
-        pandas.core.window.rolling.Rolling.quantile\
-        pandas.core.window.expanding.Expanding.quantile # There should be no backslash in the final line, please keep this comment in the last ignored function
+        pandas.core.groupby.SeriesGroupBy.plot # There should be no backslash in the final line, please keep this comment in the last ignored function
     RET=$(($RET + $?)) ; echo $MSG "DONE"
 
 fi
diff --git a/ci/deps/actions-310.yaml b/ci/deps/actions-310.yaml
index 45f1143220..a3e44e6373 100644
--- a/ci/deps/actions-310.yaml
+++ b/ci/deps/actions-310.yaml
@@ -14,7 +14,6 @@ dependencies:
   - pytest>=7.3.2
   - pytest-cov
   - pytest-xdist>=2.2.0
-  - pytest-localserver>=0.7.1
   - pytest-qt>=4.2.0
   - boto3
 
@@ -61,3 +60,4 @@ dependencies:
     - adbc-driver-postgresql>=0.8.0
     - adbc-driver-sqlite>=0.8.0
     - tzdata>=2022.7
+    - pytest-localserver>=0.7.1
diff --git a/ci/deps/actions-311.yaml b/ci/deps/actions-311.yaml
index d14686696e..95cd1a4d46 100644
--- a/ci/deps/actions-311.yaml
+++ b/ci/deps/actions-311.yaml
@@ -14,7 +14,6 @@ dependencies:
   - pytest>=7.3.2
   - pytest-cov
   - pytest-xdist>=2.2.0
-  - pytest-localserver>=0.7.1
   - pytest-qt>=4.2.0
   - boto3
 
@@ -60,4 +59,4 @@ dependencies:
   - pip:
     - adbc-driver-postgresql>=0.8.0
     - adbc-driver-sqlite>=0.8.0
-    - tzdata>=2022.7
+    - pytest-localserver>=0.7.1
diff --git a/ci/deps/actions-312.yaml b/ci/deps/actions-312.yaml
index 86aaf24b4e..a442ed6fee 100644
--- a/ci/deps/actions-312.yaml
+++ b/ci/deps/actions-312.yaml
@@ -14,7 +14,6 @@ dependencies:
   - pytest>=7.3.2
   - pytest-cov
   - pytest-xdist>=2.2.0
-  - pytest-localserver>=0.7.1
   - pytest-qt>=4.2.0
   - boto3
 
@@ -61,3 +60,4 @@ dependencies:
     - adbc-driver-postgresql>=0.8.0
     - adbc-driver-sqlite>=0.8.0
     - tzdata>=2022.7
+    - pytest-localserver>=0.7.1
diff --git a/ci/deps/actions-39.yaml b/ci/deps/actions-39.yaml
index 31ee74174c..b162a78e7f 100644
--- a/ci/deps/actions-39.yaml
+++ b/ci/deps/actions-39.yaml
@@ -14,7 +14,6 @@ dependencies:
   - pytest>=7.3.2
   - pytest-cov
   - pytest-xdist>=2.2.0
-  - pytest-localserver>=0.7.1
   - pytest-qt>=4.2.0
   - boto3
 
@@ -61,3 +60,4 @@ dependencies:
     - adbc-driver-postgresql>=0.8.0
     - adbc-driver-sqlite>=0.8.0
     - tzdata>=2022.7
+    - pytest-localserver>=0.7.1
diff --git a/doc/source/user_guide/indexing.rst b/doc/source/user_guide/indexing.rst
index 4954ee1538..7c8d3b9e1c 100644
--- a/doc/source/user_guide/indexing.rst
+++ b/doc/source/user_guide/indexing.rst
@@ -1730,7 +1730,7 @@ Returning a view versus a copy
 .. warning::
 
     :ref:`Copy-on-Write <copy_on_write>`
-    will become the new default in pandas 3.0. This means than chained indexing will
+    will become the new default in pandas 3.0. This means that chained indexing will
     never work. As a consequence, the ``SettingWithCopyWarning`` won't be necessary
     anymore.
     See :ref:`this section <copy_on_write_chained_assignment>`
@@ -1784,7 +1784,7 @@ Why does assignment fail when using chained indexing?
 .. warning::
 
     :ref:`Copy-on-Write <copy_on_write>`
-    will become the new default in pandas 3.0. This means than chained indexing will
+    will become the new default in pandas 3.0. This means that chained indexing will
     never work. As a consequence, the ``SettingWithCopyWarning`` won't be necessary
     anymore.
     See :ref:`this section <copy_on_write_chained_assignment>`
diff --git a/doc/source/whatsnew/v2.2.1.rst b/doc/source/whatsnew/v2.2.1.rst
index 56e645d4c5..13d5024b5a 100644
--- a/doc/source/whatsnew/v2.2.1.rst
+++ b/doc/source/whatsnew/v2.2.1.rst
@@ -32,6 +32,7 @@ Bug fixes
 ~~~~~~~~~
 - Fixed bug in :func:`pandas.api.interchange.from_dataframe` which was raising for Nullable integers (:issue:`55069`)
 - Fixed bug in :func:`pandas.api.interchange.from_dataframe` which was raising for empty inputs (:issue:`56700`)
+- Fixed bug in :func:`pandas.api.interchange.from_dataframe` which wasn't converting columns names to strings (:issue:`55069`)
 - Fixed bug in :meth:`DataFrame.__getitem__` for empty :class:`DataFrame` with Copy-on-Write enabled (:issue:`57130`)
 
 .. ---------------------------------------------------------------------------
diff --git a/pandas/_libs/tslibs/vectorized.pyi b/pandas/_libs/tslibs/vectorized.pyi
index de19f592da..f377c2e26a 100644
--- a/pandas/_libs/tslibs/vectorized.pyi
+++ b/pandas/_libs/tslibs/vectorized.pyi
@@ -1,7 +1,5 @@
-"""
-For cython types that cannot be represented precisely, closest-available
-python equivalents are used, and the precise types kept as adjacent comments.
-"""
+# For cython types that cannot be represented precisely, closest-available
+# python equivalents are used, and the precise types kept as adjacent comments.
 from datetime import tzinfo
 
 import numpy as np
diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py
index 5b51bc9deb..a6a5f142fa 100644
--- a/pandas/core/dtypes/dtypes.py
+++ b/pandas/core/dtypes/dtypes.py
@@ -62,8 +62,6 @@ from pandas.core.dtypes.inference import (
     is_list_like,
 )
 
-from pandas.util import capitalize_first_letter
-
 if not pa_version_under10p1:
     import pyarrow as pa
 
@@ -1087,7 +1085,7 @@ class PeriodDtype(PeriodDtypeBase, PandasExtensionDtype):
 
     def __eq__(self, other: object) -> bool:
         if isinstance(other, str):
-            return other in [self.name, capitalize_first_letter(self.name)]
+            return other[:1].lower() + other[1:] == self.name
 
         return super().__eq__(other)
 
diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py
index c4ae47348a..68626534f1 100644
--- a/pandas/core/groupby/groupby.py
+++ b/pandas/core/groupby/groupby.py
@@ -486,7 +486,7 @@ filled with the transformed values.
 
 Parameters
 ----------
-f : function, str
+func : function, str
     Function to apply to each group. See the Notes section below for requirements.
 
     Accepted inputs are:
diff --git a/pandas/core/indexers/objects.py b/pandas/core/indexers/objects.py
index f2db4886a5..5119089bac 100644
--- a/pandas/core/indexers/objects.py
+++ b/pandas/core/indexers/objects.py
@@ -399,7 +399,7 @@ class GroupbyIndexer(BaseIndexer):
         start_arrays = []
         end_arrays = []
         window_indices_start = 0
-        for key, indices in self.groupby_indices.items():
+        for indices in self.groupby_indices.values():
             index_array: np.ndarray | None
 
             if self.index_array is not None:
diff --git a/pandas/core/interchange/column.py b/pandas/core/interchange/column.py
index 350cab2c56..2e60b2a213 100644
--- a/pandas/core/interchange/column.py
+++ b/pandas/core/interchange/column.py
@@ -77,6 +77,14 @@ class PandasColumn(Column):
         Note: doesn't deal with extension arrays yet, just assume a regular
         Series/ndarray for now.
         """
+        if isinstance(column, pd.DataFrame):
+            raise TypeError(
+                "Expected a Series, got a DataFrame. This likely happened "
+                "because you called __dataframe__ on a DataFrame which, "
+                "after converting column names to string, resulted in duplicated "
+                f"names: {column.columns}. Please rename these columns before "
+                "using the interchange protocol."
+            )
         if not isinstance(column, pd.Series):
             raise NotImplementedError(f"Columns of type {type(column)} not handled yet")
 
diff --git a/pandas/core/interchange/dataframe.py b/pandas/core/interchange/dataframe.py
index 4f08b2c2b3..1ffe0e8e8d 100644
--- a/pandas/core/interchange/dataframe.py
+++ b/pandas/core/interchange/dataframe.py
@@ -32,7 +32,7 @@ class PandasDataFrameXchg(DataFrameXchg):
         Constructor - an instance of this (private) class is returned from
         `pd.DataFrame.__dataframe__`.
         """
-        self._df = df
+        self._df = df.rename(columns=str, copy=False)
         self._allow_copy = allow_copy
 
     def __dataframe__(
diff --git a/pandas/core/window/expanding.py b/pandas/core/window/expanding.py
index 1bf26c4823..c048c4a506 100644
--- a/pandas/core/window/expanding.py
+++ b/pandas/core/window/expanding.py
@@ -664,11 +664,11 @@ class Expanding(RollingAndExpandingMixin):
         create_section_header("Parameters"),
         dedent(
             """
-        quantile : float
+        q : float
             Quantile to compute. 0 <= quantile <= 1.
 
             .. deprecated:: 2.1.0
-                This will be renamed to 'q' in a future version.
+                This was renamed from 'quantile' to 'q' in version 2.1.0.
         interpolation : {{'linear', 'lower', 'higher', 'midpoint', 'nearest'}}
             This optional parameter specifies the interpolation method to use,
             when the desired quantile lies between two data points `i` and `j`:
diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py
index 72a61b2877..b55432085b 100644
--- a/pandas/core/window/rolling.py
+++ b/pandas/core/window/rolling.py
@@ -2502,11 +2502,11 @@ class Rolling(RollingAndExpandingMixin):
         create_section_header("Parameters"),
         dedent(
             """
-        quantile : float
+        q : float
             Quantile to compute. 0 <= quantile <= 1.
 
             .. deprecated:: 2.1.0
-                This will be renamed to 'q' in a future version.
+                This was renamed from 'quantile' to 'q' in version 2.1.0.
         interpolation : {{'linear', 'lower', 'higher', 'midpoint', 'nearest'}}
             This optional parameter specifies the interpolation method to use,
             when the desired quantile lies between two data points `i` and `j`:
diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py
index 26c13e95fa..80df46bf23 100644
--- a/pandas/io/formats/style_render.py
+++ b/pandas/io/formats/style_render.py
@@ -1996,7 +1996,7 @@ class Tooltips:
 
     def __init__(
         self,
-        css_props: CSSProperties = [
+        css_props: CSSProperties = [  # noqa: B006
             ("visibility", "hidden"),
             ("position", "absolute"),
             ("z-index", 1),
diff --git a/pandas/io/json/_normalize.py b/pandas/io/json/_normalize.py
index de4033d576..39fbce0b69 100644
--- a/pandas/io/json/_normalize.py
+++ b/pandas/io/json/_normalize.py
@@ -537,8 +537,8 @@ def json_normalize(
         if values.ndim > 1:
             # GH 37782
             values = np.empty((len(v),), dtype=object)
-            for i, v in enumerate(v):
-                values[i] = v
+            for i, val in enumerate(v):
+                values[i] = val
 
         result[k] = values.repeat(lengths)
     return result
diff --git a/pandas/util/__init__.py b/pandas/util/__init__.py
index 59ab324ba3..da109a5144 100644
--- a/pandas/util/__init__.py
+++ b/pandas/util/__init__.py
@@ -27,7 +27,3 @@ def __getattr__(key: str):
 
 def __dir__():
     return list(globals().keys()) + ["hash_array", "hash_pandas_object"]
-
-
-def capitalize_first_letter(s: str) -> str:
-    return s[:1].upper() + s[1:]
diff --git a/pyproject.toml b/pyproject.toml
index 96e8ea90af..934f66136f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -161,10 +161,6 @@ test-command = """
   pd.test(extra_args=["-m not clipboard and single_cpu and not slow and not network and not db", "--no-strict-data-files"]);' \
   """
 
-[tool.cibuildwheel.macos]
-archs = "x86_64 arm64"
-test-skip = "*_arm64"
-
 [tool.cibuildwheel.windows]
 before-build = "pip install delvewheel"
 repair-wheel-command = "delvewheel repair -w {dest_dir} {wheel}"
@@ -249,12 +245,6 @@ ignore = [
   "E402",
   # do not assign a lambda expression, use a def
   "E731",
-  # line break before binary operator
-  # "W503",  # not yet implemented
-  # line break after binary operator
-  # "W504",  # not yet implemented
-  # controversial
-  "B006",
   # controversial
   "B007",
   # controversial
@@ -263,18 +253,10 @@ ignore = [
   "B009",
   # getattr is used to side-step mypy
   "B010",
-  # tests use assert False
-  "B011",
   # tests use comparisons but not their returned value
   "B015",
-  # false positives
-  "B019",
-  # Loop control variable overrides iterable it iterates
-  "B020",
   # Function definition does not bind loop variable
   "B023",
-  # Functions defined inside a loop must not use variables redefined in the loop
-  # "B301",  # not yet implemented
   # Only works with python >=3.10
   "B905",
   # Too many arguments to function call
@@ -289,14 +271,10 @@ ignore = [
   "PLW2901",
   # Global statements are discouraged
   "PLW0603",
-  # Docstrings should not be included in stubs
-  "PYI021",
   # Use `typing.NamedTuple` instead of `collections.namedtuple`
   "PYI024",
   # No builtin `eval()` allowed
   "PGH001",
-  # compare-to-empty-string
-  "PLC1901",
   # while int | float can be shortened to float, the former is more explicit
   "PYI041",
   # incorrect-dict-iterator, flags valid Series.items usage
@@ -498,20 +476,10 @@ filterwarnings = [
   "ignore::ResourceWarning:asyncio",
   # From plotting doctests
   "ignore:More than 20 figures have been opened:RuntimeWarning",
-  # Will be fixed in numba 0.56: https://github.com/numba/numba/issues/7758
-  "ignore:`np.MachAr` is deprecated:DeprecationWarning:numba",
   "ignore:.*urllib3:DeprecationWarning:botocore",
   "ignore:Setuptools is replacing distutils.:UserWarning:_distutils_hack",
   # https://github.com/PyTables/PyTables/issues/822
   "ignore:a closed node found in the registry:UserWarning:tables",
-  "ignore:`np.object` is a deprecated:DeprecationWarning:tables",
-  "ignore:tostring:DeprecationWarning:tables",
-  "ignore:distutils Version classes are deprecated:DeprecationWarning:pandas_datareader",
-  "ignore:distutils Version classes are deprecated:DeprecationWarning:numexpr",
-  "ignore:distutils Version classes are deprecated:DeprecationWarning:fastparquet",
-  "ignore:distutils Version classes are deprecated:DeprecationWarning:fsspec",
-  # Can be removed once https://github.com/numpy/numpy/pull/24794 is merged
-  "ignore:.*In the future `np.long` will be defined as.*:FutureWarning",
 ]
 junit_family = "xunit2"
 markers = [


Test patch:
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
index 2b09aa9343..0fffedcb6a 100644
--- a/.github/workflows/unit-tests.yml
+++ b/.github/workflows/unit-tests.yml
@@ -202,7 +202,8 @@ jobs:
     timeout-minutes: 90
     strategy:
       matrix:
-        os: [macos-latest, windows-latest]
+        # Note: Don't use macOS latest since macos 14 appears to be arm64 only
+        os: [macos-13, macos-14, windows-latest]
         env_file: [actions-39.yaml, actions-310.yaml, actions-311.yaml, actions-312.yaml]
       fail-fast: false
     runs-on: ${{ matrix.os }}
@@ -215,8 +216,7 @@ jobs:
       PANDAS_CI: 1
       PYTEST_TARGET: pandas
       PATTERN: "not slow and not db and not network and not single_cpu"
-      # GH 47443: PYTEST_WORKERS > 0 crashes Windows builds with memory related errors
-      PYTEST_WORKERS: ${{ matrix.os == 'macos-latest' && 'auto' || '0' }}
+      PYTEST_WORKERS: 'auto'
 
     steps:
       - name: Checkout
@@ -342,7 +342,8 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        os: [ubuntu-22.04, macOS-latest, windows-latest]
+        # Separate out macOS 13 and 14, since macOS 14 is arm64 only
+        os: [ubuntu-22.04, macOS-13, macOS-14, windows-latest]
 
     timeout-minutes: 90
 
diff --git a/pandas/tests/arrays/masked/test_arithmetic.py b/pandas/tests/arrays/masked/test_arithmetic.py
index f4b571ca62..ea018d2da4 100644
--- a/pandas/tests/arrays/masked/test_arithmetic.py
+++ b/pandas/tests/arrays/masked/test_arithmetic.py
@@ -55,15 +55,15 @@ def test_array_scalar_like_equivalence(data, all_arithmetic_operators):
     scalar_array = pd.array([scalar] * len(data), dtype=data.dtype)
 
     # TODO also add len-1 array (np.array([scalar], dtype=data.dtype.numpy_dtype))
-    for scalar in [scalar, data.dtype.type(scalar)]:
+    for val in [scalar, data.dtype.type(scalar)]:
         if is_bool_not_implemented(data, all_arithmetic_operators):
             msg = "operator '.*' not implemented for bool dtypes"
             with pytest.raises(NotImplementedError, match=msg):
-                op(data, scalar)
+                op(data, val)
             with pytest.raises(NotImplementedError, match=msg):
                 op(data, scalar_array)
         else:
-            result = op(data, scalar)
+            result = op(data, val)
             expected = op(data, scalar_array)
             tm.assert_extension_array_equal(result, expected)
 
@@ -214,13 +214,13 @@ def test_error_len_mismatch(data, all_arithmetic_operators):
         msg = "operator '.*' not implemented for bool dtypes"
         err = NotImplementedError
 
-    for other in [other, np.array(other)]:
+    for val in [other, np.array(other)]:
         with pytest.raises(err, match=msg):
-            op(data, other)
+            op(data, val)
 
         s = pd.Series(data)
         with pytest.raises(err, match=msg):
-            op(s, other)
+            op(s, val)
 
 
 @pytest.mark.parametrize("op", ["__neg__", "__abs__", "__invert__"])
diff --git a/pandas/tests/config/test_localization.py b/pandas/tests/config/test_localization.py
index 3907f557d1..844f67cd2d 100644
--- a/pandas/tests/config/test_localization.py
+++ b/pandas/tests/config/test_localization.py
@@ -15,7 +15,6 @@ from pandas.compat import ISMUSL
 import pandas as pd
 
 _all_locales = get_locales()
-_current_locale = locale.setlocale(locale.LC_ALL)  # getlocale() is wrong, see GH#46595
 
 # Don't run any of these tests if we have no locales.
 pytestmark = pytest.mark.skipif(not _all_locales, reason="Need locales")
diff --git a/pandas/tests/copy_view/index/test_index.py b/pandas/tests/copy_view/index/test_index.py
index 49d756cf32..596379a326 100644
--- a/pandas/tests/copy_view/index/test_index.py
+++ b/pandas/tests/copy_view/index/test_index.py
@@ -10,7 +10,7 @@ import pandas._testing as tm
 from pandas.tests.copy_view.util import get_array
 
 
-def index_view(index_data=[1, 2]):
+def index_view(index_data):
     df = DataFrame({"a": index_data, "b": 1.5})
     view = df[:]
     df = df.set_index("a", drop=True)
@@ -142,7 +142,7 @@ def test_index_from_index(using_copy_on_write, warn_copy_on_write):
     ],
 )
 def test_index_ops(using_copy_on_write, func, request):
-    idx, view_ = index_view()
+    idx, view_ = index_view([1, 2])
     expected = idx.copy(deep=True)
     if "astype" in request.node.callspec.id:
         expected = expected.astype("Int64")
diff --git a/pandas/tests/frame/indexing/test_xs.py b/pandas/tests/frame/indexing/test_xs.py
index 535137edd1..80b4635b94 100644
--- a/pandas/tests/frame/indexing/test_xs.py
+++ b/pandas/tests/frame/indexing/test_xs.py
@@ -36,10 +36,7 @@ def four_level_index_dataframe():
 
 
 class TestXS:
-    def test_xs(
-        self, float_frame, datetime_frame, using_copy_on_write, warn_copy_on_write
-    ):
-        float_frame_orig = float_frame.copy()
+    def test_xs(self, float_frame):
         idx = float_frame.index[5]
         xs = float_frame.xs(idx)
         for item, value in xs.items():
@@ -48,6 +45,7 @@ class TestXS:
             else:
                 assert value == float_frame[item][idx]
 
+    def test_xs_mixed(self):
         # mixed-type xs
         test_data = {"A": {"1": 1, "2": 2}, "B": {"1": "1", "2": "2", "3": "3"}}
         frame = DataFrame(test_data)
@@ -56,11 +54,14 @@ class TestXS:
         assert xs["A"] == 1
         assert xs["B"] == "1"
 
+    def test_xs_dt_error(self, datetime_frame):
         with pytest.raises(
             KeyError, match=re.escape("Timestamp('1999-12-31 00:00:00')")
         ):
             datetime_frame.xs(datetime_frame.index[0] - BDay())
 
+    def test_xs_other(self, float_frame, using_copy_on_write, warn_copy_on_write):
+        float_frame_orig = float_frame.copy()
         # xs get column
         series = float_frame.xs("A", axis=1)
         expected = float_frame["A"]
diff --git a/pandas/tests/frame/test_query_eval.py b/pandas/tests/frame/test_query_eval.py
index 0a869d8f94..0e29db3ca8 100644
--- a/pandas/tests/frame/test_query_eval.py
+++ b/pandas/tests/frame/test_query_eval.py
@@ -949,8 +949,8 @@ class TestDataFrameQueryStrings:
             ops = 2 * ([eq] + [ne])
             msg = r"'(Not)?In' nodes are not implemented"
 
-            for lhs, op, rhs in zip(lhs, ops, rhs):
-                ex = f"{lhs} {op} {rhs}"
+            for lh, op_, rh in zip(lhs, ops, rhs):
+                ex = f"{lh} {op_} {rh}"
                 with pytest.raises(NotImplementedError, match=msg):
                     df.query(
                         ex,
@@ -990,8 +990,8 @@ class TestDataFrameQueryStrings:
             ops = 2 * ([eq] + [ne])
             msg = r"'(Not)?In' nodes are not implemented"
 
-            for lhs, op, rhs in zip(lhs, ops, rhs):
-                ex = f"{lhs} {op} {rhs}"
+            for lh, ops_, rh in zip(lhs, ops, rhs):
+                ex = f"{lh} {ops_} {rh}"
                 with pytest.raises(NotImplementedError, match=msg):
                     df.query(ex, engine=engine, parser=parser)
         else:
diff --git a/pandas/tests/indexes/datetimes/test_constructors.py b/pandas/tests/indexes/datetimes/test_constructors.py
index 7fdf17c797..97e768b348 100644
--- a/pandas/tests/indexes/datetimes/test_constructors.py
+++ b/pandas/tests/indexes/datetimes/test_constructors.py
@@ -1042,7 +1042,7 @@ class TestDatetimeIndex:
 
         # result may not exactly match [now, today] so we'll test it up to a tolerance.
         #  (it *may* match exactly due to rounding)
-        tolerance = pd.Timedelta(microseconds=1)
+        tolerance = pd.Timedelta(seconds=1)
 
         diff0 = result[0] - now.as_unit("s")
         assert diff0 >= pd.Timedelta(0), f"The difference is {diff0}"
diff --git a/pandas/tests/interchange/test_impl.py b/pandas/tests/interchange/test_impl.py
index c8f286f22a..4933cca974 100644
--- a/pandas/tests/interchange/test_impl.py
+++ b/pandas/tests/interchange/test_impl.py
@@ -162,8 +162,6 @@ def test_missing_from_masked():
         }
     )
 
-    df2 = df.__dataframe__()
-
     rng = np.random.default_rng(2)
     dict_null = {col: rng.integers(low=0, high=len(df)) for col in df.columns}
     for col, num_nulls in dict_null.items():
@@ -395,6 +393,30 @@ def test_large_string():
     tm.assert_frame_equal(result, expected)
 
 
+def test_non_str_names():
+    # https://github.com/pandas-dev/pandas/issues/56701
+    df = pd.Series([1, 2, 3], name=0).to_frame()
+    names = df.__dataframe__().column_names()
+    assert names == ["0"]
+
+
+def test_non_str_names_w_duplicates():
+    # https://github.com/pandas-dev/pandas/issues/56701
+    df = pd.DataFrame({"0": [1, 2, 3], 0: [4, 5, 6]})
+    dfi = df.__dataframe__()
+    with pytest.raises(
+        TypeError,
+        match=(
+            "Expected a Series, got a DataFrame. This likely happened because you "
+            "called __dataframe__ on a DataFrame which, after converting column "
+            r"names to string, resulted in duplicated names: Index\(\['0', '0'\], "
+            r"dtype='object'\). Please rename these columns before using the "
+            "interchange protocol."
+        ),
+    ):
+        pd.api.interchange.from_dataframe(dfi, allow_copy=False)
+
+
 @pytest.mark.parametrize(
     "dtype", ["Int8", pytest.param("Int8[pyarrow]", marks=td.skip_if_no("pyarrow"))]
 )
diff --git a/pandas/tests/io/test_feather.py b/pandas/tests/io/test_feather.py
index f012fcadc5..c8b5b690ae 100644
--- a/pandas/tests/io/test_feather.py
+++ b/pandas/tests/io/test_feather.py
@@ -36,7 +36,9 @@ class TestFeather:
             with tm.ensure_clean() as path:
                 to_feather(df, path)
 
-    def check_round_trip(self, df, expected=None, write_kwargs={}, **read_kwargs):
+    def check_round_trip(self, df, expected=None, write_kwargs=None, **read_kwargs):
+        if write_kwargs is None:
+            write_kwargs = {}
         if expected is None:
             expected = df.copy()
 
diff --git a/pandas/tests/plotting/common.py b/pandas/tests/plotting/common.py
index 6912016069..5a46cdcb05 100644
--- a/pandas/tests/plotting/common.py
+++ b/pandas/tests/plotting/common.py
@@ -433,7 +433,7 @@ def _check_box_return_type(
                 raise AssertionError
 
 
-def _check_grid_settings(obj, kinds, kws={}):
+def _check_grid_settings(obj, kinds, kws=None):
     # Make sure plot defaults to rcParams['axes.grid'] setting, GH 9792
 
     import matplotlib as mpl
@@ -446,6 +446,8 @@ def _check_grid_settings(obj, kinds, kws={}):
 
         return not (xoff and yoff)
 
+    if kws is None:
+        kws = {}
     spndx = 1
     for kind in kinds:
         mpl.pyplot.subplot(1, 4 * len(kinds), spndx)
diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py
index fbc3d2b8a7..f020fd45c8 100644
--- a/pandas/tests/reshape/test_pivot.py
+++ b/pandas/tests/reshape/test_pivot.py
@@ -890,10 +890,14 @@ class TestPivotTable:
         result,
         values_col,
         data,
-        index=["A", "B"],
-        columns=["C"],
+        index=None,
+        columns=None,
         margins_col="All",
     ):
+        if index is None:
+            index = ["A", "B"]
+        if columns is None:
+            columns = ["C"]
         col_margins = result.loc[result.index[:-1], margins_col]
         expected_col_margins = data.groupby(index)[values_col].mean()
         tm.assert_series_equal(col_margins, expected_col_margins, check_names=False)
diff --git a/pandas/tests/window/test_expanding.py b/pandas/tests/window/test_expanding.py
index 6d452b27f3..ad59f9e525 100644
--- a/pandas/tests/window/test_expanding.py
+++ b/pandas/tests/window/test_expanding.py
@@ -178,9 +178,9 @@ def test_expanding_count_with_min_periods_exceeding_series_length(frame_or_serie
 def test_iter_expanding_dataframe(df, expected, min_periods):
     # GH 11704
     df = DataFrame(df)
-    expected = [DataFrame(values, index=index) for (values, index) in expected]
+    expecteds = [DataFrame(values, index=index) for (values, index) in expected]
 
-    for expected, actual in zip(expected, df.expanding(min_periods)):
+    for expected, actual in zip(expecteds, df.expanding(min_periods)):
         tm.assert_frame_equal(actual, expected)
 
 
@@ -197,9 +197,9 @@ def test_iter_expanding_dataframe(df, expected, min_periods):
 )
 def test_iter_expanding_series(ser, expected, min_periods):
     # GH 11704
-    expected = [Series(values, index=index) for (values, index) in expected]
+    expecteds = [Series(values, index=index) for (values, index) in expected]
 
-    for expected, actual in zip(expected, ser.expanding(min_periods)):
+    for expected, actual in zip(expecteds, ser.expanding(min_periods)):
         tm.assert_series_equal(actual, expected)
 
 
diff --git a/pandas/tests/window/test_rolling.py b/pandas/tests/window/test_rolling.py
index fda6319872..85821ed2cf 100644
--- a/pandas/tests/window/test_rolling.py
+++ b/pandas/tests/window/test_rolling.py
@@ -760,9 +760,9 @@ def test_rolling_count_default_min_periods_with_null_values(frame_or_series):
 def test_iter_rolling_dataframe(df, expected, window, min_periods):
     # GH 11704
     df = DataFrame(df)
-    expected = [DataFrame(values, index=index) for (values, index) in expected]
+    expecteds = [DataFrame(values, index=index) for (values, index) in expected]
 
-    for expected, actual in zip(expected, df.rolling(window, min_periods=min_periods)):
+    for expected, actual in zip(expecteds, df.rolling(window, min_periods=min_periods)):
         tm.assert_frame_equal(actual, expected)
 
 
@@ -805,10 +805,10 @@ def test_iter_rolling_on_dataframe(expected, window):
         }
     )
 
-    expected = [
+    expecteds = [
         DataFrame(values, index=df.loc[index, "C"]) for (values, index) in expected
     ]
-    for expected, actual in zip(expected, df.rolling(window, on="C")):
+    for expected, actual in zip(expecteds, df.rolling(window, on="C")):
         tm.assert_frame_equal(actual, expected)
 
 
@@ -856,9 +856,11 @@ def test_iter_rolling_on_dataframe_unordered():
 )
 def test_iter_rolling_series(ser, expected, window, min_periods):
     # GH 11704
-    expected = [Series(values, index=index) for (values, index) in expected]
+    expecteds = [Series(values, index=index) for (values, index) in expected]
 
-    for expected, actual in zip(expected, ser.rolling(window, min_periods=min_periods)):
+    for expected, actual in zip(
+        expecteds, ser.rolling(window, min_periods=min_periods)
+    ):
         tm.assert_series_equal(actual, expected)
 
 
@@ -904,11 +906,11 @@ def test_iter_rolling_datetime(expected, expected_index, window):
     # GH 11704
     ser = Series(range(5), index=date_range(start="2020-01-01", periods=5, freq="D"))
 
-    expected = [
+    expecteds = [
         Series(values, index=idx) for (values, idx) in zip(expected, expected_index)
     ]
 
-    for expected, actual in zip(expected, ser.rolling(window)):
+    for expected, actual in zip(expecteds, ser.rolling(window)):
         tm.assert_series_equal(actual, expected)
 
 
diff --git a/scripts/tests/data/deps_minimum.toml b/scripts/tests/data/deps_minimum.toml
index 0424920e5f..ca1dc0c961 100644
--- a/scripts/tests/data/deps_minimum.toml
+++ b/scripts/tests/data/deps_minimum.toml
@@ -494,14 +494,11 @@ exclude_lines = [
   "pragma: no cover",
   # Don't complain about missing debug-only code:s
   "def __repr__",
-  "if self.debug",
   # Don't complain if tests don't hit defensive assertion code:
   "raise AssertionError",
   "raise NotImplementedError",
   "AbstractMethodError",
   # Don't complain if non-runnable code isn't run:
-  "if 0:",
-  "if __name__ == .__main__.:",
   "if TYPE_CHECKING:",
 ]