Files
speckle_automate_jupyter_ex…/function.ipynb
T
2023-08-25 16:03:06 +02:00

212 lines
6.2 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Speckle Automate notebook example\n",
"\n",
"This is an example jupyter notebook, that will be executed by speckle automate\n",
"\n",
"## Inputs\n",
"\n",
"The first two block block are defining two input data structures, `SpeckleProjectData` and `FunctionInputs`.\n",
"The project data class is following the data schema of Automate, you shouldn't modify it.\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from pydantic import BaseModel, ConfigDict\n",
"from stringcase import camelcase\n",
"\n",
"\n",
"class SpeckleProjectData(BaseModel):\n",
" \"\"\"\n",
" Only modify this to follow upstream changes in automate!\n",
"\n",
" Values of the project / model that triggered the run of this function.\n",
" \"\"\"\n",
"\n",
" project_id: str\n",
" model_id: str\n",
" version_id: str\n",
" speckle_server_url: str\n",
"\n",
" model_config = ConfigDict(alias_generator=camelcase, protected_namespaces=())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Parameters\n",
"\n",
"These values are supplied to the notebook, when its being run by automate.\n",
"\n",
"WANING: You really shouldn't modify this block, unless its following upstream changes from automate.\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [],
"source": [
"speckle_project_data = '{\"projectId\": \"03434ee1f1\", \"versionId\": \"09d2a0e55a\", \"modelId\": \"base design\", \"speckleServerUrl\": \"https://latest.speckle.dev\" }'\n",
"function_inputs = '{\"speckleType\": \"Objects.Geometry.Brep\"}'\n",
"token_env_var = \"SPECKLE_TOKEN\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Function inputs\n",
"\n",
"The `FunctionInputs` class defines the schema for the values, this function requires to run.\n",
"These values will be provided by the users of the function.\n",
"\n",
"Automate uses the Json Schema, generated from the class, to validate user provided values.\n",
"\n",
"The schema block is tagget with the `function_input` tag, do not remove that!\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"tags": [
"function_inputs"
]
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\"description\": \"User defined inputs to the function.\", \"properties\": {\"speckleType\": {\"title\": \"Speckletype\", \"type\": \"string\"}}, \"required\": [\"speckleType\"], \"title\": \"FunctionInputs\", \"type\": \"object\"}\n"
]
}
],
"source": [
"from pydantic import BaseModel, ConfigDict\n",
"from stringcase import camelcase\n",
"import json\n",
"\n",
"\n",
"class FunctionInputs(BaseModel):\n",
" \"\"\"User defined inputs to the function.\"\"\"\n",
"\n",
" speckle_type: str\n",
"\n",
" model_config = ConfigDict(alias_generator=camelcase)\n",
"\n",
"\n",
"print(json.dumps(FunctionInputs.model_json_schema()))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Function logic\n",
"\n",
"in this block we're defining the actual business logic of the function.\n",
"\n",
"By all means modify this block but do keep the function signature compatible with the executing main function.\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"from specklepy.api.client import SpeckleClient\n",
"from specklepy.objects import Base\n",
"from specklepy.transports.memory import MemoryTransport\n",
"from specklepy.transports.server import ServerTransport\n",
"from specklepy.api.operations import receive\n",
"from typing import Iterable\n",
"\n",
"\n",
"def flatten_base(base: Base) -> Iterable[Base]:\n",
" if hasattr(base, \"elements\"):\n",
" for element in base.elements:\n",
" yield from flatten_base(element)\n",
" yield base\n",
"\n",
"\n",
"def automate_function(\n",
" project_data: SpeckleProjectData,\n",
" function_inputs: FunctionInputs,\n",
" speckle_token: str,\n",
"):\n",
" client = SpeckleClient(project_data.speckle_server_url)\n",
" client.authenticate_with_token(speckle_token)\n",
" commit = client.commit.get(project_data.project_id, project_data.version_id)\n",
"\n",
" memory_transport = MemoryTransport()\n",
" server_transport = ServerTransport(project_data.project_id, client)\n",
" base = receive(commit.referencedObject, server_transport, memory_transport)\n",
"\n",
" matching_types = [\n",
" b for b in flatten_base(base) if b.speckle_type == function_inputs.speckle_type\n",
" ]\n",
" print(f\"Found {len(matching_types)} elements that have the speckle_type {function_inputs.speckle_type}\")"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"\n",
"def main():\n",
" inputs = FunctionInputs.model_validate_json(function_inputs)\n",
" project_data = SpeckleProjectData.model_validate_json(speckle_project_data)\n",
" speckle_token = os.environ[token_env_var]\n",
" print(project_data)\n",
" print(inputs)\n",
"\n",
" automate_function(project_data, inputs, speckle_token)\n",
" \n",
"main()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}