Skip to content

Commit 4bcf005

Browse files
chore(deps): drop poetry as a dependency in the python automate template (#40)
* chore: bump specklepy * refactor: requirements files * refactor: dockerfile * refactor: update GitHub actions * refactor: update devcontainer config * docs: updated `README` * docs: better explanations * docs: wording * chore: dependabot config * docs: keeping things in sync * fix: skip pip upgrade * refactor: updated devcontainer * refactor: toml instead of requirements * refactor: update docker * docs: updated `README` * chore: classifiers does nothing * chore: wrap up the v3 transition --------- Co-authored-by: Gergő Jedlicska <[email protected]>
1 parent cf3a8f4 commit 4bcf005

File tree

11 files changed

+136
-1484
lines changed

11 files changed

+136
-1484
lines changed

.devcontainer/devcontainer.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
"name": "Python 3",
55
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
66
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
7-
"features": {
8-
"ghcr.io/devcontainers-contrib/features/poetry:2": {}
9-
},
107

118
"remoteEnv": {
129
"SPECKLE_TOKEN": "foobar"
@@ -22,7 +19,7 @@
2219
// "forwardPorts": [],
2320

2421
// Use 'postCreateCommand' to run commands after the container is created.
25-
"postCreateCommand": "cp .env.example .env && POETRY_VIRTUALENVS_IN_PROJECT=true poetry install --no-root",
22+
"postCreateCommand": "cp .env.example .env && python -m venv .venv && . .venv/bin/activate && pip install --upgrade pip && pip install .[dev]",
2623

2724
// Configure tool-specific properties.
2825
"customizations": {
@@ -40,4 +37,4 @@
4037

4138
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
4239
// "remoteUser": "root"
43-
}
40+
}

.github/dependabot.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ updates:
44
directory: "/"
55
schedule:
66
interval: "daily"
7+
- package-ecosystem: "pip"
8+
directory: "/"
9+
schedule:
10+
interval: "weekly"

.github/workflows/main.yml

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
name: 'build and deploy Speckle functions'
1+
name: "build and deploy Speckle functions"
22
on:
33
workflow_dispatch:
44
push:
55
tags:
6-
- '*'
6+
- "*"
77

88
jobs:
99
publish-automate-function-version: # make sure the action works on a clean machine without building
@@ -14,15 +14,10 @@ jobs:
1414
- uses: actions/[email protected]
1515
- uses: actions/setup-python@v5
1616
with:
17-
python-version: '3.11'
18-
- name: Install poetry
17+
python-version: "3.11"
18+
- name: Install dependencies
1919
run: |
20-
pip install poetry==1.8.4 &&
21-
poetry config virtualenvs.create false &&
22-
poetry config virtualenvs.in-project false &&
23-
poetry config installer.parallel true
24-
- name: Restore dependencies
25-
run: poetry install --no-root
20+
pip install .[dev]
2621
- name: Extract functionInputSchema
2722
id: extract_schema
2823
run: |
@@ -34,4 +29,4 @@ jobs:
3429
speckle_token: ${{ secrets.SPECKLE_FUNCTION_TOKEN }}
3530
speckle_function_id: ${{ secrets.SPECKLE_FUNCTION_ID }}
3631
speckle_function_input_schema_file_path: ${{ env.FUNCTION_SCHEMA_FILE_NAME }}
37-
speckle_function_command: 'python -u main.py run'
32+
speckle_function_command: "python -u main.py run"

Dockerfile

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# 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
22
FROM python:3.11-slim
33

4-
# We install poetry to generate a list of dependencies which will be required by our application
5-
RUN pip install poetry==1.8.4
6-
74
# We set the working directory to be the /home/speckle directory; all of our files will be copied here.
85
WORKDIR /home/speckle
96

7+
# Copy pyproject.toml first to leverage Docker layer caching
8+
COPY pyproject.toml /home/speckle/
9+
10+
# Install the required Python packages (production dependencies only)
11+
RUN pip install --no-cache-dir .
12+
1013
# Copy all of our code and assets from the local directory into the /home/speckle directory of the container.
1114
# We also ensure that the user 'speckle' owns these files, so it can access them
1215
# This assumes that the Dockerfile is in the same directory as the rest of the code
13-
COPY . /home/speckle
14-
15-
# Using poetry, we generate a list of requirements, save them to requirements.txt, and then use pip to install them
16-
RUN poetry export --format requirements.txt --output /home/speckle/requirements.txt && pip install --requirement /home/speckle/requirements.txt
16+
COPY . /home/speckle

README.md

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,49 @@ It also has some sane defaults for development environment setups.
99
## Getting started
1010

1111
1. Use this template repository to create a new repository in your own / organization's profile.
12-
13-
Register the function
12+
1. Register the function
1413

1514
### Add new dependencies
1615

17-
To add new Python package dependencies to the project, use the following:
18-
`$ poetry add pandas`
16+
To add new Python package dependencies to the project, edit the `pyproject.toml` file:
17+
18+
**For packages your function needs to run** (like pandas, requests, etc.):
19+
```toml
20+
dependencies = [
21+
"specklepy==3.0.0",
22+
"pandas==2.1.0", # Add production dependencies here
23+
]
24+
```
25+
26+
**For development tools** (like testing or formatting tools):
27+
```toml
28+
[project.optional-dependencies]
29+
dev = [
30+
"black==23.12.1",
31+
"pytest-mock==3.11.1", # Add development dependencies here
32+
# ... other dev tools
33+
]
34+
```
35+
36+
**How to decide which section?**
37+
- If your `main.py` (or other function logic) imports it → `dependencies`
38+
- If it's just a tool to help you code → `[project.optional-dependencies].dev`
39+
40+
Example:
41+
```python
42+
# In your main.py
43+
import pandas as pd # ← This goes in dependencies
44+
import specklepy # ← This goes in dependencies
45+
46+
# You won't import these in main.py:
47+
# pytest, black, mypy ← These go in [project.optional-dependencies].dev
48+
```
1949

2050
### Change launch variables
2151

2252
Describe how the launch.json should be edited.
2353

24-
### Github Codespaces
54+
### GitHub Codespaces
2555

2656
Create a new repo from this template, and use the create new code.
2757

@@ -43,13 +73,57 @@ Create a new repo from this template, and use the create new code.
4373
## Developer Requirements
4474

4575
1. Install the following:
46-
- [Python 3](https://www.python.org/downloads/)
47-
- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
48-
1. Run `poetry shell && poetry install` to install the required Python packages.
76+
- [Python 3.11+](https://www.python.org/downloads/)
77+
1. Run the following to set up your development environment:
78+
```bash
79+
python -m venv .venv
80+
# On Windows
81+
.venv\Scripts\activate
82+
# On macOS/Linux
83+
source .venv/bin/activate
84+
85+
pip install --upgrade pip
86+
pip install .[dev]
87+
```
88+
89+
**What this installs:**
90+
- All the packages your function needs to run (`dependencies`)
91+
- Plus development tools like testing and code formatting (`[project.optional-dependencies].dev`)
92+
93+
**Why separate sections?**
94+
- `dependencies`: Only what gets deployed with your function (lightweight)
95+
- `dev` dependencies: Extra tools to help you write better code locally
4996

5097
## Building and Testing
5198

52-
The code can be tested locally by running `poetry run pytest`.
99+
The code can be tested locally by running `pytest`.
100+
101+
### Alternative dependency managers
102+
103+
This template uses the modern **PEP 621** standard in `pyproject.toml`, which works with all modern Python dependency managers:
104+
105+
#### Using Poetry
106+
```bash
107+
poetry install # Automatically reads pyproject.toml
108+
```
109+
110+
#### Using uv
111+
```bash
112+
uv sync # Automatically reads pyproject.toml
113+
```
114+
115+
#### Using pip-tools
116+
```bash
117+
pip-compile pyproject.toml # Generate requirements.txt from pyproject.toml
118+
pip install -r requirements.txt
119+
```
120+
121+
#### Using pdm
122+
```bash
123+
pdm install # Automatically reads pyproject.toml
124+
```
125+
126+
**Advantage**: All tools read the same `pyproject.toml` file, so there's no need to keep multiple files in sync!
53127
54128
### Building and running the Docker Container Image
55129

flatten.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
def flatten_base(base: Base) -> Iterable[Base]:
99
"""Flatten a base object into an iterable of bases.
10-
11-
This function recursively traverses the `elements` or `@elements` attribute of the
10+
11+
This function recursively traverses the `elements` or `@elements` attribute of the
1212
base object, yielding each nested base object.
1313
1414
Args:
@@ -19,9 +19,9 @@ def flatten_base(base: Base) -> Iterable[Base]:
1919
"""
2020
# Attempt to get the elements attribute, fallback to @elements if necessary
2121
elements = getattr(base, "elements", getattr(base, "@elements", None))
22-
22+
2323
if elements is not None:
2424
for element in elements:
2525
yield from flatten_base(element)
26-
26+
2727
yield base

main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def automate_function(
4242
automate_context: A context-helper object that carries relevant information
4343
about the runtime context of this function.
4444
It gives access to the Speckle project data that triggered this run.
45-
It also has convenient methods for attaching result data to the Speckle model.
45+
It also has convenient methods for attaching results to the Speckle model.
4646
function_inputs: An instance object matching the defined schema.
4747
"""
4848
# The context provides a convenient way to receive the triggering version.
@@ -60,7 +60,7 @@ def automate_function(
6060
automate_context.attach_error_to_objects(
6161
category="Forbidden speckle_type"
6262
f" ({function_inputs.forbidden_speckle_type})",
63-
object_ids=[o.id for o in objects_with_forbidden_speckle_type if o.id],
63+
affected_objects=objects_with_forbidden_speckle_type,
6464
message="This project should not contain the type: "
6565
f"{function_inputs.forbidden_speckle_type}",
6666
)

0 commit comments

Comments
 (0)