Repository: pandas-dev/pandas
Pull request #56568 (2023-12-19 19:25:53)

TYP: simple return types from ruff
Ruff has many "unsafe" autofixes for simple return types.

I hope to enable `--unsafe-fixes` (for only the type annotations) after a few PRs.



Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 42ff96603b..2a070e9a49 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -32,7 +32,7 @@ repos:
         # TODO: remove autofixe-only rules when they are checked by ruff
         name: ruff-selected-autofixes
         alias: ruff-selected-autofixes
-        args: [--select, "ANN001,ANN204", --fix-only, --exit-non-zero-on-fix]
+        args: [--select, "ANN001,ANN2", --fix-only, --exit-non-zero-on-fix]
 -   repo: https://github.com/jendrikseipp/vulture
     rev: 'v2.10'
     hooks:
diff --git a/doc/make.py b/doc/make.py
index c4b7ab124f..2583242786 100755
--- a/doc/make.py
+++ b/doc/make.py
@@ -102,7 +102,7 @@ class DocBuilder:
             )
 
     @staticmethod
-    def _run_os(*args):
+    def _run_os(*args) -> None:
         """
         Execute a command as a OS terminal.
 
@@ -149,7 +149,7 @@ class DocBuilder:
         ]
         return subprocess.call(cmd)
 
-    def _open_browser(self, single_doc_html):
+    def _open_browser(self, single_doc_html) -> None:
         """
         Open a browser tab showing single
         """
@@ -183,7 +183,7 @@ class DocBuilder:
 
         return title.astext()
 
-    def _add_redirects(self):
+    def _add_redirects(self) -> None:
         """
         Create in the build directory an html file with a redirect,
         for every row in REDIRECTS_FILE.
@@ -272,14 +272,14 @@ class DocBuilder:
         return self.latex(force=True)
 
     @staticmethod
-    def clean():
+    def clean() -> None:
         """
         Clean documentation generated files.
         """
         shutil.rmtree(BUILD_PATH, ignore_errors=True)
         shutil.rmtree(os.path.join(SOURCE_PATH, "reference", "api"), ignore_errors=True)
 
-    def zip_html(self):
+    def zip_html(self) -> None:
         """
         Compress HTML documentation into a zip file.
         """
diff --git a/doc/scripts/eval_performance.py b/doc/scripts/eval_performance.py
index 559689ef59..dded8362a4 100644
--- a/doc/scripts/eval_performance.py
+++ b/doc/scripts/eval_performance.py
@@ -64,7 +64,7 @@ def bench(mn=3, mx=7, num=100, engines=("python", "numexpr"), verbose=False):
     return ev, qu
 
 
-def plot_perf(df, engines, title, filename=None):
+def plot_perf(df, engines, title, filename=None) -> None:
     from matplotlib.pyplot import figure
 
     sns.set()
diff --git a/doc/source/conf.py b/doc/source/conf.py
index dbc764c88a..e7ce8511b7 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -502,7 +502,7 @@ class AccessorDocumenter(MethodDocumenter):
     # lower than MethodDocumenter so this is not chosen for normal methods
     priority = 0.6
 
-    def format_signature(self):
+    def format_signature(self) -> str:
         # this method gives an error/warning for the accessors, therefore
         # overriding it (accessor has no arguments)
         return ""
@@ -632,7 +632,7 @@ class PandasAutosummary(Autosummary):
 
 
 # based on numpy doc/source/conf.py
-def linkcode_resolve(domain, info):
+def linkcode_resolve(domain, info) -> str | None:
     """
     Determine the URL corresponding to Python object
     """
@@ -694,12 +694,12 @@ def linkcode_resolve(domain, info):
 
 # remove the docstring of the flags attribute (inherited from numpy ndarray)
 # because these give doc build errors (see GH issue 5331)
-def remove_flags_docstring(app, what, name, obj, options, lines):
+def remove_flags_docstring(app, what, name, obj, options, lines) -> None:
     if what == "attribute" and name.endswith(".flags"):
         del lines[:]
 
 
-def process_class_docstrings(app, what, name, obj, options, lines):
+def process_class_docstrings(app, what, name, obj, options, lines) -> None:
     """
     For those classes for which we use ::
 
@@ -751,7 +751,7 @@ _BUSINED_ALIASES = [
 ]
 
 
-def process_business_alias_docstrings(app, what, name, obj, options, lines):
+def process_business_alias_docstrings(app, what, name, obj, options, lines) -> None:
     """
     Starting with sphinx 3.4, the "autodoc-process-docstring" event also
     gets called for alias classes. This results in numpydoc adding the
@@ -774,7 +774,7 @@ if pattern:
     suppress_warnings.append("ref.ref")
 
 
-def rstjinja(app, docname, source):
+def rstjinja(app, docname, source) -> None:
     """
     Render our pages as a jinja template for fancy templating goodness.
     """
@@ -787,7 +787,7 @@ def rstjinja(app, docname, source):
     source[0] = rendered
 
 
-def setup(app):
+def setup(app) -> None:
     app.connect("source-read", rstjinja)
     app.connect("autodoc-process-docstring", remove_flags_docstring)
     app.connect("autodoc-process-docstring", process_class_docstrings)
diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst
index 081f822069..43bd143712 100644
--- a/doc/source/whatsnew/v2.2.0.rst
+++ b/doc/source/whatsnew/v2.2.0.rst
@@ -480,6 +480,7 @@ Other Deprecations
 - Deprecated strings ``H``, ``S``, ``U``, and ``N`` denoting units in :func:`to_timedelta` (:issue:`52536`)
 - Deprecated strings ``H``, ``T``, ``S``, ``L``, ``U``, and ``N`` denoting units in :class:`Timedelta` (:issue:`52536`)
 - Deprecated strings ``T``, ``S``, ``L``, ``U``, and ``N`` denoting frequencies in :class:`Minute`, :class:`Second`, :class:`Milli`, :class:`Micro`, :class:`Nano` (:issue:`52536`)
+- Deprecated the ``verbose`` keyword in :func:`read_csv` and :func:`read_table` (:issue:`55569`)
 - Deprecated the :attr:`.DataFrameGroupBy.grouper` and :attr:`SeriesGroupBy.grouper`; these attributes will be removed in a future version of pandas (:issue:`56521`)
 - Deprecated the :class:`.Grouping` attributes ``group_index``, ``result_index``, and ``group_arraylike``; these will be removed in a future version of pandas (:issue:`56148`)
 - Deprecated the ``errors="ignore"`` option in :func:`to_datetime`, :func:`to_timedelta`, and :func:`to_numeric`; explicitly catch exceptions instead (:issue:`54467`)
diff --git a/generate_pxi.py b/generate_pxi.py
index 47648a3937..e7e85900aa 100644
--- a/generate_pxi.py
+++ b/generate_pxi.py
@@ -4,7 +4,7 @@ import os
 from Cython import Tempita
 
 
-def process_tempita(pxifile, outfile):
+def process_tempita(pxifile, outfile) -> None:
     with open(pxifile, encoding="utf-8") as f:
         tmpl = f.read()
     pyxcontent = Tempita.sub(tmpl)
@@ -13,7 +13,7 @@ def process_tempita(pxifile, outfile):
         f.write(pyxcontent)
 
 
-def main():
+def main() -> None:
     parser = argparse.ArgumentParser()
     parser.add_argument("infile", type=str, help="Path to the input file")
     parser.add_argument("-o", "--outdir", type=str, help="Path to the output directory")
diff --git a/generate_version.py b/generate_version.py
index 06e38ce0fd..7dc1bdcf32 100644
--- a/generate_version.py
+++ b/generate_version.py
@@ -10,7 +10,7 @@ import versioneer
 sys.path.insert(0, "")
 
 
-def write_version_info(path):
+def write_version_info(path) -> None:
     version = None
     git_version = None
 
@@ -29,7 +29,7 @@ def write_version_info(path):
         file.write(f'__git_version__="{git_version}"\n')
 
 
-def main():
+def main() -> None:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         "-o",
diff --git a/pandas/io/parsers/readers.py b/pandas/io/parsers/readers.py
index 7326ad831e..61e8862d85 100644
--- a/pandas/io/parsers/readers.py
+++ b/pandas/io/parsers/readers.py
@@ -645,7 +645,7 @@ def read_csv(
     | Mapping[Hashable, Iterable[Hashable]]
     | None = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] | None = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -705,7 +705,7 @@ def read_csv(
     | None = ...,
     keep_default_na: bool = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] | None = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -765,7 +765,7 @@ def read_csv(
     | None = ...,
     keep_default_na: bool = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] | None = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -825,7 +825,7 @@ def read_csv(
     | None = ...,
     keep_default_na: bool = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] | None = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -898,7 +898,7 @@ def read_csv(
     | None = None,
     keep_default_na: bool = True,
     na_filter: bool = True,
-    verbose: bool = False,
+    verbose: bool | lib.NoDefault = lib.no_default,
     skip_blank_lines: bool = True,
     # Datetime Handling
     parse_dates: bool | Sequence[Hashable] | None = None,
@@ -944,6 +944,18 @@ def read_csv(
             FutureWarning,
             stacklevel=find_stack_level(),
         )
+
+    if verbose is not lib.no_default:
+        # GH#55569
+        warnings.warn(
+            "The 'verbose' keyword in pd.read_csv is deprecated and "
+            "will be removed in a future version.",
+            FutureWarning,
+            stacklevel=find_stack_level(),
+        )
+    else:
+        verbose = False
+
     # locals() should never be modified
     kwds = locals().copy()
     del kwds["filepath_or_buffer"]
@@ -988,7 +1000,7 @@ def read_table(
     na_values: Sequence[str] | Mapping[str, Sequence[str]] | None = ...,
     keep_default_na: bool = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -1045,7 +1057,7 @@ def read_table(
     na_values: Sequence[str] | Mapping[str, Sequence[str]] | None = ...,
     keep_default_na: bool = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -1102,7 +1114,7 @@ def read_table(
     na_values: Sequence[str] | Mapping[str, Sequence[str]] | None = ...,
     keep_default_na: bool = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -1159,7 +1171,7 @@ def read_table(
     na_values: Sequence[str] | Mapping[str, Sequence[str]] | None = ...,
     keep_default_na: bool = ...,
     na_filter: bool = ...,
-    verbose: bool = ...,
+    verbose: bool | lib.NoDefault = ...,
     skip_blank_lines: bool = ...,
     parse_dates: bool | Sequence[Hashable] = ...,
     infer_datetime_format: bool | lib.NoDefault = ...,
@@ -1231,7 +1243,7 @@ def read_table(
     na_values: Sequence[str] | Mapping[str, Sequence[str]] | None = None,
     keep_default_na: bool = True,
     na_filter: bool = True,
-    verbose: bool = False,
+    verbose: bool | lib.NoDefault = lib.no_default,
     skip_blank_lines: bool = True,
     # Datetime Handling
     parse_dates: bool | Sequence[Hashable] = False,
@@ -1278,6 +1290,17 @@ def read_table(
             stacklevel=find_stack_level(),
         )
 
+    if verbose is not lib.no_default:
+        # GH#55569
+        warnings.warn(
+            "The 'verbose' keyword in pd.read_table is deprecated and "
+            "will be removed in a future version.",
+            FutureWarning,
+            stacklevel=find_stack_level(),
+        )
+    else:
+        verbose = False
+
     # locals() should never be modified
     kwds = locals().copy()
     del kwds["filepath_or_buffer"]
diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py
index 98b55f8d69..76d64d27b2 100755
--- a/scripts/validate_docstrings.py
+++ b/scripts/validate_docstrings.py
@@ -411,8 +411,8 @@ def print_validate_all_results(
     return exit_status
 
 
-def print_validate_one_results(func_name: str):
-    def header(title, width=80, char="#"):
+def print_validate_one_results(func_name: str) -> None:
+    def header(title, width=80, char="#") -> str:
         full_line = char * width
         side_len = (width - len(title) - 2) // 2
         adj = "" if len(title) % 2 == 0 else " "
diff --git a/scripts/validate_exception_location.py b/scripts/validate_exception_location.py
index fb0dc47252..ecba1eb424 100644
--- a/scripts/validate_exception_location.py
+++ b/scripts/validate_exception_location.py
@@ -71,7 +71,7 @@ class Visitor(ast.NodeVisitor):
 
 def validate_exception_and_warning_placement(
     file_path: str, file_content: str, errors: set[str]
-):
+) -> None:
     tree = ast.parse(file_content)
     visitor = Visitor(file_path, errors)
     visitor.visit(tree)
diff --git a/setup.py b/setup.py
index d6fb4b775a..c7c76d0f76 100755
--- a/setup.py
+++ b/setup.py
@@ -75,7 +75,7 @@ for module, files in _pxi_dep_template.items():
 
 class build_ext(_build_ext):
     @classmethod
-    def render_templates(cls, pxifiles):
+    def render_templates(cls, pxifiles) -> None:
         for pxifile in pxifiles:
             # build pxifiles first, template extension must be .pxi.in
             assert pxifile.endswith(".pxi.in")
@@ -95,7 +95,7 @@ class build_ext(_build_ext):
             with open(outfile, "w", encoding="utf-8") as f:
                 f.write(pyxcontent)
 
-    def build_extensions(self):
+    def build_extensions(self) -> None:
         # if building from c files, don't need to
         # generate template output
         if _CYTHON_INSTALLED:
@@ -109,7 +109,7 @@ class CleanCommand(Command):
 
     user_options = [("all", "a", "")]
 
-    def initialize_options(self):
+    def initialize_options(self) -> None:
         self.all = True
         self._clean_me = []
         self._clean_trees = []
@@ -161,10 +161,10 @@ class CleanCommand(Command):
 
         self._clean_trees.append(d for d in ("build", "dist") if os.path.exists(d))
 
-    def finalize_options(self):
+    def finalize_options(self) -> None:
         pass
 
-    def run(self):
+    def run(self) -> None:
         for clean_me in self._clean_me:
             try:
                 os.unlink(clean_me)
@@ -227,10 +227,10 @@ class CheckSDist(sdist_class):
         "pandas/_libs/window/aggregations.pyx",
     ]
 
-    def initialize_options(self):
+    def initialize_options(self) -> None:
         sdist_class.initialize_options(self)
 
-    def run(self):
+    def run(self) -> None:
         if "cython" in cmdclass:
             self.run_command("cython")
         else:
@@ -254,7 +254,7 @@ class CheckingBuildExt(build_ext):
     Subclass build_ext to get clearer report if Cython is necessary.
     """
 
-    def check_cython_extensions(self, extensions):
+    def check_cython_extensions(self, extensions) -> None:
         for ext in extensions:
             for src in ext.sources:
                 if not os.path.exists(src):
@@ -266,7 +266,7 @@ class CheckingBuildExt(build_ext):
                 """
                     )
 
-    def build_extensions(self):
+    def build_extensions(self) -> None:
         self.check_cython_extensions(self.extensions)
         build_ext.build_extensions(self)
 
@@ -278,7 +278,7 @@ class CythonCommand(build_ext):
     C-compile method build_extension() with a no-op.
     """
 
-    def build_extension(self, ext):
+    def build_extension(self, ext) -> None:
         pass
 
 
@@ -287,13 +287,13 @@ class DummyBuildSrc(Command):
 
     user_options = []
 
-    def initialize_options(self):
+    def initialize_options(self) -> None:
         self.py_modules_dict = {}
 
-    def finalize_options(self):
+    def finalize_options(self) -> None:
         pass
 
-    def run(self):
+    def run(self) -> None:
         pass
 
 


Test patch:
diff --git a/pandas/tests/io/parser/common/test_verbose.py b/pandas/tests/io/parser/common/test_verbose.py
index 14deba8b40..fede54643d 100644
--- a/pandas/tests/io/parser/common/test_verbose.py
+++ b/pandas/tests/io/parser/common/test_verbose.py
@@ -6,6 +6,10 @@ from io import StringIO
 
 import pytest
 
+import pandas._testing as tm
+
+depr_msg = "The 'verbose' keyword in pd.read_csv is deprecated"
+
 
 def test_verbose_read(all_parsers, capsys):
     parser = all_parsers
@@ -22,11 +26,17 @@ two,1,2,3"""
     if parser.engine == "pyarrow":
         msg = "The 'verbose' option is not supported with the 'pyarrow' engine"
         with pytest.raises(ValueError, match=msg):
-            parser.read_csv(StringIO(data), verbose=True)
+            with tm.assert_produces_warning(
+                FutureWarning, match=depr_msg, check_stacklevel=False
+            ):
+                parser.read_csv(StringIO(data), verbose=True)
         return
 
     # Engines are verbose in different ways.
-    parser.read_csv(StringIO(data), verbose=True)
+    with tm.assert_produces_warning(
+        FutureWarning, match=depr_msg, check_stacklevel=False
+    ):
+        parser.read_csv(StringIO(data), verbose=True)
     captured = capsys.readouterr()
 
     if parser.engine == "c":
@@ -51,10 +61,16 @@ eight,1,2,3"""
     if parser.engine == "pyarrow":
         msg = "The 'verbose' option is not supported with the 'pyarrow' engine"
         with pytest.raises(ValueError, match=msg):
-            parser.read_csv(StringIO(data), verbose=True, index_col=0)
+            with tm.assert_produces_warning(
+                FutureWarning, match=depr_msg, check_stacklevel=False
+            ):
+                parser.read_csv(StringIO(data), verbose=True, index_col=0)
         return
 
-    parser.read_csv(StringIO(data), verbose=True, index_col=0)
+    with tm.assert_produces_warning(
+        FutureWarning, match=depr_msg, check_stacklevel=False
+    ):
+        parser.read_csv(StringIO(data), verbose=True, index_col=0)
     captured = capsys.readouterr()
 
     # Engines are verbose in different ways.
diff --git a/pandas/tests/io/parser/test_unsupported.py b/pandas/tests/io/parser/test_unsupported.py
index b099ed53b7..7a9e5b14e5 100644
--- a/pandas/tests/io/parser/test_unsupported.py
+++ b/pandas/tests/io/parser/test_unsupported.py
@@ -152,8 +152,14 @@ x   q   30      3    -0.6662 -0.5243 -0.3580  0.89145  2.5838"""
                 kwargs[default] = True
             elif default == "on_bad_lines":
                 kwargs[default] = "warn"
+
+            depr_msg = "The 'verbose' keyword in pd.read_csv is deprecated"
+            warn = None
+            if "verbose" in kwargs:
+                warn = FutureWarning
             with pytest.raises(ValueError, match=msg):
-                read_csv(StringIO(data), engine="pyarrow", **kwargs)
+                with tm.assert_produces_warning(warn, match=depr_msg):
+                    read_csv(StringIO(data), engine="pyarrow", **kwargs)
 
     def test_on_bad_lines_callable_python_or_pyarrow(self, all_parsers):
         # GH 5686
diff --git a/scripts/tests/conftest.py b/scripts/tests/conftest.py
index a7976102ea..d43741f925 100644
--- a/scripts/tests/conftest.py
+++ b/scripts/tests/conftest.py
@@ -1,6 +1,6 @@
 # pyproject.toml defines addopts: --strict-data-files
 # strict-data-files is defined & used in pandas/conftest.py
-def pytest_addoption(parser):
+def pytest_addoption(parser) -> None:
     parser.addoption(
         "--strict-data-files",
         action="store_true",
diff --git a/scripts/tests/test_no_bool_in_generic.py b/scripts/tests/test_no_bool_in_generic.py
index a57612548d..20ac214ce8 100644
--- a/scripts/tests/test_no_bool_in_generic.py
+++ b/scripts/tests/test_no_bool_in_generic.py
@@ -4,7 +4,7 @@ BAD_FILE = "def foo(a: bool) -> bool:\n    return bool(0)\n"
 GOOD_FILE = "def foo(a: bool_t) -> bool_t:\n    return bool(0)\n"
 
 
-def test_bad_file_with_replace():
+def test_bad_file_with_replace() -> None:
     content = BAD_FILE
     mutated, result = check_for_bool_in_generic(content)
     expected = GOOD_FILE
@@ -12,7 +12,7 @@ def test_bad_file_with_replace():
     assert mutated
 
 
-def test_good_file_with_replace():
+def test_good_file_with_replace() -> None:
     content = GOOD_FILE
     mutated, result = check_for_bool_in_generic(content)
     expected = content
diff --git a/scripts/tests/test_sort_whatsnew_note.py b/scripts/tests/test_sort_whatsnew_note.py
index 95ba74bbe4..6b8ea3ef97 100644
--- a/scripts/tests/test_sort_whatsnew_note.py
+++ b/scripts/tests/test_sort_whatsnew_note.py
@@ -1,7 +1,7 @@
 from scripts.sort_whatsnew_note import sort_whatsnew_note
 
 
-def test_sort_whatsnew_note():
+def test_sort_whatsnew_note() -> None:
     content = (
         ".. _whatsnew_200:\n"
         "\n"
diff --git a/scripts/tests/test_use_io_common_urlopen.py b/scripts/tests/test_use_io_common_urlopen.py
index 4bba550a4c..c2c4a7fe9c 100644
--- a/scripts/tests/test_use_io_common_urlopen.py
+++ b/scripts/tests/test_use_io_common_urlopen.py
@@ -5,7 +5,7 @@ from scripts.use_io_common_urlopen import use_io_common_urlopen
 PATH = "t.py"
 
 
-def test_inconsistent_usage(capsys):
+def test_inconsistent_usage(capsys) -> None:
     content = "from urllib.request import urlopen"
     result_msg = (
         "t.py:1:0: Don't use urllib.request.urlopen, "
@@ -17,7 +17,7 @@ def test_inconsistent_usage(capsys):
     assert result_msg == expected_msg
 
 
-def test_consistent_usage():
+def test_consistent_usage() -> None:
     # should not raise
     content = "from pandas.io.common import urlopen"
     use_io_common_urlopen(content, PATH)
diff --git a/scripts/tests/test_use_pd_array_in_core.py b/scripts/tests/test_use_pd_array_in_core.py
index 8f13a6e735..f58c92722c 100644
--- a/scripts/tests/test_use_pd_array_in_core.py
+++ b/scripts/tests/test_use_pd_array_in_core.py
@@ -10,7 +10,7 @@ PATH = "t.py"
 
 
 @pytest.mark.parametrize("content", [BAD_FILE_0, BAD_FILE_1])
-def test_inconsistent_usage(content, capsys):
+def test_inconsistent_usage(content, capsys) -> None:
     result_msg = (
         "t.py:2:0: Don't use pd.array in core, import array as pd_array instead\n"
     )
@@ -21,6 +21,6 @@ def test_inconsistent_usage(content, capsys):
 
 
 @pytest.mark.parametrize("content", [GOOD_FILE_0, GOOD_FILE_1])
-def test_consistent_usage(content):
+def test_consistent_usage(content) -> None:
     # should not raise
     use_pd_array(content, PATH)
diff --git a/scripts/tests/test_validate_docstrings.py b/scripts/tests/test_validate_docstrings.py
index ffe1e9acd1..02c6808658 100644
--- a/scripts/tests/test_validate_docstrings.py
+++ b/scripts/tests/test_validate_docstrings.py
@@ -9,12 +9,12 @@ from scripts import validate_docstrings
 class BadDocstrings:
     """Everything here has a bad docstring"""
 
-    def private_classes(self):
+    def private_classes(self) -> None:
         """
         This mentions NDFrame, which is not correct.
         """
 
-    def prefix_pandas(self):
+    def prefix_pandas(self) -> None:
         """
         Have `pandas` prefix in See Also section.
 
@@ -24,7 +24,7 @@ class BadDocstrings:
         DataFrame.head : The first `n` rows of the caller object.
         """
 
-    def redundant_import(self, paramx=None, paramy=None):
+    def redundant_import(self, paramx=None, paramy=None) -> None:
         """
         A sample DataFrame method.
 
@@ -45,7 +45,7 @@ class BadDocstrings:
         Series([], dtype: bool)
         """
 
-    def unused_import(self):
+    def unused_import(self) -> None:
         """
         Examples
         --------
@@ -53,7 +53,7 @@ class BadDocstrings:
         >>> df = pd.DataFrame(np.ones((3, 3)), columns=('a', 'b', 'c'))
         """
 
-    def missing_whitespace_around_arithmetic_operator(self):
+    def missing_whitespace_around_arithmetic_operator(self) -> None:
         """
         Examples
         --------
@@ -61,7 +61,7 @@ class BadDocstrings:
         7
         """
 
-    def indentation_is_not_a_multiple_of_four(self):
+    def indentation_is_not_a_multiple_of_four(self) -> None:
         """
         Examples
         --------
@@ -69,19 +69,19 @@ class BadDocstrings:
         ...   pass
         """
 
-    def missing_whitespace_after_comma(self):
+    def missing_whitespace_after_comma(self) -> None:
         """
         Examples
         --------
         >>> df = pd.DataFrame(np.ones((3,3)),columns=('a','b', 'c'))
         """
 
-    def write_array_like_with_hyphen_not_underscore(self):
+    def write_array_like_with_hyphen_not_underscore(self) -> None:
         """
         In docstrings, use array-like over array_like
         """
 
-    def leftover_files(self):
+    def leftover_files(self) -> None:
         """
         Examples
         --------
@@ -117,7 +117,7 @@ class TestValidator:
 
         return base_path
 
-    def test_bad_class(self, capsys):
+    def test_bad_class(self, capsys) -> None:
         errors = validate_docstrings.pandas_validate(
             self._import_path(klass="BadDocstrings")
         )["errors"]
@@ -192,20 +192,20 @@ class TestValidator:
             ),
         ],
     )
-    def test_bad_docstrings(self, capsys, klass, func, msgs):
+    def test_bad_docstrings(self, capsys, klass, func, msgs) -> None:
         result = validate_docstrings.pandas_validate(
             self._import_path(klass=klass, func=func)
         )
         for msg in msgs:
             assert msg in " ".join([err[1] for err in result["errors"]])
 
-    def test_leftover_files_raises(self):
+    def test_leftover_files_raises(self) -> None:
         with pytest.raises(Exception, match="The following files"):
             validate_docstrings.pandas_validate(
                 self._import_path(klass="BadDocstrings", func="leftover_files")
             )
 
-    def test_validate_all_ignore_functions(self, monkeypatch):
+    def test_validate_all_ignore_functions(self, monkeypatch) -> None:
         monkeypatch.setattr(
             validate_docstrings,
             "get_all_api_items",
@@ -231,7 +231,7 @@ class TestValidator:
         assert len(result) == 1
         assert "pandas.Index.all" in result
 
-    def test_validate_all_ignore_deprecated(self, monkeypatch):
+    def test_validate_all_ignore_deprecated(self, monkeypatch) -> None:
         monkeypatch.setattr(
             validate_docstrings,
             "pandas_validate",
@@ -303,7 +303,7 @@ class TestApiItems:
             (4, "random.randint"),
         ],
     )
-    def test_item_name(self, idx, name):
+    def test_item_name(self, idx, name) -> None:
         result = list(validate_docstrings.get_api_items(self.api_doc))
         assert result[idx][0] == name
 
@@ -311,7 +311,7 @@ class TestApiItems:
         "idx,func",
         [(0, "cycle"), (1, "count"), (2, "chain"), (3, "seed"), (4, "randint")],
     )
-    def test_item_function(self, idx, func):
+    def test_item_function(self, idx, func) -> None:
         result = list(validate_docstrings.get_api_items(self.api_doc))
         assert callable(result[idx][1])
         assert result[idx][1].__name__ == func
@@ -326,7 +326,7 @@ class TestApiItems:
             (4, "Random"),
         ],
     )
-    def test_item_section(self, idx, section):
+    def test_item_section(self, idx, section) -> None:
         result = list(validate_docstrings.get_api_items(self.api_doc))
         assert result[idx][2] == section
 
@@ -334,7 +334,7 @@ class TestApiItems:
         "idx,subsection",
         [(0, "Infinite"), (1, "Infinite"), (2, "Finite"), (3, "All"), (4, "All")],
     )
-    def test_item_subsection(self, idx, subsection):
+    def test_item_subsection(self, idx, subsection) -> None:
         result = list(validate_docstrings.get_api_items(self.api_doc))
         assert result[idx][3] == subsection
 
@@ -343,7 +343,7 @@ class TestPandasDocstringClass:
     @pytest.mark.parametrize(
         "name", ["pandas.Series.str.isdecimal", "pandas.Series.str.islower"]
     )
-    def test_encode_content_write_to_file(self, name):
+    def test_encode_content_write_to_file(self, name) -> None:
         # GH25466
         docstr = validate_docstrings.PandasDocstring(name).validate_pep8()
         # the list of pep8 errors should be empty
@@ -351,7 +351,7 @@ class TestPandasDocstringClass:
 
 
 class TestMainFunction:
-    def test_exit_status_for_main(self, monkeypatch):
+    def test_exit_status_for_main(self, monkeypatch) -> None:
         monkeypatch.setattr(
             validate_docstrings,
             "pandas_validate",
@@ -375,7 +375,7 @@ class TestMainFunction:
         )
         assert exit_status == 0
 
-    def test_exit_status_errors_for_validate_all(self, monkeypatch):
+    def test_exit_status_errors_for_validate_all(self, monkeypatch) -> None:
         monkeypatch.setattr(
             validate_docstrings,
             "validate_all",
@@ -406,7 +406,7 @@ class TestMainFunction:
         )
         assert exit_status == 5
 
-    def test_no_exit_status_noerrors_for_validate_all(self, monkeypatch):
+    def test_no_exit_status_noerrors_for_validate_all(self, monkeypatch) -> None:
         monkeypatch.setattr(
             validate_docstrings,
             "validate_all",
@@ -425,7 +425,7 @@ class TestMainFunction:
         )
         assert exit_status == 0
 
-    def test_exit_status_for_validate_all_json(self, monkeypatch):
+    def test_exit_status_for_validate_all_json(self, monkeypatch) -> None:
         print("EXECUTED")
         monkeypatch.setattr(
             validate_docstrings,
@@ -451,7 +451,7 @@ class TestMainFunction:
         )
         assert exit_status == 0
 
-    def test_errors_param_filters_errors(self, monkeypatch):
+    def test_errors_param_filters_errors(self, monkeypatch) -> None:
         monkeypatch.setattr(
             validate_docstrings,
             "validate_all",
diff --git a/scripts/tests/test_validate_exception_location.py b/scripts/tests/test_validate_exception_location.py
index 9d493ee04d..18bd118549 100644
--- a/scripts/tests/test_validate_exception_location.py
+++ b/scripts/tests/test_validate_exception_location.py
@@ -34,7 +34,7 @@ def error_type(request):
 
 def test_class_that_inherits_an_exception_and_is_not_in_the_testing_rst_is_flagged(
     capsys, error_type
-):
+) -> None:
     content = TEST_CODE.format(
         custom_name=CUSTOM_EXCEPTION_NOT_IN_TESTING_RST, error_type=error_type
     )
@@ -47,13 +47,13 @@ def test_class_that_inherits_an_exception_and_is_not_in_the_testing_rst_is_flagg
 
 def test_class_that_inherits_an_exception_but_is_in_the_testing_rst_is_not_flagged(
     capsys, error_type
-):
+) -> None:
     content = TEST_CODE.format(
         custom_name=CUSTOM_EXCEPTION__IN_TESTING_RST, error_type=error_type
     )
     validate_exception_and_warning_placement(PATH, content, ERRORS_IN_TESTING_RST)
 
 
-def test_class_that_does_not_inherit_an_exception_is_not_flagged(capsys):
+def test_class_that_does_not_inherit_an_exception_is_not_flagged(capsys) -> None:
     content = "class MyClass(NonExceptionClass): pass"
     validate_exception_and_warning_placement(PATH, content, ERRORS_IN_TESTING_RST)
diff --git a/scripts/tests/test_validate_min_versions_in_sync.py b/scripts/tests/test_validate_min_versions_in_sync.py
index ac33f8dcbf..b6e339c138 100644
--- a/scripts/tests/test_validate_min_versions_in_sync.py
+++ b/scripts/tests/test_validate_min_versions_in_sync.py
@@ -46,7 +46,7 @@ from scripts.validate_min_versions_in_sync import (
         ),
     ],
 )
-def test_pin_min_versions_to_yaml_file(src_toml, src_yaml, expected_yaml):
+def test_pin_min_versions_to_yaml_file(src_toml, src_yaml, expected_yaml) -> None:
     with open(src_toml, "rb") as toml_f:
         toml_map = tomllib.load(toml_f)
     with open(src_yaml, encoding="utf-8") as yaml_f:
diff --git a/scripts/tests/test_validate_unwanted_patterns.py b/scripts/tests/test_validate_unwanted_patterns.py
index b4423197e2..bef9d369a0 100644
--- a/scripts/tests/test_validate_unwanted_patterns.py
+++ b/scripts/tests/test_validate_unwanted_patterns.py
@@ -38,7 +38,7 @@ class TestBarePytestRaises:
             ),
         ],
     )
-    def test_pytest_raises(self, data):
+    def test_pytest_raises(self, data) -> None:
         fd = io.StringIO(data.strip())
         result = list(validate_unwanted_patterns.bare_pytest_raises(fd))
         assert result == []
@@ -147,7 +147,7 @@ class TestBarePytestRaises:
             ),
         ],
     )
-    def test_pytest_raises_raises(self, data, expected):
+    def test_pytest_raises_raises(self, data, expected) -> None:
         fd = io.StringIO(data.strip())
         result = list(validate_unwanted_patterns.bare_pytest_raises(fd))
         assert result == expected
@@ -200,7 +200,7 @@ class TestStringsWithWrongPlacedWhitespace:
             ),
         ],
     )
-    def test_strings_with_wrong_placed_whitespace(self, data):
+    def test_strings_with_wrong_placed_whitespace(self, data) -> None:
         fd = io.StringIO(data.strip())
         result = list(
             validate_unwanted_patterns.strings_with_wrong_placed_whitespace(fd)
@@ -369,7 +369,7 @@ class TestStringsWithWrongPlacedWhitespace:
             ),
         ],
     )
-    def test_strings_with_wrong_placed_whitespace_raises(self, data, expected):
+    def test_strings_with_wrong_placed_whitespace_raises(self, data, expected) -> None:
         fd = io.StringIO(data.strip())
         result = list(
             validate_unwanted_patterns.strings_with_wrong_placed_whitespace(fd)
@@ -401,7 +401,7 @@ b: lib.NoDefault = lib.no_default
             ),
         ],
     )
-    def test_nodefault_used_not_only_for_typing(self, data):
+    def test_nodefault_used_not_only_for_typing(self, data) -> None:
         fd = io.StringIO(data.strip())
         result = list(validate_unwanted_patterns.nodefault_used_not_only_for_typing(fd))
         assert result == []
@@ -440,7 +440,7 @@ if a is NoDefault:
             ),
         ],
     )
-    def test_nodefault_used_not_only_for_typing_raises(self, data, expected):
+    def test_nodefault_used_not_only_for_typing_raises(self, data, expected) -> None:
         fd = io.StringIO(data.strip())
         result = list(validate_unwanted_patterns.nodefault_used_not_only_for_typing(fd))
         assert result == expected
diff --git a/web/tests/test_pandas_web.py b/web/tests/test_pandas_web.py
index 827c1d4dbe..a5f76875df 100644
--- a/web/tests/test_pandas_web.py
+++ b/web/tests/test_pandas_web.py
@@ -10,7 +10,7 @@ from web.pandas_web import Preprocessors
 
 
 class MockResponse:
-    def __init__(self, status_code: int, response: dict):
+    def __init__(self, status_code: int, response: dict) -> None:
         self.status_code = status_code
         self._resp = response
 
@@ -18,7 +18,7 @@ class MockResponse:
         return self._resp
 
     @staticmethod
-    def raise_for_status():
+    def raise_for_status() -> None:
         return
 
 
@@ -31,7 +31,7 @@ def context() -> dict:
 
 
 @pytest.fixture(scope="function")
-def mock_response(monkeypatch, request):
+def mock_response(monkeypatch, request) -> None:
     def mocked_resp(*args, **kwargs):
         status_code, response = request.param
         return MockResponse(status_code, response)
@@ -80,7 +80,7 @@ _releases_list = [
 
 
 @pytest.mark.parametrize("mock_response", [(200, _releases_list)], indirect=True)
-def test_web_preprocessor_creates_releases(mock_response, context):
+def test_web_preprocessor_creates_releases(mock_response, context) -> None:
     m = mock_open()
     with patch("builtins.open", m):
         context = Preprocessors.home_add_releases(context)