From 8da37e0e8d8caa9be88d9754269a9ff4b54c8e92 Mon Sep 17 00:00:00 2001 From: Hannes Neuschmidt Date: Mon, 24 Aug 2026 13:42:12 +0200 Subject: [PATCH 1/3] Add draft of annotation-reading code --- test/test_parameters.py | 18 ++++++++++++++++++ xcengine/parameters.py | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/test/test_parameters.py b/test/test_parameters.py index 77e6400..8b3a0b7 100644 --- a/test/test_parameters.py +++ b/test/test_parameters.py @@ -377,3 +377,21 @@ 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 + """ + ) + expected = [ + {"annotation": "int", "value": "42", "target": "my_int", "line": 2}, + {"annotation": "'EOInput'", "value": "None", "target": "eoproduct", "line": 3}, + ] + + annotations = NotebookParameters.read_annotations(annotated_code) + + assert annotations == expected \ No newline at end of file diff --git a/xcengine/parameters.py b/xcengine/parameters.py index 4536f63..c621d25 100644 --- a/xcengine/parameters.py +++ b/xcengine/parameters.py @@ -232,3 +232,21 @@ def cwl_type(type_: type) -> str: }[type_] except KeyError: raise ValueError(f"Unhandled type {type_}") + + @staticmethod + def read_annotations(code: str) -> list[dict[str, Any]]: + import ast + tree = ast.parse(code) + annotations: list[dict[str, Any]] = [] + for node in ast.walk(tree): + if not isinstance(node, ast.AnnAssign): + continue + + annotations.append({ + "annotation": ast.unparse(node.annotation), + "value": ast.unparse(node.value) if node.value else None, + "target": ast.unparse(node.target), + "line": node.lineno, + }) + + return annotations From 1a49a2b3736f4cad0af1dceb8127116046179cea Mon Sep 17 00:00:00 2001 From: Pontus Lurcock Date: Thu, 27 Aug 2026 13:53:24 +0200 Subject: [PATCH 2/3] Simplify annotation reading code read_annotations now simply returns a target -> annotation dict. --- test/test_parameters.py | 19 +++++++------------ xcengine/parameters.py | 22 +++++++--------------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/test/test_parameters.py b/test/test_parameters.py index 8b3a0b7..4275a15 100644 --- a/test/test_parameters.py +++ b/test/test_parameters.py @@ -381,17 +381,12 @@ def test_read_datasets_from_product_missing_items( def test_read_annotations_from_code(): import textwrap - annotated_code = textwrap.dedent( - """ + + annotated_code = textwrap.dedent(""" my_int: int = 42 eoproduct: "EOInput" = None - """ - ) - expected = [ - {"annotation": "int", "value": "42", "target": "my_int", "line": 2}, - {"annotation": "'EOInput'", "value": "None", "target": "eoproduct", "line": 3}, - ] - - annotations = NotebookParameters.read_annotations(annotated_code) - - assert annotations == expected \ No newline at end of file + """) + assert NotebookParameters.read_annotations(annotated_code) == { + "my_int": "int", + "eoproduct": "'EOInput'", + } diff --git a/xcengine/parameters.py b/xcengine/parameters.py index c621d25..090203d 100644 --- a/xcengine/parameters.py +++ b/xcengine/parameters.py @@ -234,19 +234,11 @@ def cwl_type(type_: type) -> str: raise ValueError(f"Unhandled type {type_}") @staticmethod - def read_annotations(code: str) -> list[dict[str, Any]]: + def read_annotations(code: str) -> dict[str, str]: import ast - tree = ast.parse(code) - annotations: list[dict[str, Any]] = [] - for node in ast.walk(tree): - if not isinstance(node, ast.AnnAssign): - continue - - annotations.append({ - "annotation": ast.unparse(node.annotation), - "value": ast.unparse(node.value) if node.value else None, - "target": ast.unparse(node.target), - "line": node.lineno, - }) - - return annotations + + return { + ast.unparse(node.target): ast.unparse(node.annotation) + for node in ast.walk(ast.parse(code)) + if isinstance(node, ast.AnnAssign) + } From 0c20079ea8f94e4bca9fdba4f0633761f6096e84 Mon Sep 17 00:00:00 2001 From: Pontus Lurcock Date: Thu, 27 Aug 2026 16:03:32 +0200 Subject: [PATCH 3/3] Update changelog --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) 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