gin-config
gin-config copied to clipboard
automatically generate a documentation of all configurables?
Hi guys,
First of all, I really like your work! 👏. I have a question regarding documentation and transparency. If I have multiple places in my code that use @gin.configurable
, can I somehow aggregate all those places and maybe even generate (Sphinx) documentation out of it?
Example:
@gin.configurable
def fun_a(param_a: str, param_b: bool = False, param_c: Sequence[int] = (1, 2, 3)):
"""some docstring that even describes the parameters"""
pass
@gin.configurable
def fun_b(param_a: float = 1.0):
pass
Can I get output like
Configurables:
fun_a
param_a: string
I am parameter A.
param_b: bool, default `False`
I am parameter B.
param_c: Sequence of integers, default `(1, 2, 3)`
I am parameter A.
fun_b
param_a: float, default 1.0
I am parameter A.
maybe even in machine readable format that anything could read and further process.
As a step on the way to this, these are the functions I currently use to get all gin parameters:
def get_all_gin_configurable_signatures() -> dict[str, inspect.Signature]:
"""Get the signatures for all things that are gin-configurable before gin has been applied.
Returns
-------
A dictionary mapping, for each configurable, name (including full module path) to a dictionary mapping parameter
name to default value. Example: If we only have the L1Loss configurable, we can expect
.. code-block:: python
{"torch.nn.L1Loss": {"size_average": None, "reduce": None, "reduction": "mean"}}
as a result. Parameters might be :class:`inspect.Parameter.empty`.
"""
gin_configurables = {}
for name, selectable in gin.config._REGISTRY._selector_map.items():
gin_configurables[name] = inspect.signature(selectable.wrapped)
return gin_configurables
def get_all_gin_parameters() -> dict[tuple[str, str], Any]:
"""Get parameters for all things that are gin-configurable after gin-settings have been applied.
Returns
-------
A dictionary mapping, for each configurable, name (including full module path) to a dictionary mapping parameter
name to default value. If multiple scopes are defined, we return multiple entries. This includes configurables that
have not been set by gin.
Example: If we have the L1Loss configurable and have it defined with different parameters in the scope
`surface_head`, we can expect
.. code-block:: python
{
("", "torch.nn.L1Loss"): {"size_average": None, "reduce": None, "reduction": "mean"},
("surface_head", "torch.nn.L1Loss"): {"size_average": None, "reduce": None, "reduction": "sum"}
}
as a result. Parameters might be :class:`inspect.Parameter.empty`.
Does not currently resolve macros or class definitions.
"""
gin_signatures = get_all_gin_configurable_signatures()
gin_configurables: dict[tuple[str, str], Any] = {}
empty_scope = ""
for name, signature in gin_signatures.items():
# Add the default parameters with an empty scope.
gin_configurables[(empty_scope, name)] = {k: v.default for k, v in signature.parameters.items()}
for (scope, name), param_dict in get_gin_set_params().items():
gin_configurables[(scope, name)] = copy.deepcopy(gin_configurables[(empty_scope, name)])
for param_name, new_val in param_dict.items():
gin_configurables[(scope, name)][param_name] = new_val
return gin_configurables
def get_gin_set_params() -> dict[tuple[str, str], Any]:
"""Get parameters for all things that gin is modifying.
Returns
-------
A dictionary mapping, for each configurable, a tuple of (scope, name) mapped to the parameter it is set to.
scope is an empty string if this applies to everything.
"""
return gin.config._CONFIG