generated from specklesystems/speckle_automate_python_example
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
20ae21a
commit ac11eb5
Showing
3 changed files
with
73 additions
and
93 deletions.
There are no files selected for viewing
This file contains 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,50 @@ | ||
def automate_function( | ||
automate_context: AutomationContext, | ||
function_inputs: FunctionInputs, | ||
) -> None: | ||
"""This is an example Speckle Automate function. | ||
Args: | ||
automate_context: A context helper object, that carries relevant information | ||
about the runtime context of this function. | ||
It gives access to the Speckle project data, that triggered this run. | ||
It also has convenience methods attach result data to the Speckle model. | ||
function_inputs: An instance object matching the defined schema. | ||
""" | ||
|
||
# the context provides a convenient way, to receive the triggering version | ||
version_root_object = automate_context.receive_version() | ||
|
||
flat_list_of_objects = flatten_base(version_root_object) | ||
|
||
# filter the list to only include objects that are displayable. | ||
# this is a simple example, that checks if the object has a displayValue | ||
displayable_objects = [ | ||
speckle_object | ||
for speckle_object in flat_list_of_objects | ||
if ( | ||
getattr(speckle_object, "displayValue", None) | ||
or getattr(speckle_object, "@displayValue", None) | ||
) | ||
and getattr(speckle_object, "id", None) is not None | ||
] | ||
|
||
if len(displayable_objects) == 0: | ||
automate_context.mark_run_failed( | ||
"Automation failed: No displayable objects found." | ||
) | ||
|
||
else: | ||
# select a random object from the list | ||
random_object = random.choice(displayable_objects) | ||
|
||
automate_context.attach_info_to_objects( | ||
category="Selected Object", | ||
object_ids=[random_object.id], | ||
message=function_inputs.comment_phrase, | ||
) | ||
|
||
automate_context.mark_run_success("Added a comment to a random object.") | ||
|
||
# set the automation context view, to the original model / version view | ||
automate_context.set_context_view() |
This file contains 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,16 @@ | ||
from pydantic import Field | ||
from speckle_automate import AutomateBase | ||
|
||
|
||
class FunctionInputs(AutomateBase): | ||
"""These are function author defined values. | ||
Automate will make sure to supply them matching the types specified here. | ||
Please use the pydantic model schema to define your inputs: | ||
https://docs.pydantic.dev/latest/usage/models/ | ||
""" | ||
|
||
comment_phrase: str = Field( | ||
title="Comment Phrase", | ||
description="This phrase will be added to a random model element.", | ||
) |
This file contains 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 |
---|---|---|
@@ -1,103 +1,17 @@ | ||
"""This module contains the function's business logic. | ||
Use the automation_context module to wrap your function in an Automate context helper. | ||
""" | ||
This main entry point is the command line interface for the Speckle Automate function. | ||
""" | ||
|
||
from pydantic import Field, SecretStr | ||
from speckle_automate import ( | ||
AutomateBase, | ||
AutomationContext, | ||
execute_automate_function, | ||
) | ||
|
||
from flatten import flatten_base | ||
|
||
|
||
class FunctionInputs(AutomateBase): | ||
"""These are function author-defined values. | ||
Automate will make sure to supply them matching the types specified here. | ||
Please use the pydantic model schema to define your inputs: | ||
https://docs.pydantic.dev/latest/usage/models/ | ||
""" | ||
|
||
# An example of how to use secret values. | ||
whisper_message: SecretStr = Field(title="This is a secret message") | ||
forbidden_speckle_type: str = Field( | ||
title="Forbidden speckle type", | ||
description=( | ||
"If a object has the following speckle_type," | ||
" it will be marked with an error." | ||
), | ||
) | ||
|
||
|
||
def automate_function( | ||
automate_context: AutomationContext, | ||
function_inputs: FunctionInputs, | ||
) -> None: | ||
"""This is an example Speckle Automate function. | ||
Args: | ||
automate_context: A context-helper object that carries relevant information | ||
about the runtime context of this function. | ||
It gives access to the Speckle project data that triggered this run. | ||
It also has convenient methods for attaching result data to the Speckle model. | ||
function_inputs: An instance object matching the defined schema. | ||
""" | ||
# The context provides a convenient way to receive the triggering version. | ||
version_root_object = automate_context.receive_version() | ||
|
||
objects_with_forbidden_speckle_type = [ | ||
b | ||
for b in flatten_base(version_root_object) | ||
if b.speckle_type == function_inputs.forbidden_speckle_type | ||
] | ||
count = len(objects_with_forbidden_speckle_type) | ||
|
||
if count > 0: | ||
# This is how a run is marked with a failure cause. | ||
automate_context.attach_error_to_objects( | ||
category="Forbidden speckle_type" | ||
f" ({function_inputs.forbidden_speckle_type})", | ||
object_ids=[o.id for o in objects_with_forbidden_speckle_type if o.id], | ||
message="This project should not contain the type: " | ||
f"{function_inputs.forbidden_speckle_type}", | ||
) | ||
automate_context.mark_run_failed( | ||
"Automation failed: " | ||
f"Found {count} object that have one of the forbidden speckle types: " | ||
f"{function_inputs.forbidden_speckle_type}" | ||
) | ||
|
||
# Set the automation context view to the original model/version view | ||
# to show the offending objects. | ||
automate_context.set_context_view() | ||
|
||
else: | ||
automate_context.mark_run_success("No forbidden types found.") | ||
|
||
# If the function generates file results, this is how it can be | ||
# attached to the Speckle project/model | ||
# automate_context.store_file_result("./report.pdf") | ||
|
||
|
||
def automate_function_without_inputs(automate_context: AutomationContext) -> None: | ||
"""A function example without inputs. | ||
If your function does not need any input variables, | ||
besides what the automation context provides, | ||
the inputs argument can be omitted. | ||
""" | ||
pass | ||
|
||
import Exercises.exercise_0.inputs.FunctionInputs as FunctionInputs | ||
import Exercises.exercise_0.function.automate_function as automate_function | ||
|
||
# make sure to call the function with the executor | ||
# Pass in the function reference with the inputs schema to the executor. | ||
# If the function has no arguments, the executor can handle it like so | ||
# execute_automate_function(automate_function_without_inputs) | ||
if __name__ == "__main__": | ||
# NOTE: always pass in the automate function by its reference; do not invoke it! | ||
|
||
# Pass in the function reference with the inputs schema to the executor. | ||
execute_automate_function(automate_function, FunctionInputs) | ||
|
||
# If the function has no arguments, the executor can handle it like so | ||
# execute_automate_function(automate_function_without_inputs) |