Repository: pandas-dev/pandas

Issue:
Deprecated pandas.lib redirect messages
Currently, you get the following message when you try to access one of the `pandas.lib` functions:

```
In [1]: pd.lib.Timedelta
/home/joris/miniconda3/envs/dev/bin/ipython:1: FutureWarning: pandas.lib.Timedelta is deprecated. 
Please use pandas._libs.lib.Timedelta instead.
  #!/home/joris/miniconda3/envs/dev/bin/python
Out[1]: pandas._libs.tslib.Timedelta

In [1]: pd.lib.is_bool
/home/joris/miniconda3/envs/dev/bin/ipython:1: FutureWarning: pandas.lib.is_bool is deprecated. 
Please use pandas._libs.lib.is_bool instead.
  #!/home/joris/miniconda3/envs/dev/bin/python
Out[1]: <function pandas._libs.lib.is_bool>
```

(apart from `infer_dtypes`, for which there is already another redirect).

We shouldn't recommend to use `pandas._lib.lib`. 
For some there is a public alternative (like `Timestamp`, `Timedelta`), others are probably just private and shouldn't have an alternative. 

We could list all of them as `removals` and `moved` in `lib = _DeprecatedModule(..)`, but that will be a long list. Or we could just don't provide an alternative import path by default, and only include some specific ones for which there is an alternative.


Discussion:
xref #15909 

is this issue about ``is_*`` that are directly imported from ``pandas.lib``?

> is this issue about is_* that are directly imported from pandas.lib?

It is about *all* functions that are imported in `pandas.lib`. Currently that simply does `from pandas._libs.lib import *`.  
So all functions available in `_libs.lib` are also accessible from `pandas.lib`, which is not necessarily bad (for backward compat), but they should not recommend to use the `pandas._libs.lib` version. So we should assess the `pandas._libs.lib` namespace and see which we want to expose publicly (and where) and which not.

Probably it is something like:

- Timestamp, Timedelta, NaT -> refer to top-level
- certain of the `is_*` methods -> refer to types module
- all the rest = private -> do not refer to other import, just say it will be removed 
hmm, I think then will just turn off the ``*`` imports. If any breakage that IS useful can just add to the public API (if we want). users should not use *anything* from these private libraries unless explicity exposed (that's the entire point of the API). *most* of these routines are *already* exposed in the API (e.g. the is_*). 

I *suppose* putting deprecation warnings is ok here though.
Eg `pd.lib.Timestamp` is used (based on a quick SO search), so we should certainly put some things in `pandas.lib` for backwards compat. Easier to do * import IMO, but just changing the depr message.
yes aside from the ones you already have moved.
Dask is making use of `lib.is_bool_array` (https://github.com/dask/dask/blob/master/dask/dataframe/hashing.py#L8). Should we expose this in `types` ?
Ah, since this for compat with older pandas versions (before ``has_pandas_object`` was introduced), probably not worth it, they could do the import inline after the 'else' clause.

Resolving patch:
diff --git a/pandas/__init__.py b/pandas/__init__.py
--- a/pandas/__init__.py
+++ b/pandas/__init__.py
@@ -74,8 +74,11 @@
 parser = _DeprecatedModule(deprmod='pandas.parser',
                            removals=['na_values'],
                            moved={'CParserError': 'pandas.errors.ParserError'})
-lib = _DeprecatedModule(deprmod='pandas.lib', deprmodto='pandas._libs.lib',
-                        moved={'infer_dtype': 'pandas.api.lib.infer_dtype'})
+lib = _DeprecatedModule(deprmod='pandas.lib', deprmodto=False,
+                        moved={'Timestamp': 'pandas.Timestamp',
+                               'Timedelta': 'pandas.Timedelta',
+                               'NaT': 'pandas.NaT',
+                               'infer_dtype': 'pandas.api.lib.infer_dtype'})
 tslib = _DeprecatedModule(deprmod='pandas.tslib',
                           moved={'Timestamp': 'pandas.Timestamp',
                                  'Timedelta': 'pandas.Timedelta',
diff --git a/pandas/util/depr_module.py b/pandas/util/depr_module.py
--- a/pandas/util/depr_module.py
+++ b/pandas/util/depr_module.py
@@ -75,15 +75,22 @@ def __getattr__(self, name):
                 FutureWarning, stacklevel=2)
         else:
             deprmodto = self.deprmodto
-            if deprmodto is None:
-                deprmodto = "{modname}.{name}".format(
-                    modname=obj.__module__, name=name)
-            # The object is actually located in another module.
-            warnings.warn(
-                "{deprmod}.{name} is deprecated. Please use "
-                "{deprmodto}.{name} instead.".format(
-                    deprmod=self.deprmod, name=name, deprmodto=deprmodto),
-                FutureWarning, stacklevel=2)
+            if deprmodto is False:
+                warnings.warn(
+                    "{deprmod}.{name} is deprecated and will be removed in "
+                    "a future version.".format(
+                        deprmod=self.deprmod, name=name),
+                    FutureWarning, stacklevel=2)
+            else:
+                if deprmodto is None:
+                    deprmodto = "{modname}.{name}".format(
+                        modname=obj.__module__, name=name)
+                # The object is actually located in another module.
+                warnings.warn(
+                    "{deprmod}.{name} is deprecated. Please use "
+                    "{deprmodto}.{name} instead.".format(
+                        deprmod=self.deprmod, name=name, deprmodto=deprmodto),
+                    FutureWarning, stacklevel=2)
 
         return obj
 


Test patch: