yahp icon indicating copy to clipboard operation
yahp copied to clipboard

Add `hp.from_init_signature` helper method

Open ravi-mosaicml opened this issue 3 years ago • 0 comments

Consider the following:

import dataclasses
import yahp as hp

class Foo:
    """Foo class

    Args:
        bar (int, optional): Most helpful docstring ever
    """

    def __init__(self, bar: int = 5):
         self.bar = bar

@dataclasses.dataclass
class FooHparams:
    bar: int = hp.optional("Most helpful docstring ever", default=5)

It's kinda redundant to have to copy and paste the docstring and default value in the yahp dataclass. Wouldn't it be nice if you could just do this?

import yahp as hp
import dataclasses

@dataclasses.dataclass
class FooHparams(hp.Hparams):
    bar: int = hp.from_init_signature(Foo, kwarg_name="bar")  # equivalent to: hp.optional("Most helpful docstring ever", default=5)

Implementation

This should be possible via python's inspect and https://pypi.org/project/docstring-parser/ As for the API, I'm thinking something like this:


def init_from_signature(cls: Type[Any], kwarg_name: str):
  '''Infer the docstring and default value from the ``__init__`` signature.

     Args:
        cls (type):  The class's `__init__` signature to parse. 
        kwarg_name (str,): The name of the argument in the `__init__` signature.

          If this field has a default value, then the YAHP dataclass field will be optional,
          and that default value will be used.
          If the field does not have a default value, then the YAHP dataclass field is required. '''
  ...

Other Designs

Originally, I thought it would have been nice to support the following:

import yahp as hp
import dataclasses

@dataclasses.dataclass
class FooHparams(hp.Hparams):
    bar: int = hp.from_init_signature(Foo)  # automatically infer that it's the `bar` argument from the field name in the hparams.

However, hp.from_init_signature would not know whether to return a hp.optional or hp.required since it doesn't know the field name. It is impossible to set this information later (such as on __init_subclass__), since python's dataclasses parses this on the @dataclass decorator. We would need our own @yahp_datalcass decorator to preprocess the class before passing it to python's dataclasses. This is a feature that can be done later if this is a design that we want...

ravi-mosaicml avatar Jan 19 '22 00:01 ravi-mosaicml