From 26fad1b70cbda40da4ae59787cc0640c0646719d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Fri, 8 Apr 2022 09:30:39 -0400 Subject: [PATCH 1/4] TYP: type/privatize public symbols --- pandas/__init__.py | 26 +++++++++++++------------- pandas/_config/config.py | 15 ++++++++++----- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/pandas/__init__.py b/pandas/__init__.py index 1b18af0f69cf2..3645e8744d8af 100644 --- a/pandas/__init__.py +++ b/pandas/__init__.py @@ -3,33 +3,33 @@ __docformat__ = "restructuredtext" # Let users know if they're missing any of our hard dependencies -hard_dependencies = ("numpy", "pytz", "dateutil") -missing_dependencies = [] +_hard_dependencies = ("numpy", "pytz", "dateutil") +_missing_dependencies = [] -for dependency in hard_dependencies: +for _dependency in _hard_dependencies: try: - __import__(dependency) - except ImportError as e: - missing_dependencies.append(f"{dependency}: {e}") + __import__(_dependency) + except ImportError as _e: + _missing_dependencies.append(f"{_dependency}: {_e}") -if missing_dependencies: +if _missing_dependencies: raise ImportError( - "Unable to import required dependencies:\n" + "\n".join(missing_dependencies) + "Unable to import required dependencies:\n" + "\n".join(_missing_dependencies) ) -del hard_dependencies, dependency, missing_dependencies +del _hard_dependencies, _dependency, _missing_dependencies # numpy compat from pandas.compat import is_numpy_dev as _is_numpy_dev try: from pandas._libs import hashtable as _hashtable, lib as _lib, tslib as _tslib -except ImportError as err: # pragma: no cover - module = err.name +except ImportError as _err: # pragma: no cover + _module = _err.name raise ImportError( - f"C extension: {module} not built. If you want to import " + f"C extension: {_module} not built. If you want to import " "pandas from the source directory, you may need to run " "'python setup.py build_ext --force' to build the C extensions first." - ) from err + ) from _err else: del _tslib, _lib, _hashtable diff --git a/pandas/_config/config.py b/pandas/_config/config.py index 58c9eae5fe7f3..eec91638c7e8c 100644 --- a/pandas/_config/config.py +++ b/pandas/_config/config.py @@ -58,13 +58,17 @@ from typing import ( Any, Callable, + Generic, Iterable, NamedTuple, cast, ) import warnings -from pandas._typing import F +from pandas._typing import ( + F, + T, +) class DeprecatedOption(NamedTuple): @@ -247,16 +251,17 @@ def __dir__(self) -> Iterable[str]: # of options, and option descriptions. -class CallableDynamicDoc: - def __init__(self, func, doc_tmpl) -> None: +class CallableDynamicDoc(Generic[T]): + def __init__(self, func: Callable[..., T], doc_tmpl: str) -> None: self.__doc_tmpl__ = doc_tmpl self.__func__ = func - def __call__(self, *args, **kwds): + def __call__(self, *args, **kwds) -> T: return self.__func__(*args, **kwds) + # error: Signature of "__doc__" incompatible with supertype "object" @property - def __doc__(self): + def __doc__(self) -> str: # type: ignore[override] opts_desc = _describe_option("all", _print_desc=False) opts_list = pp_options_list(list(_registered_options.keys())) return self.__doc_tmpl__.format(opts_desc=opts_desc, opts_list=opts_list) From 48154cba97aae314150cc0e1668c07dfcbffe9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Fri, 8 Apr 2022 09:38:38 -0400 Subject: [PATCH 2/4] take care of the fallout --- pandas/_libs/indexing.pyi | 9 +++++++++ pandas/_libs/json.pyi | 23 +++++++++++++++++++++++ pandas/_libs/reduction.pyi | 4 ++++ pandas/core/indexing.py | 18 ++++++++++++++++-- pandas/io/sas/_sas.pyi | 5 +++++ 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 pandas/_libs/indexing.pyi create mode 100644 pandas/_libs/json.pyi create mode 100644 pandas/_libs/reduction.pyi create mode 100644 pandas/io/sas/_sas.pyi diff --git a/pandas/_libs/indexing.pyi b/pandas/_libs/indexing.pyi new file mode 100644 index 0000000000000..ca74a939c8265 --- /dev/null +++ b/pandas/_libs/indexing.pyi @@ -0,0 +1,9 @@ +from typing import Any + +class NDFrameIndexerBase: + name: str + obj: Any + + def __init__(self, name: str, obj: Any) -> None: ... + @property + def ndim(self) -> int: ... diff --git a/pandas/_libs/json.pyi b/pandas/_libs/json.pyi new file mode 100644 index 0000000000000..555484a37c83f --- /dev/null +++ b/pandas/_libs/json.pyi @@ -0,0 +1,23 @@ +from typing import ( + Any, + Callable, +) + +def dumps( + obj: Any, + ensure_ascii: bool = ..., + double_precision: int = ..., + indent: int = ..., + orient: str = ..., + date_unit: str = ..., + iso_dates: bool = ..., + default_handler: None + | Callable[[Any], str | int | float | bool | list | dict | None] = ..., +) -> str: ... +def loads( + s: str, + precise_float: bool = ..., + numpy: bool = ..., + dtype: None = ..., + labelled: bool = ..., +) -> Any: ... diff --git a/pandas/_libs/reduction.pyi b/pandas/_libs/reduction.pyi new file mode 100644 index 0000000000000..d9d1d1c662a5a --- /dev/null +++ b/pandas/_libs/reduction.pyi @@ -0,0 +1,4 @@ +from typing import Any + +def check_result_array(obj: object, dtype: object) -> None: ... +def extract_result(res: object) -> Any: ... diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index ddae58fd46bb0..5f6a030aa6827 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -629,6 +629,9 @@ class _LocationIndexer(NDFrameIndexerBase): _valid_types: str axis = None + # sub-classes need to set _takeable + _takeable: bool + @final def __call__(self, axis=None): # we need to return a copy of ourselves @@ -935,7 +938,11 @@ def _getitem_lowerdim(self, tup: tuple): # is equivalent. # (see the other place where we call _handle_lowerdim_multi_index_axis0) with suppress(IndexingError): - return self._handle_lowerdim_multi_index_axis0(tup) + # error "_LocationIndexer" has no attribute + # "_handle_lowerdim_multi_index_axis0" + return self._handle_lowerdim_multi_index_axis0( # type: ignore[attr-defined] + tup + ) tup = self._validate_key_length(tup) @@ -991,7 +998,11 @@ def _getitem_nested_tuple(self, tup: tuple): # DataFrame, IndexingError is not raised when slice(None,None,None) # with one row. with suppress(IndexingError): - return self._handle_lowerdim_multi_index_axis0(tup) + # error "_LocationIndexer" has no attribute + # "_handle_lowerdim_multi_index_axis0" + return self._handle_lowerdim_multi_index_axis0( # type: ignore[attr-defined] + tup + ) elif isinstance(self.obj, ABCSeries) and any( isinstance(k, tuple) for k in tup ): @@ -2296,6 +2307,9 @@ class _ScalarAccessIndexer(NDFrameIndexerBase): Access scalars quickly. """ + # sub-classes need to set _takeable + _takeable: bool + def _convert_key(self, key): raise AbstractMethodError(self) diff --git a/pandas/io/sas/_sas.pyi b/pandas/io/sas/_sas.pyi new file mode 100644 index 0000000000000..527193dd71e57 --- /dev/null +++ b/pandas/io/sas/_sas.pyi @@ -0,0 +1,5 @@ +from pandas.io.sas.sas7bdat import SAS7BDATReader + +class Parser: + def __init__(self, parser: SAS7BDATReader) -> None: ... + def read(self, nrows: int) -> None: ... From a2033a50dca7f010bef3962112fc1895a4851f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Fri, 8 Apr 2022 10:00:52 -0400 Subject: [PATCH 3/4] return types --- pandas/_config/config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/_config/config.py b/pandas/_config/config.py index eec91638c7e8c..756c3b2d4b2b6 100644 --- a/pandas/_config/config.py +++ b/pandas/_config/config.py @@ -128,7 +128,7 @@ def _get_single_key(pat: str, silent: bool) -> str: return key -def _get_option(pat: str, silent: bool = False): +def _get_option(pat: str, silent: bool = False) -> Any: key = _get_single_key(pat, silent) # walk the nested dict @@ -168,7 +168,7 @@ def _set_option(*args, **kwargs) -> None: o.cb(key) -def _describe_option(pat: str = "", _print_desc: bool = True): +def _describe_option(pat: str = "", _print_desc: bool = True) -> str | None: keys = _select_options(pat) if len(keys) == 0: @@ -178,8 +178,8 @@ def _describe_option(pat: str = "", _print_desc: bool = True): if _print_desc: print(s) - else: - return s + return None + return s def _reset_option(pat: str, silent: bool = False) -> None: From 17f3cb63d07baed39615bc0252f830c5eff53469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20W=C3=B6rtwein?= Date: Fri, 15 Apr 2022 09:05:09 -0400 Subject: [PATCH 4/4] keep only the __init__ changes --- pandas/_config/config.py | 23 +++++++++-------------- pandas/_libs/indexing.pyi | 9 --------- pandas/_libs/json.pyi | 23 ----------------------- pandas/_libs/reduction.pyi | 4 ---- pandas/core/indexing.py | 18 ++---------------- pandas/io/sas/_sas.pyi | 5 ----- 6 files changed, 11 insertions(+), 71 deletions(-) delete mode 100644 pandas/_libs/indexing.pyi delete mode 100644 pandas/_libs/json.pyi delete mode 100644 pandas/_libs/reduction.pyi delete mode 100644 pandas/io/sas/_sas.pyi diff --git a/pandas/_config/config.py b/pandas/_config/config.py index 756c3b2d4b2b6..58c9eae5fe7f3 100644 --- a/pandas/_config/config.py +++ b/pandas/_config/config.py @@ -58,17 +58,13 @@ from typing import ( Any, Callable, - Generic, Iterable, NamedTuple, cast, ) import warnings -from pandas._typing import ( - F, - T, -) +from pandas._typing import F class DeprecatedOption(NamedTuple): @@ -128,7 +124,7 @@ def _get_single_key(pat: str, silent: bool) -> str: return key -def _get_option(pat: str, silent: bool = False) -> Any: +def _get_option(pat: str, silent: bool = False): key = _get_single_key(pat, silent) # walk the nested dict @@ -168,7 +164,7 @@ def _set_option(*args, **kwargs) -> None: o.cb(key) -def _describe_option(pat: str = "", _print_desc: bool = True) -> str | None: +def _describe_option(pat: str = "", _print_desc: bool = True): keys = _select_options(pat) if len(keys) == 0: @@ -178,8 +174,8 @@ def _describe_option(pat: str = "", _print_desc: bool = True) -> str | None: if _print_desc: print(s) - return None - return s + else: + return s def _reset_option(pat: str, silent: bool = False) -> None: @@ -251,17 +247,16 @@ def __dir__(self) -> Iterable[str]: # of options, and option descriptions. -class CallableDynamicDoc(Generic[T]): - def __init__(self, func: Callable[..., T], doc_tmpl: str) -> None: +class CallableDynamicDoc: + def __init__(self, func, doc_tmpl) -> None: self.__doc_tmpl__ = doc_tmpl self.__func__ = func - def __call__(self, *args, **kwds) -> T: + def __call__(self, *args, **kwds): return self.__func__(*args, **kwds) - # error: Signature of "__doc__" incompatible with supertype "object" @property - def __doc__(self) -> str: # type: ignore[override] + def __doc__(self): opts_desc = _describe_option("all", _print_desc=False) opts_list = pp_options_list(list(_registered_options.keys())) return self.__doc_tmpl__.format(opts_desc=opts_desc, opts_list=opts_list) diff --git a/pandas/_libs/indexing.pyi b/pandas/_libs/indexing.pyi deleted file mode 100644 index ca74a939c8265..0000000000000 --- a/pandas/_libs/indexing.pyi +++ /dev/null @@ -1,9 +0,0 @@ -from typing import Any - -class NDFrameIndexerBase: - name: str - obj: Any - - def __init__(self, name: str, obj: Any) -> None: ... - @property - def ndim(self) -> int: ... diff --git a/pandas/_libs/json.pyi b/pandas/_libs/json.pyi deleted file mode 100644 index 555484a37c83f..0000000000000 --- a/pandas/_libs/json.pyi +++ /dev/null @@ -1,23 +0,0 @@ -from typing import ( - Any, - Callable, -) - -def dumps( - obj: Any, - ensure_ascii: bool = ..., - double_precision: int = ..., - indent: int = ..., - orient: str = ..., - date_unit: str = ..., - iso_dates: bool = ..., - default_handler: None - | Callable[[Any], str | int | float | bool | list | dict | None] = ..., -) -> str: ... -def loads( - s: str, - precise_float: bool = ..., - numpy: bool = ..., - dtype: None = ..., - labelled: bool = ..., -) -> Any: ... diff --git a/pandas/_libs/reduction.pyi b/pandas/_libs/reduction.pyi deleted file mode 100644 index d9d1d1c662a5a..0000000000000 --- a/pandas/_libs/reduction.pyi +++ /dev/null @@ -1,4 +0,0 @@ -from typing import Any - -def check_result_array(obj: object, dtype: object) -> None: ... -def extract_result(res: object) -> Any: ... diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 5f6a030aa6827..ddae58fd46bb0 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -629,9 +629,6 @@ class _LocationIndexer(NDFrameIndexerBase): _valid_types: str axis = None - # sub-classes need to set _takeable - _takeable: bool - @final def __call__(self, axis=None): # we need to return a copy of ourselves @@ -938,11 +935,7 @@ def _getitem_lowerdim(self, tup: tuple): # is equivalent. # (see the other place where we call _handle_lowerdim_multi_index_axis0) with suppress(IndexingError): - # error "_LocationIndexer" has no attribute - # "_handle_lowerdim_multi_index_axis0" - return self._handle_lowerdim_multi_index_axis0( # type: ignore[attr-defined] - tup - ) + return self._handle_lowerdim_multi_index_axis0(tup) tup = self._validate_key_length(tup) @@ -998,11 +991,7 @@ def _getitem_nested_tuple(self, tup: tuple): # DataFrame, IndexingError is not raised when slice(None,None,None) # with one row. with suppress(IndexingError): - # error "_LocationIndexer" has no attribute - # "_handle_lowerdim_multi_index_axis0" - return self._handle_lowerdim_multi_index_axis0( # type: ignore[attr-defined] - tup - ) + return self._handle_lowerdim_multi_index_axis0(tup) elif isinstance(self.obj, ABCSeries) and any( isinstance(k, tuple) for k in tup ): @@ -2307,9 +2296,6 @@ class _ScalarAccessIndexer(NDFrameIndexerBase): Access scalars quickly. """ - # sub-classes need to set _takeable - _takeable: bool - def _convert_key(self, key): raise AbstractMethodError(self) diff --git a/pandas/io/sas/_sas.pyi b/pandas/io/sas/_sas.pyi deleted file mode 100644 index 527193dd71e57..0000000000000 --- a/pandas/io/sas/_sas.pyi +++ /dev/null @@ -1,5 +0,0 @@ -from pandas.io.sas.sas7bdat import SAS7BDATReader - -class Parser: - def __init__(self, parser: SAS7BDATReader) -> None: ... - def read(self, nrows: int) -> None: ...