From 7406659ee0a7bf95a24e09ce12335cfbfec6ce17 Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Wed, 24 Jun 2026 11:06:52 -0600 Subject: [PATCH 1/5] Bump aiohttp, requests, pytest to patch dependabot CVEs --- requirements.txt | 6 +++--- setup.py | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/requirements.txt b/requirements.txt index 092cbb0..87fbe2a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ flake8==3.7.8 flake8-docstrings==1.5.0 -pytest==7.1.2 +pytest==9.0.3 python-dateutil==2.8.0 -requests==2.32.4 +requests==2.33.0 jsonschema==4.25.1 -aiohttp==3.13.4 +aiohttp==3.14.1 azure-functions>=1.11.3b3 nox==2019.11.9 furl==2.1.0 diff --git a/setup.py b/setup.py index abc268d..7fba48e 100644 --- a/setup.py +++ b/setup.py @@ -55,8 +55,8 @@ def run(self, *args, **kwargs): python_requires='>=3.9,<4', install_requires=[ 'azure-functions>=1.12.0', - 'aiohttp>=3.13.3', - 'requests==2.*', + 'aiohttp>=3.14.1', + 'requests>=2.33.0,<3', 'python-dateutil>=2.8.0', 'furl>=2.1.0', 'opentelemetry-api>=1.32.1', @@ -65,9 +65,9 @@ def run(self, *args, **kwargs): extra_requires=[ 'flake8==3.7.8', 'flake8-docstrings==1.5.0', - 'pytest==7.1.2', + 'pytest==9.0.3', 'python-dateutil==2.8.0', - 'requests==2.22.0', + 'requests==2.33.0', 'jsonschema==4.25.1', 'azure-functions>=1.2.0', 'nox==2019.11.9', From 62568e6a0a95d15ed3ee2b693586cfb05531281b Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Wed, 24 Jun 2026 11:18:35 -0600 Subject: [PATCH 2/5] Bump Python minimum to 3.10, test and add support for 3.14 --- .github/workflows/durable_python_action.yml | 4 ++-- .github/workflows/validate.yml | 24 +++++++++++++-------- CONTRIBUTING.md | 2 +- azure-pipelines-release.yml | 2 +- azure-pipelines.yml | 17 +++++++++------ eng/templates/build.yml | 19 ++++++++++------ noxfile.py | 8 +++---- setup.py | 7 +++++- 8 files changed, 52 insertions(+), 31 deletions(-) diff --git a/.github/workflows/durable_python_action.yml b/.github/workflows/durable_python_action.yml index 0bff1cc..3336326 100644 --- a/.github/workflows/durable_python_action.yml +++ b/.github/workflows/durable_python_action.yml @@ -12,10 +12,10 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Set up Python 3.9.x + - name: Set up Python 3.10.x uses: actions/setup-python@v1 with: - python-version: 3.9.x + python-version: 3.10.x - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index a6d50db..c17c702 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -17,11 +17,15 @@ jobs: fail-fast: false matrix: include: - # Fallback path: on Python 3.9 the SDK's df_dumps / df_loads cannot - # be installed (azure-functions 2.x requires >=3.13 and the 1.26.0 - # line requires >=3.10), so this leg exercises the legacy - # serialization fallback in df_serialization. - - python-version: "3.9" + # Floor version. Pin an older azure-functions (< 1.26.0) that + # predates the centralized df_dumps / df_loads serializers so this + # leg exercises the legacy serialization fallback in + # df_serialization. + - python-version: "3.10" + functions-sdk: "azure-functions<1.26.0" + - python-version: "3.11" + functions-sdk: "" + - python-version: "3.12" functions-sdk: "" # SDK path: Python 3.13 with the beta that first ships df_dumps / # df_loads, exercising the SDK-delegated serialization branch. @@ -29,6 +33,8 @@ jobs: # drop the explicit override step below. - python-version: "3.13" functions-sdk: "azure-functions>=2.2.0b5" + - python-version: "3.14" + functions-sdk: "" steps: - name: Checkout repository uses: actions/checkout@v2 @@ -41,7 +47,7 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - - name: Install Functions SDK override + - name: Pin azure-functions version if: matrix.functions-sdk != '' run: pip install "${{ matrix.functions-sdk }}" - name: Run Linter @@ -49,8 +55,8 @@ jobs: # changed f-string tokenization so pycodestyle inspects tokens inside # f-strings, producing false positives (e.g. the ':' in 'http://' or # the indentation of multi-line f-string concatenations). Linting is - # environment-agnostic, so running it once on 3.9 is sufficient. - if: matrix.python-version == '3.9' + # environment-agnostic, so running it once on 3.10 is sufficient. + if: matrix.python-version == '3.10' run: | cd azure flake8 . --count --show-source --statistics @@ -73,7 +79,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: "3.10" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8b43db8..9bccaef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ Thank you for taking the time to contribute to Durable Functions in [Python](htt - MacOS (or) Windows10 Ubuntu WSL - Language Runtimes - .NET Core 2.0 - - \>= Python 3.9.x + - \>= Python 3.10.x Note: Some ML libraries may not be compatible with newer Python versions. Make sure the library is compatible with the Python version. diff --git a/azure-pipelines-release.yml b/azure-pipelines-release.yml index cc9df70..1e3da8e 100644 --- a/azure-pipelines-release.yml +++ b/azure-pipelines-release.yml @@ -17,7 +17,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.9' + versionSpec: '3.10' - download: DurablePyCI - script: "rm -r ./azure_functions_durable/_manifest" displayName: 'Remove _manifest folder' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e1cfc4e..95cb2ad 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -13,7 +13,7 @@ trigger: - v* variables: - python.version: '3.9' + python.version: '3.10' baseFolder: . componentArtifactName: 'azure_functions_durable' #componentArtifactName: 'dist' @@ -38,6 +38,11 @@ stages: python -m pip install --upgrade pip pip install -r requirements.txt pip install wheel + # Pin an older azure-functions (< 1.26.0) that predates the + # centralized df_dumps / df_loads serializers so this job exercises + # the legacy serialization fallback in df_serialization. The + # Test_Functions_Sdk_Path job covers the SDK-delegated branch. + pip install "azure-functions<1.26.0" workingDirectory: $(baseFolder) displayName: 'Install dependencies' @@ -68,11 +73,11 @@ stages: - job: Test_Functions_Sdk_Path displayName: Test SDK Serialization Path (Py 3.13) - # The Build_Durable_Functions job runs on Python 3.9, where the SDK's - # df_dumps / df_loads cannot be installed (azure-functions 2.x requires - # >=3.13), so it only exercises the legacy serialization fallback. This - # job runs on Python 3.13 with the beta that first ships df_dumps / - # df_loads to cover the SDK-delegated branch in df_serialization. + # The Build_Durable_Functions job runs on Python 3.10 with an older + # azure-functions (< 1.26.0) pinned, so it only exercises the legacy + # serialization fallback. This job runs on Python 3.13 with the beta + # that first ships df_dumps / df_loads to cover the SDK-delegated branch + # in df_serialization. # TODO: change the override to 'azure-functions>=2.2.0' once 2.2.0 GA # ships, and drop the explicit install step. pool: diff --git a/eng/templates/build.yml b/eng/templates/build.yml index 24205b9..22ebd74 100644 --- a/eng/templates/build.yml +++ b/eng/templates/build.yml @@ -12,11 +12,16 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: '3.9.x' + versionSpec: '3.10.x' - script: | python -m pip install --upgrade pip pip install -r requirements.txt pip install wheel + # Pin an older azure-functions (< 1.26.0) that predates the + # centralized df_dumps / df_loads serializers so this job + # exercises the legacy serialization fallback in df_serialization. + # The Test_Functions_Sdk_Path job covers the SDK-delegated branch. + pip install "azure-functions<1.26.0" workingDirectory: $(System.DefaultWorkingDirectory) displayName: 'Install dependencies' @@ -44,11 +49,11 @@ jobs: - job: Test_Functions_Sdk_Path displayName: Test SDK Serialization Path (Py 3.13) - # The Build job runs on Python 3.9, where the SDK's df_dumps / df_loads - # cannot be installed (azure-functions 2.x requires >=3.13), so it only - # exercises the legacy serialization fallback. This job runs on Python - # 3.13 with the beta that first ships df_dumps / df_loads to cover the - # SDK-delegated branch in df_serialization. + # The Build job runs on Python 3.10 with an older azure-functions + # (< 1.26.0) pinned, so it only exercises the legacy serialization + # fallback. This job runs on Python 3.13 with the beta that first ships + # df_dumps / df_loads to cover the SDK-delegated branch in + # df_serialization. # TODO: change the override to 'azure-functions>=2.2.0' once 2.2.0 GA # ships, and drop the explicit install step. steps: @@ -64,4 +69,4 @@ jobs: - script: | pip install pytest pytest-azurepipelines pytest --ignore=samples-v2 - displayName: 'pytest' + displayName: 'pytest' diff --git a/noxfile.py b/noxfile.py index ae784ca..b467b75 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,6 +1,6 @@ import nox -@nox.session(python=["3.9","3.11"]) +@nox.session(python=["3.10","3.11"]) def tests(session): # same as pip install -r -requirements.txt session.install("-r", "requirements.txt") @@ -8,19 +8,19 @@ def tests(session): session.run("pytest", "-v", "tests") -@nox.session(python=["3.9","3.11"]) +@nox.session(python=["3.10","3.11"]) def lint(session): session.install("flake8") session.install("flake8-docstrings") session.run("flake8", "./azure/") -@nox.session(python=["3.9","3.11"]) +@nox.session(python=["3.10","3.11"]) def typecheck(session): session.install("-r", "requirements.txt") session.install("mypy") session.run("mypy", "./azure/") -@nox.session(python=["3.9","3.11"]) +@nox.session(python=["3.10","3.11"]) def autopep(session): session.install("-r", "requirements.txt") session.run("autopep8", "--in-place --aggressive --aggressive --recursive \"./azure/\"") \ No newline at end of file diff --git a/setup.py b/setup.py index 7fba48e..7dcf520 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,11 @@ def run(self, *args, **kwargs): 'License :: OSI Approved :: MIT License', 'Intended Audience :: Developers', 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Operating System :: MacOS :: MacOS X', @@ -52,7 +57,7 @@ def run(self, *args, **kwargs): 'Development Status :: 5 - Production/Stable', ], license='MIT', - python_requires='>=3.9,<4', + python_requires='>=3.10,<4', install_requires=[ 'azure-functions>=1.12.0', 'aiohttp>=3.14.1', From fde5c72f413f8afb3aed68b9690ceb2fb820a45f Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Wed, 24 Jun 2026 11:26:03 -0600 Subject: [PATCH 3/5] Update noxfile --- noxfile.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/noxfile.py b/noxfile.py index b467b75..9b961ff 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,6 +1,16 @@ import nox -@nox.session(python=["3.10","3.11"]) +# Mirror the supported range exercised by CI (.github/workflows/validate.yml). +# nox automatically skips interpreters that aren't installed locally. +SUPPORTED_PYTHONS = ["3.10", "3.11", "3.12", "3.13", "3.14"] + +# Lint and autopep run on a single canonical version: on Python 3.12+ the PEP +# 701 f-string tokenization changes cause pycodestyle false positives, so CI +# lints only on 3.10 and we match that here. +CANONICAL_PYTHON = "3.10" + + +@nox.session(python=SUPPORTED_PYTHONS) def tests(session): # same as pip install -r -requirements.txt session.install("-r", "requirements.txt") @@ -8,19 +18,19 @@ def tests(session): session.run("pytest", "-v", "tests") -@nox.session(python=["3.10","3.11"]) +@nox.session(python=CANONICAL_PYTHON) def lint(session): session.install("flake8") session.install("flake8-docstrings") session.run("flake8", "./azure/") -@nox.session(python=["3.10","3.11"]) +@nox.session(python=SUPPORTED_PYTHONS) def typecheck(session): session.install("-r", "requirements.txt") session.install("mypy") session.run("mypy", "./azure/") -@nox.session(python=["3.10","3.11"]) +@nox.session(python=CANONICAL_PYTHON) def autopep(session): session.install("-r", "requirements.txt") session.run("autopep8", "--in-place --aggressive --aggressive --recursive \"./azure/\"") \ No newline at end of file From 014f1d12d5cc7b1dd9bd2583e06dbf12fb00a1a5 Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Wed, 24 Jun 2026 11:38:09 -0600 Subject: [PATCH 4/5] Bump test deps for 3.14 compat --- requirements.txt | 6 +++--- setup.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index 87fbe2a..c47d123 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ -flake8==3.7.8 -flake8-docstrings==1.5.0 +flake8==7.1.1 +flake8-docstrings==1.7.0 pytest==9.0.3 python-dateutil==2.8.0 requests==2.33.0 @@ -9,7 +9,7 @@ azure-functions>=1.11.3b3 nox==2019.11.9 furl==2.1.0 pytest-asyncio==0.20.2 -autopep8 +autopep8==2.3.2 types-python-dateutil opentelemetry-api==1.32.1 opentelemetry-sdk==1.32.1 diff --git a/setup.py b/setup.py index 7dcf520..c3e7f11 100644 --- a/setup.py +++ b/setup.py @@ -68,8 +68,8 @@ def run(self, *args, **kwargs): 'opentelemetry-sdk>=1.32.1' ], extra_requires=[ - 'flake8==3.7.8', - 'flake8-docstrings==1.5.0', + 'flake8==7.1.1', + 'flake8-docstrings==1.7.0', 'pytest==9.0.3', 'python-dateutil==2.8.0', 'requests==2.33.0', From ce153b991ab491f44848df8ee4ea20526855756d Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Wed, 24 Jun 2026 11:45:46 -0600 Subject: [PATCH 5/5] Bump pytest-asyncio to cleanup 3.14 test warnings --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index c47d123..12f9a8a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ aiohttp==3.14.1 azure-functions>=1.11.3b3 nox==2019.11.9 furl==2.1.0 -pytest-asyncio==0.20.2 +pytest-asyncio==1.4.0 autopep8==2.3.2 types-python-dateutil opentelemetry-api==1.32.1 diff --git a/setup.py b/setup.py index c3e7f11..6727f41 100644 --- a/setup.py +++ b/setup.py @@ -77,7 +77,7 @@ def run(self, *args, **kwargs): 'azure-functions>=1.2.0', 'nox==2019.11.9', 'furl==2.1.0', - 'pytest-asyncio==0.20.2' + 'pytest-asyncio==1.4.0' ], include_package_data=True, data_files= [