From d6c877985794be494adaf7dcbbb043dc75860fc2 Mon Sep 17 00:00:00 2001 From: Paul Timmins Date: Sun, 14 Sep 2025 05:07:12 +0000 Subject: [PATCH 01/16] chore: Add 3.14 and 3.14t builds: update GHA matrix, bump uv and cibuildwheel to include 3.14rc2, and handle new pandas warning, and mark unsupported packages as < 3.14. --- .github/workflows/cleanup_pypi.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/packaging_sdist.yml | 2 +- .github/workflows/packaging_wheels.yml | 9 ++++---- pyproject.toml | 32 +++++++++++++++++--------- tests/pytest.ini | 2 ++ 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/.github/workflows/cleanup_pypi.yml b/.github/workflows/cleanup_pypi.yml index c4300be3..e290faae 100644 --- a/.github/workflows/cleanup_pypi.yml +++ b/.github/workflows/cleanup_pypi.yml @@ -52,7 +52,7 @@ jobs: - name: Install Astral UV uses: astral-sh/setup-uv@v6 with: - version: "0.7.14" + version: "0.8.16" - name: Run Cleanup env: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index fdd2a838..ab696897 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -70,7 +70,7 @@ jobs: - name: Install Astral UV and enable the cache uses: astral-sh/setup-uv@v6 with: - version: "0.7.14" + version: "0.8.16" python-version: 3.9 enable-cache: true cache-suffix: -${{ github.workflow }} diff --git a/.github/workflows/packaging_sdist.yml b/.github/workflows/packaging_sdist.yml index 2723b437..87923f4c 100644 --- a/.github/workflows/packaging_sdist.yml +++ b/.github/workflows/packaging_sdist.yml @@ -58,7 +58,7 @@ jobs: - name: Install Astral UV uses: astral-sh/setup-uv@v6 with: - version: "0.7.14" + version: "0.8.16" python-version: 3.11 - name: Build sdist diff --git a/.github/workflows/packaging_wheels.yml b/.github/workflows/packaging_wheels.yml index 4c7599a6..00e5cdea 100644 --- a/.github/workflows/packaging_wheels.yml +++ b/.github/workflows/packaging_wheels.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - python: [ cp39, cp310, cp311, cp312, cp313 ] + python: [ cp39, cp310, cp311, cp312, cp313, cp314, cp314t ] platform: - { os: windows-2025, arch: amd64, cibw_system: win } - { os: ubuntu-24.04, arch: x86_64, cibw_system: manylinux } @@ -79,16 +79,17 @@ jobs: # Install Astral UV, which will be used as build-frontend for cibuildwheel - uses: astral-sh/setup-uv@v6 with: - version: "0.7.14" + version: "0.8.16" enable-cache: false cache-suffix: -${{ matrix.python }}-${{ matrix.platform.cibw_system }}_${{ matrix.platform.arch }} + python-version: ${{ matrix.python }} - name: Build${{ inputs.testsuite != 'none' && ' and test ' || ' ' }}wheels - uses: pypa/cibuildwheel@v3.0 + uses: pypa/cibuildwheel@v3.1 env: CIBW_ARCHS: ${{ matrix.platform.arch == 'amd64' && 'AMD64' || matrix.platform.arch }} CIBW_BUILD: ${{ matrix.python }}-${{ matrix.platform.cibw_system }}_${{ matrix.platform.arch }} - + CIBW_ENVIRONMENT: PYTHON_GIL=1 - name: Upload wheel uses: actions/upload-artifact@v4 with: diff --git a/pyproject.toml b/pyproject.toml index 6291b811..edd71a02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,8 +47,8 @@ all = [ # users can install duckdb with 'duckdb[all]', which will install this l "fsspec", # used in duckdb.filesystem "numpy", # used in duckdb.experimental.spark and in duckdb.fetchnumpy() "pandas", # used for pandas dataframes all over the place - "pyarrow", # used for pyarrow support - "adbc_driver_manager", # for the adbc driver (TODO: this should live under the duckdb package) + "pyarrow; python_version < '3.14'", # used for pyarrow support + "adbc_driver_manager; python_version < '3.14'", # for the adbc driver (TODO: this should live under the duckdb package) ] ###################################################################################################### @@ -123,6 +123,13 @@ if.env.COVERAGE = false inherit.cmake.define = "append" cmake.define.DISABLE_UNITY = "1" +[[tool.scikit-build.overrides]] +# Windows Free-Threading +if.platform-system = "^win32" +if.abi-flags = "t" +inherit.cmake.define = "append" +cmake.define.CMAKE_C_FLAGS="/DPy_MOD_GIL_USED /DPy_GIL_DISABLED" +cmake.define.CMAKE_CXX_FLAGS="/DPy_MOD_GIL_USED /DPy_GIL_DISABLED" [tool.scikit-build.sdist] include = [ @@ -204,6 +211,7 @@ required-environments = [ # ... but do always resolve for all of them "python_version >= '3.9' and sys_platform == 'linux' and platform_machine == 'x86_64'", "python_version >= '3.9' and sys_platform == 'linux' and platform_machine == 'aarch64'", ] +prerelease = "allow" # for 3.14 # We just need pytorch for tests, wihtout GPU acceleration. PyPI doesn't host a cpu-only version for Linux, so we have # to configure the index url for cpu-only pytorch manually @@ -220,8 +228,8 @@ torchvision = [ { index = "pytorch-cpu" } ] stubdeps = [ # dependencies used for typehints in the stubs "fsspec", "pandas", - "polars", - "pyarrow", + "polars; python_version < '3.14'", + "pyarrow; python_version < '3.14'", ] test = [ # dependencies used for running tests "pytest", @@ -229,21 +237,21 @@ test = [ # dependencies used for running tests "pytest-timeout", "mypy", "coverage", - "gcovr", + "gcovr; python_version < '3.14'", "gcsfs", "packaging", - "polars", + "polars; python_version < '3.14'", "psutil", "py4j", "pyotp", - "pyspark", + "pyspark; python_version < '3.14'", "pytz", "requests", "urllib3", "fsspec>=2022.11.0", "pandas>=2.0.0", - "pyarrow>=18.0.0", - "torch>=2.2.2; sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13'", + "pyarrow>=18.0.0; python_version < '3.14'", + "torch>=2.2.2; python_version < '3.14' and (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13')", "tensorflow==2.14.0; sys_platform == 'darwin' and python_version < '3.12'", "tensorflow-cpu>=2.14.0; sys_platform == 'linux' and platform_machine != 'aarch64' and python_version < '3.12'", "tensorflow-cpu>=2.14.0; sys_platform == 'win32' and python_version < '3.12'", @@ -258,8 +266,8 @@ scripts = [ # dependencies used for running scripts "numpy", "pandas", "pcpp", - "polars", - "pyarrow", + "polars; python_version < '3.14'", + "pyarrow; python_version < '3.14'", "pytz" ] pypi = [ # dependencies used by the pypi cleanup script @@ -305,6 +313,7 @@ filterwarnings = [ # Pyspark is throwing these warnings "ignore:distutils Version classes are deprecated:DeprecationWarning", "ignore:is_datetime64tz_dtype is deprecated:DeprecationWarning", + "ignore:ChainedAssignmentError.*:FutureWarning" ] [tool.coverage.run] @@ -379,6 +388,7 @@ manylinux-x86_64-image = "manylinux_2_28" manylinux-pypy_x86_64-image = "manylinux_2_28" manylinux-aarch64-image = "manylinux_2_28" manylinux-pypy_aarch64-image = "manylinux_2_28" +enable = ["cpython-freethreading", "cpython-prerelease"] [tool.cibuildwheel.linux] before-build = ["yum install -y ccache"] diff --git a/tests/pytest.ini b/tests/pytest.ini index 0c17afd5..5081ee33 100644 --- a/tests/pytest.ini +++ b/tests/pytest.ini @@ -2,6 +2,8 @@ [pytest] filterwarnings = error + # Pandas ChainedAssignmentError warnings for 3.0 + ignore:ChainedAssignmentError.*:FutureWarning ignore::UserWarning ignore::DeprecationWarning # Jupyter is throwing DeprecationWarnings From 69415c1278ad5e5ada666f93fb7fbef17f7042be Mon Sep 17 00:00:00 2001 From: Paul Timmins Date: Sun, 14 Sep 2025 18:58:38 +0000 Subject: [PATCH 02/16] chore: remove pandas 3.0 warnings -> instead, disable pandas for 3.14 for now. --- pyproject.toml | 3 +- tests/conftest.py | 40 ++++++++++++++++++++----- tests/fast/numpy/test_numpy_new_path.py | 1 + tests/pytest.ini | 2 -- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index edd71a02..657ab2b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -211,7 +211,7 @@ required-environments = [ # ... but do always resolve for all of them "python_version >= '3.9' and sys_platform == 'linux' and platform_machine == 'x86_64'", "python_version >= '3.9' and sys_platform == 'linux' and platform_machine == 'aarch64'", ] -prerelease = "allow" # for 3.14 +prerelease = "if-necessary-or-explicit" # for 3.14 # We just need pytorch for tests, wihtout GPU acceleration. PyPI doesn't host a cpu-only version for Linux, so we have # to configure the index url for cpu-only pytorch manually @@ -313,7 +313,6 @@ filterwarnings = [ # Pyspark is throwing these warnings "ignore:distutils Version classes are deprecated:DeprecationWarning", "ignore:is_datetime64tz_dtype is deprecated:DeprecationWarning", - "ignore:ChainedAssignmentError.*:FutureWarning" ] [tool.coverage.run] diff --git a/tests/conftest.py b/tests/conftest.py index ce2d0e68..6c3cb2fb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,24 +6,37 @@ import duckdb import warnings from importlib import import_module +import sys try: # need to ignore warnings that might be thrown deep inside pandas's import tree (from dateutil in this case) - warnings.simplefilter(action='ignore', category=DeprecationWarning) - pandas = import_module('pandas') + warnings.simplefilter(action="ignore", category=DeprecationWarning) + pandas = import_module("pandas") warnings.resetwarnings() - pyarrow_dtype = getattr(pandas, 'ArrowDtype', None) + pyarrow_dtype = getattr(pandas, "ArrowDtype", None) except ImportError: pandas = None pyarrow_dtype = None + # Only install mock after we've failed to import pandas for conftest.py + class MockPandas: + def __getattr__(self, name): + pytest.skip("pandas not available", allow_module_level=True) + + sys.modules["pandas"] = MockPandas() + sys.modules["pandas.testing"] = MockPandas() + sys.modules["pandas._testing"] = MockPandas() + # Check if pandas has arrow dtypes enabled -try: - from pandas.compat import pa_version_under7p0 +if pandas is not None: + try: + from pandas.compat import pa_version_under7p0 - pyarrow_dtypes_enabled = not pa_version_under7p0 -except ImportError: + pyarrow_dtypes_enabled = not pa_version_under7p0 + except (ImportError, AttributeError): + pyarrow_dtypes_enabled = False +else: pyarrow_dtypes_enabled = False @@ -31,7 +44,7 @@ def import_pandas(): if pandas: return pandas else: - pytest.skip("Couldn't import pandas") + pytest.skip("Couldn't import pandas", allow_module_level=True) # https://docs.pytest.org/en/latest/example/simple.html#control-skipping-of-tests-according-to-command-line-option @@ -39,6 +52,17 @@ def import_pandas(): def pytest_addoption(parser): parser.addoption("--skiplist", action="append", nargs="+", type=str, help="skip listed tests") +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_call(item): + """Convert pandas requirement exceptions to skips""" + outcome = yield + try: + outcome.get_result() + except Exception as e: + if "'pandas' is required for this operation but it was not installed" in str(e): + pytest.skip("pandas not available - test requires pandas functionality") + + def pytest_collection_modifyitems(config, items): tests_to_skip = config.getoption("--skiplist") diff --git a/tests/fast/numpy/test_numpy_new_path.py b/tests/fast/numpy/test_numpy_new_path.py index 4267085c..6e424c9f 100644 --- a/tests/fast/numpy/test_numpy_new_path.py +++ b/tests/fast/numpy/test_numpy_new_path.py @@ -6,6 +6,7 @@ import duckdb from datetime import timedelta import pytest +import pandas # https://github.com/duckdb/duckdb-python/issues/48 class TestScanNumpy(object): diff --git a/tests/pytest.ini b/tests/pytest.ini index 5081ee33..0c17afd5 100644 --- a/tests/pytest.ini +++ b/tests/pytest.ini @@ -2,8 +2,6 @@ [pytest] filterwarnings = error - # Pandas ChainedAssignmentError warnings for 3.0 - ignore:ChainedAssignmentError.*:FutureWarning ignore::UserWarning ignore::DeprecationWarning # Jupyter is throwing DeprecationWarnings From ded40ec1b1e981198e92344c12b23cc97926af39 Mon Sep 17 00:00:00 2001 From: paultiq <104510378+paultiq@users.noreply.github.com> Date: Sun, 14 Sep 2025 16:45:18 -0400 Subject: [PATCH 03/16] test: Disable Pandas for 3.14 Not yet available --- pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 657ab2b8..9a1cb980 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ all = [ # users can install duckdb with 'duckdb[all]', which will install this l "ipython", # used in duckdb.query_graph "fsspec", # used in duckdb.filesystem "numpy", # used in duckdb.experimental.spark and in duckdb.fetchnumpy() - "pandas", # used for pandas dataframes all over the place + "pandas; python_version < '3.14'", # used for pandas dataframes all over the place "pyarrow; python_version < '3.14'", # used for pyarrow support "adbc_driver_manager; python_version < '3.14'", # for the adbc driver (TODO: this should live under the duckdb package) ] @@ -227,7 +227,7 @@ torchvision = [ { index = "pytorch-cpu" } ] [dependency-groups] # used for development only, requires pip >=25.1.0 stubdeps = [ # dependencies used for typehints in the stubs "fsspec", - "pandas", + "pandas; python_version < '3.14'", "polars; python_version < '3.14'", "pyarrow; python_version < '3.14'", ] @@ -249,7 +249,7 @@ test = [ # dependencies used for running tests "requests", "urllib3", "fsspec>=2022.11.0", - "pandas>=2.0.0", + "pandas>=2.0.0; python_version < '3.14'", "pyarrow>=18.0.0; python_version < '3.14'", "torch>=2.2.2; python_version < '3.14' and (sys_platform != 'darwin' or platform_machine != 'x86_64' or python_version < '3.13')", "tensorflow==2.14.0; sys_platform == 'darwin' and python_version < '3.12'", @@ -264,7 +264,7 @@ scripts = [ # dependencies used for running scripts "ipython", "ipywidgets", "numpy", - "pandas", + "pandas; python_version < '3.14'", "pcpp", "polars; python_version < '3.14'", "pyarrow; python_version < '3.14'", From 2ad03500ac59a5188d84735b29db8223272e4286 Mon Sep 17 00:00:00 2001 From: Paul Timmins Date: Mon, 15 Sep 2025 02:15:05 +0000 Subject: [PATCH 04/16] test: disable failing test "Windows fatal exception: access violation" --- tests/fast/api/test_connection_interrupt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fast/api/test_connection_interrupt.py b/tests/fast/api/test_connection_interrupt.py index 4efd68b5..eae6cbb8 100644 --- a/tests/fast/api/test_connection_interrupt.py +++ b/tests/fast/api/test_connection_interrupt.py @@ -1,12 +1,13 @@ import platform import threading import time - +import sys import duckdb import pytest class TestConnectionInterrupt(object): + @pytest.mark.xfail(sys.platform == "win32" and sys.version_info[:2] == (3, 14) and __import__('sysconfig').get_config_var("Py_GIL_DISABLED") == 1, reason="known issue on Windows 3.14t (free-threaded)", strict=False) @pytest.mark.xfail( condition=platform.system() == "Emscripten", reason="threads not allowed on Emscripten", From 557df244fb22c688cc463127bfea6fa1fba07632 Mon Sep 17 00:00:00 2001 From: Paul Timmins Date: Mon, 15 Sep 2025 02:43:20 +0000 Subject: [PATCH 05/16] tests: skip, don't xfail --- tests/fast/api/test_connection_interrupt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fast/api/test_connection_interrupt.py b/tests/fast/api/test_connection_interrupt.py index eae6cbb8..931ceaeb 100644 --- a/tests/fast/api/test_connection_interrupt.py +++ b/tests/fast/api/test_connection_interrupt.py @@ -7,7 +7,7 @@ class TestConnectionInterrupt(object): - @pytest.mark.xfail(sys.platform == "win32" and sys.version_info[:2] == (3, 14) and __import__('sysconfig').get_config_var("Py_GIL_DISABLED") == 1, reason="known issue on Windows 3.14t (free-threaded)", strict=False) + @pytest.mark.skipif(sys.platform == "win32" and sys.version_info[:2] == (3, 14) and __import__('sysconfig').get_config_var("Py_GIL_DISABLED") == 1, reason="known issue on Windows 3.14t (free-threaded)") @pytest.mark.xfail( condition=platform.system() == "Emscripten", reason="threads not allowed on Emscripten", From b4e404e78fc8e8bcd3d75d7bf6b4b8b4ab92fef3 Mon Sep 17 00:00:00 2001 From: Paul Timmins Date: Mon, 15 Sep 2025 03:22:05 +0000 Subject: [PATCH 06/16] exclude Windows --- .github/workflows/packaging_wheels.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/packaging_wheels.yml b/.github/workflows/packaging_wheels.yml index 00e5cdea..f1e9ddf0 100644 --- a/.github/workflows/packaging_wheels.yml +++ b/.github/workflows/packaging_wheels.yml @@ -45,6 +45,8 @@ jobs: - { minimal: true, python: cp311 } - { minimal: true, python: cp312 } - { minimal: true, platform: { arch: universal2 } } + - { python: cp314t, platform: { os: windows-2025 } } + runs-on: ${{ matrix.platform.os }} env: CIBW_TEST_SKIP: ${{ inputs.testsuite == 'none' && '*' || '*-macosx_universal2' }} From a540862c7c10de17863979adfe64b30dc4838980 Mon Sep 17 00:00:00 2001 From: Paul Timmins Date: Mon, 15 Sep 2025 03:23:40 +0000 Subject: [PATCH 07/16] tests: revert the skip since we're excluding Windows 3.14t builds entirely. --- tests/fast/api/test_connection_interrupt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/fast/api/test_connection_interrupt.py b/tests/fast/api/test_connection_interrupt.py index 931ceaeb..f9fa37d0 100644 --- a/tests/fast/api/test_connection_interrupt.py +++ b/tests/fast/api/test_connection_interrupt.py @@ -7,7 +7,6 @@ class TestConnectionInterrupt(object): - @pytest.mark.skipif(sys.platform == "win32" and sys.version_info[:2] == (3, 14) and __import__('sysconfig').get_config_var("Py_GIL_DISABLED") == 1, reason="known issue on Windows 3.14t (free-threaded)") @pytest.mark.xfail( condition=platform.system() == "Emscripten", reason="threads not allowed on Emscripten", From 3f8c7d7f95dfdfcc26c67f407e219e6aa4dd2bdf Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Sun, 14 Sep 2025 23:55:11 -0400 Subject: [PATCH 08/16] revert: import that was added, no longer needed --- tests/fast/api/test_connection_interrupt.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/fast/api/test_connection_interrupt.py b/tests/fast/api/test_connection_interrupt.py index f9fa37d0..ce9d2599 100644 --- a/tests/fast/api/test_connection_interrupt.py +++ b/tests/fast/api/test_connection_interrupt.py @@ -1,7 +1,6 @@ import platform import threading import time -import sys import duckdb import pytest From 8b11bc43a03ed8a4f0a3f0601d5216371b81cf72 Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Mon, 15 Sep 2025 00:34:12 -0400 Subject: [PATCH 09/16] revert: exactly to original --- tests/fast/api/test_connection_interrupt.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fast/api/test_connection_interrupt.py b/tests/fast/api/test_connection_interrupt.py index ce9d2599..4efd68b5 100644 --- a/tests/fast/api/test_connection_interrupt.py +++ b/tests/fast/api/test_connection_interrupt.py @@ -1,6 +1,7 @@ import platform import threading import time + import duckdb import pytest From 6c35985b0be27e02d4ee0a5dcfe5ae7f700555dc Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Mon, 15 Sep 2025 07:22:11 -0400 Subject: [PATCH 10/16] test: Mark test xfail --- tests/fast/numpy/test_numpy_new_path.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fast/numpy/test_numpy_new_path.py b/tests/fast/numpy/test_numpy_new_path.py index 6e424c9f..abc09ef5 100644 --- a/tests/fast/numpy/test_numpy_new_path.py +++ b/tests/fast/numpy/test_numpy_new_path.py @@ -2,14 +2,15 @@ Therefore, we only test the new codes and exec paths. """ +import sys import numpy as np import duckdb from datetime import timedelta import pytest -import pandas # https://github.com/duckdb/duckdb-python/issues/48 class TestScanNumpy(object): + @pytest.mark.skipif(sys.version_info[:2] == (3, 14), reason="Fails when testing without pandas https://github.com/duckdb/duckdb-python/issues/48") def test_scan_numpy(self, duckdb_cursor): z = np.array([1, 2, 3]) res = duckdb_cursor.sql("select * from z").fetchall() From 64b70d6008be7aaafce0233e79f261fa5e3eb0a0 Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Mon, 15 Sep 2025 07:23:15 -0400 Subject: [PATCH 11/16] test: mark test xfail --- tests/fast/numpy/test_numpy_new_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fast/numpy/test_numpy_new_path.py b/tests/fast/numpy/test_numpy_new_path.py index abc09ef5..c1122797 100644 --- a/tests/fast/numpy/test_numpy_new_path.py +++ b/tests/fast/numpy/test_numpy_new_path.py @@ -10,7 +10,7 @@ class TestScanNumpy(object): - @pytest.mark.skipif(sys.version_info[:2] == (3, 14), reason="Fails when testing without pandas https://github.com/duckdb/duckdb-python/issues/48") + @pytest.mark.xfail(sys.version_info[:2] == (3, 14), reason="Fails when testing without pandas https://github.com/duckdb/duckdb-python/issues/48") def test_scan_numpy(self, duckdb_cursor): z = np.array([1, 2, 3]) res = duckdb_cursor.sql("select * from z").fetchall() From 80c57b0068de4f1f8f55271d84c6bbe8be5e822a Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Mon, 15 Sep 2025 09:34:33 -0400 Subject: [PATCH 12/16] chore: Add comments and todo's for workflow changes --- .github/workflows/packaging_wheels.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/packaging_wheels.yml b/.github/workflows/packaging_wheels.yml index f1e9ddf0..463faea8 100644 --- a/.github/workflows/packaging_wheels.yml +++ b/.github/workflows/packaging_wheels.yml @@ -45,7 +45,9 @@ jobs: - { minimal: true, python: cp311 } - { minimal: true, python: cp312 } - { minimal: true, platform: { arch: universal2 } } - - { python: cp314t, platform: { os: windows-2025 } } + # Windows+cp314t disabled due to test failures in CI. + # TODO: Diagnose why tests fail (access violations) in some configurations + - { python: cp314t, platform: { os: windows-2025 } } runs-on: ${{ matrix.platform.os }} env: @@ -91,6 +93,8 @@ jobs: env: CIBW_ARCHS: ${{ matrix.platform.arch == 'amd64' && 'AMD64' || matrix.platform.arch }} CIBW_BUILD: ${{ matrix.python }}-${{ matrix.platform.cibw_system }}_${{ matrix.platform.arch }} + # PYTHON_GIL=1: Suppresses the RuntimeWarning that the GIL is enabled on free-threaded builds. + # TODO: Remove PYTHON_GIL=1 when free-threaded is supported. CIBW_ENVIRONMENT: PYTHON_GIL=1 - name: Upload wheel uses: actions/upload-artifact@v4 From e315bb77d6ce92a35bb4d1d08b3f66b03733625a Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Mon, 15 Sep 2025 09:38:57 -0400 Subject: [PATCH 13/16] chore: Remove unused section for Windows 3.14t builds. --- pyproject.toml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9a1cb980..bcbb24f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -123,14 +123,6 @@ if.env.COVERAGE = false inherit.cmake.define = "append" cmake.define.DISABLE_UNITY = "1" -[[tool.scikit-build.overrides]] -# Windows Free-Threading -if.platform-system = "^win32" -if.abi-flags = "t" -inherit.cmake.define = "append" -cmake.define.CMAKE_C_FLAGS="/DPy_MOD_GIL_USED /DPy_GIL_DISABLED" -cmake.define.CMAKE_CXX_FLAGS="/DPy_MOD_GIL_USED /DPy_GIL_DISABLED" - [tool.scikit-build.sdist] include = [ "README.md", From fd26187890c608cff891a96b4051c8d45773637b Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Mon, 15 Sep 2025 10:14:39 -0400 Subject: [PATCH 14/16] chore: Add version check to only allow no-Pandas for 3.14, plus a TODO --- tests/conftest.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 6c3cb2fb..e2f427c3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import os +import sys import pytest import shutil from os.path import abspath, join, dirname, normpath @@ -52,16 +53,22 @@ def import_pandas(): def pytest_addoption(parser): parser.addoption("--skiplist", action="append", nargs="+", type=str, help="skip listed tests") + @pytest.hookimpl(hookwrapper=True) def pytest_runtest_call(item): """Convert pandas requirement exceptions to skips""" + outcome = yield - try: - outcome.get_result() - except Exception as e: - if "'pandas' is required for this operation but it was not installed" in str(e): - pytest.skip("pandas not available - test requires pandas functionality") + # TODO: Remove skip when Pandas releases for 3.14. After, consider bumping to 3.15 + if sys.version_info[:2] == (3, 14): + try: + outcome.get_result() + except Exception as e: + if "'pandas' is required for this operation but it was not installed" in str(e): + pytest.skip("pandas not available - test requires pandas functionality") + else: + raise e def pytest_collection_modifyitems(config, items): From 6044ea033df3472cdfddc22bc20fc45953d04aad Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Mon, 15 Sep 2025 16:44:55 -0400 Subject: [PATCH 15/16] tests: Narrow pandas not installed skip to duckdb.InvalidInputException --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index e2f427c3..5e297aee 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -64,7 +64,7 @@ def pytest_runtest_call(item): if sys.version_info[:2] == (3, 14): try: outcome.get_result() - except Exception as e: + except duckdb.InvalidInputException as e: if "'pandas' is required for this operation but it was not installed" in str(e): pytest.skip("pandas not available - test requires pandas functionality") else: From d899bcfc5285a9e722c83d6d2f2c71d09d65be0a Mon Sep 17 00:00:00 2001 From: "paul@iqmo.com" Date: Tue, 16 Sep 2025 07:07:27 -0400 Subject: [PATCH 16/16] tests: revert xfail for 3.14 now that #48 is merged --- tests/fast/numpy/test_numpy_new_path.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/fast/numpy/test_numpy_new_path.py b/tests/fast/numpy/test_numpy_new_path.py index c1122797..3735ff6e 100644 --- a/tests/fast/numpy/test_numpy_new_path.py +++ b/tests/fast/numpy/test_numpy_new_path.py @@ -10,7 +10,6 @@ class TestScanNumpy(object): - @pytest.mark.xfail(sys.version_info[:2] == (3, 14), reason="Fails when testing without pandas https://github.com/duckdb/duckdb-python/issues/48") def test_scan_numpy(self, duckdb_cursor): z = np.array([1, 2, 3]) res = duckdb_cursor.sql("select * from z").fetchall()