diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 36f9622fc5..918954e295 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,7 +27,7 @@ jobs: strategy: fail-fast: false matrix: - python: [ "3.10", 3.13 ] + python: [ "3.10", 3.14 ] os: [ macos-latest, ubuntu-24.04, windows-latest ] defaults: run: diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index d5ce319bf1..17efb3fb33 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.10", 3.11, 3.12, 3.13] + python: ["3.10", 3.11, 3.12, 3.13, 3.14] steps: - name: Checkout uses: actions/checkout@v6.0.2 @@ -51,7 +51,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.10", 3.11, 3.12, 3.13] + python: ["3.10", 3.11, 3.12, 3.13, 3.14] wordsize: [64] steps: - name: Checkout @@ -125,7 +125,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.10", 3.11, 3.12, 3.13] + python: ["3.10", 3.11, 3.12, 3.13, 3.14] runner: [macos-15, macos-15-intel] include: - runner: macos-15 @@ -163,7 +163,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.10", 3.11, 3.12, 3.13] + python: ["3.10", 3.11, 3.12, 3.13, 3.14] wordsize: [64] steps: - name: Download wheels @@ -188,7 +188,7 @@ jobs: strategy: fail-fast: false matrix: - python: ["3.10", 3.11, 3.12, 3.13] + python: ["3.10", 3.11, 3.12, 3.13, 3.14] include: - python: "3.10" wheel: cp310 @@ -198,6 +198,8 @@ jobs: wheel: cp312 - python: 3.13 wheel: cp313 + - python: 3.14 + wheel: cp314 steps: - name: Download wheels uses: actions/download-artifact@v7.0.0 diff --git a/python/CHANGELOG.rst b/python/CHANGELOG.rst index d11a2a0e2d..804c538f4d 100644 --- a/python/CHANGELOG.rst +++ b/python/CHANGELOG.rst @@ -8,6 +8,10 @@ ID is e.g. a population name, rather than silently returning no samples. (:user:`hyanwong`, :pr:`3344`) +**Maintenance** + +- Add support for Python 3.14 + -------------------- [1.0.0] - 2025-11-27 -------------------- @@ -22,7 +26,7 @@ - ``TreeSequence.tables`` now returns a zero-copy immutable view of the tables. To get a mutable copy, use ``TreeSequence.dump_tables()``. (:user:`benjeffery`, :pr:`3288`, :issue:`760`) - + - For a tree sequence to be valid, the mutation parents in the table collection must be correct and consistent with the topology of the tree at each mutation site. ``TableCollection.tree_sequence()`` will raise a ``_tskit.LibraryError`` if this @@ -146,7 +150,7 @@ (:user:`hyanwong`, :pr:`3165`, :issue:`3164`) - Add ``TreeSequence.map_to_vcf_model`` method to return a mapping of - the tree sequence to the VCF model. + the tree sequence to the VCF model. (:user:`benjeffery`, :pr:`3163`) - Use a thin space as the thousands separator in HTML output, @@ -157,14 +161,14 @@ - Correct assertion message when tables are compared with metadata ignored. (:user:`benjeffery`, :pr:`3162`, :issue:`3161`) - -**Breaking changes** + +**Breaking changes** - ``TreeSequence.write_vcf`` now filters non-sample nodes from individuals by default, instead of raising an error. These nodes can be included using the - new ``include_non_sample_nodes`` argument. + new ``include_non_sample_nodes`` argument. By default individual names (sample IDs) in VCF output are now of the form - ``tsk_{individual.id}`` Previously these were always + ``tsk_{individual.id}`` Previously these were always ``"tsk_{j}" for j in range(num_individuals)``. This may break some downstream code if individuals are specified. To fix, manually specify ``individual_names`` to the required pattern. diff --git a/python/pyproject.toml b/python/pyproject.toml index 9a4af869e4..f1c6eb550b 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -19,6 +19,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3 :: Only", "Development Status :: 5 - Production/Stable", "Environment :: Other Environment", @@ -68,9 +69,9 @@ test = [ "kastore==0.3.3", "lshmm==0.0.8", "msgpack==1.1.0", - "msprime==1.3.4", + "msprime==1.4.0b2", "networkx==3.2.1", - "numba==0.61.2", + "numba==0.63.1", "portion==2.6.0", "pytest==8.3.5", "pytest-cov==6.0.0", @@ -88,8 +89,8 @@ docs = [ "sphinx-autodoc-typehints==2.3.0", "sphinx-issues==5.0.0", "sphinx-argparse==0.5.2", - "msprime==1.3.3", - "numba==0.61.2", + "msprime==1.4.0b2", + "numba==0.63.1", "sphinx-book-theme", "pandas==2.2.3", ] @@ -117,7 +118,7 @@ dev = [ "xmlunittest", "newick", "zarr<3", - "jupyter-book", + "jupyter-book<2", "breathe", "sphinx-autodoc-typehints", "sphinx-issues", diff --git a/python/tests/test_balance_metrics.py b/python/tests/test_balance_metrics.py index f554ec745f..5571557a50 100644 --- a/python/tests/test_balance_metrics.py +++ b/python/tests/test_balance_metrics.py @@ -192,7 +192,7 @@ def test_b2_base(self, base, expected): @pytest.mark.parametrize("base", [0, -0.001, -1, -1e-6, -1e200]) def test_b2_bad_base(self, base): - with pytest.raises(ValueError, match="math domain"): + with pytest.raises(ValueError): self.tree().b2_index(base=base) def test_b2_base1(self):