Skip to content

Commit b892fc6

Browse files
authored
TYP: use __all__ to signal public API to type checkers (#43695)
1 parent db179c4 commit b892fc6

File tree

5 files changed

+179
-14
lines changed

5 files changed

+179
-14
lines changed

pandas/__init__.py

+120-4
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
qcut,
132132
)
133133

134-
import pandas.api
134+
from pandas import api, arrays, errors, io, plotting, testing, tseries
135135
from pandas.util._print_versions import show_versions
136136

137137
from pandas.io.api import (
@@ -170,8 +170,6 @@
170170
from pandas.io.json import _json_normalize as json_normalize
171171

172172
from pandas.util._tester import test
173-
import pandas.testing
174-
import pandas.arrays
175173

176174
# use the closest tagged version if possible
177175
from pandas._version import get_versions
@@ -181,7 +179,6 @@
181179
__git_version__ = v.get("full-revisionid")
182180
del get_versions, v
183181

184-
185182
# GH 27101
186183
__deprecated_num_index_names = ["Float64Index", "Int64Index", "UInt64Index"]
187184

@@ -303,3 +300,122 @@ def __getattr__(name):
303300
- Time series-specific functionality: date range generation and frequency
304301
conversion, moving window statistics, date shifting and lagging.
305302
"""
303+
304+
# Use __all__ to let type checkers know what is part of the public API.
305+
# Pandas is not (yet) a py.typed library: the public API is determined
306+
# based on the documentation.
307+
__all__ = [
308+
"BooleanDtype",
309+
"Categorical",
310+
"CategoricalDtype",
311+
"CategoricalIndex",
312+
"DataFrame",
313+
"DateOffset",
314+
"DatetimeIndex",
315+
"DatetimeTZDtype",
316+
"ExcelFile",
317+
"ExcelWriter",
318+
"Flags",
319+
"Float32Dtype",
320+
"Float64Dtype",
321+
"Grouper",
322+
"HDFStore",
323+
"Index",
324+
"IndexSlice",
325+
"Int16Dtype",
326+
"Int32Dtype",
327+
"Int64Dtype",
328+
"Int8Dtype",
329+
"Interval",
330+
"IntervalDtype",
331+
"IntervalIndex",
332+
"MultiIndex",
333+
"NA",
334+
"NaT",
335+
"NamedAgg",
336+
"NumericIndex",
337+
"Period",
338+
"PeriodDtype",
339+
"PeriodIndex",
340+
"RangeIndex",
341+
"Series",
342+
"SparseDtype",
343+
"StringDtype",
344+
"Timedelta",
345+
"TimedeltaIndex",
346+
"Timestamp",
347+
"UInt16Dtype",
348+
"UInt32Dtype",
349+
"UInt64Dtype",
350+
"UInt8Dtype",
351+
"api",
352+
"array",
353+
"arrays",
354+
"bdate_range",
355+
"concat",
356+
"crosstab",
357+
"cut",
358+
"date_range",
359+
"describe_option",
360+
"errors",
361+
"eval",
362+
"factorize",
363+
"get_dummies",
364+
"get_option",
365+
"infer_freq",
366+
"interval_range",
367+
"io",
368+
"isna",
369+
"isnull",
370+
"json_normalize",
371+
"lreshape",
372+
"melt",
373+
"merge",
374+
"merge_asof",
375+
"merge_ordered",
376+
"notna",
377+
"notnull",
378+
"offsets",
379+
"option_context",
380+
"options",
381+
"period_range",
382+
"pivot",
383+
"pivot_table",
384+
"plotting",
385+
"qcut",
386+
"read_clipboard",
387+
"read_csv",
388+
"read_excel",
389+
"read_feather",
390+
"read_fwf",
391+
"read_gbq",
392+
"read_hdf",
393+
"read_html",
394+
"read_json",
395+
"read_orc",
396+
"read_parquet",
397+
"read_pickle",
398+
"read_sas",
399+
"read_spss",
400+
"read_sql",
401+
"read_sql_query",
402+
"read_sql_table",
403+
"read_stata",
404+
"read_table",
405+
"read_xml",
406+
"reset_option",
407+
"set_eng_float_format",
408+
"set_option",
409+
"show_versions",
410+
"test",
411+
"testing",
412+
"timedelta_range",
413+
"to_datetime",
414+
"to_numeric",
415+
"to_pickle",
416+
"to_timedelta",
417+
"tseries",
418+
"unique",
419+
"value_counts",
420+
"wide_to_long",
421+
]

pandas/io/__init__.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from typing import TYPE_CHECKING
2+
3+
if TYPE_CHECKING:
4+
# import modules that have public classes/functions
5+
from pandas.io import (
6+
formats,
7+
json,
8+
stata,
9+
)
10+
11+
# and mark only those modules as public
12+
__all__ = ["formats", "json", "stata"]

pandas/io/formats/__init__.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from typing import TYPE_CHECKING
2+
3+
if TYPE_CHECKING:
4+
# import modules that have public classes/functions
5+
from pandas.io.formats import style
6+
7+
# and mark only those modules as public
8+
__all__ = ["style"]

pandas/tests/api/test_api.py

+28-10
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,18 @@ class TestPDApi(Base):
3030
ignored = ["tests", "locale", "conftest"]
3131

3232
# top-level sub-packages
33-
lib = [
33+
public_lib = [
3434
"api",
3535
"arrays",
36-
"compat",
37-
"core",
38-
"errors",
39-
"pandas",
40-
"plotting",
36+
"options",
4137
"test",
4238
"testing",
43-
"tseries",
44-
"util",
45-
"options",
39+
"errors",
40+
"plotting",
4641
"io",
42+
"tseries",
4743
]
44+
private_lib = ["compat", "core", "pandas", "util"]
4845

4946
# these are already deprecated; awaiting removal
5047
deprecated_modules: list[str] = ["np", "datetime"]
@@ -204,7 +201,8 @@ class TestPDApi(Base):
204201
def test_api(self):
205202

206203
checkthese = (
207-
self.lib
204+
self.public_lib
205+
+ self.private_lib
208206
+ self.misc
209207
+ self.modules
210208
+ self.classes
@@ -217,6 +215,26 @@ def test_api(self):
217215
)
218216
self.check(namespace=pd, expected=checkthese, ignored=self.ignored)
219217

218+
def test_api_all(self):
219+
expected = set(
220+
self.public_lib
221+
+ self.misc
222+
+ self.modules
223+
+ self.classes
224+
+ self.funcs
225+
+ self.funcs_option
226+
+ self.funcs_read
227+
+ self.funcs_json
228+
+ self.funcs_to
229+
) - set(self.deprecated_classes)
230+
actual = set(pd.__all__)
231+
232+
extraneous = actual - expected
233+
assert not extraneous
234+
235+
missing = expected - actual
236+
assert not missing
237+
220238
def test_depr(self):
221239
deprecated_list = (
222240
self.deprecated_modules

pandas/tseries/__init__.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from typing import TYPE_CHECKING
2+
3+
if TYPE_CHECKING:
4+
# import modules that have public classes/functions:
5+
from pandas.tseries import (
6+
frequencies,
7+
offsets,
8+
)
9+
10+
# and mark only those modules as public
11+
__all__ = ["frequencies", "offsets"]

0 commit comments

Comments
 (0)