Repository: scikit-hep/pyhf

Issue:
Improve typing rendering in docs
### Summary

As more of Issue #1284 is addressed (e.g. PR #1940) the rendering of the APIs in the reference docs has the unfortunate side effect of becoming increasingly unreadable and complicated.

As [`autodoc_type_aliases`](https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#confval-autodoc_type_aliases) exist in Sphinx, these could be a way to restore the clean and simple API reference that has previously been presented.

### Documentation Page Link

https://scikit-hep.org/pyhf/_generated/pyhf.tensor.numpy_backend.numpy_backend.html

### Code of Conduct

- [X] I agree to follow the Code of Conduct


Discussion:

Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -141,6 +141,36 @@ def setup(app):
     'tensorflow_probability',
 ]
 
+
+_type_aliases_inverted = {
+    'pyhf.typing': [
+        'PathOrStr',
+        'ParameterBase',
+        'Parameter',
+        'Measurement',
+        'ModifierBase',
+        'NormSys',
+        'NormFactor',
+        'HistoSys',
+        'StatError',
+        'ShapeSys',
+        'ShapeFactor',
+        'LumiSys',
+        'Modifier',
+        'Sample',
+        'Channel',
+        'Observation',
+        'Workspace',
+        'Literal',
+    ],
+    'numpy.typing': ['ArrayLike', 'DTypeLike', 'NBitBase', 'NDArray'],
+}
+autodoc_type_aliases = {
+    item: f'{k}.{item}' for k, v in _type_aliases_inverted.items() for item in v
+}
+
+autodoc_typehints_format = 'fully-qualified'
+
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 # This patterns also effect to html_static_path and html_extra_path
diff --git a/src/pyhf/tensor/numpy_backend.py b/src/pyhf/tensor/numpy_backend.py
--- a/src/pyhf/tensor/numpy_backend.py
+++ b/src/pyhf/tensor/numpy_backend.py
@@ -15,7 +15,7 @@
 T = TypeVar("T", bound=NBitBase)
 
 Tensor = Union["NDArray[np.number[T]]", "NDArray[np.bool_]"]
-
+FloatIntOrBool = Literal["float", "int", "bool"]
 log = logging.getLogger(__name__)
 
 
@@ -53,7 +53,7 @@ def __init__(self, **kwargs: dict[str, str]):
         self.name = 'numpy'
         self.precision = kwargs.get('precision', '64b')
         self.dtypemap: Mapping[
-            Literal['float', 'int', 'bool'],
+            FloatIntOrBool,
             DTypeLike,  # Type[np.floating[T]] | Type[np.integer[T]] | Type[np.bool_],
         ] = {
             'float': np.float64 if self.precision == '64b' else np.float32,
@@ -206,7 +206,7 @@ def isfinite(self, tensor: Tensor[T]) -> NDArray[np.bool_]:
         return np.isfinite(tensor)
 
     def astensor(
-        self, tensor_in: ArrayLike, dtype: Literal['float'] = 'float'
+        self, tensor_in: ArrayLike, dtype: FloatIntOrBool = 'float'
     ) -> ArrayLike:
         """
         Convert to a NumPy array.
@@ -247,9 +247,7 @@ def product(self, tensor_in: Tensor[T], axis: Shape | None = None) -> ArrayLike:
     def abs(self, tensor: Tensor[T]) -> ArrayLike:
         return np.abs(tensor)
 
-    def ones(
-        self, shape: Shape, dtype: Literal["float", "int", "bool"] = "float"
-    ) -> ArrayLike:
+    def ones(self, shape: Shape, dtype: FloatIntOrBool = "float") -> ArrayLike:
         try:
             dtype_obj = self.dtypemap[dtype]
         except KeyError:
@@ -261,9 +259,7 @@ def ones(
 
         return np.ones(shape, dtype=dtype_obj)
 
-    def zeros(
-        self, shape: Shape, dtype: Literal["float", "int", "bool"] = "float"
-    ) -> ArrayLike:
+    def zeros(self, shape: Shape, dtype: FloatIntOrBool = "float") -> ArrayLike:
         try:
             dtype_obj = self.dtypemap[dtype]
         except KeyError:


Test patch: