Repository: pyjanitor-devs/pyjanitor

Issue:
[DOC] Fix type annotation issues in documentation 
Two things that can be improved:

1) Type annotations in the docs hurt readability 

This is an example:

![image](https://user-images.githubusercontent.com/4762711/66703876-25f52700-ece5-11e9-8199-9f4d67767ad6.png)

I think we could alleviate this quite a bit by bolding the actual parameters names or something akin to that.

2) Abbreviated descriptions on the functions list page do weird things with type annotations and cut info out:

![image](https://user-images.githubusercontent.com/4762711/66703872-1d045580-ece5-11e9-99bd-096c8b497f25.png)

It might make sense to exclude type annotations here entirely.


Discussion:
Is this purely in the realm of how docs get autogenerated, i.e. source code/docstrings don't need to be touched?
>Is this purely in the realm of how docs get autogenerated, i.e. source code/docstrings don't need to be touched? 

I think so. Wonder if there’s a sphinx config for this?
Oh wait, I think I found where this is controlled. 

https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html

Resolving patch:
diff --git a/janitor/chemistry.py b/janitor/chemistry.py
--- a/janitor/chemistry.py
+++ b/janitor/chemistry.py
@@ -2,7 +2,7 @@
 Chemistry and cheminformatics-oriented data cleaning functions.
 """
 
-from typing import Union
+from typing import Hashable, Union
 
 import numpy as np
 import pandas as pd
@@ -80,8 +80,8 @@
 @deprecated_alias(smiles_col="smiles_column_name", mols_col="mols_column_name")
 def smiles2mol(
     df: pd.DataFrame,
-    smiles_column_name: str,
-    mols_column_name: str,
+    smiles_column_name: Hashable,
+    mols_column_name: Hashable,
     drop_nulls: bool = True,
     progressbar: Union[None, str] = None,
 ) -> pd.DataFrame:
@@ -277,7 +277,7 @@ def morgan_fingerprint(
 @pf.register_dataframe_method
 @deprecated_alias(mols_col="mols_column_name")
 def molecular_descriptors(
-    df: pd.DataFrame, mols_column_name: str
+    df: pd.DataFrame, mols_column_name: Hashable
 ) -> pd.DataFrame:
     """
     Convert a column of RDKIT mol objects into a Pandas DataFrame
@@ -394,7 +394,7 @@ def molecular_descriptors(
 @pf.register_dataframe_method
 @deprecated_alias(mols_col="mols_column_name")
 def maccs_keys_fingerprint(
-    df: pd.DataFrame, mols_column_name: str
+    df: pd.DataFrame, mols_column_name: Hashable
 ) -> pd.DataFrame:
     """
     Convert a column of RDKIT mol objects into MACCS Keys Fingerprints.
diff --git a/janitor/engineering.py b/janitor/engineering.py
--- a/janitor/engineering.py
+++ b/janitor/engineering.py
@@ -2,6 +2,8 @@
 Engineering-specific data cleaning functions.
 """
 
+from typing import Hashable
+
 import numpy as np
 import pandas as pd
 import pandas_flavor as pf
diff --git a/janitor/ml.py b/janitor/ml.py
--- a/janitor/ml.py
+++ b/janitor/ml.py
@@ -1,73 +1,73 @@
-""" Machine learning specific functions. """
-
-import unicodedata
-from typing import Any, Iterable, List, Tuple, Union
-
-import numpy as np
-import pandas as pd
-import pandas_flavor as pf
-
-from .utils import deprecated_alias
-
-
-@pf.register_dataframe_method
-@deprecated_alias(
-    target_columns="target_column_names",
-    feature_columns="feature_column_names",
-)
-def get_features_targets(
-    df: pd.DataFrame,
-    target_column_names: Union[str, Union[List, Tuple], Any],
-    feature_column_names: Union[str, Iterable[str], Any] = None,
-):
-    """
-    Get the features and targets as separate DataFrames/Series.
-
-    This method does not mutate the original DataFrame.
-
-    The behaviour is as such:
-
-    - ``target_column_names`` is mandatory.
-    - If ``feature_column_names`` is present, then we will respect the column
-        names inside there.
-    - If ``feature_column_names`` is not passed in, then we will assume that
-    the rest of the columns are feature columns, and return them.
-
-    Functional usage example:
-
-    .. code-block:: python
-
-        X, y = get_features_targets(df, target_column_names="measurement")
-
-    Method chaining example:
-
-    .. code-block:: python
-
-        import pandas as pd
-        import janitor.ml
-        df = pd.DataFrame(...)
-        target_cols = ['output1', 'output2']
-        X, y = df.get_features_targets(target_column_names=target_cols)
-
-    :param df: The pandas DataFrame object.
-    :param str/iterable target_column_names: Either a column name or an
-        iterable (list or tuple) of column names that are the target(s) to be
-        predicted.
-    :param str/iterable feature_column_names: (optional) The column name or
-        iterable of column names that are the features (a.k.a. predictors)
-        used to predict the targets.
-    :returns: (X, Y) the feature matrix (X) and the target matrix (Y). Both
-        are pandas DataFrames.
-    """
-    Y = df[target_column_names]
-
-    if feature_column_names:
-        X = df[feature_column_names]
-    else:
-        if isinstance(target_column_names, (list, tuple)):  # noqa: W503
-            xcols = [c for c in df.columns if c not in target_column_names]
-        else:
-            xcols = [c for c in df.columns if target_column_names != c]
-
-        X = df[xcols]
-    return X, Y
+""" Machine learning specific functions. """
+
+import unicodedata
+from typing import Hashable, Iterable, List, Tuple, Union
+
+import numpy as np
+import pandas as pd
+import pandas_flavor as pf
+
+from .utils import deprecated_alias
+
+
+@pf.register_dataframe_method
+@deprecated_alias(
+    target_columns="target_column_names",
+    feature_columns="feature_column_names",
+)
+def get_features_targets(
+    df: pd.DataFrame,
+    target_column_names: Union[str, Union[List, Tuple], Hashable],
+    feature_column_names: Union[str, Iterable[str], Hashable] = None,
+):
+    """
+    Get the features and targets as separate DataFrames/Series.
+
+    This method does not mutate the original DataFrame.
+
+    The behaviour is as such:
+
+    - ``target_column_names`` is mandatory.
+    - If ``feature_column_names`` is present, then we will respect the column
+        names inside there.
+    - If ``feature_column_names`` is not passed in, then we will assume that
+    the rest of the columns are feature columns, and return them.
+
+    Functional usage example:
+
+    .. code-block:: python
+
+        X, y = get_features_targets(df, target_column_names="measurement")
+
+    Method chaining example:
+
+    .. code-block:: python
+
+        import pandas as pd
+        import janitor.ml
+        df = pd.DataFrame(...)
+        target_cols = ['output1', 'output2']
+        X, y = df.get_features_targets(target_column_names=target_cols)
+
+    :param df: The pandas DataFrame object.
+    :param str/iterable target_column_names: Either a column name or an
+        iterable (list or tuple) of column names that are the target(s) to be
+        predicted.
+    :param str/iterable feature_column_names: (optional) The column name or
+        iterable of column names that are the features (a.k.a. predictors)
+        used to predict the targets.
+    :returns: (X, Y) the feature matrix (X) and the target matrix (Y). Both
+        are pandas DataFrames.
+    """
+    Y = df[target_column_names]
+
+    if feature_column_names:
+        X = df[feature_column_names]
+    else:
+        if isinstance(target_column_names, (list, tuple)):  # noqa: W503
+            xcols = [c for c in df.columns if c not in target_column_names]
+        else:
+            xcols = [c for c in df.columns if target_column_names != c]
+
+        X = df[xcols]
+    return X, Y


Test patch: