equinor / webviz-config

Make Dash applications from a user-friendly config file :book: :snake:
https://github.com/orgs/equinor/projects/24
MIT License
54 stars 39 forks source link

Be smarter wrt. type hints #199

Open anders-kiaer opened 4 years ago

anders-kiaer commented 4 years ago

webviz-config already uses type hint annotations in plugins, to automatically check (at the time of parsing the webviz config file) that the user provided values are consistent with the values expected by the plugin author.

Currently we do not support e.g. Optional(pathlib.Path) or Union[dict, pathlib.Path].

Could we improve on this in a robust way? E.g. if it is Union[dict, pathlib.Path], return absolute pathlib.Path if input corresponds to a file, otherwise the input in config should be a dict.

Optional[...] should be easy to support.

Should aim for as little "special-casing" as possible.

asnyv commented 4 years ago

Could not find a simple solution to handle all types, but Union[pathlib.Path, some_nonepath_type] and possibly Union[List[pathlib.Path], some_nonepath_type] where paths are prioritized should be possible. In the latter case it would be necessary to decide a behavior when some, but not all, paths exists. Think it would be natural to raise an error? (Optional actually resolves to a type typing.Union[some_type, NoneType] and is therefore solved in the same manner)

Plausible solution: subtypes of typing.Union have the attributes __origin__ and __args__. If we check hasattr(expected_type, "__origin__"), and if so; expected_type.__origin__ == typing.Union, we can get a tuple of the arguments for typing.Union with union_args = expected_type.__args__ (from py 3.8 you get functions typing.get_origin and typing.get_args). Then check if pathlib.Path in union_args and possibly if typing.List[pathlib.Path] in union_args. Then check if it is possible to resolve paths that exist, and if not do an isinstance check of the config argument towards the rest of the union_args tuple. Could also include a if typing.Any in union_args -> proceed before the isinstance check to allow for the generous case of all types allowed.

anders-kiaer commented 4 years ago

While waiting on dropping both Python 3.6 and 3.7 support (in quite some time), it probably is cleaner to use this back-port https://pypi.org/project/typing-inspect/ on Python < 3.8.

Would also be nice if we could support recursion etc.

anders-kiaer commented 4 years ago

We should ideally also support overloading (e.g. that plugin authors use https://www.python.org/dev/peps/pep-0484/#function-method-overloading to define different "combinations of arguments"). This could then also be used to further improve both automatic documentation and YAML schema generation.

anders-kiaer commented 3 years ago

We can out source the majority of this work to pydantic - see https://github.com/samuelcolvin/pydantic/issues/2127.