diff --git a/.circleci/config.yml b/.circleci/config.yml index 69dd2472ae..67b37f7187 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -183,16 +183,12 @@ jobs: command: | cd python rm -fR build - python setup.py sdist - python setup.py check - python -m twine check dist/*.tar.gz + python -m pip install build python -m venv venv - source venv/bin/activate - pip install --upgrade setuptools pip wheel - python setup.py build_ext - python setup.py egg_info - python setup.py bdist_wheel - pip install dist/*.tar.gz + python -m build --sdist + python -m twine check dist/*.tar.gz + python -m build --wheel + pip install dist/*.whl tskit --help build-32: @@ -218,6 +214,7 @@ workflows: test: jobs: - build - - build-32 + #Temporarily disabled due avoid compiling numpy on 32bit + # - build-32 diff --git a/.github/workflows/docker/buildwheel.sh b/.github/workflows/docker/buildwheel.sh index ad0cd14b03..3e9e6e324b 100644 --- a/.github/workflows/docker/buildwheel.sh +++ b/.github/workflows/docker/buildwheel.sh @@ -13,15 +13,12 @@ cd python for V in "${PYTHON_VERSIONS[@]}"; do PYBIN=/opt/python/$V/bin rm -rf build/ # Avoid lib build by narrow Python is used by wide python - # Instead of letting setup.py install a newer numpy we install it here - # using the oldest supported version for ABI compatibility - $PYBIN/pip install oldest-supported-numpy - $PYBIN/python setup.py build_ext --inplace - $PYBIN/python setup.py bdist_wheel + $PYBIN/python -m pip install build + $PYBIN/python -m build --wheel done cd dist for whl in *.whl; do auditwheel repair "$whl" rm "$whl" -done \ No newline at end of file +done diff --git a/.github/workflows/docker/shared.env b/.github/workflows/docker/shared.env index 3f299243a5..c10e471e72 100644 --- a/.github/workflows/docker/shared.env +++ b/.github/workflows/docker/shared.env @@ -1,6 +1,6 @@ PYTHON_VERSIONS=( + cp312-cp312 cp311-cp311 cp310-cp310 cp39-cp39 - cp38-cp38 ) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f45258e3a9..4cf4e454fd 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -9,17 +9,18 @@ on: env: COMMIT_EMAIL: ben.jeffery.well+adminbot@gmail.com - DOXYGEN: true MAKE_TARGET: -C python OWNER: tskit-dev REPO: tskit REQUIREMENTS: python/requirements/CI-docs/requirements.txt - APTGET: doxygen jobs: build-deploy-docs: name: Docs runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} steps: - name: Cancel Previous Runs uses: styfle/cancel-workflow-action@0.12.1 @@ -28,28 +29,35 @@ jobs: - uses: actions/checkout@v4 - - name: Install apt deps - if: env.APTGET - run: sudo apt-get install -y ${{env.APTGET}} + - name: Setup Mambaforge + uses: conda-incubator/setup-miniconda@v3 + with: + miniforge-variant: Mambaforge + miniforge-version: latest + activate-environment: tskit-docs-env + use-mamba: true - - uses: actions/setup-python@v5 + - name: Cache Conda env + uses: actions/cache@v3 with: - python-version: "3.10" - cache: 'pip' + path: ${{ env.CONDA }}/envs + key: conda-${{ runner.os }}--${{ runner.arch }}--${{ hashFiles(env.REQUIREMENTS) }}-${{ env.CACHE_NUMBER }} + env: + CACHE_NUMBER: 0 + id: cache - - name: Create venv and install deps + - name: Update environment run: | - pip install --upgrade pip wheel - pip install -r ${{env.REQUIREMENTS}} + mamba install -y python=3.10 doxygen pip + pip install -r ${{ env.REQUIREMENTS }} + if: steps.cache.outputs.cache-hit != 'true' - name: Build C module if: env.MAKE_TARGET - run: | - make $MAKE_TARGET + run: make $MAKE_TARGET - name: Build Docs - run: | - make -C docs + run: make -C docs - name: Trigger docs site rebuild if: github.ref == 'refs/heads/main' @@ -57,4 +65,4 @@ jobs: curl -X POST https://api.github.com/repos/tskit-dev/tskit-site/dispatches \ -H 'Accept: application/vnd.github.everest-preview+json' \ -u AdminBot-tskit:${{ secrets.ADMINBOT_TOKEN }} \ - --data '{"event_type":"build-docs"}' + --data '{"event_type":"build-docs"}' \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ab6a496eeb..c1498cb242 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -60,7 +60,7 @@ jobs: strategy: fail-fast: false matrix: - python: [ 3.8, 3.9, "3.11" ] + python: [ 3.9, 3.12 ] os: [ macos-latest, ubuntu-latest, windows-latest ] defaults: run: @@ -121,7 +121,6 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' shell: bash -l {0} run: | - pip install setuptools==57.5.0 #v58 broke some deps https://setuptools.pypa.io/en/latest/history.html#v58-0-0 pip install -r python/requirements/CI-tests-pip/requirements.txt # Remove tskit installed by conda pip uninstall -y tskit @@ -133,11 +132,6 @@ jobs: conda activate anaconda-client-env python setup.py build_ext --inplace - - name: Remove py311 incompatible tests (lack of numba support for 3.11, needed for lshmm) - if: matrix.python == '3.11' - run: | - rm python/tests/test_*matching* - - name: Run tests working-directory: python run: | diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 110d02bb98..50f430619e 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -15,7 +15,7 @@ jobs: runs-on: macos-latest strategy: matrix: - python: [3.8, 3.9, "3.10", 3.11] + python: [3.9, "3.10", 3.11, 3.12] steps: - name: Checkout uses: actions/checkout@v4 @@ -25,21 +25,11 @@ jobs: python-version: ${{ matrix.python }} - name: Install deps run: | - # Upgrade pip to get bdist_wheel - pip install --upgrade pip - pip install setuptools wheel - # Instead of letting setup.py install a newer numpy we install it here - # using the oldest supported version for ABI compatibility - pip install oldest-supported-numpy - - name: Build C extension - run: | - cd python - python -VV - python setup.py build_ext --inplace + pip install build - name: Build Wheel run: | cd python - python setup.py bdist_wheel + python -m build --wheel - name: Delocate to bundle dynamic libs run: | cd python @@ -55,7 +45,7 @@ jobs: runs-on: windows-latest strategy: matrix: - python: [3.8, 3.9, "3.10", 3.11] + python: [3.9, "3.10", 3.11, 3.12] wordsize: [64] steps: - name: Checkout @@ -66,12 +56,8 @@ jobs: shell: bash run: | set -ex - ${PYTHON} -m pip install --upgrade pip - ${PYTHON} -m pip install setuptools wheel - # Instead of letting setup.py install a newer numpy we install it here - # using the oldest supported version for ABI compatibility - ${PYTHON} -m pip install oldest-supported-numpy - - name: Build C Extension + ${PYTHON} -m pip install build + - name: Build Wheel env: PYTHON: "py -${{ matrix.python }}-${{ matrix.wordsize }}" shell: bash @@ -86,15 +72,7 @@ jobs: cp -r --dereference ../c/subprojects lib/. cp -r --dereference ../c/tskit lib/. cp ../c/tskit.h lib/. - ${PYTHON} setup.py build_ext --inplace - - name: Build Wheel - env: - PYTHON: "py -${{ matrix.python }}-${{ matrix.wordsize }}" - shell: bash - run: | - set -ex - cd python - ${PYTHON} setup.py bdist_wheel + ${PYTHON} -m build --wheel - name: Upload Wheels uses: actions/upload-artifact@v4 with: @@ -107,16 +85,17 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Set up Python 3.8 + - name: Set up Python 3.9 uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: 3.9 - name: Build sdist shell: bash run: | cd python - python setup.py sdist + python -m pip install build + python -m build --sdist - name: Upload sdist uses: actions/upload-artifact@v4 @@ -140,7 +119,7 @@ jobs: runs-on: macos-latest strategy: matrix: - python: [3.8, 3.9, "3.10", 3.11] + python: [3.9, "3.10", 3.11, 3.12] steps: - name: Download wheels uses: actions/download-artifact@v4 @@ -162,7 +141,7 @@ jobs: runs-on: windows-latest strategy: matrix: - python: [3.8, 3.9, "3.10", 3.11] + python: [3.9, "3.10", 3.11, 3.12] wordsize: [64] steps: - name: Download wheels @@ -186,17 +165,17 @@ jobs: needs: ['manylinux'] strategy: matrix: - python: [3.8, 3.9, "3.10", 3.11] + python: [3.9, "3.10", 3.11, 3.12] include: - - python: 3.8 - wheel: cp38 - python: 3.9 wheel: cp39 - python: "3.10" wheel: cp310 - python: 3.11 wheel: cp311 + - python: 3.12 + wheel: cp312 steps: - name: Download wheels uses: actions/download-artifact@v4 @@ -234,4 +213,4 @@ jobs: repository_url: https://test.pypi.org/legacy/ - name: Publish distribution to PRODUCTION PyPI if: github.event_name == 'release' && !startsWith(github.event.release.tag_name, 'C_') - uses: pypa/gh-action-pypi-publish@release/v1 \ No newline at end of file + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.mergify.yml b/.mergify.yml index 48d34a24a3..d51c1a62a7 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -5,15 +5,12 @@ queue_rules: - "#changes-requested-reviews-by=0" - status-success=Docs - status-success=Lint - - status-success=Python (3.8, macos-latest) - status-success=Python (3.9, macos-latest) - - status-success=Python (3.11, macos-latest) - - status-success=Python (3.8, ubuntu-latest) + - status-success=Python (3.12, macos-latest) - status-success=Python (3.9, ubuntu-latest) - - status-success=Python (3.11, ubuntu-latest) - - status-success=Python (3.8, windows-latest) + - status-success=Python (3.12, ubuntu-latest) - status-success=Python (3.9, windows-latest) - - status-success=Python (3.11, windows-latest) + - status-success=Python (3.12, windows-latest) - "status-success=ci/circleci: build" pull_request_rules: - name: Automatic rebase, CI and merge @@ -25,15 +22,12 @@ pull_request_rules: - label=AUTOMERGE-REQUESTED - status-success=Docs - status-success=Lint - - status-success=Python (3.8, macos-latest) - status-success=Python (3.9, macos-latest) - - status-success=Python (3.11, macos-latest) - - status-success=Python (3.8, ubuntu-latest) + - status-success=Python (3.12, macos-latest) - status-success=Python (3.9, ubuntu-latest) - - status-success=Python (3.11, ubuntu-latest) - - status-success=Python (3.8, windows-latest) + - status-success=Python (3.12, ubuntu-latest) - status-success=Python (3.9, windows-latest) - - status-success=Python (3.11, windows-latest) + - status-success=Python (3.12, windows-latest) - "status-success=ci/circleci: build" #- status-success=codecov/patch #- status-success=codecov/project/c-tests diff --git a/c/tests/test_minimal_cpp.cpp b/c/tests/test_minimal_cpp.cpp index 8754f4f636..8e9296f410 100644 --- a/c/tests/test_minimal_cpp.cpp +++ b/c/tests/test_minimal_cpp.cpp @@ -1,6 +1,6 @@ /* * MIT License * - * Copyright (c) 2019-2023 Tskit Developers + * Copyright (c) 2019-2024 Tskit Developers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/c/tskit.h b/c/tskit.h index e55ffc664a..e8f1b69f60 100644 --- a/c/tskit.h +++ b/c/tskit.h @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2019 Tskit Developers + * Copyright (c) 2019-2024 Tskit Developers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/c/tskit/tables.h b/c/tskit/tables.h index 38f3096c9d..204e39e2db 100644 --- a/c/tskit/tables.h +++ b/c/tskit/tables.h @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2019-2023 Tskit Developers + * Copyright (c) 2019-2024 Tskit Developers * Copyright (c) 2017-2018 University of Oxford * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/python/lwt_interface/dict_encoding_testlib.py b/python/lwt_interface/dict_encoding_testlib.py index 72acea4dce..01ed9a865c 100644 --- a/python/lwt_interface/dict_encoding_testlib.py +++ b/python/lwt_interface/dict_encoding_testlib.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2018-2022 Tskit Developers +# Copyright (c) 2018-2024 Tskit Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/python/pyproject.toml b/python/pyproject.toml new file mode 100644 index 0000000000..f4d2a8bda7 --- /dev/null +++ b/python/pyproject.toml @@ -0,0 +1,67 @@ +[build-system] +requires = ["setuptools>=45", "wheel", "numpy>=2.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "tskit" +dynamic = ["version"] +authors = [ + {name = "Tskit Developers", email = "admin@tskit.dev"}, +] +description = "The tree sequence toolkit." +readme = "README.rst" +license = {text = "MIT"} +classifiers = [ + "Programming Language :: C", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3 :: Only", + "Development Status :: 5 - Production/Stable", + "Environment :: Other Environment", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Bio-Informatics", +] +keywords = [ + "population genetics", + "tree sequence", + "ancestral recombination graph", + "evolutionary tree", + "statistical genetics", + "phylogenetics", + "tskit", +] +requires-python = ">=3.9" +dependencies = [ + "jsonschema>=3.0.0", + "numpy>=1.23.5", + "svgwrite>=1.1.10", +] + +[project.urls] +Homepage = "https://tskit.dev/tskit" +Documentation = "https://tskit.dev/tskit/docs/stable" +Changelog = "https://tskit.dev/tskit/docs/stable/changelogs.html" +"Bug Tracker" = "https://github.com/tskit-dev/tskit/issues" +GitHub = "https://github.com/tskit-dev/tskit/" + +[project.scripts] +tskit = "tskit.cli:tskit_main" + +[tool.setuptools] +packages = ["tskit"] + +[tool.setuptools.dynamic] +version = {attr = "tskit._version.tskit_version"} + +[tool.pytest.ini_options] +addopts = "-n 4" +testpaths = ["tests"] diff --git a/python/pytest.ini b/python/pytest.ini deleted file mode 100644 index 50b8418b9c..0000000000 --- a/python/pytest.ini +++ /dev/null @@ -1,4 +0,0 @@ -[pytest] -addopts = -n 4 -testpaths = - tests diff --git a/python/requirements/CI-complete/requirements.txt b/python/requirements/CI-complete/requirements.txt index 62e2d3d365..257b08c4ce 100644 --- a/python/requirements/CI-complete/requirements.txt +++ b/python/requirements/CI-complete/requirements.txt @@ -1,16 +1,15 @@ -biopython==1.81 -coverage==7.2.7 -dendropy==4.6.1 +biopython==1.83 +coverage==7.5.4 +dendropy==5.0.1 h5py==3.9.0 -kastore==0.3.2 +kastore==0.3.3 lshmm==0.0.8 -msgpack==1.0.5 -msprime==1.2.0 -networkx==3.1 -portion==2.4.1 -pytest==7.4.0 -pytest-cov==4.1.0 -pytest-xdist==3.3.1 -tszip==0.2.2 +msgpack==1.0.8 +msprime==1.3.1 +networkx==3.3 +portion==2.4.2 +pytest==8.2.2 +pytest-cov==5.0.0 +pytest-xdist==3.6.1 +tszip==0.2.3 xmlunittest==0.5.0 -llvmlite==0.39.1 diff --git a/python/requirements/CI-docs/requirements.txt b/python/requirements/CI-docs/requirements.txt index 8ba78c7aa4..3b5a3118ea 100644 --- a/python/requirements/CI-docs/requirements.txt +++ b/python/requirements/CI-docs/requirements.txt @@ -1,9 +1,8 @@ -jupyter-book==0.15.1 +jupyter-book==1.0.0 breathe==4.35.0 -sphinx-autodoc-typehints==1.19.1 -sphinx-issues==3.0.1 +sphinx-autodoc-typehints==2.2.2 +sphinx-issues==4.1.0 sphinx-argparse==0.4.0 -numpy==1.25.1 svgwrite==1.4.3 -msprime==1.2.0 +msprime==1.3.1 sphinx-book-theme \ No newline at end of file diff --git a/python/requirements/CI-tests-conda/requirements.txt b/python/requirements/CI-tests-conda/requirements.txt index 66e5f62b37..3c58381b9e 100644 --- a/python/requirements/CI-tests-conda/requirements.txt +++ b/python/requirements/CI-tests-conda/requirements.txt @@ -1,2 +1,3 @@ -msprime==1.2.0 -h5py==3.7.0 +msprime==1.3.1 +tszip==0.2.3 +h5py==3.11.0 diff --git a/python/requirements/CI-tests-pip/requirements.txt b/python/requirements/CI-tests-pip/requirements.txt index d713bbdea0..96010f3958 100644 --- a/python/requirements/CI-tests-pip/requirements.txt +++ b/python/requirements/CI-tests-pip/requirements.txt @@ -1,17 +1,14 @@ lshmm==0.0.8 -numpy==1.24.1 -pytest==7.1.3 -pytest-cov==4.0.0 -pytest-xdist==2.5.0 +pytest==8.2.2 +pytest-cov==5.0.0 +pytest-xdist==3.6.1 svgwrite==1.4.3 -portion==2.3.0 +portion==2.4.2 xmlunittest==0.5.0 -biopython==1.79 -dendropy==4.5.2 -networkx==3.1 -msgpack==1.0.4 -newick==1.3.2 -tszip==0.2.2 -kastore==0.3.2 -lxml==4.9.2 -numba<=0.59.1 #Pinned directly as 0.60.0 fails +biopython==1.83 +dendropy==5.0.1 +networkx==3.2.1 +msgpack==1.0.8 +newick==1.9.0 +kastore==0.3.3 +jsonschema==4.22.0 \ No newline at end of file diff --git a/python/setup.cfg b/python/setup.cfg deleted file mode 100644 index 350d3c1d0b..0000000000 --- a/python/setup.cfg +++ /dev/null @@ -1,72 +0,0 @@ -[metadata] -name = tskit -author= Tskit Developers -author_email = admin@tskit.dev -license = MIT -description= The tree sequence toolkit. -long_description_content_type = text/x-rst -long_description = file: README.rst -url = https://tskit.dev/tskit -project_urls = - Documentation = https://tskit.dev/tskit/docs/stable - Changelog = https://tskit.dev/tskit/docs/stable/changelogs.html - Bug Tracker = https://github.com/tskit-dev/tskit/issues - GitHub = https://github.com/tskit-dev/tskit/ -classifiers = - Programming Language :: C - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3 :: Only - Development Status :: 5 - Production/Stable - Environment :: Other Environment - Intended Audience :: Science/Research - License :: OSI Approved :: MIT License - Operating System :: POSIX - Operating System :: MacOS :: MacOS X - Operating System :: Microsoft :: Windows - Topic :: Scientific/Engineering - Topic :: Scientific/Engineering :: Bio-Informatics -keywords = - population genetics - tree sequence - ancestral recombination graph - evolutionary tree - statistical genetics - phylogenetics - tskit -platforms = - POSIX - Windows - MacOS X - -[options] -packages = tskit -python_requires = >=3.8 -include_package_data = True -install_requires = - jsonschema>=3.0.0 - numpy>=1.7,<2 - svgwrite>=1.1.10 -setup_requires = - numpy>=1.7 - setuptools - -[options.entry_points] -console_scripts = - tskit = tskit.cli:tskit_main - -[tool:pytest] -addopts = -n 4 -testpaths = - tests - -[bdist_wheel] -# This flag says to generate wheels that support both Python 2 and Python -# 3. If your code will not run unchanged on both Python 2 and 3, you will -# need to generate separate wheels for each Python version that you -# support. -universal=0 diff --git a/python/setup.py b/python/setup.py index 44e15b9869..0f8e77abdb 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,28 +1,13 @@ -import os.path +import os import platform +import numpy from setuptools import Extension from setuptools import setup -from setuptools.command.build_ext import build_ext - IS_WINDOWS = platform.system() == "Windows" -# Obscure magic required to allow numpy be used as a 'setup_requires'. -# Based on https://stackoverflow.com/questions/19919905 -class local_build_ext(build_ext): - def finalize_options(self): - build_ext.finalize_options(self) - import builtins - - # Prevent numpy from thinking it is still in its setup process: - builtins.__NUMPY_SETUP__ = False - import numpy - - self.include_dirs.append(numpy.get_include()) - - libdir = "lib" kastore_dir = os.path.join(libdir, "subprojects", "kastore") tsk_source_files = [ @@ -43,7 +28,6 @@ def finalize_options(self): defines = [] libraries = [] if IS_WINDOWS: - # Needed for generating UUIDs libraries.append("Advapi32") defines.append(("WIN32", None)) @@ -53,21 +37,9 @@ def finalize_options(self): extra_compile_args=["-std=c99"], libraries=libraries, define_macros=defines, - include_dirs=["lwt_interface", libdir, kastore_dir], + include_dirs=["lwt_interface", libdir, kastore_dir, numpy.get_include()], ) - -# After exec'ing this file we have tskit_version defined. -tskit_version = None # Keep PEP8 happy. -version_file = os.path.join("tskit", "_version.py") -with open(version_file) as f: - exec(f.read()) - setup( - # The package name along with all the other metadata is specified in setup.cfg - # However, GitHub's dependency graph can't see the package unless we put this here. - name="tskit", - version=tskit_version, ext_modules=[_tskit_module], - cmdclass={"build_ext": local_build_ext}, ) diff --git a/python/tests/ibd.py b/python/tests/ibd.py index 53e28cc5c0..64f1e8be63 100644 --- a/python/tests/ibd.py +++ b/python/tests/ibd.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2020-2022 Tskit Developers +# Copyright (c) 2020-2024 Tskit Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/python/tests/simplify.py b/python/tests/simplify.py index 1e62c9d11b..9e416c3e78 100644 --- a/python/tests/simplify.py +++ b/python/tests/simplify.py @@ -157,7 +157,9 @@ def __init__( if self.update_sample_flags: flags = self.tables.nodes.flags # Zero out other sample flags - flags = np.bitwise_and(flags, ~tskit.NODE_IS_SAMPLE) + flags = np.bitwise_and( + flags, np.uint32(~tskit.NODE_IS_SAMPLE & 0xFFFFFFFF) + ) flags[sample] |= tskit.NODE_IS_SAMPLE self.tables.nodes.flags = flags.astype(np.uint32) diff --git a/python/tests/test_avl_tree.py b/python/tests/test_avl_tree.py index 999b09b528..2afaa0615e 100644 --- a/python/tests/test_avl_tree.py +++ b/python/tests/test_avl_tree.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2021 Tskit Developers +# Copyright (c) 2021-2024 Tskit Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/python/tests/test_coalrate.py b/python/tests/test_coalrate.py index dcfcfc8d66..471f63ff1d 100644 --- a/python/tests/test_coalrate.py +++ b/python/tests/test_coalrate.py @@ -464,7 +464,7 @@ def test_missing_leaves(self): """ t = self.example_ts().dump_tables() ss0 = np.flatnonzero(t.nodes.population == 0) - remove = np.in1d(t.edges.child, ss0) + remove = np.isin(t.edges.child, ss0) assert np.any(remove) t.edges.set_columns( left=t.edges.left[~remove], diff --git a/python/tests/test_haplotype_matching.py b/python/tests/test_haplotype_matching.py index dc01e8370d..4c7d5fc18a 100644 --- a/python/tests/test_haplotype_matching.py +++ b/python/tests/test_haplotype_matching.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2019-2023 Tskit Developers +# Copyright (c) 2019-2024 Tskit Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/python/tests/test_ld_matrix.py b/python/tests/test_ld_matrix.py index 1733ea140f..761658224e 100644 --- a/python/tests/test_ld_matrix.py +++ b/python/tests/test_ld_matrix.py @@ -46,8 +46,8 @@ @contextlib.contextmanager -def suppress_division_by_zero_warning(): - with np.errstate(invalid="ignore", divide="ignore"): +def suppress_overflow_div0_warning(): + with np.errstate(over="ignore", invalid="ignore", divide="ignore"): yield @@ -901,7 +901,7 @@ def r2_summary_func( D = p_AB - (p_A * p_B) denom = p_A * p_B * (1 - p_A) * (1 - p_B) - with suppress_division_by_zero_warning(): + with suppress_overflow_div0_warning(): result[k] = (D * D) / denom @@ -952,7 +952,7 @@ def D_prime_summary_func( p_B = p_AB + p_aB D = p_AB - (p_A * p_B) - with suppress_division_by_zero_warning(): + with suppress_overflow_div0_warning(): if D >= 0: result[k] = D / min(p_A * (1 - p_B), (1 - p_A) * p_B) else: @@ -975,7 +975,7 @@ def r_summary_func( D = p_AB - (p_A * p_B) denom = p_A * p_B * (1 - p_A) * (1 - p_B) - with suppress_division_by_zero_warning(): + with suppress_overflow_div0_warning(): result[k] = D / np.sqrt(denom) @@ -1034,7 +1034,7 @@ def pi2_unbiased( w_Ab = state[1, k] w_aB = state[2, k] w_ab = n - (w_AB + w_Ab + w_aB) - with suppress_division_by_zero_warning(): + with suppress_overflow_div0_warning(): result[k] = (1 / (n * (n - 1) * (n - 2) * (n - 3))) * ( ((w_AB + w_Ab) * (w_aB + w_ab) * (w_AB + w_aB) * (w_Ab + w_ab)) - ((w_AB * w_ab) * (w_AB + w_ab + (3 * w_Ab) + (3 * w_aB) - 1)) @@ -1052,7 +1052,7 @@ def dz_unbiased( w_Ab = state[1, k] w_aB = state[2, k] w_ab = n - (w_AB + w_Ab + w_aB) - with suppress_division_by_zero_warning(): + with suppress_overflow_div0_warning(): result[k] = (1 / (n * (n - 1) * (n - 2) * (n - 3))) * ( ( ((w_AB * w_ab) - (w_Ab * w_aB)) @@ -1074,7 +1074,7 @@ def d2_unbiased( w_Ab = state[1, k] w_aB = state[2, k] w_ab = n - (w_AB + w_Ab + w_aB) - with suppress_division_by_zero_warning(): + with suppress_overflow_div0_warning(): result[k] = (1 / (n * (n - 1) * (n - 2) * (n - 3))) * ( ((w_aB**2) * (w_Ab - 1) * w_Ab) + ((w_ab - 1) * w_ab * (w_AB - 1) * w_AB) diff --git a/python/tests/test_lowlevel.py b/python/tests/test_lowlevel.py index 54b19b1d6f..0fd20b3442 100644 --- a/python/tests/test_lowlevel.py +++ b/python/tests/test_lowlevel.py @@ -1671,7 +1671,7 @@ def test_divergence_matrix(self): ts.divergence_matrix(windows, [1, 1], [0, bad_node]) with pytest.raises(ValueError, match="Sum of sample_set_sizes"): ts.divergence_matrix(windows, [1, 2], [0, 1]) - with pytest.raises(ValueError, match="Overflow"): + with pytest.raises((ValueError, OverflowError), match="Overflow|out of bounds"): ts.divergence_matrix(windows, [-1, 2], [0]) with pytest.raises(TypeError, match="str"): @@ -3321,23 +3321,19 @@ def test_bad_tracked_samples(self): ) for bad_sample in [10**6, -1e6]: with pytest.raises(ValueError): - # Implicit conversion to integers using __int__ is deprecated - with pytest.deprecated_call(): - _tskit.Tree( - ts, - options=options, - tracked_samples=[bad_sample], - ) + _tskit.Tree( + ts, + options=options, + tracked_samples=[bad_sample], + ) with pytest.raises(ValueError): - with pytest.deprecated_call(): - _tskit.Tree( - ts, - options=options, - tracked_samples=[1, bad_sample], - ) + _tskit.Tree( + ts, + options=options, + tracked_samples=[1, bad_sample], + ) with pytest.raises(ValueError): - with pytest.deprecated_call(): - _tskit.Tree(ts, tracked_samples=[1, bad_sample, 1]) + _tskit.Tree(ts, tracked_samples=[1, bad_sample, 1]) def test_while_loop_semantics(self): for ts in self.get_example_tree_sequences(): diff --git a/python/tests/test_metadata.py b/python/tests/test_metadata.py index d57e6ea9d3..b6c2ed664b 100644 --- a/python/tests/test_metadata.py +++ b/python/tests/test_metadata.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2018-2022 Tskit Developers +# Copyright (c) 2018-2024 Tskit Developers # Copyright (c) 2017 University of Oxford # # Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/python/tests/test_tables.py b/python/tests/test_tables.py index 51852a2c79..7551f3250c 100644 --- a/python/tests/test_tables.py +++ b/python/tests/test_tables.py @@ -1254,7 +1254,7 @@ def verify_metadata_vector(self, table, key, dtype, default_value=9999): else: md = default_value break - assert np.all(np.cast[dtype](md) == x) + assert np.all(np.asarray(md, dtype=dtype) == x) def test_metadata_vector_errors(self): table = self.table_class() @@ -1396,9 +1396,7 @@ def test_metadata_schema(self, table_5row): table2.metadata_schema = tskit.MetadataSchema({"codec": "json"}) with pytest.raises( AssertionError, - match=f"{type(table_5row).__name__} metadata schemas differ: self=None " - f"other=OrderedDict([('codec', " - "'json')])", + match=f"{type(table_5row).__name__} metadata schemas differ:", ): table_5row.assert_equals(table2) table_5row.assert_equals(table2, ignore_metadata=True) @@ -4091,10 +4089,7 @@ def test_metadata_schema(self, t1, t2): t2.metadata_schema = tskit.MetadataSchema(None) with pytest.raises( AssertionError, - match=re.escape( - "Metadata schemas differ: self=OrderedDict([('codec', 'json')]) " - "other=None" - ), + match=re.escape("Metadata schemas differ"), ): t1.assert_equals(t2) t1.assert_equals(t2, ignore_metadata=True) @@ -4140,10 +4135,7 @@ def test_ignore_metadata(self, t1, t2, table_name): table.metadata_schema = tskit.MetadataSchema(None) with pytest.raises( AssertionError, - match=re.escape( - f"{type(table).__name__} metadata schemas differ: " - f"self=OrderedDict([('codec', 'json')]) other=None" - ), + match=re.escape(f"{type(table).__name__} metadata schemas differ:"), ): t1.assert_equals(t2) t1.assert_equals(t2, ignore_metadata=True) @@ -4201,10 +4193,7 @@ def test_ignore_reference_sequence(self, t1, t2): t2.reference_sequence.clear() with pytest.raises( AssertionError, - match=re.escape( - "Metadata schemas differ: " - "self=OrderedDict([('codec', 'json')]) other=None" - ), + match=re.escape("Metadata schemas differ"), ): t1.assert_equals(t2) t1.assert_equals(t2, ignore_reference_sequence=True) diff --git a/python/tests/test_tree_stats.py b/python/tests/test_tree_stats.py index a272c4f8cf..4b608b5d75 100644 --- a/python/tests/test_tree_stats.py +++ b/python/tests/test_tree_stats.py @@ -1280,7 +1280,7 @@ def site_segregating_sites(ts, sample_sets, windows=None, span_normalise=True): haps = ts.genotype_matrix(isolated_as_missing=False) site_positions = [x.position for x in ts.sites()] for i, X in enumerate(sample_sets): - X_index = np.where(np.in1d(samples, X))[0] + X_index = np.where(np.isin(samples, X))[0] for k in range(ts.num_sites): if (site_positions[k] >= begin) and (site_positions[k] < end): num_alleles = len(set(haps[k, X_index])) @@ -1428,7 +1428,7 @@ def site_tajimas_d(ts, sample_sets, windows=None): nn = n[i] S = 0 T = 0 - X_index = np.where(np.in1d(samples, X))[0] + X_index = np.where(np.isin(samples, X))[0] for k in range(ts.num_sites): if (site_positions[k] >= begin) and (site_positions[k] < end): hX = haps[k, X_index] @@ -4571,7 +4571,7 @@ def branch_trait_covariance(ts, W, windows=None, span_normalise=True): has_trees = True SS = 0 for u in range(ts.num_nodes): - below = np.in1d(samples, list(tr.samples(u))) + below = np.isin(samples, list(tr.samples(u))) branch_length = tr.branch_length(u) SS += covsq(w, below) * branch_length S += SS * (min(end, tr.interval.right) - max(begin, tr.interval.left)) @@ -4606,7 +4606,7 @@ def node_trait_covariance(ts, W, windows=None, span_normalise=True): break SS = np.zeros(ts.num_nodes) for u in range(ts.num_nodes): - below = np.in1d(samples, list(tr.samples(u))) + below = np.isin(samples, list(tr.samples(u))) SS[u] += covsq(w, below) S += SS * (min(end, tr.interval.right) - max(begin, tr.interval.left)) out[j, :, i] = S @@ -4782,7 +4782,7 @@ def branch_trait_correlation(ts, W, windows=None, span_normalise=True): has_trees = True SS = 0 for u in range(ts.num_nodes): - below = np.in1d(samples, list(tr.samples(u))) + below = np.isin(samples, list(tr.samples(u))) p = np.mean(below) if p > 0 and p < 1: branch_length = tr.branch_length(u) @@ -4823,7 +4823,7 @@ def node_trait_correlation(ts, W, windows=None, span_normalise=True): break SS = np.zeros(ts.num_nodes) for u in range(ts.num_nodes): - below = np.in1d(samples, list(tr.samples(u))) + below = np.isin(samples, list(tr.samples(u))) p = np.mean(below) if p > 0 and p < 1: # SS[u] += sum(w[below])**2 / 2 @@ -5046,7 +5046,7 @@ def branch_trait_linear_model(ts, W, Z, windows=None, span_normalise=True): has_trees = True SS = 0 for u in range(ts.num_nodes): - below = np.in1d(samples, list(tr.samples(u))) + below = np.isin(samples, list(tr.samples(u))) branch_length = tr.branch_length(u) SS += linear_model(w, below, Z) * branch_length S += SS * (min(end, tr.interval.right) - max(begin, tr.interval.left)) @@ -5081,7 +5081,7 @@ def node_trait_linear_model(ts, W, Z, windows=None, span_normalise=True): break SS = np.zeros(ts.num_nodes) for u in range(ts.num_nodes): - below = np.in1d(samples, list(tr.samples(u))) + below = np.isin(samples, list(tr.samples(u))) SS[u] += linear_model(w, below, Z) S += SS * (min(end, tr.interval.right) - max(begin, tr.interval.left)) out[j, :, i] = S diff --git a/python/tests/test_util.py b/python/tests/test_util.py index eaed4d07e3..4a124619fa 100644 --- a/python/tests/test_util.py +++ b/python/tests/test_util.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2018-2023 Tskit Developers +# Copyright (c) 2018-2024 Tskit Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -196,8 +196,7 @@ def test_nonrectangular_input(self): # On some platforms and Python / numpy versions, a ValueError # occurs instead with pytest.raises((TypeError, ValueError)): - with pytest.deprecated_call(): - util.safe_np_int_cast(bad_input, dtype) + util.safe_np_int_cast(bad_input, dtype) class TestIntervalOps: diff --git a/python/tests/test_version.py b/python/tests/test_version.py index 19cd2bc5dc..65a8ab5b13 100644 --- a/python/tests/test_version.py +++ b/python/tests/test_version.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2020-2022 Tskit Developers +# Copyright (c) 2020-2024 Tskit Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal diff --git a/python/tskit/formats.py b/python/tskit/formats.py index ac466ce1a8..76d0ad7376 100644 --- a/python/tskit/formats.py +++ b/python/tskit/formats.py @@ -1,6 +1,6 @@ # MIT License # -# Copyright (c) 2018-2023 Tskit Developers +# Copyright (c) 2018-2024 Tskit Developers # Copyright (c) 2016-2017 University of Oxford # # Permission is hereby granted, free of charge, to any person obtaining a copy @@ -150,9 +150,9 @@ def _load_legacy_hdf5_v2(root, remove_duplicate_positions): population[cr_node] = cr_population if "samples" in root: samples_group = root["samples"] - population[:sample_size] = samples_group["population"] + population[:sample_size] = np.array(samples_group["population"], copy=True) if "time" in samples_group: - time[:sample_size] = samples_group["time"] + time[:sample_size] = np.array(samples_group["time"], copy=True) tables.nodes.set_columns(flags=flags, population=population, time=time) _set_populations(tables)