diff --git a/CHANGES.md b/CHANGES.md index d493366..b3923d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ `s:softwareVersion` (#90) * Allow creation of EOAP-only and xcube-server-only images, omitting unnecessary dependencies (#56) +* Add a utility function to read annotations from notebook code (#91) ## Changes in 0.1.2 diff --git a/test/test_parameters.py b/test/test_parameters.py index 77e6400..4275a15 100644 --- a/test/test_parameters.py +++ b/test/test_parameters.py @@ -377,3 +377,16 @@ def test_read_datasets_from_product_missing_items( params.read_datasets_from_product(tmp_path, {}) for substring in "missing", "foo", "bar": assert substring in str(error) + + +def test_read_annotations_from_code(): + import textwrap + + annotated_code = textwrap.dedent(""" + my_int: int = 42 + eoproduct: "EOInput" = None + """) + assert NotebookParameters.read_annotations(annotated_code) == { + "my_int": "int", + "eoproduct": "'EOInput'", + } diff --git a/xcengine/parameters.py b/xcengine/parameters.py index 15220f7..c88f3dc 100644 --- a/xcengine/parameters.py +++ b/xcengine/parameters.py @@ -234,3 +234,13 @@ def cwl_type(type_: type) -> str: }[type_] except KeyError: raise ValueError(f"Unhandled type {type_}") + + @staticmethod + def read_annotations(code: str) -> dict[str, str]: + import ast + + return { + ast.unparse(node.target): ast.unparse(node.annotation) + for node in ast.walk(ast.parse(code)) + if isinstance(node, ast.AnnAssign) + }