Skip to content

Commit e7bfd08

Browse files
Merge remote-tracking branch 'origin/main' into fix/error-handling-and-logging
# Conflicts: # pyproject.toml # uv.lock
2 parents 3ee1db0 + af14443 commit e7bfd08

10 files changed

Lines changed: 292 additions & 31 deletions

File tree

.github/workflows/docs_pages.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ jobs:
2121
- name: Install uv
2222
uses: astral-sh/setup-uv@v6
2323

24-
- name: Install Python 3.13
25-
run: uv python install 3.13
24+
- name: Install Python 3.14
25+
run: uv python install 3.14
2626

2727
- name: Install dependencies
2828
run: uv sync --all-extras

.github/workflows/linting.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ jobs:
1010
- name: Install uv
1111
uses: astral-sh/setup-uv@v6
1212

13-
- name: Install Python 3.13
14-
run: uv python install 3.13
13+
- name: Install Python 3.14
14+
run: uv python install 3.14
1515

1616
- name: Install dependencies
1717
run: uv sync --all-extras

.github/workflows/publish.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ jobs:
2424
strategy:
2525
fail-fast: true
2626
matrix:
27-
python-version: [ "3.12", "3.13", "3.14" ]
27+
# Mirrors the blocking legs of tests.yaml. Deliberately excludes the
28+
# experimental 3.15 lane — a release gate must not depend on a leg
29+
# that is allowed to fail.
30+
python-version: [ "3.11", "3.12", "3.13", "3.14" ]
2831
name: pytest (Python ${{ matrix.python-version }})
2932
steps:
3033
- name: Checkout
@@ -56,8 +59,8 @@ jobs:
5659
- name: Install uv
5760
uses: astral-sh/setup-uv@v6
5861

59-
- name: Install Python 3.13
60-
run: uv python install 3.13
62+
- name: Install Python 3.14
63+
run: uv python install 3.14
6164

6265
- name: Install dependencies
6366
run: uv sync --all-extras
@@ -80,8 +83,8 @@ jobs:
8083
- name: Install uv
8184
uses: astral-sh/setup-uv@v6
8285

83-
- name: Install Python 3.13
84-
run: uv python install 3.13
86+
- name: Install Python 3.14
87+
run: uv python install 3.14
8588

8689
- name: Build
8790
run: uv build

.github/workflows/tests.yaml

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,24 @@ jobs:
3434
strategy:
3535
fail-fast: false
3636
matrix:
37-
python-version: [ "3.12", "3.13", "3.14" ]
38-
name: pytest (Python ${{ matrix.python-version }})
37+
# Supported range: 3.11 (floor, see requires-python in pyproject.toml)
38+
# through 3.14 (the development version, see .python-version).
39+
python-version: [ "3.11", "3.12", "3.13", "3.14" ]
40+
experimental: [ false ]
41+
include:
42+
# Forward-looking lane for the next release (3.15, due 2026-10-01).
43+
# Non-blocking on purpose: as of 3.15.0a8 this fails during
44+
# *dependency installation*, not during our tests — shapely has no
45+
# 3.15 wheels yet, so uv falls back to a source build that needs
46+
# numpy headers. That is an upstream packaging gap, NOT an
47+
# OSHConnect incompatibility. Expect this leg to go green on its
48+
# own once shapely ships 3.15 wheels; if it fails for any other
49+
# reason, that IS worth investigating.
50+
- python-version: "3.15"
51+
experimental: true
52+
name: pytest (Python ${{ matrix.python-version }}${{ matrix.experimental && ' — experimental, non-blocking' || '' }})
53+
# Only the experimental leg is allowed to fail without failing the run.
54+
continue-on-error: ${{ matrix.experimental }}
3955
steps:
4056
- name: Checkout
4157
uses: actions/checkout@v5
@@ -85,12 +101,12 @@ jobs:
85101
- name: Install uv
86102
uses: astral-sh/setup-uv@v6
87103

88-
- name: Install Python 3.13
89-
run: uv python install 3.13
104+
- name: Install Python 3.14
105+
run: uv python install 3.14
90106

91107
- name: Install package with NO extras
92108
run: |
93-
uv venv --python 3.13
109+
uv venv --python 3.14
94110
uv pip install .
95111
96112
- name: Import smoke test (no extras)
@@ -138,8 +154,8 @@ jobs:
138154
- name: Install uv
139155
uses: astral-sh/setup-uv@v6
140156

141-
- name: Install Python 3.13
142-
run: uv python install 3.13
157+
- name: Install Python 3.14
158+
run: uv python install 3.14
143159

144160
- name: Install dependencies
145161
run: uv sync --all-extras
@@ -186,8 +202,8 @@ jobs:
186202
- name: Install uv
187203
uses: astral-sh/setup-uv@v6
188204

189-
- name: Install Python 3.13
190-
run: uv python install 3.13
205+
- name: Install Python 3.14
206+
run: uv python install 3.14
191207

192208
# Append `.dev<run_number>` to the version in pyproject.toml so each
193209
# dev push gets a fresh PEP 440-compliant pre-release (e.g.

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,11 @@ cython_debug/
161161

162162
.idea/
163163

164-
.python-version
164+
# .python-version is intentionally TRACKED — it pins development to 3.14.
165+
# Without it, uv selects the newest stable interpreter satisfying
166+
# requires-python (>=3.11), so every contributor would silently move to
167+
# 3.15 the day it ships. 3.15 is meant to be a non-blocking preview lane
168+
# in tests.yaml, not the dev environment.
165169

166170
poetry.lock
167171

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.14

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,13 @@ coverage is on, source is scoped to `src/oshconnect`, and obvious dead lines
9494
(`if TYPE_CHECKING:`, `raise NotImplementedError`, etc.) are excluded.
9595

9696
CI (`.github/workflows/tests.yaml`) runs the suite with `--cov` on every push
97-
across Python 3.12 / 3.13 / 3.14 and uploads `coverage.xml` as a workflow
98-
artifact (downloadable from the run page).
97+
across Python 3.11 / 3.12 / 3.13 / 3.14 and uploads `coverage.xml` as a workflow
98+
artifact (downloadable from the run page). A further non-blocking lane runs
99+
against the 3.15 pre-release as an early-warning signal; it is allowed to fail
100+
and does not gate merges.
101+
102+
Development happens on Python 3.14 (pinned in `.python-version`); 3.11 is the
103+
supported floor.
99104

100105
## Logging
101106

docs/source/architecture/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ For the inverse direction (creating resources server-side), see
103103

104104
- **pydantic** — all resource and schema models. Bumping the minimum requires
105105
confirming pre-built wheels exist for all supported Python versions
106-
(3.12 – 3.14).
106+
(3.11 – 3.14).
107107
- **shapely** — geometry handling for spatial resources.
108108
- **paho-mqtt** — MQTT streaming for CS API Part 3.
109109
- **websockets** / **aiohttp** — WebSocket and async HTTP streaming.

pyproject.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ readme = "README.md"
66
authors = [
77
{ name = "Ian Patterson", email = "ian.patterson@georobotix.us" },
88
]
9-
requires-python = "<4.0,>=3.12"
9+
# Floor is 3.11, not 3.10: `datetime.fromisoformat` only accepts arbitrary
10+
# ISO 8601 fractional-second precision from 3.11 on. 3.10 rejects the
11+
# 5-digit form OSH emits (`…T17:12:58.51182Z`) with "Invalid isoformat
12+
# string", failing tests/test_resource_datamodels.py::test_control_stream_resource.
13+
# Dropping to 3.10 is possible but needs a parsing shim in timemanagement.py —
14+
# don't lower this without adding one. Development happens on 3.14 (see
15+
# .python-version); the full matrix is in .github/workflows/tests.yaml.
16+
requires-python = "<4.0,>=3.11"
1017
# Core stays transport-free: HTTP discovery/CRUD and the pydantic model layer
1118
# only. Streaming transports are opt-in extras ([mqtt], [nats], [streaming])
1219
# so minimal installs stay small — see [project.optional-dependencies].

0 commit comments

Comments
 (0)