From 512d042bcb04a1c6f5de40d09793e1e076474585 Mon Sep 17 00:00:00 2001 From: lufire Date: Mon, 9 Mar 2026 14:44:07 +0000 Subject: [PATCH] chore: accept new Cruft update --- .cruft.json | 10 ++++-- .vscode/settings.json | 2 +- MANIFEST.in | 1 - README.md | 3 ++ mkdocs.yml | 1 - pyproject.toml | 28 ++++++++++++++-- requirements_docs.txt | 4 --- .../actions/__init__.py | 3 ++ .../actions/simple_action/__init__.py | 30 +++++++++++++++++ .../actions/simple_action/activities.py | 8 +++++ .../actions/simple_action/models.py | 15 +++++++++ .../actions/simple_action/workflows.py | 24 ++++++++++++++ tests/actions/test_action.py | 32 +++++++++++++++++++ 13 files changed, 148 insertions(+), 13 deletions(-) delete mode 100644 requirements_docs.txt create mode 100644 src/nomad_plugin_parser_example/actions/__init__.py create mode 100644 src/nomad_plugin_parser_example/actions/simple_action/__init__.py create mode 100644 src/nomad_plugin_parser_example/actions/simple_action/activities.py create mode 100644 src/nomad_plugin_parser_example/actions/simple_action/models.py create mode 100644 src/nomad_plugin_parser_example/actions/simple_action/workflows.py create mode 100644 tests/actions/test_action.py diff --git a/.cruft.json b/.cruft.json index 36a8136..6e82da3 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin", - "commit": "d306850507a46af96b5ab71129582655ce534c86", + "commit": "89bf9fe1aa0a9a3fe74fd2af5ccc74d5ea974ced", "checkout": null, "context": { "cookiecutter": { @@ -17,11 +17,15 @@ "include_parser": true, "include_app": false, "include_example_uploads": true, + "include_action": true, + "include_north_tools": false, + "north_tool_name": "my_north_tool", "_copy_without_render": [ - "*.html" + "*.html", + "*.png" ], "_template": "https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin", - "_commit": "d306850507a46af96b5ab71129582655ce534c86" + "_commit": "89bf9fe1aa0a9a3fe74fd2af5ccc74d5ea974ced" } }, "directory": null diff --git a/.vscode/settings.json b/.vscode/settings.json index 0c8648f..4f6a41e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "editor.rulers": [ - 90 + 88 ], "editor.renderWhitespace": "all", "editor.tabSize": 4, diff --git a/MANIFEST.in b/MANIFEST.in index 133607b..f7c5876 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1 @@ -recursive-include * nomad_plugin.yaml graft src/nomad_plugin_parser_example/example_uploads diff --git a/README.md b/README.md index 13f88af..21dcfd2 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,9 @@ Read the [NOMAD plugin documentation](https://nomad-lab.eu/prod/v1/staging/docs/ We now recommend using the dedicated [`nomad-distro-dev`](https://github.com/FAIRmat-NFDI/nomad-distro-dev) repository to simplify the process. Please refer to that repository for detailed instructions. +## Publish note +In the [GitHub actions workflow](./.github/workflows/publish.yml) for publishing the nomad_plugin_parser_example plugin to PyPI, we commented out the `deploy` job . If you want to publish the plugin to `PyPI`, you need to set up your project in `PyPI`. There are several online tutorials on publishing a Python package to PyPI, e.g., [How to Publish a Python Package to PyPI](https://realpython.com/pypi-publish-python-package/). After that, you can uncomment the `deploy` job in the workflow file and push the changes to GitHub. The workflow will be triggered and the package will be published to `PyPI` when you create a new release on GitHub. + ### Template update We use [`cruft`](https://github.com/cruft/cruft) to update the project based on template changes. To run the check for updates locally, run `cruft update` in the root of the project. More details see the instructions on [`cruft` website](https://cruft.github.io/cruft/#updating-a-project). diff --git a/mkdocs.yml b/mkdocs.yml index 4e65d9e..37b4822 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -56,5 +56,4 @@ extra_css: - stylesheets/extra.css extra_javascript: - javascript.js - - https://polyfill.io/v3/polyfill.min.js?features=es6 - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js diff --git a/pyproject.toml b/pyproject.toml index 05659a3..60a348a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,16 +25,31 @@ maintainers = [ ] license = { file = "LICENSE" } dependencies = [ - "nomad-lab>=1.3.0", - "python-magic-bin; sys_platform == 'win32'", + "nomad-lab>=1.4.1", + "pydantic", + "temporalio" ] [project.urls] Repository = "https://github.com/ZBT-Tools/nomad_plugin_parser_example" [project.optional-dependencies] -dev = ["ruff", "pytest", "structlog"] +dev = [ + "ruff", + "pytest", + "structlog", + "mkdocs", + "mkdocs-material==8.1.1", + "pymdown-extensions", + "mkdocs-click", + "pytest-asyncio", +] +[tool.uv] +extra-index-url = [ + "https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple", +] + [tool.ruff] # Exclude a variety of commonly ignored directories. exclude = [ @@ -82,6 +97,8 @@ select = [ ignore = [ "F403", # 'from module import *' used; unable to detect undefined names + "PLC0415", # `import` should be at the top-level of a file + "E501", # line too long ] fixable = ["ALL"] @@ -89,6 +106,9 @@ fixable = ["ALL"] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["PLC0415"] # import-outside-top-level + # this is entirely optional, you can remove this if you wish to [tool.ruff.format] # use single quotes for strings. @@ -115,6 +135,8 @@ schema_package_entry_point = "nomad_plugin_parser_example.schema_packages:schema example_upload_entry_point = "nomad_plugin_parser_example.example_uploads:example_upload_entry_point" +action_entry_point = "nomad_plugin_parser_example.actions:simple_action_entry_point" + [tool.cruft] # Avoid updating workflow files, this leads to permissions issues skip = [".github/*"] diff --git a/requirements_docs.txt b/requirements_docs.txt deleted file mode 100644 index bacf1ed..0000000 --- a/requirements_docs.txt +++ /dev/null @@ -1,4 +0,0 @@ -mkdocs -mkdocs-material==8.1.1 -pymdown-extensions -mkdocs-click diff --git a/src/nomad_plugin_parser_example/actions/__init__.py b/src/nomad_plugin_parser_example/actions/__init__.py new file mode 100644 index 0000000..b262ee7 --- /dev/null +++ b/src/nomad_plugin_parser_example/actions/__init__.py @@ -0,0 +1,3 @@ +from nomad_plugin_parser_example.actions.simple_action import simple_action_entry_point + +__all__ = ['simple_action_entry_point'] diff --git a/src/nomad_plugin_parser_example/actions/simple_action/__init__.py b/src/nomad_plugin_parser_example/actions/simple_action/__init__.py new file mode 100644 index 0000000..1afe24c --- /dev/null +++ b/src/nomad_plugin_parser_example/actions/simple_action/__init__.py @@ -0,0 +1,30 @@ +from nomad.actions import TaskQueue +from pydantic import Field +from temporalio import workflow + +with workflow.unsafe.imports_passed_through(): + from nomad.config.models.plugins import ActionEntryPoint + + +class SimpleActionEntryPoint(ActionEntryPoint): + task_queue: str = Field( + default=TaskQueue.CPU, description='Determines the task queue for this action' + ) + + def load(self): + from nomad.actions import Action + + from nomad_plugin_parser_example.actions.simple_action.activities import greet + from nomad_plugin_parser_example.actions.simple_action.workflows import SimpleWorkflow + + return Action( + task_queue=self.task_queue, + workflow=SimpleWorkflow, + activities=[greet], + ) + + +simple_action_entry_point = SimpleActionEntryPoint( + name='SimpleAction', + description='A simple action that returns a greeting.', +) diff --git a/src/nomad_plugin_parser_example/actions/simple_action/activities.py b/src/nomad_plugin_parser_example/actions/simple_action/activities.py new file mode 100644 index 0000000..a9053ab --- /dev/null +++ b/src/nomad_plugin_parser_example/actions/simple_action/activities.py @@ -0,0 +1,8 @@ +from temporalio import activity + +from nomad_plugin_parser_example.actions.simple_action.models import SimpleWorkflowInput + + +@activity.defn +async def greet(data: SimpleWorkflowInput) -> str: + return f'hello {data.name} - created by user {data.user_id} for upload {data.upload_id}' diff --git a/src/nomad_plugin_parser_example/actions/simple_action/models.py b/src/nomad_plugin_parser_example/actions/simple_action/models.py new file mode 100644 index 0000000..fa5dea4 --- /dev/null +++ b/src/nomad_plugin_parser_example/actions/simple_action/models.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel, Field + + +class SimpleWorkflowInput(BaseModel): + """Input model for the simple workflow""" + + upload_id: str = Field( + ..., + description='Unique identifier for the upload associated with the workflow.', + ) + user_id: str = Field( + ..., description='Unique identifier for the user who initiated the workflow.' + ) + + name: str = Field(..., description='The name to greet.') diff --git a/src/nomad_plugin_parser_example/actions/simple_action/workflows.py b/src/nomad_plugin_parser_example/actions/simple_action/workflows.py new file mode 100644 index 0000000..578ed56 --- /dev/null +++ b/src/nomad_plugin_parser_example/actions/simple_action/workflows.py @@ -0,0 +1,24 @@ +from datetime import timedelta + +from temporalio import workflow +from temporalio.common import RetryPolicy + +with workflow.unsafe.imports_passed_through(): + from nomad_plugin_parser_example.actions.simple_action.activities import greet + from nomad_plugin_parser_example.actions.simple_action.models import SimpleWorkflowInput + + +@workflow.defn +class SimpleWorkflow: + @workflow.run + async def run(self, data: SimpleWorkflowInput) -> str: + retry_policy = RetryPolicy( + maximum_attempts=3, + ) + result = await workflow.execute_activity( + greet, + data, + start_to_close_timeout=timedelta(seconds=60), + retry_policy=retry_policy, + ) + return result diff --git a/tests/actions/test_action.py b/tests/actions/test_action.py new file mode 100644 index 0000000..8168098 --- /dev/null +++ b/tests/actions/test_action.py @@ -0,0 +1,32 @@ +import pytest +from temporalio.testing import WorkflowEnvironment +from temporalio.worker import Worker + +from nomad_plugin_parser_example.actions.simple_action.activities import greet +from nomad_plugin_parser_example.actions.simple_action.models import SimpleWorkflowInput +from nomad_plugin_parser_example.actions.simple_action.workflows import SimpleWorkflow + + +@pytest.mark.asyncio +async def test_simple_workflow(): + task_queue = 'test-simple-workflow' + async with await WorkflowEnvironment.start_local() as env: + async with Worker( + env.client, + task_queue=task_queue, + workflows=[SimpleWorkflow], + activities=[greet], + ): + result = await env.client.execute_workflow( + SimpleWorkflow.run, + SimpleWorkflowInput( + upload_id='upload_id', + user_id='user_id', + name='World', + ), + id='test-workflow', + task_queue=task_queue, + ) + assert ( + result == 'hello World - created by user user_id for upload upload_id' + )