-
Notifications
You must be signed in to change notification settings - Fork 0
Python sdk #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Python sdk #37
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
5dfb3ad
feat: add .gitignore file for Python and tooling caches
nicosammito 4767cb9
feat: add Python version and pyproject.toml for SDK configuration
nicosammito 6598969
feat: add build_definitions.py for generating Python modules from cod…
nicosammito 4a7f4e4
feat: add initial implementation of event and function managers with …
nicosammito 3442582
feat: add .gitignore file to exclude Python environment and cache files
nicosammito 96987c5
feat: add initial project structure with example action and runtime f…
nicosammito d602ddf
feat: add unit tests for Pydantic-based data types and export functio…
nicosammito 68c02ee
feat: update .gitignore to exclude generated definitions from code0-d…
nicosammito bdd8681
feat: configure editable install mode for setuptools compatibility wi…
nicosammito a65fa02
feat: update .gitignore to exclude IDE configuration files
nicosammito e321de5
feat: add CI configuration for Python SDK build and publish process
nicosammito 171cf3d
Update py/pyproject.toml
nicosammito File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Python | ||
| __pycache__/ | ||
| *.py[cod] | ||
| *.egg-info/ | ||
| .eggs/ | ||
| build/ | ||
| dist/ | ||
| .venv/ | ||
| venv/ | ||
|
|
||
| # Tooling caches | ||
| .pytest_cache/ | ||
| .mypy_cache/ | ||
|
|
||
| # IDE (machine-specific: interpreter paths, module config) | ||
| .idea/ | ||
| *.iml | ||
|
|
||
| # Node helper (hercules/_tsgen): keep sources + lockfile, ignore installed deps | ||
| hercules/_tsgen/node_modules/ | ||
|
|
||
| # Generated definitions (built from a code0-definition release via | ||
| # scripts/build_definitions.py); regenerated, not committed. | ||
| hercules/definitions/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 3.12 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| # code0-hercules (Python) | ||
|
|
||
| Python SDK for the hercules action runner — the counterpart to the TypeScript | ||
| `@code0-tech/hercules` package. Define data types, functions, and events, and | ||
| connect them to aquila. | ||
|
|
||
| ## Install | ||
|
|
||
| ```bash | ||
| pip install code0-hercules | ||
| ``` | ||
|
|
||
| Requirements: | ||
|
|
||
| - **Python 3.10+** | ||
| - **Node.js** — data-type schemas are converted to/from TypeScript via a bundled | ||
| Node helper (`hercules/_tsgen`). Its npm dependencies are installed automatically | ||
| on first use. | ||
|
|
||
| ## Develop | ||
|
|
||
| This project uses [uv](https://docs.astral.sh/uv/). | ||
|
|
||
| ```bash | ||
| uv sync # create .venv + install (incl. dev deps) | ||
| npm ci --prefix hercules/_tsgen # install the Node schema helper | ||
| uv run pytest # run the tests | ||
| ``` | ||
|
|
||
| The runnable example lives in [`examples/simple-example-py`](examples/simple-example-py). | ||
|
|
||
| ## Built-in definitions | ||
|
|
||
| The built-in data types / functions in `hercules/definitions/` are **generated** | ||
| (not committed) from a [`code0-definition`](https://github.com/code0-tech/code0-definition) | ||
| release: | ||
|
|
||
| ```bash | ||
| uv run python scripts/build_definitions.py --version def-0.0.34 | ||
| ``` | ||
|
|
||
| ## Build & release | ||
|
|
||
| Packages are built with `uv build` and published to PyPI from CI: | ||
|
|
||
| - **`build.yml`** builds and tests the package on every push. | ||
| - **`publish.yml`** runs on a pushed git tag: it sets the package version from the | ||
| tag, regenerates the definitions, builds, and publishes to PyPI via | ||
| [trusted publishing](https://docs.pypi.org/trusted-publishers/) (OIDC — no token). | ||
|
|
||
| To cut a release, push a PEP 440 version tag (e.g. `0.1.0`): | ||
|
|
||
| ```bash | ||
| git tag 0.1.0 && git push origin 0.1.0 | ||
| ``` | ||
|
|
||
| The `code0-definition` release used for the built-in definitions is controlled by | ||
| the `HERCULES_DEFINITIONS_VERSION` repository variable (default `def-0.0.34`). | ||
|
|
||
| Build locally: | ||
|
|
||
| ```bash | ||
| uv build # -> dist/*.whl and dist/*.tar.gz | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .venv/ | ||
| __pycache__/ | ||
| *.py[cod] | ||
| .env | ||
| module.json |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 3.12 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # simple-example-py | ||
|
|
||
| A minimal example action built with the Python `hercules` SDK. | ||
|
|
||
| This is a self-contained [uv](https://docs.astral.sh/uv/) project that depends on | ||
| the SDK from the local checkout (`../..`), mirroring the TypeScript example's | ||
| `"@code0-tech/hercules": "file:../.."` setup. | ||
|
|
||
| ## Setup | ||
|
|
||
| ```bash | ||
| uv sync # creates .venv and installs hercules (editable) + deps | ||
| ``` | ||
|
|
||
| ## Run | ||
|
|
||
| ```bash | ||
| uv run python index.py | ||
| ``` | ||
|
|
||
| Environment variables (see `example.env`): `ACTION_ID`, `VERSION`, `AQUILA_URL`, | ||
| `AUTH_TOKEN`. | ||
|
|
||
| ## Export the action as a Module JSON | ||
|
|
||
| Without connecting to aquila: | ||
|
|
||
| ```bash | ||
| uv run hercules export index.py # print to stdout | ||
| uv run hercules export index.py -o module.json | ||
| uv run hercules export index.py --compact | ||
| ``` | ||
|
|
||
| ## Notes | ||
|
|
||
| - Requires **Python 3.10+** (pinned to 3.12 via `.python-version`). | ||
| - The SDK converts data-type schemas to TypeScript via a bundled Node helper, so | ||
| **Node.js** must be installed for data types to build. |
Empty file.
13 changes: 13 additions & 0 deletions
13
py/examples/simple-example-py/data_types/email_data_type.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from hercules import Identifier, Name, Schema | ||
| from hercules.schema import RootModel, Annotated, StringConstraints | ||
|
|
||
|
|
||
| class EmailModel(RootModel[Annotated[str, StringConstraints(pattern=r"^[^@]+@[^@]+\.[^@]+$")]]): | ||
| """An email address, described as a constrained string.""" | ||
|
|
||
|
|
||
| @Identifier("email_address") | ||
| @Name({"code": "en-US", "content": "Email Address"}) | ||
| @Schema(EmailModel) | ||
| class EmailDataType: | ||
| pass |
Empty file.
15 changes: 15 additions & 0 deletions
15
py/examples/simple-example-py/events/user_created_runtime_event.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| from hercules import Description, DisplayMessage, Identifier, Name, Signature | ||
|
|
||
|
|
||
| @Identifier("user_created") | ||
| @Signature("(): {userId: number}") | ||
| @Name({"code": "en-US", "content": "User created event"}) | ||
| @DisplayMessage({"code": "en-US", "content": "Triggers on user creation"}) | ||
| @Description( | ||
| { | ||
| "code": "en-US", | ||
| "content": "Triggers on user creation and has a payload including the user database id", | ||
| } | ||
| ) | ||
| class UserCreatedRuntimeEvent: | ||
| pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| ACTION_ID=testing-action | ||
| VERSION=0.0.0 | ||
| AQUILA_URL=127.0.0.1:8081 | ||
| AUTH_TOKEN=your_auth_token_here |
Empty file.
19 changes: 19 additions & 0 deletions
19
py/examples/simple-example-py/functions/fibonacci_function.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| from hercules import Identifier, Name, Parameter | ||
|
|
||
| from functions.fibonacci_runtime_function import FibonacciRuntimeFunction | ||
|
|
||
|
|
||
| @Identifier("fibonacci") | ||
| @Name({"code": "en-US", "content": "Compute Fibonacci Number"}) | ||
| @Parameter( | ||
| { | ||
| "runtime_name": "test", | ||
| "name": [{"code": "en-US", "content": "Input Number"}], | ||
| "description": [ | ||
| {"code": "en-US", "content": "The position in the Fibonacci sequence"} | ||
| ], | ||
| "default_value": 10, | ||
| } | ||
| ) | ||
| class FibonacciFunction(FibonacciRuntimeFunction): | ||
| pass |
27 changes: 27 additions & 0 deletions
27
py/examples/simple-example-py/functions/fibonacci_runtime_function.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| from hercules import ( | ||
| DisplayMessage, | ||
| FunctionContext, | ||
| Identifier, | ||
| Name, | ||
| OmitRuntimeFunction, | ||
| Parameter, | ||
| RuntimeFunctionRunnable, | ||
| Signature, | ||
| ) | ||
|
|
||
|
|
||
| @Identifier("fibonacci_runtime") | ||
| @Signature("(test: number): number") | ||
| @Name({"code": "en-US", "content": "Fibonacci (Runtime)"}) | ||
| @DisplayMessage({"code": "en-US", "content": "Computes the n-th Fibonacci number"}) | ||
| @OmitRuntimeFunction() | ||
| @Parameter({"runtime_name": "test", "name": [{"code": "en-US", "content": "N"}]}) | ||
| class FibonacciRuntimeFunction(RuntimeFunctionRunnable): | ||
| def run(self, context: FunctionContext, test): | ||
| print(f"[fibonacci] project={context.project_id} execution={context.execution_id}") | ||
| return self._fib(test) | ||
|
|
||
| def _fib(self, n): | ||
| if n <= 1: | ||
| return n | ||
| return self._fib(n - 1) + self._fib(n - 2) |
41 changes: 41 additions & 0 deletions
41
py/examples/simple-example-py/functions/for_each_runtime_function.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| from hercules import ( | ||
| DisplayMessage, | ||
| FunctionContext, | ||
| Identifier, | ||
| Name, | ||
| Parameter, | ||
| RuntimeFunctionRunnable, | ||
| Signature, | ||
| ) | ||
|
|
||
|
|
||
| @Identifier("for_each_runtime") | ||
| @Signature("<T>(list: LIST<T>, consumer: CONSUMER<T>): void") | ||
| @Name({"code": "en-US", "content": "For Each"}) | ||
| @DisplayMessage({"code": "en-US", "content": "For each element of ${list} do ${consumer}"}) | ||
| @Parameter( | ||
| { | ||
| "runtime_name": "list", | ||
| "name": [{"code": "en-US", "content": "List"}], | ||
| "description": [ | ||
| {"code": "en-US", "content": "The list whose elements are iterated over"} | ||
| ], | ||
| } | ||
| ) | ||
| @Parameter( | ||
| { | ||
| "runtime_name": "consumer", | ||
| "name": [{"code": "en-US", "content": "Consumer"}], | ||
| "description": [ | ||
| { | ||
| "code": "en-US", | ||
| "content": "The sub flow (item) => void executed once per element", | ||
| } | ||
| ], | ||
| } | ||
| ) | ||
| class ForEachRuntimeFunction(RuntimeFunctionRunnable): | ||
| async def run(self, context: FunctionContext, items, consumer): | ||
| for element in items: | ||
| result = await consumer(element) | ||
| print("[for_each] sub flow result:", result) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeScript has been kind of an exception in the other packages. I would prefer
pythonhere