We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove incorrect(?) warning for `register_check_method()` in docs
#### Location of the documentation

https://pandera.readthedocs.io/en/latest/reference/generated/pandera.extensions.html

#### Documentation problem

It's documented for `register_check_method()` that

> **Warning**
> This is the legacy method for registering check methods. Use the `register_check()` decorator instead.

I can't see any reference to `register_check()` in the docs or the repo, so I assume this is an out-dated warning and `register_check_method()` is infact the defacto function for this kind of stuff. 

Might I be missing something? Maybe this warning is supposed to refer to another function.

#### Suggested fix for documentation

Remove warning as it's seemingly not warranted (at least in this moment).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pandera/api/extensions.py`
Content:
```
1 """Extensions module."""
2 
3 import inspect
4 import warnings
5 from enum import Enum
6 from functools import partial, wraps
7 from inspect import signature
8 from typing import Callable, List, Optional, Tuple, Type, Union
9 
10 import pandas as pd
11 import typing_inspect
12 
13 from pandera.api.checks import Check
14 from pandera.api.hypotheses import Hypothesis
15 from pandera.strategies.base_strategies import STRATEGY_DISPATCHER
16 
17 
18 class BuiltinCheckRegistrationError(Exception):
19     """
20     Exception raised when registering a built-in check implementation but the
21     default check function implementation hasn't been registered with
22     :py:meth:`~flytekit.core.base.BaseCheck.register_builtin_check_fn`.
23     """
24 
25 
26 # pylint: disable=too-many-locals
27 def register_builtin_check(
28     fn=None,
29     strategy: Optional[Callable] = None,
30     _check_cls: Type = Check,
31     **outer_kwargs,
32 ):
33     """Register a check method to the Check namespace.
34 
35     This is the primary way for extending the Check api to define additional
36     built-in checks.
37     """
38 
39     if fn is None:
40         return partial(
41             register_builtin_check,
42             strategy=strategy,
43             _check_cls=_check_cls,
44             **outer_kwargs,
45         )
46 
47     name = fn.__name__
48 
49     # see if the check function is already registered
50     check_fn = _check_cls.CHECK_FUNCTION_REGISTRY.get(name)
51     fn_sig = signature(fn)
52 
53     # register the check strategy for this particular check, identified
54     # by the check `name`, and the data type of the check function. This
55     # supports Union types. Also assume that the data type of the data
56     # object to validate is the first argument.
57     data_type = [*fn_sig.parameters.values()][0].annotation
58 
59     if typing_inspect.get_origin(data_type) is Tuple:
60         data_type, *_ = typing_inspect.get_args(data_type)
61 
62     if typing_inspect.get_origin(data_type) is Union:
63         data_types = typing_inspect.get_args(data_type)
64     else:
65         data_types = (data_type,)
66 
67     if strategy is not None:
68         for dt in data_types:
69             STRATEGY_DISPATCHER[(name, dt)] = strategy
70 
71     if check_fn is None:  # pragma: no cover
72         raise BuiltinCheckRegistrationError(
73             f"Check '{name}' doesn't have a base check implementation. "
74             f"You need to create a stub method in the {_check_cls} class and "
75             "then register a base check function implementation with the "
76             f"{_check_cls}.register_builtin_check_fn method.\n"
77             "See the `pandera.api.base.builtin_checks` and "
78             "`pandera.backends.pandas.builtin_checks` modules as an example."
79         )
80 
81     check_fn.register(fn)  # type: ignore
82 
83     return fn
84 
85 
86 def register_builtin_hypothesis(**kwargs):
87     """Register a new hypothesis."""
88     return partial(
89         register_builtin_check,
90         _check_cls=Hypothesis,
91         **kwargs,
92     )
93 
94 
95 # --------------------------------
96 # CUSTOM CHECK REGISTRATION METHOD
97 # --------------------------------
98 #
99 # The `register_check_method` decorator is the legacy method for registering
100 # custom checks and will slated for deprecation after merging the core
101 # internals overhaul.
102 
103 
104 class CheckType(Enum):
105     """Check types for registered check methods."""
106 
107     VECTORIZED = 1  #: Check applied to a Series or DataFrame
108     ELEMENT_WISE = 2  #: Check applied to an element of a Series or DataFrame
109     GROUPBY = 3  #: Check applied to dictionary of Series or DataFrames.
110 
111 
112 def register_check_statistics(statistics_args):
113     """Decorator to set statistics based on Check method."""
114 
115     def register_check_statistics_decorator(class_method):
116         @wraps(class_method)
117         def _wrapper(cls, *args, **kwargs):
118             args = list(args)
119             arg_names = inspect.getfullargspec(class_method).args[1:]
120             if not arg_names:
121                 arg_names = statistics_args
122             args_dict = {**dict(zip(arg_names, args)), **kwargs}
123             check = class_method(cls, *args, **kwargs)
124             check.statistics = {
125                 stat: args_dict.get(stat) for stat in statistics_args
126             }
127             check.statistics_args = statistics_args
128             return check
129 
130         return _wrapper
131 
132     return register_check_statistics_decorator
133 
134 
135 def register_check_method(
136     check_fn=None,
137     *,
138     statistics: Optional[List[str]] = None,
139     supported_types: Union[type, Tuple, List] = (pd.DataFrame, pd.Series),
140     check_type: Union[CheckType, str] = "vectorized",
141     strategy=None,
142 ):
143     """Registers a function as a :class:`~pandera.api.checks.Check` method.
144 
145     See the :ref:`user guide<extensions>` for more details.
146 
147     .. warning::
148 
149         This is the legacy method for registering check methods. Use the
150         :py:func:`~pandera.api.extensions.register_check` decorator instead.
151 
152     :param check_fn: check function to register. The function should take one
153         positional argument for the object to validate and additional
154         keyword-only arguments for the check statistics.
155     :param statistics: list of keyword-only arguments in the ``check_fn``,
156         which serve as the statistics needed to serialize/de-serialize the
157         check and generate data if a ``strategy`` function is provided.
158     :param supported_types: the pandas type(s) supported by the check function.
159         Valid values are ``pd.DataFrame``, ``pd.Series``, or a list/tuple of
160         ``(pa.DataFrame, pa.Series)`` if both types are supported.
161     :param check_type: the expected input of the check function. Valid values
162         are :class:`~pandera.extensions.CheckType` enums or
163         ``{"vectorized", "element_wise", "groupby"}``. The input signature of
164         ``check_fn`` is determined by this argument:
165 
166         - if ``vectorized``, the first positional argument of ``check_fn``
167           should be one of the ``supported_types``.
168         - if ``element_wise``, the first positional argument of ``check_fn``
169           should be a single scalar element in the pandas Series or DataFrame.
170         - if ``groupby``, the first positional argument of ``check_fn`` should
171           be a dictionary mapping group names to subsets of the Series or
172           DataFrame.
173 
174     :param strategy: data-generation strategy associated with the check
175         function.
176     :return: register check function wrapper.
177     """
178 
179     # pylint: disable=import-outside-toplevel
180     from pandera.strategies.pandas_strategies import register_check_strategy
181 
182     if statistics is None:
183         statistics = []
184 
185     if isinstance(check_type, str):
186         check_type = CheckType[check_type.upper()]
187 
188     msg = (
189         "{} is not a valid input type for check_fn. You must specify one of "
190         "pandas.DataFrame, pandas.Series, or a tuple of both."
191     )
192     if isinstance(supported_types, list):
193         supported_types = tuple(supported_types)
194     elif not isinstance(supported_types, tuple):
195         supported_types = (supported_types,)
196 
197     for supported_type in supported_types:  # type: ignore
198         if supported_type not in {pd.DataFrame, pd.Series}:
199             raise TypeError(msg.format(supported_type))
200 
201     if check_type is CheckType.ELEMENT_WISE and set(supported_types) != {
202         pd.DataFrame,
203         pd.Series,
204     }:  # type: ignore
205         raise ValueError(
206             "Element-wise checks should support DataFrame and Series "
207             "validation. Use the default setting for the 'supported_types' "
208             "argument."
209         )
210 
211     if check_fn is None:
212         return partial(
213             register_check_method,
214             statistics=statistics,
215             supported_types=supported_types,
216             check_type=check_type,
217             strategy=strategy,
218         )
219     else:
220         sig = signature(check_fn)
221         for statistic in statistics:
222             if statistic not in sig.parameters:
223                 raise TypeError(
224                     f"statistic '{statistic}' is not part of "
225                     f"{check_fn.__name__}'s signature."
226                 )
227 
228     def register_check_wrapper(check_fn: Callable):
229         """Register a function as a :class:`~pandera.api.checks.Check` method."""
230 
231         if hasattr(Check, check_fn.__name__):
232             raise ValueError(
233                 f"method with name '{check_fn.__name__}' already defined. "
234                 "Check methods must have a unique method name."
235             )
236 
237         @wraps(check_fn)
238         def check_fn_wrapper(validate_obj, **kwargs):
239             """Wrapper for check_fn to validate inputs."""
240             return check_fn(validate_obj, **kwargs)
241 
242         def validate_check_kwargs(check_kwargs):
243             msg = (
244                 f"'{check_fn.__name__} has check_type={check_type}. "
245                 "Providing the following arguments will have no effect: "
246                 "{}. Remove these arguments to avoid this warning."
247             )
248 
249             no_effect_args = {
250                 CheckType.ELEMENT_WISE: ["element_wise", "groupby", "groups"],
251                 CheckType.VECTORIZED: ["element_wise", "groupby", "groups"],
252                 CheckType.GROUPBY: ["element_wise"],
253             }[check_type]
254 
255             if any(arg in check_kwargs for arg in no_effect_args):
256                 warnings.warn(msg.format(no_effect_args))
257                 for arg in no_effect_args:
258                     check_kwargs.pop(arg, None)
259 
260             if check_type is CheckType.ELEMENT_WISE:
261                 check_kwargs["element_wise"] = True
262 
263             return check_kwargs
264 
265         @register_check_statistics(statistics)
266         def check_method(cls, *args, **kwargs):
267             """Wrapper function that serves as the Check method."""
268             stats, check_kwargs = {}, {}
269 
270             if args:
271                 stats = dict(zip(statistics, args))
272 
273             for k, v in kwargs.items():
274                 if k in statistics:
275                     stats[k] = v
276                 else:
277                     check_kwargs[k] = v
278 
279             return cls(
280                 partial(check_fn_wrapper, **stats),
281                 name=check_fn.__name__,
282                 **validate_check_kwargs(check_kwargs),
283             )
284 
285         if strategy is not None:
286             check_method = register_check_strategy(strategy)(check_method)
287 
288         Check.REGISTERED_CUSTOM_CHECKS[check_fn.__name__] = partial(
289             check_method, Check
290         )
291 
292     return register_check_wrapper(check_fn)
293
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pandera/api/extensions.py b/pandera/api/extensions.py
--- a/pandera/api/extensions.py
+++ b/pandera/api/extensions.py
@@ -144,11 +144,6 @@
 
     See the :ref:`user guide<extensions>` for more details.
 
-    .. warning::
-
-        This is the legacy method for registering check methods. Use the
-        :py:func:`~pandera.api.extensions.register_check` decorator instead.
-
     :param check_fn: check function to register. The function should take one
         positional argument for the object to validate and additional
         keyword-only arguments for the check statistics.

{"golden_diff": "diff --git a/pandera/api/extensions.py b/pandera/api/extensions.py\n--- a/pandera/api/extensions.py\n+++ b/pandera/api/extensions.py\n@@ -144,11 +144,6 @@\n \n     See the :ref:`user guide<extensions>` for more details.\n \n-    .. warning::\n-\n-        This is the legacy method for registering check methods. Use the\n-        :py:func:`~pandera.api.extensions.register_check` decorator instead.\n-\n     :param check_fn: check function to register. The function should take one\n         positional argument for the object to validate and additional\n         keyword-only arguments for the check statistics.\n", "issue": "Remove incorrect(?) warning for `register_check_method()` in docs\n#### Location of the documentation\r\n\r\nhttps://pandera.readthedocs.io/en/latest/reference/generated/pandera.extensions.html\r\n\r\n#### Documentation problem\r\n\r\nIt's documented for `register_check_method()` that\r\n\r\n> **Warning**\r\n> This is the legacy method for registering check methods. Use the `register_check()` decorator instead.\r\n\r\nI can't see any reference to `register_check()` in the docs or the repo, so I assume this is an out-dated warning and `register_check_method()` is infact the defacto function for this kind of stuff. \r\n\r\nMight I be missing something? Maybe this warning is supposed to refer to another function.\r\n\r\n#### Suggested fix for documentation\r\n\r\nRemove warning as it's seemingly not warranted (at least in this moment).\n", "before_files": [{"content": "\"\"\"Extensions module.\"\"\"\n\nimport inspect\nimport warnings\nfrom enum import Enum\nfrom functools import partial, wraps\nfrom inspect import signature\nfrom typing import Callable, List, Optional, Tuple, Type, Union\n\nimport pandas as pd\nimport typing_inspect\n\nfrom pandera.api.checks import Check\nfrom pandera.api.hypotheses import Hypothesis\nfrom pandera.strategies.base_strategies import STRATEGY_DISPATCHER\n\n\nclass BuiltinCheckRegistrationError(Exception):\n    \"\"\"\n    Exception raised when registering a built-in check implementation but the\n    default check function implementation hasn't been registered with\n    :py:meth:`~flytekit.core.base.BaseCheck.register_builtin_check_fn`.\n    \"\"\"\n\n\n# pylint: disable=too-many-locals\ndef register_builtin_check(\n    fn=None,\n    strategy: Optional[Callable] = None,\n    _check_cls: Type = Check,\n    **outer_kwargs,\n):\n    \"\"\"Register a check method to the Check namespace.\n\n    This is the primary way for extending the Check api to define additional\n    built-in checks.\n    \"\"\"\n\n    if fn is None:\n        return partial(\n            register_builtin_check,\n            strategy=strategy,\n            _check_cls=_check_cls,\n            **outer_kwargs,\n        )\n\n    name = fn.__name__\n\n    # see if the check function is already registered\n    check_fn = _check_cls.CHECK_FUNCTION_REGISTRY.get(name)\n    fn_sig = signature(fn)\n\n    # register the check strategy for this particular check, identified\n    # by the check `name`, and the data type of the check function. This\n    # supports Union types. Also assume that the data type of the data\n    # object to validate is the first argument.\n    data_type = [*fn_sig.parameters.values()][0].annotation\n\n    if typing_inspect.get_origin(data_type) is Tuple:\n        data_type, *_ = typing_inspect.get_args(data_type)\n\n    if typing_inspect.get_origin(data_type) is Union:\n        data_types = typing_inspect.get_args(data_type)\n    else:\n        data_types = (data_type,)\n\n    if strategy is not None:\n        for dt in data_types:\n            STRATEGY_DISPATCHER[(name, dt)] = strategy\n\n    if check_fn is None:  # pragma: no cover\n        raise BuiltinCheckRegistrationError(\n            f\"Check '{name}' doesn't have a base check implementation. \"\n            f\"You need to create a stub method in the {_check_cls} class and \"\n            \"then register a base check function implementation with the \"\n            f\"{_check_cls}.register_builtin_check_fn method.\\n\"\n            \"See the `pandera.api.base.builtin_checks` and \"\n            \"`pandera.backends.pandas.builtin_checks` modules as an example.\"\n        )\n\n    check_fn.register(fn)  # type: ignore\n\n    return fn\n\n\ndef register_builtin_hypothesis(**kwargs):\n    \"\"\"Register a new hypothesis.\"\"\"\n    return partial(\n        register_builtin_check,\n        _check_cls=Hypothesis,\n        **kwargs,\n    )\n\n\n# --------------------------------\n# CUSTOM CHECK REGISTRATION METHOD\n# --------------------------------\n#\n# The `register_check_method` decorator is the legacy method for registering\n# custom checks and will slated for deprecation after merging the core\n# internals overhaul.\n\n\nclass CheckType(Enum):\n    \"\"\"Check types for registered check methods.\"\"\"\n\n    VECTORIZED = 1  #: Check applied to a Series or DataFrame\n    ELEMENT_WISE = 2  #: Check applied to an element of a Series or DataFrame\n    GROUPBY = 3  #: Check applied to dictionary of Series or DataFrames.\n\n\ndef register_check_statistics(statistics_args):\n    \"\"\"Decorator to set statistics based on Check method.\"\"\"\n\n    def register_check_statistics_decorator(class_method):\n        @wraps(class_method)\n        def _wrapper(cls, *args, **kwargs):\n            args = list(args)\n            arg_names = inspect.getfullargspec(class_method).args[1:]\n            if not arg_names:\n                arg_names = statistics_args\n            args_dict = {**dict(zip(arg_names, args)), **kwargs}\n            check = class_method(cls, *args, **kwargs)\n            check.statistics = {\n                stat: args_dict.get(stat) for stat in statistics_args\n            }\n            check.statistics_args = statistics_args\n            return check\n\n        return _wrapper\n\n    return register_check_statistics_decorator\n\n\ndef register_check_method(\n    check_fn=None,\n    *,\n    statistics: Optional[List[str]] = None,\n    supported_types: Union[type, Tuple, List] = (pd.DataFrame, pd.Series),\n    check_type: Union[CheckType, str] = \"vectorized\",\n    strategy=None,\n):\n    \"\"\"Registers a function as a :class:`~pandera.api.checks.Check` method.\n\n    See the :ref:`user guide<extensions>` for more details.\n\n    .. warning::\n\n        This is the legacy method for registering check methods. Use the\n        :py:func:`~pandera.api.extensions.register_check` decorator instead.\n\n    :param check_fn: check function to register. The function should take one\n        positional argument for the object to validate and additional\n        keyword-only arguments for the check statistics.\n    :param statistics: list of keyword-only arguments in the ``check_fn``,\n        which serve as the statistics needed to serialize/de-serialize the\n        check and generate data if a ``strategy`` function is provided.\n    :param supported_types: the pandas type(s) supported by the check function.\n        Valid values are ``pd.DataFrame``, ``pd.Series``, or a list/tuple of\n        ``(pa.DataFrame, pa.Series)`` if both types are supported.\n    :param check_type: the expected input of the check function. Valid values\n        are :class:`~pandera.extensions.CheckType` enums or\n        ``{\"vectorized\", \"element_wise\", \"groupby\"}``. The input signature of\n        ``check_fn`` is determined by this argument:\n\n        - if ``vectorized``, the first positional argument of ``check_fn``\n          should be one of the ``supported_types``.\n        - if ``element_wise``, the first positional argument of ``check_fn``\n          should be a single scalar element in the pandas Series or DataFrame.\n        - if ``groupby``, the first positional argument of ``check_fn`` should\n          be a dictionary mapping group names to subsets of the Series or\n          DataFrame.\n\n    :param strategy: data-generation strategy associated with the check\n        function.\n    :return: register check function wrapper.\n    \"\"\"\n\n    # pylint: disable=import-outside-toplevel\n    from pandera.strategies.pandas_strategies import register_check_strategy\n\n    if statistics is None:\n        statistics = []\n\n    if isinstance(check_type, str):\n        check_type = CheckType[check_type.upper()]\n\n    msg = (\n        \"{} is not a valid input type for check_fn. You must specify one of \"\n        \"pandas.DataFrame, pandas.Series, or a tuple of both.\"\n    )\n    if isinstance(supported_types, list):\n        supported_types = tuple(supported_types)\n    elif not isinstance(supported_types, tuple):\n        supported_types = (supported_types,)\n\n    for supported_type in supported_types:  # type: ignore\n        if supported_type not in {pd.DataFrame, pd.Series}:\n            raise TypeError(msg.format(supported_type))\n\n    if check_type is CheckType.ELEMENT_WISE and set(supported_types) != {\n        pd.DataFrame,\n        pd.Series,\n    }:  # type: ignore\n        raise ValueError(\n            \"Element-wise checks should support DataFrame and Series \"\n            \"validation. Use the default setting for the 'supported_types' \"\n            \"argument.\"\n        )\n\n    if check_fn is None:\n        return partial(\n            register_check_method,\n            statistics=statistics,\n            supported_types=supported_types,\n            check_type=check_type,\n            strategy=strategy,\n        )\n    else:\n        sig = signature(check_fn)\n        for statistic in statistics:\n            if statistic not in sig.parameters:\n                raise TypeError(\n                    f\"statistic '{statistic}' is not part of \"\n                    f\"{check_fn.__name__}'s signature.\"\n                )\n\n    def register_check_wrapper(check_fn: Callable):\n        \"\"\"Register a function as a :class:`~pandera.api.checks.Check` method.\"\"\"\n\n        if hasattr(Check, check_fn.__name__):\n            raise ValueError(\n                f\"method with name '{check_fn.__name__}' already defined. \"\n                \"Check methods must have a unique method name.\"\n            )\n\n        @wraps(check_fn)\n        def check_fn_wrapper(validate_obj, **kwargs):\n            \"\"\"Wrapper for check_fn to validate inputs.\"\"\"\n            return check_fn(validate_obj, **kwargs)\n\n        def validate_check_kwargs(check_kwargs):\n            msg = (\n                f\"'{check_fn.__name__} has check_type={check_type}. \"\n                \"Providing the following arguments will have no effect: \"\n                \"{}. Remove these arguments to avoid this warning.\"\n            )\n\n            no_effect_args = {\n                CheckType.ELEMENT_WISE: [\"element_wise\", \"groupby\", \"groups\"],\n                CheckType.VECTORIZED: [\"element_wise\", \"groupby\", \"groups\"],\n                CheckType.GROUPBY: [\"element_wise\"],\n            }[check_type]\n\n            if any(arg in check_kwargs for arg in no_effect_args):\n                warnings.warn(msg.format(no_effect_args))\n                for arg in no_effect_args:\n                    check_kwargs.pop(arg, None)\n\n            if check_type is CheckType.ELEMENT_WISE:\n                check_kwargs[\"element_wise\"] = True\n\n            return check_kwargs\n\n        @register_check_statistics(statistics)\n        def check_method(cls, *args, **kwargs):\n            \"\"\"Wrapper function that serves as the Check method.\"\"\"\n            stats, check_kwargs = {}, {}\n\n            if args:\n                stats = dict(zip(statistics, args))\n\n            for k, v in kwargs.items():\n                if k in statistics:\n                    stats[k] = v\n                else:\n                    check_kwargs[k] = v\n\n            return cls(\n                partial(check_fn_wrapper, **stats),\n                name=check_fn.__name__,\n                **validate_check_kwargs(check_kwargs),\n            )\n\n        if strategy is not None:\n            check_method = register_check_strategy(strategy)(check_method)\n\n        Check.REGISTERED_CUSTOM_CHECKS[check_fn.__name__] = partial(\n            check_method, Check\n        )\n\n    return register_check_wrapper(check_fn)\n", "path": "pandera/api/extensions.py"}], "after_files": [{"content": "\"\"\"Extensions module.\"\"\"\n\nimport inspect\nimport warnings\nfrom enum import Enum\nfrom functools import partial, wraps\nfrom inspect import signature\nfrom typing import Callable, List, Optional, Tuple, Type, Union\n\nimport pandas as pd\nimport typing_inspect\n\nfrom pandera.api.checks import Check\nfrom pandera.api.hypotheses import Hypothesis\nfrom pandera.strategies.base_strategies import STRATEGY_DISPATCHER\n\n\nclass BuiltinCheckRegistrationError(Exception):\n    \"\"\"\n    Exception raised when registering a built-in check implementation but the\n    default check function implementation hasn't been registered with\n    :py:meth:`~flytekit.core.base.BaseCheck.register_builtin_check_fn`.\n    \"\"\"\n\n\n# pylint: disable=too-many-locals\ndef register_builtin_check(\n    fn=None,\n    strategy: Optional[Callable] = None,\n    _check_cls: Type = Check,\n    **outer_kwargs,\n):\n    \"\"\"Register a check method to the Check namespace.\n\n    This is the primary way for extending the Check api to define additional\n    built-in checks.\n    \"\"\"\n\n    if fn is None:\n        return partial(\n            register_builtin_check,\n            strategy=strategy,\n            _check_cls=_check_cls,\n            **outer_kwargs,\n        )\n\n    name = fn.__name__\n\n    # see if the check function is already registered\n    check_fn = _check_cls.CHECK_FUNCTION_REGISTRY.get(name)\n    fn_sig = signature(fn)\n\n    # register the check strategy for this particular check, identified\n    # by the check `name`, and the data type of the check function. This\n    # supports Union types. Also assume that the data type of the data\n    # object to validate is the first argument.\n    data_type = [*fn_sig.parameters.values()][0].annotation\n\n    if typing_inspect.get_origin(data_type) is Tuple:\n        data_type, *_ = typing_inspect.get_args(data_type)\n\n    if typing_inspect.get_origin(data_type) is Union:\n        data_types = typing_inspect.get_args(data_type)\n    else:\n        data_types = (data_type,)\n\n    if strategy is not None:\n        for dt in data_types:\n            STRATEGY_DISPATCHER[(name, dt)] = strategy\n\n    if check_fn is None:  # pragma: no cover\n        raise BuiltinCheckRegistrationError(\n            f\"Check '{name}' doesn't have a base check implementation. \"\n            f\"You need to create a stub method in the {_check_cls} class and \"\n            \"then register a base check function implementation with the \"\n            f\"{_check_cls}.register_builtin_check_fn method.\\n\"\n            \"See the `pandera.api.base.builtin_checks` and \"\n            \"`pandera.backends.pandas.builtin_checks` modules as an example.\"\n        )\n\n    check_fn.register(fn)  # type: ignore\n\n    return fn\n\n\ndef register_builtin_hypothesis(**kwargs):\n    \"\"\"Register a new hypothesis.\"\"\"\n    return partial(\n        register_builtin_check,\n        _check_cls=Hypothesis,\n        **kwargs,\n    )\n\n\n# --------------------------------\n# CUSTOM CHECK REGISTRATION METHOD\n# --------------------------------\n#\n# The `register_check_method` decorator is the legacy method for registering\n# custom checks and will slated for deprecation after merging the core\n# internals overhaul.\n\n\nclass CheckType(Enum):\n    \"\"\"Check types for registered check methods.\"\"\"\n\n    VECTORIZED = 1  #: Check applied to a Series or DataFrame\n    ELEMENT_WISE = 2  #: Check applied to an element of a Series or DataFrame\n    GROUPBY = 3  #: Check applied to dictionary of Series or DataFrames.\n\n\ndef register_check_statistics(statistics_args):\n    \"\"\"Decorator to set statistics based on Check method.\"\"\"\n\n    def register_check_statistics_decorator(class_method):\n        @wraps(class_method)\n        def _wrapper(cls, *args, **kwargs):\n            args = list(args)\n            arg_names = inspect.getfullargspec(class_method).args[1:]\n            if not arg_names:\n                arg_names = statistics_args\n            args_dict = {**dict(zip(arg_names, args)), **kwargs}\n            check = class_method(cls, *args, **kwargs)\n            check.statistics = {\n                stat: args_dict.get(stat) for stat in statistics_args\n            }\n            check.statistics_args = statistics_args\n            return check\n\n        return _wrapper\n\n    return register_check_statistics_decorator\n\n\ndef register_check_method(\n    check_fn=None,\n    *,\n    statistics: Optional[List[str]] = None,\n    supported_types: Union[type, Tuple, List] = (pd.DataFrame, pd.Series),\n    check_type: Union[CheckType, str] = \"vectorized\",\n    strategy=None,\n):\n    \"\"\"Registers a function as a :class:`~pandera.api.checks.Check` method.\n\n    See the :ref:`user guide<extensions>` for more details.\n\n    :param check_fn: check function to register. The function should take one\n        positional argument for the object to validate and additional\n        keyword-only arguments for the check statistics.\n    :param statistics: list of keyword-only arguments in the ``check_fn``,\n        which serve as the statistics needed to serialize/de-serialize the\n        check and generate data if a ``strategy`` function is provided.\n    :param supported_types: the pandas type(s) supported by the check function.\n        Valid values are ``pd.DataFrame``, ``pd.Series``, or a list/tuple of\n        ``(pa.DataFrame, pa.Series)`` if both types are supported.\n    :param check_type: the expected input of the check function. Valid values\n        are :class:`~pandera.extensions.CheckType` enums or\n        ``{\"vectorized\", \"element_wise\", \"groupby\"}``. The input signature of\n        ``check_fn`` is determined by this argument:\n\n        - if ``vectorized``, the first positional argument of ``check_fn``\n          should be one of the ``supported_types``.\n        - if ``element_wise``, the first positional argument of ``check_fn``\n          should be a single scalar element in the pandas Series or DataFrame.\n        - if ``groupby``, the first positional argument of ``check_fn`` should\n          be a dictionary mapping group names to subsets of the Series or\n          DataFrame.\n\n    :param strategy: data-generation strategy associated with the check\n        function.\n    :return: register check function wrapper.\n    \"\"\"\n\n    # pylint: disable=import-outside-toplevel\n    from pandera.strategies.pandas_strategies import register_check_strategy\n\n    if statistics is None:\n        statistics = []\n\n    if isinstance(check_type, str):\n        check_type = CheckType[check_type.upper()]\n\n    msg = (\n        \"{} is not a valid input type for check_fn. You must specify one of \"\n        \"pandas.DataFrame, pandas.Series, or a tuple of both.\"\n    )\n    if isinstance(supported_types, list):\n        supported_types = tuple(supported_types)\n    elif not isinstance(supported_types, tuple):\n        supported_types = (supported_types,)\n\n    for supported_type in supported_types:  # type: ignore\n        if supported_type not in {pd.DataFrame, pd.Series}:\n            raise TypeError(msg.format(supported_type))\n\n    if check_type is CheckType.ELEMENT_WISE and set(supported_types) != {\n        pd.DataFrame,\n        pd.Series,\n    }:  # type: ignore\n        raise ValueError(\n            \"Element-wise checks should support DataFrame and Series \"\n            \"validation. Use the default setting for the 'supported_types' \"\n            \"argument.\"\n        )\n\n    if check_fn is None:\n        return partial(\n            register_check_method,\n            statistics=statistics,\n            supported_types=supported_types,\n            check_type=check_type,\n            strategy=strategy,\n        )\n    else:\n        sig = signature(check_fn)\n        for statistic in statistics:\n            if statistic not in sig.parameters:\n                raise TypeError(\n                    f\"statistic '{statistic}' is not part of \"\n                    f\"{check_fn.__name__}'s signature.\"\n                )\n\n    def register_check_wrapper(check_fn: Callable):\n        \"\"\"Register a function as a :class:`~pandera.api.checks.Check` method.\"\"\"\n\n        if hasattr(Check, check_fn.__name__):\n            raise ValueError(\n                f\"method with name '{check_fn.__name__}' already defined. \"\n                \"Check methods must have a unique method name.\"\n            )\n\n        @wraps(check_fn)\n        def check_fn_wrapper(validate_obj, **kwargs):\n            \"\"\"Wrapper for check_fn to validate inputs.\"\"\"\n            return check_fn(validate_obj, **kwargs)\n\n        def validate_check_kwargs(check_kwargs):\n            msg = (\n                f\"'{check_fn.__name__} has check_type={check_type}. \"\n                \"Providing the following arguments will have no effect: \"\n                \"{}. Remove these arguments to avoid this warning.\"\n            )\n\n            no_effect_args = {\n                CheckType.ELEMENT_WISE: [\"element_wise\", \"groupby\", \"groups\"],\n                CheckType.VECTORIZED: [\"element_wise\", \"groupby\", \"groups\"],\n                CheckType.GROUPBY: [\"element_wise\"],\n            }[check_type]\n\n            if any(arg in check_kwargs for arg in no_effect_args):\n                warnings.warn(msg.format(no_effect_args))\n                for arg in no_effect_args:\n                    check_kwargs.pop(arg, None)\n\n            if check_type is CheckType.ELEMENT_WISE:\n                check_kwargs[\"element_wise\"] = True\n\n            return check_kwargs\n\n        @register_check_statistics(statistics)\n        def check_method(cls, *args, **kwargs):\n            \"\"\"Wrapper function that serves as the Check method.\"\"\"\n            stats, check_kwargs = {}, {}\n\n            if args:\n                stats = dict(zip(statistics, args))\n\n            for k, v in kwargs.items():\n                if k in statistics:\n                    stats[k] = v\n                else:\n                    check_kwargs[k] = v\n\n            return cls(\n                partial(check_fn_wrapper, **stats),\n                name=check_fn.__name__,\n                **validate_check_kwargs(check_kwargs),\n            )\n\n        if strategy is not None:\n            check_method = register_check_strategy(strategy)(check_method)\n\n        Check.REGISTERED_CUSTOM_CHECKS[check_fn.__name__] = partial(\n            check_method, Check\n        )\n\n    return register_check_wrapper(check_fn)\n", "path": "pandera/api/extensions.py"}]}