Skip to content

Commit 23f74d3

Browse files
API: Add pandas.api.typing (#48578)
* API: Add pandas.api.typing * whatsnew note * Don't import Styler * Test fixup for Styler * API: Add pandas.api.typing * Add back Styler * Revert Styler changes * Point to pandas.api.typing for GroupBy objects * Add references to pandas.api.typing * fixup * Refinements * Add references to User Guide; fixup docstrings * Add references * fixup * Move whatsnew to 2.1.0 * Docstring fixup * Test dir of api.typing --------- Co-authored-by: Simon Hawkins <[email protected]>
1 parent c3e835a commit 23f74d3

21 files changed

+151
-40
lines changed

doc/source/reference/groupby.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ GroupBy
77
=======
88
.. currentmodule:: pandas.core.groupby
99

10-
GroupBy objects are returned by groupby calls: :func:`pandas.DataFrame.groupby`, :func:`pandas.Series.groupby`, etc.
10+
:class:`pandas.api.typing.DataFrameGroupBy` and :class:`pandas.api.typing.SeriesGroupBy`
11+
instances are returned by groupby calls :func:`pandas.DataFrame.groupby` and
12+
:func:`pandas.Series.groupby` respectively.
1113

1214
Indexing, iteration
1315
-------------------

doc/source/reference/index.rst

+18-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,24 @@ API reference
99
This page gives an overview of all public pandas objects, functions and
1010
methods. All classes and functions exposed in ``pandas.*`` namespace are public.
1111

12-
Some subpackages are public which include ``pandas.errors``,
13-
``pandas.plotting``, and ``pandas.testing``. Public functions in
14-
``pandas.io`` and ``pandas.tseries`` submodules are mentioned in
15-
the documentation. ``pandas.api.types`` subpackage holds some
16-
public functions related to data types in pandas.
12+
The following subpackages are public.
13+
14+
- ``pandas.errors``: Custom exception and warnings classes that are raised by pandas.
15+
- ``pandas.plotting``: Plotting public API.
16+
- ``pandas.testing``: Functions that are useful for writing tests involving pandas objects.
17+
- ``pandas.api.extensions``: Functions and classes for extending pandas objects.
18+
- ``pandas.api.indexers``: Functions and classes for rolling window indexers.
19+
- ``pandas.api.interchange``: DataFrame interchange protocol.
20+
- ``pandas.api.types``: Datatype classes and functions.
21+
- ``pandas.api.typing``: Classes that may be necessary for type-hinting. These are
22+
classes that are encountered as intermediate results but should not be
23+
instantiated directly by users. These classes are not to be confused with
24+
classes from the `pandas-stubs <https://github.com/pandas-dev/pandas-stubs>`_
25+
package which has classes in addition to those that occur in pandas for type-hinting.
26+
27+
In addition, public functions in ``pandas.io`` and ``pandas.tseries`` submodules
28+
are mentioned in the documentation.
29+
1730

1831
.. warning::
1932

doc/source/reference/resampling.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ Resampling
77
==========
88
.. currentmodule:: pandas.core.resample
99

10-
Resampler objects are returned by resample calls: :func:`pandas.DataFrame.resample`, :func:`pandas.Series.resample`.
10+
:class:`pandas.api.typing.Resampler` instances are returned by
11+
resample calls: :func:`pandas.DataFrame.resample`, :func:`pandas.Series.resample`.
1112

1213
Indexing, iteration
1314
~~~~~~~~~~~~~~~~~~~

doc/source/reference/window.rst

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
Window
77
======
88

9-
Rolling objects are returned by ``.rolling`` calls: :func:`pandas.DataFrame.rolling` and :func:`pandas.Series.rolling`.
10-
Expanding objects are returned by ``.expanding`` calls: :func:`pandas.DataFrame.expanding` and :func:`pandas.Series.expanding`.
11-
ExponentialMovingWindow objects are returned by ``.ewm`` calls: :func:`pandas.DataFrame.ewm` and :func:`pandas.Series.ewm`.
9+
:class:`pandas.api.typing.Rolling` instances are returned by ``.rolling`` calls:
10+
:func:`pandas.DataFrame.rolling` and :func:`pandas.Series.rolling`.
11+
:class:`pandas.api.typing.Expanding` instances are returned by ``.expanding`` calls:
12+
:func:`pandas.DataFrame.expanding` and :func:`pandas.Series.expanding`.
13+
:class:`pandas.api.typing.ExponentialMovingWindow` instances are returned by ``.ewm``
14+
calls: :func:`pandas.DataFrame.ewm` and :func:`pandas.Series.ewm`.
1215

1316
.. _api.functions_rolling:
1417

doc/source/user_guide/groupby.rst

+4-2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ consider the following ``DataFrame``:
128128
df
129129
130130
On a DataFrame, we obtain a GroupBy object by calling :meth:`~DataFrame.groupby`.
131+
This method returns a ``pandas.api.typing.DataFrameGroupBy`` instance.
131132
We could naturally group by either the ``A`` or ``B`` columns, or both:
132133

133134
.. ipython:: python
@@ -1419,8 +1420,9 @@ Groupby a specific column with the desired frequency. This is like resampling.
14191420
14201421
df.groupby([pd.Grouper(freq="1M", key="Date"), "Buyer"])[["Quantity"]].sum()
14211422
1422-
You have an ambiguous specification in that you have a named index and a column
1423-
that could be potential groupers.
1423+
When ``freq`` is specified, the object returned by ``pd.Grouper`` will be an
1424+
instance of ``pandas.api.typing.TimeGrouper``. You have an ambiguous specification
1425+
in that you have a named index and a column that could be potential groupers.
14241426

14251427
.. ipython:: python
14261428

doc/source/user_guide/io.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -2069,7 +2069,7 @@ is ``None``. To explicitly force ``Series`` parsing, pass ``typ=series``
20692069
seconds, milliseconds, microseconds or nanoseconds respectively.
20702070
* ``lines`` : reads file as one json object per line.
20712071
* ``encoding`` : The encoding to use to decode py3 bytes.
2072-
* ``chunksize`` : when used in combination with ``lines=True``, return a JsonReader which reads in ``chunksize`` lines per iteration.
2072+
* ``chunksize`` : when used in combination with ``lines=True``, return a ``pandas.api.typing.JsonReader`` which reads in ``chunksize`` lines per iteration.
20732073
* ``engine``: Either ``"ujson"``, the built-in JSON parser, or ``"pyarrow"`` which dispatches to pyarrow's ``pyarrow.json.read_json``.
20742074
The ``"pyarrow"`` is only available when ``lines=True``
20752075

@@ -5991,15 +5991,15 @@ Reading from Stata format
59915991
'''''''''''''''''''''''''
59925992

59935993
The top-level function ``read_stata`` will read a dta file and return
5994-
either a ``DataFrame`` or a :class:`~pandas.io.stata.StataReader` that can
5994+
either a ``DataFrame`` or a :class:`pandas.api.typing.StataReader` that can
59955995
be used to read the file incrementally.
59965996

59975997
.. ipython:: python
59985998
59995999
pd.read_stata("stata.dta")
60006000
60016001
Specifying a ``chunksize`` yields a
6002-
:class:`~pandas.io.stata.StataReader` instance that can be used to
6002+
:class:`pandas.api.typing.StataReader` instance that can be used to
60036003
read ``chunksize`` lines from the file at a time. The ``StataReader``
60046004
object can be used as an iterator.
60056005

doc/source/user_guide/timeseries.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -1750,8 +1750,9 @@ We can instead only resample those groups where we have points as follows:
17501750
Aggregation
17511751
~~~~~~~~~~~
17521752

1753-
Similar to the :ref:`aggregating API <basics.aggregate>`, :ref:`groupby API <groupby.aggregate>`, and the :ref:`window API <window.overview>`,
1754-
a ``Resampler`` can be selectively resampled.
1753+
The ``resample()`` method returns a ``pandas.api.typing.Resampler`` instance. Similar to
1754+
the :ref:`aggregating API <basics.aggregate>`, :ref:`groupby API <groupby.aggregate>`,
1755+
and the :ref:`window API <window.overview>`, a ``Resampler`` can be selectively resampled.
17551756

17561757
Resampling a ``DataFrame``, the default will be to act on all columns with the same function.
17571758

doc/source/user_guide/window.rst

+8-8
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ pandas supports 4 types of windowing operations:
3737
#. Expanding window: Accumulating window over the values.
3838
#. Exponentially Weighted window: Accumulating and exponentially weighted window over the values.
3939

40-
============================= ================= =========================== =========================== ======================== =================================== ===========================
41-
Concept Method Returned Object Supports time-based windows Supports chained groupby Supports table method Supports online operations
42-
============================= ================= =========================== =========================== ======================== =================================== ===========================
43-
Rolling window ``rolling`` ``Rolling`` Yes Yes Yes (as of version 1.3) No
44-
Weighted window ``rolling`` ``Window`` No No No No
45-
Expanding window ``expanding`` ``Expanding`` No Yes Yes (as of version 1.3) No
46-
Exponentially Weighted window ``ewm`` ``ExponentialMovingWindow`` No Yes (as of version 1.2) No Yes (as of version 1.3)
47-
============================= ================= =========================== =========================== ======================== =================================== ===========================
40+
============================= ================= ============================================= =========================== ======================== =================================== ===========================
41+
Concept Method Returned Object Supports time-based windows Supports chained groupby Supports table method Supports online operations
42+
============================= ================= ============================================= =========================== ======================== =================================== ===========================
43+
Rolling window ``rolling`` ``pandas.typing.api.Rolling`` Yes Yes Yes (as of version 1.3) No
44+
Weighted window ``rolling`` ``pandas.typing.api.Window`` No No No No
45+
Expanding window ``expanding`` ``pandas.typing.api.Expanding`` No Yes Yes (as of version 1.3) No
46+
Exponentially Weighted window ``ewm`` ``pandas.typing.api.ExponentialMovingWindow`` No Yes (as of version 1.2) No Yes (as of version 1.3)
47+
============================= ================= ============================================= =========================== ======================== =================================== ===========================
4848

4949
As noted above, some operations support specifying a window based on a time offset:
5050

doc/source/whatsnew/v2.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ Other enhancements
8686
- Add dtype of categories to ``repr`` information of :class:`CategoricalDtype` (:issue:`52179`)
8787
- Added to the escape mode "latex-math" preserving without escaping all characters between "\(" and "\)" in formatter (:issue:`51903`)
8888
- Adding ``engine_kwargs`` parameter to :meth:`DataFrame.read_excel` (:issue:`52214`)
89+
- Classes that are useful for type-hinting have been added to the public API in the new submodule ``pandas.api.typing`` (:issue:`48577`)
8990
- Implemented ``__from_arrow__`` on :class:`DatetimeTZDtype`. (:issue:`52201`)
9091
- Implemented ``__pandas_priority__`` to allow custom types to take precedence over :class:`DataFrame`, :class:`Series`, :class:`Index`, or :class:`ExtensionArray` for arithmetic operations, :ref:`see the developer guide <extending.pandas_priority>` (:issue:`48347`)
9192
- Improve error message when having incompatible columns using :meth:`DataFrame.merge` (:issue:`51861`)

pandas/api/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
indexers,
55
interchange,
66
types,
7+
typing,
78
)
89

910
__all__ = [
1011
"interchange",
1112
"extensions",
1213
"indexers",
1314
"types",
15+
"typing",
1416
]

pandas/api/typing/__init__.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""
2+
Public API classes that store intermediate results useful for type-hinting.
3+
"""
4+
5+
from pandas.core.groupby import (
6+
DataFrameGroupBy,
7+
SeriesGroupBy,
8+
)
9+
from pandas.core.resample import (
10+
DatetimeIndexResamplerGroupby,
11+
PeriodIndexResamplerGroupby,
12+
Resampler,
13+
TimedeltaIndexResamplerGroupby,
14+
TimeGrouper,
15+
)
16+
from pandas.core.window import (
17+
Expanding,
18+
ExpandingGroupby,
19+
ExponentialMovingWindow,
20+
ExponentialMovingWindowGroupby,
21+
Rolling,
22+
RollingGroupby,
23+
Window,
24+
)
25+
26+
# TODO: Can't import Styler without importing jinja2
27+
# from pandas.io.formats.style import Styler
28+
from pandas.io.json._json import JsonReader
29+
from pandas.io.stata import StataReader
30+
31+
__all__ = [
32+
"DataFrameGroupBy",
33+
"DatetimeIndexResamplerGroupby",
34+
"Expanding",
35+
"ExpandingGroupby",
36+
"ExponentialMovingWindow",
37+
"ExponentialMovingWindowGroupby",
38+
"JsonReader",
39+
"PeriodIndexResamplerGroupby",
40+
"Resampler",
41+
"Rolling",
42+
"RollingGroupby",
43+
"SeriesGroupBy",
44+
"StataReader",
45+
# See TODO above
46+
# "Styler",
47+
"TimedeltaIndexResamplerGroupby",
48+
"TimeGrouper",
49+
"Window",
50+
]

pandas/core/generic.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8681,7 +8681,7 @@ def resample(
86818681
86828682
Returns
86838683
-------
8684-
pandas.core.Resampler
8684+
pandas.api.typing.Resampler
86858685
:class:`~pandas.core.Resampler` object.
86868686
86878687
See Also

pandas/core/groupby/groupby.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -2641,8 +2641,11 @@ def resample(self, rule, *args, **kwargs):
26412641
26422642
Returns
26432643
-------
2644-
Grouper
2645-
Return a new grouper with our resampler appended.
2644+
pandas.api.typing.DatetimeIndexResamplerGroupby,
2645+
pandas.api.typing.PeriodIndexResamplerGroupby, or
2646+
pandas.api.typing.TimedeltaIndexResamplerGroupby
2647+
Return a new groupby object, with type depending on the data
2648+
being resampled.
26462649
26472650
See Also
26482651
--------
@@ -2806,7 +2809,7 @@ def rolling(self, *args, **kwargs) -> RollingGroupby:
28062809
28072810
Returns
28082811
-------
2809-
RollingGroupby
2812+
pandas.api.typing.RollingGroupby
28102813
Return a new grouper with our rolling appended.
28112814
28122815
See Also
@@ -2869,6 +2872,10 @@ def expanding(self, *args, **kwargs) -> ExpandingGroupby:
28692872
"""
28702873
Return an expanding grouper, providing expanding
28712874
functionality per group.
2875+
2876+
Returns
2877+
-------
2878+
pandas.api.typing.ExpandingGroupby
28722879
"""
28732880
from pandas.core.window import ExpandingGroupby
28742881

@@ -2885,6 +2892,10 @@ def expanding(self, *args, **kwargs) -> ExpandingGroupby:
28852892
def ewm(self, *args, **kwargs) -> ExponentialMovingWindowGroupby:
28862893
"""
28872894
Return an ewm grouper, providing ewm functionality per group.
2895+
2896+
Returns
2897+
-------
2898+
pandas.api.typing.ExponentialMovingWindowGroupby
28882899
"""
28892900
from pandas.core.window import ExponentialMovingWindowGroupby
28902901

pandas/core/groupby/grouper.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ class Grouper:
120120
121121
Returns
122122
-------
123-
A specification for a groupby instruction
123+
Grouper or pandas.api.typing.TimeGrouper
124+
A TimeGrouper is returned if ``freq`` is not ``None``. Otherwise, a Grouper
125+
is returned.
124126
125127
Examples
126128
--------

pandas/core/shared_docs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178
179179
Returns
180180
-------
181-
%(klass)sGroupBy
181+
pandas.api.typing.%(klass)sGroupBy
182182
Returns a groupby object that contains information about the groups.
183183
184184
See Also

pandas/core/window/ewm.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ class ExponentialMovingWindow(BaseWindow):
231231
232232
Returns
233233
-------
234-
``ExponentialMovingWindow`` subclass
234+
pandas.api.typing.ExponentialMovingWindow
235235
236236
See Also
237237
--------

pandas/core/window/expanding.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class Expanding(RollingAndExpandingMixin):
7272
7373
Returns
7474
-------
75-
``Expanding`` subclass
75+
pandas.api.typing.Expanding
7676
7777
See Also
7878
--------

pandas/core/window/rolling.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -965,9 +965,9 @@ class Window(BaseWindow):
965965
966966
Returns
967967
-------
968-
``Window`` subclass if a ``win_type`` is passed
969-
970-
``Rolling`` subclass if ``win_type`` is not passed
968+
pandas.api.typing.Window or pandas.api.typing.Rolling
969+
An instance of Window is returned if ``win_type`` is passed. Otherwise,
970+
an instance of Rolling is returned.
971971
972972
See Also
973973
--------

pandas/io/json/_json.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,9 @@ def read_json(
665665
666666
Returns
667667
-------
668-
Series or DataFrame
669-
The type returned depends on the value of `typ`.
668+
Series, DataFrame, or pandas.api.typing.JsonReader
669+
A JsonReader is returned when ``chunksize`` is not ``0`` or ``None``.
670+
Otherwise, the type returned depends on the value of ``typ``.
670671
671672
See Also
672673
--------

pandas/io/stata.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@
156156
157157
Returns
158158
-------
159-
DataFrame or StataReader
159+
DataFrame or pandas.api.typing.StataReader
160160
161161
See Also
162162
--------

pandas/tests/api/test_api.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pandas as pd
66
from pandas import api
77
import pandas._testing as tm
8+
from pandas.api import typing as api_typing
89

910

1011
class Base:
@@ -236,11 +237,32 @@ def test_depr(self):
236237

237238

238239
class TestApi(Base):
239-
allowed = ["types", "extensions", "indexers", "interchange"]
240+
allowed = ["types", "extensions", "indexers", "interchange", "typing"]
241+
allowed_typing = [
242+
"DataFrameGroupBy",
243+
"DatetimeIndexResamplerGroupby",
244+
"Expanding",
245+
"ExpandingGroupby",
246+
"ExponentialMovingWindow",
247+
"ExponentialMovingWindowGroupby",
248+
"JsonReader",
249+
"PeriodIndexResamplerGroupby",
250+
"Resampler",
251+
"Rolling",
252+
"RollingGroupby",
253+
"SeriesGroupBy",
254+
"StataReader",
255+
"TimedeltaIndexResamplerGroupby",
256+
"TimeGrouper",
257+
"Window",
258+
]
240259

241260
def test_api(self):
242261
self.check(api, self.allowed)
243262

263+
def test_api_typing(self):
264+
self.check(api_typing, self.allowed_typing)
265+
244266

245267
class TestTesting(Base):
246268
funcs = [

0 commit comments

Comments
 (0)