From 3dbcf5707c4525472cad57492e1e2281f2092e64 Mon Sep 17 00:00:00 2001 From: Arya Massarat <23412689+aryarm@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:10:20 -0700 Subject: [PATCH] try to switch to dev-env.yml file --- .devcontainer.json | 41 +++++++++ .github/pull_request_template.md | 13 +++ .github/workflows/constraints.txt | 5 -- .github/workflows/tests.yml | 125 ++++++++++++-------------- .readthedocs.yaml | 28 +++--- dev-env.yml | 13 +++ docs/project_info/contributing.rst | 137 ++++++++++++++++++++++++++--- environment.yml | 9 -- noxfile.py | 53 ++++++----- 9 files changed, 298 insertions(+), 126 deletions(-) create mode 100644 .devcontainer.json create mode 100644 .github/pull_request_template.md delete mode 100644 .github/workflows/constraints.txt create mode 100644 dev-env.yml delete mode 100644 environment.yml diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 0000000..253be95 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,41 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu +{ + "name": "Ubuntu", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/base:jammy", + "features": { + "ghcr.io/rocker-org/devcontainer-features/miniforge:1": { + "version": "latest", + "variant": "Mambaforge" + } + }, + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "mamba env create -n happler -f dev-env.yml && conda run -n happler poetry install", + + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": ["ms-python.python"], + "settings": { + "python.condaPath": "/opt/conda/condabin/conda", + "python.defaultInterpreterPath": "/opt/conda/envs/happler/bin/python", + "python.terminal.activateEnvironment": true, + "python.terminal.activateEnvInCurrentTerminal": true, + "python.venvFolders": ["/home/vscode/.cache/pypoetry/virtualenvs"], + "terminal.integrated.environmentChangesRelaunch": true, + "terminal.integrated.hideOnStartup": "always" + } + } + } + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..2fbe6d9 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## Checklist + +* [ ] I've checked to ensure there aren't already other open [pull requests](../../../pulls) for the same update/change +* [ ] I've prefixed the title of my PR according to [the conventional commits specification](https://www.conventionalcommits.org/). If your PR fixes a bug, please prefix the PR with `fix: `. Otherwise, if it introduces a new feature, please prefix it with `feat: `. If it introduces a breaking change, please add an exclamation before the colon, like `feat!: `. If the scope of the PR changes because of a revision to it, please update the PR title, since the title will be used in our CHANGELOG. +* [ ] At the top of the PR, I've [listed any open issues that this PR will resolve](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword). For example, "resolves #0" if this PR resolves issue #0 +- [ ] I've explained my changes in a manner that will make it possible for both users and maintainers of happler to understand them +* [ ] I have followed the [contributing guidelines](https://happler.readthedocs.io/en/stable/project_info/contributing.html#how-to-fix-a-bug-or-implement-a-new-feature) +* [ ] I have adhered to the [style guidelines](https://happler.readthedocs.io/en/stable/project_info/contributing.html#style) +* [ ] I've added tests for any new functionality. Or, if this PR fixes a bug, I've added test(s) that replicate it +* [ ] I've updated the relevant documentation and checked that the newly built documentation is formatted properly +* [ ] All functions, modules, classes etc. still conform to [numpy docstring standards](https://numpydoc.readthedocs.io/en/latest/format.html) +* [ ] (if applicable) I've updated the pyproject.toml file with any changes I've made to happler's dependencies, and I've run `poetry lock --no-update` to ensure the lock file stays up to date and that our dependencies are locked to their minimum versions +* [ ] In the body of this PR, I've included a short address to the reviewer highlighting one or two items that might deserve their focus diff --git a/.github/workflows/constraints.txt b/.github/workflows/constraints.txt deleted file mode 100644 index cff7619..0000000 --- a/.github/workflows/constraints.txt +++ /dev/null @@ -1,5 +0,0 @@ -pip==22.2.2 -nox==2022.8.7 -nox-poetry==1.0.1 -poetry==1.1.15 -virtualenv==20.16.6 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 91dcb79..5cbc2b7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,7 +1,6 @@ name: Tests -on: - - pull_request +on: [pull_request, workflow_call] jobs: tests: @@ -11,13 +10,16 @@ jobs: fail-fast: false matrix: include: - - { python: "3.7", os: "ubuntu-latest", session: "lint" } + - { python: "3.8", os: "ubuntu-latest", session: "lint" } - { python: "3.7", os: "ubuntu-latest", session: "tests" } - { python: "3.8", os: "ubuntu-latest", session: "tests" } - { python: "3.9", os: "ubuntu-latest", session: "tests" } - { python: "3.10", os: "ubuntu-latest", session: "tests" } - # - { python: "3.10", os: "windows-latest", session: "tests" } - # - { python: "3.10", os: "macos-latest", session: "tests" } + - { python: "3.11", os: "ubuntu-latest", session: "tests" } + - { python: "3.12", os: "ubuntu-latest", session: "tests" } + # - { python: "3.11", os: "windows-latest", session: "tests" } + - { python: "3.9", os: "macos-latest", session: "tests" } + - { python: "3.8", os: "ubuntu-latest", session: "size" } env: NOXSESSION: ${{ matrix.session }} @@ -26,90 +28,75 @@ jobs: steps: - name: Check out the repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v3 + - name: Setup Mambaforge + uses: conda-incubator/setup-miniconda@v3 with: - python-version: ${{ matrix.python }} + activate-environment: happler + miniforge-variant: Mambaforge + auto-activate-base: false + miniforge-version: latest + use-mamba: true - - name: Upgrade pip - run: | - pip install --constraint=.github/workflows/constraints.txt pip - pip --version - - name: Upgrade pip in virtual environments - shell: python - run: | - import os - import pip - with open(os.environ["GITHUB_ENV"], mode="a") as io: - print(f"VIRTUALENV_PIP={pip.__version__}", file=io) - - name: Install Poetry + - name: Get Date + id: get-date + run: echo "today=$(/bin/date -u '+%Y%m%d')" >> $GITHUB_OUTPUT + shell: bash + + - name: Cache Conda env + uses: actions/cache@v3 + with: + path: ${{ env.CONDA }}/envs + key: + conda-${{ runner.os }}--${{ runner.arch }}--${{ steps.get-date.outputs.today }}-${{ hashFiles('dev-env.yml') }}-${{ env.CACHE_NUMBER }} + env: + # Increase this value to reset cache if dev-env.yml has not changed + CACHE_NUMBER: 0 + id: cache + + - name: Install dev environment + run: + mamba env update -n happler -f dev-env.yml + if: steps.cache.outputs.cache-hit != 'true' + + - name: Try to build happler + shell: bash -el {0} run: | - pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry - poetry --version - - name: Install Nox + poetry build --no-ansi + + - name: Check distribution size + if: matrix.session == 'size' run: | - pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox - pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry - nox --version - - name: Run Nox + du -csh dist/* + # check that the generated dist/ directory does not exceed 0.3 MB + # if this check fails, it's because you forgot to list large files in a "tool.poetry.exclude" section of our pyproject.toml + # https://python-poetry.org/docs/pyproject/#include-and-exclude + [ $(du -b dist | cut -f1) -lt 300000 ] + + - name: Run tests with nox + if: matrix.session != 'size' + shell: bash -el {0} run: | - nox --python=${{ matrix.python }} + nox --verbose --python=${{ matrix.python }} + - name: Upload coverage data if: always() && matrix.session == 'tests' uses: "actions/upload-artifact@v3" with: name: coverage-data path: ".coverage.*" + large-files: name: File sizes runs-on: ubuntu-latest steps: - name: Check out the repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + - name: Check for large files uses: actionsdesk/lfs-warning@v3.2 with: token: ${{ secrets.GITHUB_TOKEN }} # Optional filesizelimit: 500000b labelName: large-files - - # coverage: - # runs-on: ubuntu-latest - # needs: tests - # steps: - # - name: Check out the repository - # uses: actions/checkout@v3 - - # - name: Set up Python - # uses: actions/setup-python@v3 - # with: - # python-version: "3.10" - - # - name: Upgrade pip - # run: | - # pip install --constraint=.github/workflows/constraints.txt pip - # pip --version - # - name: Install Poetry - # run: | - # pipx install --pip-args=--constraint=.github/workflows/constraints.txt poetry - # poetry --version - # - name: Install Nox - # run: | - # pipx install --pip-args=--constraint=.github/workflows/constraints.txt nox - # pipx inject --pip-args=--constraint=.github/workflows/constraints.txt nox nox-poetry - # nox --version - # - name: Download coverage data - # uses: actions/download-artifact@v3 - # with: - # name: coverage-data - - # - name: Combine coverage data and display human readable report - # run: | - # nox --session=coverage - # - name: Create coverage report - # run: | - # nox --session=coverage -- xml - # - name: Upload coverage report - # uses: codecov/codecov-action@v3.1.0 diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 35cdbe0..5a0c216 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -2,18 +2,26 @@ # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details -# Note: I used https://github.com/readthedocs/readthedocs.org/issues/4912#issuecomment-664002569 for inspiration +# Note: I used https://docs.readthedocs.io/en/stable/build-customization.html#install-dependencies-with-poetry for inspiration version: 2 +build: + os: "ubuntu-22.04" + tools: + python: "3.8" + jobs: + post_create_environment: + # Install poetry + # https://python-poetry.org/docs/#installing-manually + - pip install poetry + # Tell poetry to not use a virtual environment + - poetry config virtualenvs.create false + post_install: + # Install dependencies with 'docs' dependency group + # https://python-poetry.org/docs/managing-dependencies/#dependency-groups + - poetry install --only main,docs + sphinx: configuration: docs/conf.py - -python: - version: 3.7 - install: - - method: pip - path: . - extra_requirements: - - docs - + fail_on_warning: true diff --git a/dev-env.yml b/dev-env.yml new file mode 100644 index 0000000..985b69e --- /dev/null +++ b/dev-env.yml @@ -0,0 +1,13 @@ +channels: + - conda-forge + - bioconda + - nodefaults +dependencies: + - conda-forge::python=3.8 # the lowest version of python that we formally support + - conda-forge::pip==23.3.2 + - conda-forge::poetry==1.7.1 + - conda-forge::nox==2023.04.22 + - conda-forge::poetry-plugin-export==1.6.0 + - pip: + - nox-poetry==1.0.3 + - poetry-conda==0.1.1 diff --git a/docs/project_info/contributing.rst b/docs/project_info/contributing.rst index 1b97900..8e3aa38 100644 --- a/docs/project_info/contributing.rst +++ b/docs/project_info/contributing.rst @@ -13,7 +13,7 @@ Types of Contributions ~~~~~~~~~~~~ Report a bug ~~~~~~~~~~~~ -If you have found a bug, please report it on `our issues page `_ rather than emailing us directly. Others may have the same issue and this helps us get that information to them. +If you have found a bug, please report it on `our issues page `_ rather than emailing us directly. Others may have the same issue and this helps us get that information to them. Before you submit a bug, please search through our issues to ensure it hasn't already been reported. If you encounter an issue that has already been reported, please upvote it by reacting with a thumbs-up emoji. This helps us prioritize the issue. @@ -26,12 +26,14 @@ Fix a bug ~~~~~~~~~ Look through our issues page for bugs. We especially need help with bugs labeled "help wanted". If you want to start working on a bug then please write a message within the thread for that issue on our issues page, so that no one is duplicating work. +Please add a test reproducing the bug in our `tests/ directory `_. + ~~~~~~~~~~~~~~~~~~~~~~~ Implement a new feature ~~~~~~~~~~~~~~~~~~~~~~~ Our issues page will almost always have features on our wishlist. Once again, if you want to start working on a feature then please write a message within the thread for that feature on our issues page, so that no one is duplicating work. -Have an idea for a new feature that isn't on our wishlist? We'd love to hear about it! Before getting to work, please create a Github issue for it, so that you can make sure we're in agreement about what it should do. +Have an idea for a new feature that isn't on our wishlist? We'd love to hear about it! Before getting to work, please create a Github issue for it, so that you can make sure we're in agreement about what it should do. After you finish the feature, please add tests and documentation for it, as well. ------------------------------------------- How to fix a bug or implement a new feature @@ -48,11 +50,11 @@ To create a pull request you need to do these steps: 5. Create a new branch off of the :code:`main` branch with :code:`git checkout -b `. Please follow `best practices `_ when naming your branch 6. Setup our development environment by following the instructions in :ref:`dev-setup-instructions` below 7. Make your changes to the code - 8. Add additional tests to the :code:`tests/` directory and add comments to the documentation to explain how to use your new code. We use pytest for testing and sphinx/numpydoc for documentation + 8. Add additional tests to the :code:`tests/` directory and add comments to the documentation to explain how to use your new code. We use pytest for testing and sphinx/numpydoc for documentation. If you add example code or an example command to the documentation, you should make sure to create an automated test that executes it, as well. 9. Run the automated code-checking steps detailed in :ref:`code-check-instructions` below 10. Commit your changes. Please use informative commit messages and do your best to ensure the commit history is clean and easy to interpret 11. Now you can push your changes to your Github copy of happler by running :code:`git push origin ` - 12. Go to your Github copy of happler in your browser and create a pull request. `conventional commits spec `_. Be sure to change the pull request target branch to :code:`main` on this original repository. + 12. Go to your Github copy of happler in your browser and create a pull request titled according to the `conventional commits spec `_. Be sure to change the pull request target branch to :code:`main` on this original repository. 13. Please write an informative pull request detailing the changes you have made and why you made them. Tag any related issues by referring to them by a hashtag followed by their ID @@ -68,19 +70,19 @@ Follow these steps to set up a development environment. .. code-block:: bash - conda env create -n happler-dev -f environment.yml -2. Activate the environment + conda env create -n happler -f dev-env.yml +2. Install happler and its dependencies into a separate environment managed by ``poetry`` .. code-block:: bash - conda activate happler-dev -3. Install our dependencies + conda run -n happler poetry install - .. code-block:: bash +3. Now, whenever you'd like to run/import ``happler`` or ``pytest``, you will first need to activate both environments - poetry install -E docs -E tests + .. code-block:: bash -Now, try importing ``happler`` or running it on the command line. + conda activate happler + poetry shell --------------------- Managing Dependencies @@ -99,6 +101,82 @@ You should specify a `version constraint =8.0.4' + +------------------------------------------ +Modifying our command line interface (CLI) +------------------------------------------ +We use the `click library `_ to define ``happler``'s command line interface as `nested commands `_. All of the CLI logic is defined in `__main__.py `_. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Add or modify a command-line option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +First, locate the definition of the command in `__main__.py `_ + +You can add a ``@click.option`` or ``@click.argument`` line if you want to add a new option or argument. Please follow `click's convention `_ and only use ``@click.argument`` for required arguments and ``@click.option`` for optional ones. See `the click documentation `_ for directions on modifying or adding parameters like options/arguments. + +Please note that any modifications to our CLI represent a BREAKING change to happler. To note this, please add an exclamation point ``!`` to your pull request prefix as described in the `conventional commits spec `_. + +~~~~~~~~~~~~~~~~~ +Add a new command +~~~~~~~~~~~~~~~~~ +To add a new command, you only have to define a new function in `__main__.py `_. Within that function, you can import and call the rest of your code. For example, to add a command called ``mycommand`` which takes a single required file called ``arg1``, you might do the following. + +.. code-block:: python + + @main.command(short_help="A short description of my command") + @click.argument("arg1", type=click.Path(exists=True, path_type=Path)) + @click.option( + "-o", + "--output", + type=click.Path(path_type=Path), + default=Path("/dev/stdout"), + show_default="stdout", + help="The output of my command", + ) + @click.option( + "-v", + "--verbosity", + type=click.Choice(["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "NOTSET"]), + default="INFO", + show_default=True, + help="The level of verbosity desired", + ) + def mycommand( + arg1: Path, + output: Path = None, + verbosity: str = "INFO", + ): + """ + A longer description of mycommand + """ + + from .mycommand import run_things + from haptools.logging import getLogger + + log = getLogger(name="mycommand", level=verbosity) + + run_things(arg1, output, log) + +Notice that we usually define a logging object here to use throughout our code. For more information about logging, see the :ref:`section about it below `. All ``happler`` commands should use a default verbosity of ``INFO``. + +~~~~~~~~~~~~~~~~~~~~~ +Documentating our CLI +~~~~~~~~~~~~~~~~~~~~~ + ++++++++++++++++++++++++++++++++ +For command-line option changes ++++++++++++++++++++++++++++++++ + +Any new or modified command-line options will be automatically documented via **click**. The changes should appear in the *Detailed Usage* section of the documentation for the command that you changed. + +In addition to the auto-documented changes, you might want to consider adding a new example of the usage of your option to the *Examples* section of the documentation for the command that you changed. All examples in our documentation should also be executed within a file in our `tests/ directory `_. + +++++++++++++++++ +For new commands +++++++++++++++++ + +After you add a new command, you should make sure to create tests for it in the `tests/ directory `_. You should also create a new page in the *Commands* section of our documentation with sections for a short description, an abbreviated usage, example commands, and a detailed usage (which is auto-generated). You can refer to :ref:`the index command ` as an example. To ensure your new documentation page appears in our table of contents, add the name of the page to the list at the bottom of our `index.rst file `_. + .. _code-check-instructions: ----------- @@ -117,7 +195,7 @@ Before creating your pull request, please run each of our code checks. .. code-block:: bash sphinx-build docs docs/_build - open docs/_build/html/index.html + open docs/_build/index.html 3. Run all of the tests @@ -131,6 +209,18 @@ Before creating your pull request, please run each of our code checks. nox --session=tests +--------------------- +Publish a new version +--------------------- +To publish a new version of happler: + +1. First, locate `the most recent happler PR `_ prefixed "chore(main)" created by our Github actions bot +2. List an admin on our repository (currently: ``@aryarm``) as a reviewer of the PR and ask them to merge it +3. The bot will automatically create a new version on PyPI and tag a release on Github +4. A few hours later, bioconda will automatically detect the new release on PyPI and create a PR in `their repository `_ +5. Check that all of the dependencies in the recipe have been updated properly. If they are, you should comment on the bioconda PR with "@BiocondaBot please add label" +6. After 1-2 days, someone from the bioconda team will merge our PR and the version will get updated on bioconda. Otherwise, ping them a reminder on `Gitter `_ + ----- Style ----- @@ -146,6 +236,29 @@ Code ii. from external, third party packages iii. from our own internal code +.. _contributing-style-errors: + +~~~~~~ +Errors +~~~~~~ +We use the `Python logging module `_ for all messages, including warnings, debugging info, and otherwise. For example, all classes in the ``data`` module have a ``log`` property that stores a logger object. If you are creating a new command, you can use our custom logging module to retrieve a suitable object. + +.. code-block:: python + + from haptools.logging import getLogger + + # the level of verbosity desired by the user + # can be: CRITICAL, ERROR, WARNING, INFO, DEBUG, or NOTSET + verbosity = "DEBUG" + + # create a new logger object for the transform command + log = getLogger(name="transform", level=verbosity) + + # log a warning message to the logger + log.warning("This is a warning") + +This way, the user can choose their level of verbosity among *CRITICAL*, *ERROR*, *WARNING*, *INFO*, *DEBUG*, and *NOTSET*. However, for critical errors (especially for those in the ``data`` module), our convention is to raise exceptions, usually with a custom ``ValueError``. + ~~~~~~~~~~~~~~~~~~~ Git commit messages ~~~~~~~~~~~~~~~~~~~ diff --git a/environment.yml b/environment.yml deleted file mode 100644 index 31cf21a..0000000 --- a/environment.yml +++ /dev/null @@ -1,9 +0,0 @@ -channels: - - conda-forge - - nodefaults -dependencies: - - poetry==1.1.15 - - python=3.7 - - statsmodels==0.13.2 # this belongs in pyproject.toml but we've pinned it here for now b/c of https://github.com/statsmodels/statsmodels/issues/8200 - - gxx_linux-64 - diff --git a/noxfile.py b/noxfile.py index f213500..b599fc8 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,6 +1,5 @@ """Nox sessions.""" import os -import sys import shutil from pathlib import Path @@ -10,8 +9,9 @@ package = "happler" -python_versions = ["3.7", "3.8", "3.9", "3.10"] -nox.needs_version = ">= 2021.6.6" +python_versions = ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] +locked_python_version = "3.8" +nox.needs_version = ">= 2022.11.21" nox.options.sessions = ( "docs", "lint", @@ -19,15 +19,13 @@ ) -@session(python=python_versions[0]) +@session(python=locked_python_version) def docs(session: Session) -> None: """Build the documentation.""" args = session.posargs or ["docs", "docs/_build"] if not session.posargs and "FORCE_COLOR" in os.environ: args.insert(0, "--color") - session.install("statsmodels=0.13.2") - build_dir = Path("docs", "_build") if build_dir.exists(): shutil.rmtree(build_dir) @@ -35,11 +33,22 @@ def docs(session: Session) -> None: session.run("sphinx-build", *args) -@session(python=python_versions[0]) +@session(python=locked_python_version) def lint(session: Session) -> None: """Lint our code.""" session.install("black") - session.run("black", "--check", ".") + session.run("black", "--verbose", "--check", ".") + + +def install_handle_python_numpy(session): + """ + handle incompatibilities with python and numpy versions + see https://github.com/cjolowicz/nox-poetry/issues/1116 + """ + if session._session.python in ["3.11", "3.12"]: + session._session.install(".") + else: + session.install(".") # detect whether conda/mamba is installed @@ -53,14 +62,16 @@ def lint(session: Session) -> None: def tests(session: Session) -> None: """Run the test suite.""" session.conda_install( - "coverage[toml]", "pytest", "statsmodels=0.13.2", channel="conda-forge" + "coverage[toml]", + "pytest", + "numpy>=1.20.0", + channel="conda-forge", ) - # TODO: change this to ".[files]" once plink-ng Alpha 3.8 is released - # https://github.com/chrchang/plink-ng/releases - session.install(".") - + install_handle_python_numpy(session) try: - session.run("coverage", "run", "--parallel", "-m", "pytest", "tests/") + session.run( + "coverage", "run", "--parallel", "-m", "pytest", *session.posargs + ) finally: if session.interactive: session.notify("coverage", posargs=[]) @@ -70,21 +81,21 @@ def tests(session: Session) -> None: @session(python=python_versions) def tests(session: Session) -> None: """Run the test suite.""" - session.install("coverage[toml]", "pytest", "statsmodels==0.13.2") - # TODO: change this to ".[files]" once plink-ng Alpha 3.8 is released - # https://github.com/chrchang/plink-ng/releases - session.install(".") - + session.install("coverage[toml]", "pytest") + install_handle_python_numpy(session) try: - session.run("coverage", "run", "--parallel", "-m", "pytest", "tests/") + session.run( + "coverage", "run", "--parallel", "-m", "pytest", *session.posargs + ) finally: if session.interactive: session.notify("coverage", posargs=[]) -@session(python=python_versions[0]) +@session(python=locked_python_version) def coverage(session: Session) -> None: """Produce the coverage report.""" + session.install("coverage[toml]") args = session.posargs or ["report"] if not session.posargs and any(Path().glob(".coverage.*")):