From 5d612c2e58c97fd6b737b18e9dc5eb29ce93c15d Mon Sep 17 00:00:00 2001 From: thomasstvr <65630492+thomasstvr@users.noreply.github.com> Date: Tue, 22 Sep 2026 09:49:55 -0500 Subject: [PATCH 1/5] Added python 3.14 to automated tests --- .github/workflows/ci.yml | 2 +- .github/workflows/publish-tagged.yml | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8293b195..d94c35f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: FULL=false [[ "$GITHUB_REF_NAME" == "main" || "$BASE_REF" == "main" ]] && FULL=true if [[ "$FULL" == "true" ]]; then - echo 'matrix={"os":["ubuntu-latest","windows-latest"],"python-version":["3.11","3.13"]}' >> "$GITHUB_OUTPUT" + echo 'matrix={"os":["ubuntu-latest","windows-latest"],"python-version":["3.11","3.13","3.14"]}' >> "$GITHUB_OUTPUT" else echo 'matrix={"os":["ubuntu-latest"],"python-version":["3.11"]}' >> "$GITHUB_OUTPUT" fi diff --git a/.github/workflows/publish-tagged.yml b/.github/workflows/publish-tagged.yml index e8bfefd3..85ae6664 100644 --- a/.github/workflows/publish-tagged.yml +++ b/.github/workflows/publish-tagged.yml @@ -90,6 +90,9 @@ jobs: pytest: runs-on: ubuntu-latest needs: [validate] + strategy: + matrix: + python-version: ["3.13", "3.14"] permissions: contents: read steps: @@ -99,7 +102,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: "3.13" + python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | @@ -124,6 +127,9 @@ jobs: test-pip-install: runs-on: ubuntu-latest needs: [validate] + strategy: + matrix: + python-version: ["3.13", "3.14"] permissions: contents: read steps: @@ -133,7 +139,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: "3.13" + python-version: ${{ matrix.python-version }} - name: Test pip install run: | @@ -144,6 +150,9 @@ jobs: pytest-macos: runs-on: macos-latest needs: [validate] + strategy: + matrix: + python-version: ["3.13", "3.14"] permissions: contents: read steps: @@ -153,7 +162,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.13" + python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | From ce74a07a4738935b7755cb57d6e04d5e1b67b9eb Mon Sep 17 00:00:00 2001 From: thomasstvr <65630492+thomasstvr@users.noreply.github.com> Date: Tue, 22 Sep 2026 09:51:16 -0500 Subject: [PATCH 2/5] Added test for structured output --- tests/test_ai_definition.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/test_ai_definition.py b/tests/test_ai_definition.py index 29cd1f20..7197187e 100644 --- a/tests/test_ai_definition.py +++ b/tests/test_ai_definition.py @@ -3,6 +3,7 @@ import pandas as pd import pytest import wrangles +from pydantic import ValidationError import wrangles.ai_definition as ai_definition import wrangles.ai_cache as ai_cache @@ -334,6 +335,32 @@ def test_outputs_are_nullable_by_default_but_keys_remain_required(): ) +@pytest.mark.parametrize( + "field_schema", + [ + {"type": ["string", "integer", "null"]}, + {"anyOf": [{"type": "string"}, {"type": "integer"}, {"type": "null"}]}, + ], + ids=["type-list", "anyOf"], +) +@pytest.mark.parametrize("value", ["25mm", 25, None, [], {}]) +def test_structured_output_union_validation(field_schema, value): + """Union fields must build and validate on every supported Python version.""" + schema = { + "type": "object", + "properties": {"value": field_schema}, + "required": ["value"], + "additionalProperties": False, + } + parsed = {"value": value} + + if isinstance(value, (list, dict)): + with pytest.raises(ValidationError): + openai_responses.validate_structured_output(parsed, schema) + else: + assert openai_responses.validate_structured_output(parsed, schema) == parsed + + def test_nullable_false_is_an_explicit_opt_out(): compiled = ai_definition.compile_definition( { From f4e997379fd58b673e85d2b83eaec45e2c26ea5e Mon Sep 17 00:00:00 2001 From: thomasstvr <65630492+thomasstvr@users.noreply.github.com> Date: Tue, 22 Sep 2026 09:51:42 -0500 Subject: [PATCH 3/5] Updated to work with Python 3.14 and older versions --- wrangles/openai_responses.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wrangles/openai_responses.py b/wrangles/openai_responses.py index 9b16bafa..cd5af64f 100644 --- a/wrangles/openai_responses.py +++ b/wrangles/openai_responses.py @@ -429,7 +429,7 @@ def schema_type_to_python(schema: dict, name: str) -> _Any: if isinstance(option, dict) ) if python_types: - return _Union.__getitem__(python_types) + return _Union[python_types] if schema.get("enum"): return _Literal.__getitem__(tuple(schema["enum"])) @@ -440,7 +440,7 @@ def schema_type_to_python(schema: dict, name: str) -> _Any: schema_type_to_python({**schema, "type": item}, name) for item in schema_type ) - return _Union.__getitem__(python_types) + return _Union[python_types] if schema_type == "array": return _List[schema_type_to_python(schema.get("items", {}), f"{name}Item")] From 37e7e4ae48b9503db2b704c0696c8da105bd4336 Mon Sep 17 00:00:00 2001 From: thomasstvr <65630492+thomasstvr@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:06:49 -0500 Subject: [PATCH 4/5] Updated readme to include python 3.14 --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 22cc4f1e..209e7441 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,18 @@ Full documentation available at [wrangles.io](https://wrangles.io/python). +## Python support + +Wrangles supports Python 3.11, 3.12, 3.13, and 3.14. Pull requests targeting +`main` and pushes to `main` run tests and package-install checks on Python 3.11, +3.13, and 3.14 on Ubuntu and Windows. Tagged releases run tests on Python 3.13 +and 3.14 on Ubuntu and macOS, plus package-install checks on Ubuntu. + ## Local development -Supported local development uses Python 3.13. On Windows, create or refresh the -complete test and tooling environment with one command from the repository -root: +The standard local development environment uses Python 3.13. On Windows, +create or refresh the complete test and tooling environment with one command +from the repository root: ```powershell .\scripts\bootstrap-dev.ps1 From 046124523daaff459f75556413f08b85d10b6aff Mon Sep 17 00:00:00 2001 From: thomasstvr <65630492+thomasstvr@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:07:28 -0500 Subject: [PATCH 5/5] Added python 3.14 --- .github/agents/test.agent.md | 6 ++++-- .github/copilot-instructions.md | 11 +++++++---- setup.py | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/agents/test.agent.md b/.github/agents/test.agent.md index a08c1ac2..e27a30b0 100644 --- a/.github/agents/test.agent.md +++ b/.github/agents/test.agent.md @@ -27,7 +27,9 @@ You are a **Software Development Engineer in Test (SDET)** for a Python data wra ## 📚 Project Knowledge ### Tech Stack -- **Core:** Python 3.11–3.13, pytest, pandas, numpy, polars +- **Core:** Python 3.11–3.14, pytest, pandas, numpy, polars +- **CI coverage:** Main-targeted PRs and main pushes test Python 3.11, 3.13, and 3.14 on Ubuntu and Windows; tagged releases test Python 3.13 and 3.14 on Ubuntu and macOS. +- **Development baseline:** The standard local environment, development container, and CI test image use Python 3.13. - **Data:** SQLAlchemy, boto3, pymongo, Pydantic - **Templates:** Jinja2 @@ -311,4 +313,4 @@ Tests should: Every test you write is an investment in the project's long-term maintainability and reliability. ---- \ No newline at end of file +--- diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 892f893a..b04e4f3b 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -13,7 +13,7 @@ ## Tech Stack -- **Python:** 3.11, 3.12, 3.13 (multi-version support) +- **Python:** 3.11, 3.12, 3.13, 3.14 (package support); the standard local development environment uses Python 3.13 - **Core Dependencies:** pandas (>=2.0,<3.0), numpy, polars (1.33.0), pyyaml - **Database Connectors:** sqlalchemy, pymssql, psycopg2-binary, pymysql, pymongo - **Cloud/External:** boto3 (AWS S3), simple-salesforce, fabric (SFTP) @@ -243,7 +243,7 @@ current `main`; never merge `dev` wholesale into `main`. **Pushing to a feature branch currently runs nothing.** Open a pull request to `main` (Draft is fine) to trigger `ci.yml`. A PR to `main` runs the full Ubuntu -and Windows, Python 3.11 and 3.13 matrix. +and Windows, Python 3.11, 3.13, and 3.14 matrix. PR #1115 established the current workflows, but some triggers still mention the legacy `dev` branch. That support is transitional compatibility and does not @@ -281,8 +281,8 @@ to define. ### GitHub Actions Workflows - **ci.yml** (*CI*)**:** PRs into `main` and pushes to `main`; legacy `dev` triggers remain temporarily while recovery is completed - - Pytest on Ubuntu + Windows across Python 3.11 + 3.13 for `main` PRs - - Test pip installation + - Pytest on Ubuntu + Windows across Python 3.11 + 3.13 + 3.14 for `main` PRs and pushes + - Test pip installation across the same matrix - Generate and test JSON schema - Build the CI test image and, on PRs, run smoke checks and local recipes against that exact image - Push the image on merges to `main` under the new policy @@ -293,6 +293,9 @@ to define. - **publish-tagged.yml** (*Deploy Prod*)**:** `v*` tag push. GHCR, then CodeArtifact, then PyPI. The file name is pinned by PyPI Trusted Publishing and cannot be renamed without updating the publisher on PyPI first. + - Pytest on Ubuntu + macOS across Python 3.13 + 3.14 + - Test pip installation on Ubuntu across Python 3.13 + 3.14 + - Validate the Python 3.13 CI test image before package publication ### Workflow Jobs 1. **pytest:** Run test suite across OS/Python matrix diff --git a/setup.py b/setup.py index fa4b5360..93bc571b 100644 --- a/setup.py +++ b/setup.py @@ -29,6 +29,7 @@ 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'License :: OSI Approved :: Apache Software License', 'Operating System :: OS Independent' ],