-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate tests and lint suite to Nox (#21)
* Basic nox file initiated * Add lint check in nox sessions * Use nox in GitHub workflow * Fix GitHub action workflwo file in wrong place * Add codecov upload in nox sessions * Add codecov in dev dependencies * Add a GitHub action to upload coverage dada * Define in default sessions run by nox * Bump minor version to workaround bug in noxfile * Optimize noxfile to install only used dependencies * Move coverage report upload in tests workflow * Add colors in GitHub action logs for Nox * Update documentation with poetry and nox usage
- Loading branch information
1 parent
3ca77ef
commit 89d9d30
Showing
8 changed files
with
295 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pip==20.1.1 | ||
nox==2020.5.24 | ||
poetry==1.0.10 |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions | ||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions | ||
|
||
name: Tests | ||
|
||
on: | ||
push: | ||
branches: [master] | ||
pull_request: | ||
branches: [master] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
python-version: [3.6, 3.7, 3.8] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-python@v1 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
architecture: x64 | ||
|
||
- name: Upgrade pip | ||
run: | | ||
pip install --constraint=.github/workflows/constraints.txt pip | ||
pip --version | ||
- name: Install Poetry | ||
run: | | ||
pip install --constraint=.github/workflows/constraints.txt poetry | ||
poetry --version | ||
- name: Install Nox | ||
run: | | ||
pip install --constraint=.github/workflows/constraints.txt nox | ||
nox --version | ||
- name: Run Nox | ||
run: nox --force-color | ||
|
||
- name: Create coverage report | ||
run: | | ||
nox --force-color --session=coverage -- xml | ||
- name: Upload coverage report | ||
uses: codecov/[email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
"""Nox sessions.""" | ||
import contextlib | ||
import tempfile | ||
from pathlib import Path | ||
from typing import Iterator, cast | ||
|
||
import nox | ||
from nox.sessions import Session | ||
|
||
python_versions = ["3.8", "3.7", "3.6"] | ||
package = "meteofrance_api" | ||
nox.options.sessions = "lint", "tests" | ||
locations = "src", "tests", "noxfile.py" | ||
|
||
|
||
class Poetry: | ||
"""Helper class for invoking Poetry inside a Nox session. | ||
Attributes: | ||
session: The Session object. | ||
""" | ||
|
||
def __init__(self, session: Session) -> None: | ||
"""Constructor.""" | ||
self.session = session | ||
|
||
@contextlib.contextmanager | ||
def export(self, *args: str) -> Iterator[Path]: | ||
"""Export the lock file to requirements format. | ||
Args: | ||
args: Command-line arguments for ``poetry export``. | ||
Yields: | ||
The path to the requirements file. | ||
""" | ||
with tempfile.TemporaryDirectory() as directory: | ||
requirements = Path(directory) / "requirements.txt" | ||
self.session.run( | ||
"poetry", | ||
"export", | ||
*args, | ||
"--format=requirements.txt", | ||
f"--output={requirements}", | ||
external=True, | ||
) | ||
yield requirements | ||
|
||
def version(self) -> str: | ||
"""Retrieve the package version. | ||
Returns: | ||
The package version. | ||
""" | ||
output = self.session.run( | ||
"poetry", "version", external=True, silent=True, stderr=None | ||
) | ||
return cast(str, output).split()[1] | ||
|
||
def build(self, *args: str) -> None: | ||
"""Build the package. | ||
Args: | ||
args: Command-line arguments for ``poetry build``. | ||
""" | ||
self.session.run("poetry", "build", *args, external=True) | ||
|
||
|
||
def install_package(session: Session) -> None: | ||
"""Build and install the package. | ||
Build a wheel from the package, and install it into the virtual environment | ||
of the specified Nox session. | ||
The package requirements are installed using the versions specified in | ||
Poetry's lock file. | ||
Args: | ||
session: The Session object. | ||
""" | ||
poetry = Poetry(session) | ||
|
||
with poetry.export() as requirements: | ||
session.install(f"--requirement={requirements}") | ||
|
||
poetry.build("--format=wheel") | ||
|
||
version = poetry.version() | ||
session.install( | ||
"--no-deps", "--force-reinstall", f"dist/{package}-{version}-py3-none-any.whl" | ||
) | ||
|
||
|
||
def install(session: Session, *args: str) -> None: | ||
"""Install development dependencies into the session's virtual environment. | ||
This function is a wrapper for nox.sessions.Session.install. | ||
The packages must be managed as development dependencies in Poetry. | ||
Args: | ||
session: The Session object. | ||
args: Command-line arguments for ``pip install``. | ||
""" | ||
poetry = Poetry(session) | ||
with poetry.export("--dev") as requirements: | ||
session.install(f"--constraint={requirements}", *args) | ||
|
||
|
||
@nox.session(python=python_versions) | ||
def tests(session: Session) -> None: | ||
"""Run the test suite.""" | ||
install_package(session) | ||
install(session, "coverage[toml]", "pytest", "requests-mock") | ||
try: | ||
session.run("coverage", "run", "--parallel", "-m", "pytest", *session.posargs) | ||
finally: | ||
session.notify("coverage") | ||
|
||
|
||
@nox.session(python=python_versions) | ||
def lint(session): | ||
"""Lint using flake8.""" | ||
args = session.posargs or locations | ||
install_package(session) | ||
install(session, "flake8", "flake8-docstrings") | ||
session.run("flake8", *args) | ||
|
||
|
||
@nox.session | ||
def coverage(session: Session) -> None: | ||
"""Produce the coverage report.""" | ||
# Do not use session.posargs unless this is the only session. | ||
has_args = session.posargs and len(session._runner.manifest) == 1 | ||
args = session.posargs if has_args else ["report"] | ||
|
||
install(session, "coverage[toml]") | ||
|
||
if not has_args and any(Path().glob(".coverage.*")): | ||
session.run("coverage", "combine") | ||
|
||
session.run("coverage", *args) |
Oops, something went wrong.