Skip to content

Commit

Permalink
feat: read automation function inputs from file
Browse files Browse the repository at this point in the history
  • Loading branch information
gjedlicska committed Dec 11, 2023
1 parent ae6fc85 commit 558b25b
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 33 deletions.
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ repos:

- repo: https://github.com/commitizen-tools/commitizen
hooks:
- id: commitizen
- id: commitizen-branch
stages:
- push
rev: 3.12.0
- id: commitizen
- id: commitizen-branch
stages:
- push
rev: v3.13.0

- repo: https://github.com/pycqa/isort
rev: 5.12.0
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "specklepy"
version = "2.17.8"
version = "2.17.14"
description = "The Python SDK for Speckle 2.0"
readme = "README.md"
authors = ["Speckle Systems <[email protected]>"]
Expand All @@ -18,7 +18,7 @@ packages = [
python = ">=3.8.0, <4.0"
pydantic = "^2.0"
appdirs = "^1.4.4"
gql = {extras = ["requests", "websockets"], version = "^3.3.0"}
gql = { extras = ["requests", "websockets"], version = "^3.3.0" }
ujson = "^5.3.0"
Deprecated = "^1.2.13"
stringcase = "^1.2.0"
Expand Down
91 changes: 65 additions & 26 deletions src/speckle_automate/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,58 @@
that conforms to the AutomateFunction "interface"
"""
import json
import os
import sys
import traceback
from pathlib import Path
from typing import Callable, Optional, TypeVar, Union, overload
from typing import Callable, Optional, Tuple, TypeVar, Union, overload

from pydantic import create_model
from pydantic.json_schema import GenerateJsonSchema

from speckle_automate.automation_context import AutomationContext
from speckle_automate.schema import AutomateBase, AutomationStatus
from speckle_automate.schema import AutomateBase, AutomationRunData, AutomationStatus

T = TypeVar("T", bound=AutomateBase)

AutomateFunction = Callable[[AutomationContext, T], None]
AutomateFunctionWithoutInputs = Callable[[AutomationContext], None]


def _read_input_data(inputs_location: str) -> str:
input_path = Path(inputs_location)
if not input_path.exists():
raise ValueError(f"Cannot find the function inputs file at {input_path}")

Check warning on line 27 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L25-L27

Added lines #L25 - L27 were not covered by tests

return input_path.read_text()

Check warning on line 29 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L29

Added line #L29 was not covered by tests


def _parse_input_data(
input_location: str, input_schema: Optional[type[T]]
) -> Tuple[AutomationRunData, Optional[T], str]:
input_json_string = _read_input_data(input_location)

Check warning on line 35 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L35

Added line #L35 was not covered by tests

class FunctionRunData(AutomateBase):
speckle_token: str
automation_run_data: AutomationRunData
function_inputs: None = None

Check warning on line 40 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L37-L40

Added lines #L37 - L40 were not covered by tests

parser_model = FunctionRunData

Check warning on line 42 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L42

Added line #L42 was not covered by tests

if input_schema:
parser_model = create_model(

Check warning on line 45 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L44-L45

Added lines #L44 - L45 were not covered by tests
"FunctionRunDataWithInputs",
function_inputs=(input_schema, ...),
__base__=FunctionRunData,
)

input_data = parser_model.model_validate_json(input_json_string)
return (

Check warning on line 52 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L51-L52

Added lines #L51 - L52 were not covered by tests
input_data.automation_run_data,
input_data.function_inputs,
input_data.speckle_token,
)


@overload
def execute_automate_function(
automate_function: AutomateFunction[T],
Expand All @@ -32,6 +69,13 @@ def execute_automate_function(automate_function: AutomateFunctionWithoutInputs)
...


class AutomateGenerateJsonSchema(GenerateJsonSchema):
def generate(self, schema, mode="validation"):
json_schema = super().generate(schema, mode=mode)
json_schema["$schema"] = self.schema_dialect
return json_schema

Check warning on line 76 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L74-L76

Added lines #L74 - L76 were not covered by tests


def execute_automate_function(
automate_function: Union[AutomateFunction[T], AutomateFunctionWithoutInputs],
input_schema: Optional[type[T]] = None,
Expand All @@ -40,49 +84,44 @@ def execute_automate_function(
# first arg is the python file name, we do not need that
args = sys.argv[1:]

if len(args) < 2:
raise ValueError("too few arguments specified need minimum 2")

if len(args) > 4:
raise ValueError("too many arguments specified, max supported is 4")
if len(args) != 2:
raise ValueError("Incorrect number of arguments specified need 2")

Check warning on line 88 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L87-L88

Added lines #L87 - L88 were not covered by tests

# we rely on a command name convention to decide what to do.
# this is here, so that the function authors do not see any of this
command = args[0]
command, argument = args

Check warning on line 92 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L92

Added line #L92 was not covered by tests

if command == "generate_schema":
path = Path(args[1])
path = Path(argument)

Check warning on line 95 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L95

Added line #L95 was not covered by tests
schema = json.dumps(
input_schema.model_json_schema(by_alias=True) if input_schema else {}
input_schema.model_json_schema(
by_alias=True, schema_generator=AutomateGenerateJsonSchema
)
if input_schema
else {}
)
path.write_text(schema)

elif command == "run":
automation_run_data = args[1]
function_inputs = args[2]

speckle_token = os.environ.get("SPECKLE_TOKEN", None)
if not speckle_token and len(args) != 4:
raise ValueError("Cannot get speckle token from arguments or environment")
automation_run_data, function_inputs, speckle_token = _parse_input_data(

Check warning on line 106 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L106

Added line #L106 was not covered by tests
argument, input_schema
)

speckle_token = speckle_token if speckle_token else args[3]
automation_context = AutomationContext.initialize(
automation_run_data, speckle_token
)

inputs = (
input_schema.model_validate_json(function_inputs)
if input_schema
else input_schema
)

if inputs:
if function_inputs:

Check warning on line 114 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L114

Added line #L114 was not covered by tests
automation_context = run_function(
automation_context,
automate_function, # type: ignore
inputs,
function_inputs, # type: ignore
)

else:
automation_context = AutomationContext.initialize(

Check warning on line 122 in src/speckle_automate/runner.py

View check run for this annotation

Codecov / codecov/patch

src/speckle_automate/runner.py#L122

Added line #L122 was not covered by tests
automation_run_data, speckle_token
)
automation_context = run_function(
automation_context,
automate_function, # type: ignore
Expand Down

0 comments on commit 558b25b

Please sign in to comment.