6 Commits

Author SHA1 Message Date
Gergo Jedlicska c09bd87092 bump tools 2025-11-17 20:50:31 +01:00
Gergő Jedlicska e73c4f6bdd bump specklepy 2024-10-03 16:35:07 +01:00
Gergő Jedlicska 74356833ce Merge branch 'main' of github.com:specklesystems/speckle_automate_python_example into gergo/specklepy_bump 2024-10-03 16:32:31 +01:00
Gergő Jedlicska 99aeb0453b feat: update specklepy 2024-06-07 19:26:14 +02:00
Gergő Jedlicska d0dbcb6d17 Merge branch 'main' into gergo/specklepy_bump 2024-06-07 19:25:04 +02:00
Gergő Jedlicska 9ebe9d3a29 feat: bump to new specklepy 2024-06-07 18:02:14 +02:00
12 changed files with 1341 additions and 145 deletions
+5 -2
View File
@@ -4,6 +4,9 @@
"name": "Python 3",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
"features": {
"ghcr.io/devcontainers-contrib/features/poetry:2": {}
},
"remoteEnv": {
"SPECKLE_TOKEN": "foobar"
@@ -19,7 +22,7 @@
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "cp .env.example .env && python -m venv .venv && . .venv/bin/activate && pip install --upgrade pip && pip install .[dev]",
"postCreateCommand": "cp .env.example .env && POETRY_VIRTUALENVS_IN_PROJECT=true poetry install --no-root",
// Configure tool-specific properties.
"customizations": {
@@ -37,4 +40,4 @@
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
}
-4
View File
@@ -4,7 +4,3 @@ updates:
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
+16 -10
View File
@@ -1,9 +1,9 @@
name: "build and deploy Speckle functions"
name: 'build and deploy Speckle functions'
on:
workflow_dispatch:
push:
tags:
- "*"
- '*'
jobs:
publish-automate-function-version: # make sure the action works on a clean machine without building
@@ -11,13 +11,19 @@ jobs:
FUNCTION_SCHEMA_FILE_NAME: functionSchema.json
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.7
- uses: actions/setup-python@v6
- uses: actions/checkout@v4.1.6
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
pip install .[dev]
python-version: '3.11'
- name: Install and configure Poetry
uses: snok/install-poetry@v1
with:
version: 1.3.2
virtualenvs-create: false
virtualenvs-in-project: false
installer-parallel: true
- name: Restore dependencies
run: poetry install --no-root
- name: Extract functionInputSchema
id: extract_schema
run: |
@@ -25,8 +31,8 @@ jobs:
- name: Speckle Automate Function - Build and Publish
uses: specklesystems/speckle-automate-github-composite-action@0.8.1
with:
speckle_automate_url: ${{ env.SPECKLE_AUTOMATE_URL || vars.SPECKLE_AUTOMATE_URL || 'https://automate.speckle.dev' }}
speckle_automate_url: ${{ env.SPECKLE_AUTOMATE_URL || vars.SPECKLE_AUTOMATE_URL || 'https://automate.speckle.dev' }}
speckle_token: ${{ secrets.SPECKLE_FUNCTION_TOKEN }}
speckle_function_id: ${{ secrets.SPECKLE_FUNCTION_ID }}
speckle_function_input_schema_file_path: ${{ env.FUNCTION_SCHEMA_FILE_NAME }}
speckle_function_command: "python -u main.py run"
speckle_function_command: 'python -u main.py run'
+7 -7
View File
@@ -1,16 +1,16 @@
# We use the official Python 3.11 image as our base image and will add our code to it. For more details, see https://hub.docker.com/_/python
FROM python:3.11-slim
# We install poetry to generate a list of dependencies which will be required by our application
RUN pip install poetry
# We set the working directory to be the /home/speckle directory; all of our files will be copied here.
WORKDIR /home/speckle
# Copy pyproject.toml first to leverage Docker layer caching
COPY pyproject.toml /home/speckle/
# Install the required Python packages (production dependencies only)
RUN pip install --no-cache-dir .
# Copy all of our code and assets from the local directory into the /home/speckle directory of the container.
# We also ensure that the user 'speckle' owns these files, so it can access them
# This assumes that the Dockerfile is in the same directory as the rest of the code
COPY . /home/speckle
COPY . /home/speckle
# Using poetry, we generate a list of requirements, save them to requirements.txt, and then use pip to install them
RUN poetry export --format requirements.txt --output /home/speckle/requirements.txt && pip install --requirement /home/speckle/requirements.txt
+9 -83
View File
@@ -9,49 +9,19 @@ It also has some sane defaults for development environment setups.
## Getting started
1. Use this template repository to create a new repository in your own / organization's profile.
1. Register the function
Register the function
### Add new dependencies
To add new Python package dependencies to the project, edit the `pyproject.toml` file:
**For packages your function needs to run** (like pandas, requests, etc.):
```toml
dependencies = [
"specklepy==3.0.0",
"pandas==2.1.0", # Add production dependencies here
]
```
**For development tools** (like testing or formatting tools):
```toml
[project.optional-dependencies]
dev = [
"black==23.12.1",
"pytest-mock==3.11.1", # Add development dependencies here
# ... other dev tools
]
```
**How to decide which section?**
- If your `main.py` (or other function logic) imports it → `dependencies`
- If it's just a tool to help you code → `[project.optional-dependencies].dev`
Example:
```python
# In your main.py
import pandas as pd # ← This goes in dependencies
import specklepy # ← This goes in dependencies
# You won't import these in main.py:
# pytest, black, mypy ← These go in [project.optional-dependencies].dev
```
To add new Python package dependencies to the project, use the following:
`$ poetry add pandas`
### Change launch variables
Describe how the launch.json should be edited.
### GitHub Codespaces
### Github Codespaces
Create a new repo from this template, and use the create new code.
@@ -73,57 +43,13 @@ Create a new repo from this template, and use the create new code.
## Developer Requirements
1. Install the following:
- [Python 3.11+](https://www.python.org/downloads/)
1. Run the following to set up your development environment:
```bash
python -m venv .venv
# On Windows
.venv\Scripts\activate
# On macOS/Linux
source .venv/bin/activate
pip install --upgrade pip
pip install .[dev]
```
**What this installs:**
- All the packages your function needs to run (`dependencies`)
- Plus development tools like testing and code formatting (`[project.optional-dependencies].dev`)
**Why separate sections?**
- `dependencies`: Only what gets deployed with your function (lightweight)
- `dev` dependencies: Extra tools to help you write better code locally
- [Python 3](https://www.python.org/downloads/)
- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
1. Run `poetry shell && poetry install` to install the required Python packages.
## Building and Testing
The code can be tested locally by running `pytest`.
### Alternative dependency managers
This template uses the modern **PEP 621** standard in `pyproject.toml`, which works with all modern Python dependency managers:
#### Using Poetry
```bash
poetry install # Automatically reads pyproject.toml
```
#### Using uv
```bash
uv sync # Automatically reads pyproject.toml
```
#### Using pip-tools
```bash
pip-compile pyproject.toml # Generate requirements.txt from pyproject.toml
pip install -r requirements.txt
```
#### Using pdm
```bash
pdm install # Automatically reads pyproject.toml
```
**Advantage**: All tools read the same `pyproject.toml` file, so there's no need to keep multiple files in sync!
The code can be tested locally by running `poetry run pytest`.
### Building and running the Docker Container Image
+4 -4
View File
@@ -7,8 +7,8 @@ from specklepy.objects import Base
def flatten_base(base: Base) -> Iterable[Base]:
"""Flatten a base object into an iterable of bases.
This function recursively traverses the `elements` or `@elements` attribute of the
This function recursively traverses the `elements` or `@elements` attribute of the
base object, yielding each nested base object.
Args:
@@ -19,9 +19,9 @@ def flatten_base(base: Base) -> Iterable[Base]:
"""
# Attempt to get the elements attribute, fallback to @elements if necessary
elements = getattr(base, "elements", getattr(base, "@elements", None))
if elements is not None:
for element in elements:
yield from flatten_base(element)
yield base
+2 -2
View File
@@ -42,7 +42,7 @@ def automate_function(
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 results to the Speckle model.
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.
@@ -60,7 +60,7 @@ def automate_function(
automate_context.attach_error_to_objects(
category="Forbidden speckle_type"
f" ({function_inputs.forbidden_speckle_type})",
affected_objects=objects_with_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}",
)
+2
View File
@@ -0,0 +1,2 @@
[tools]
python = '3.13'
Generated
+1267
View File
File diff suppressed because it is too large Load Diff
+24 -27
View File
@@ -1,37 +1,34 @@
[project]
name = "speckle-automate-function"
[tool.poetry]
name = "speckle-automate-py"
version = "0.1.0"
requires-python = ">=3.11"
authors = [{ name = "Speckle Systems", email = "hello@speckle.systems" }]
maintainers = [{ name = "Speckle Systems", email = "hello@speckle.systems" }]
description = "A Speckle Automate function template using specklepy"
description = "Example function for Speckle Automate using specklepy"
authors = ["Gergő Jedlicska <gergo@jedlicska.com>"]
readme = "README.md"
license = "Apache-2.0"
keywords = ["speckle", "automate", "bim", "aec"]
dependencies = ["specklepy==3.0.0"]
[tool.poetry.dependencies]
python = "^3.11"
specklepy = "^2.19.6"
[project.optional-dependencies]
dev = [
"mypy==1.13.0",
"pytest==7.4.4",
"ruff==0.11.12",
]
[tool.poetry.group.dev.dependencies]
black = "^23.3.0"
mypy = "^1.3.0"
ruff = "^0.0.271"
pydantic-settings = "^2.3.0"
pytest = "^7.4.2"
# specklepy = { path = "../specklepy", develop = true }
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.ruff]
exclude = [".venv", "**/*.yml"]
[tool.ruff.lint]
select = [
"E", # pycodestyle
"F", # pyflakes
"UP", # pyupgrade
"D", # pydocstyle
"I", # isort
"E", # pycodestyle
"F", # pyflakes
"UP", # pyupgrade
"D", # pydocstyle
"I", # isort
]
[tool.ruff.lint.pydocstyle]
[tool.ruff.pydocstyle]
convention = "google"
[tool.setuptools]
py-modules = []
-1
View File
@@ -1 +0,0 @@
"""Tests for the automate function."""
+5 -5
View File
@@ -1,20 +1,20 @@
"""Run integration tests with a speckle server."""
from pydantic import SecretStr
from speckle_automate import (
AutomationContext,
AutomationRunData,
AutomationStatus,
run_function,
run_function
)
from speckle_automate.fixtures import * # noqa: F403
from main import FunctionInputs, automate_function
from speckle_automate.fixtures import *
def test_function_run(
test_automation_run_data: AutomationRunData, test_automation_token: str
):
def test_function_run(test_automation_run_data: AutomationRunData, test_automation_token: str):
"""Run an integration test for the automate function."""
automation_context = AutomationContext.initialize(
test_automation_run_data, test_automation_token