Ejemplo n.º 1
0
def do_release(session: nox.Session) -> None:
    """Do a release to PyPI."""
    # TODO: maybe add version validation
    if modified_files_in_git() or modified_files_in_git("--staged"):
        session.error(
            "Repository not clean, please remove, unstage, or commit your changes"
        )

    if not len(session.posargs):
        session.error("Usage: nox -s publish -- <version> [publish-args]")
    else:
        version = session.posargs[0]

    update_version(session, version, MAIN_MODULE)
    update_changelog(session, version, CHANGELOG)
    commit_files(session, [MAIN_MODULE, CHANGELOG],
                 message=f"Prepare for release {version}")
    create_git_tag(session, version, message=f"Release {version}")

    with isolated_temporary_checkout(session) as workdir:
        session.chdir(workdir)
        session.install("flit")
        session.run("flit", "publish", *session.posargs[1:])

    session.chdir(THIS_DIR)
    update_version(session, next_development_version(version), MAIN_MODULE)
    update_changelog(session, "<unreleased>", CHANGELOG)
    commit_files(session, [MAIN_MODULE, CHANGELOG],
                 message="Let's get back to development")
    session.log(
        "Alright, just do a push to GitHub and everything should be done")
    session.log("If you're paranoid, go ahead, verify that things are fine")
    session.log("If not, sit back and relax, you just did a release 🎉")
Ejemplo n.º 2
0
def update_constraints(session: nox.Session) -> None:
    """
    Update the dependencies inplace.
    """
    session.install("pip-tools")
    assert isinstance(session.python, str)
    python_version = session.python.replace(".", "")
    env = os.environ.copy()
    # CUSTOM_COMPILE_COMMAND is a pip-compile option that tells users how to
    # regenerate the constraints files
    env["CUSTOM_COMPILE_COMMAND"] = f"nox -s {session.name}"
    session.run(
        "pip-compile",
        "--allow-unsafe",
        "--upgrade",
        "cibuildwheel/resources/constraints.in",
        f"--output-file=cibuildwheel/resources/constraints-python{python_version}.txt",
        env=env,
    )
    if session.python == PYTHON_ALL_VERSIONS[-1]:
        RESOURCES = DIR / "cibuildwheel" / "resources"
        shutil.copyfile(
            RESOURCES / f"constraints-python{python_version}.txt",
            RESOURCES / "constraints.txt",
        )
Ejemplo n.º 3
0
def check_versions(session: nox.Session) -> None:
    """Check that the version numbers declared for this project all match up."""
    import httpx

    # Note: this can be linked to a specific hash by adding it between raw and {file.name} as another route segment.
    with httpx.Client() as client:
        requirements = client.get(
            "https://gist.githubusercontent.com/FasterSpeeding/139801789f00d15b4aa8ed2598fb524e/raw/requirements.json"
        ).json()

        # Note: this can be linked to a specific hash by adding it between raw and {file.name} as another route segment.
        code = client.get(
            "https://gist.githubusercontent.com/FasterSpeeding/139801789f00d15b4aa8ed2598fb524e/raw/check_versions.py"
        ).read()

    session.install(".", "--use-feature=in-tree-build")
    session.install(*requirements)
    # This is saved to a temporary file to avoid the source showing up in any of the output.

    # A try, finally is used to delete the file rather than relying on delete=True behaviour
    # as on Windows the file cannot be accessed by other processes if delete is True.
    file = tempfile.NamedTemporaryFile(delete=False)
    try:
        with file:
            file.write(code)

        required_version = _try_find_option(session, "--required-version", "-r")
        args = ["--required-version", required_version] if required_version else []
        session.run("python", file.name, "-r", "sake", *args)

    finally:
        pathlib.Path(file.name).unlink(missing_ok=False)
Ejemplo n.º 4
0
def do_tests(session: nox.Session, *, coverage: bool) -> None:
    # Allow running test suite with a specific version of Black installed.
    # TODO: maybe consider dropping this and expect it to be done manually
    # using the environment created by setup-env. Although that would require
    # installing the test suite dependencies in that environment too, which
    # I am not too keen on :/
    black_req = ""
    if "--black-req" in session.posargs:
        index = session.posargs.index("--black-req")
        black_req = session.posargs[index + 1]
        del session.posargs[index]
        del session.posargs[index]

    session.install("flit")
    # Use editable installs even without coverage because it's faster.
    session.run("flit", "install", _FLIT_EDITABLE, silent=True)
    session.install(black_req or "black")
    install_requirement(session, "tests-base")
    if coverage:
        install_requirement(session, "tests-cov")

    cmd = ["pytest"]
    if coverage:
        cmd.extend(
            ["--cov", "--cov-branch", "--cov-context", "test", "--cov-append"])
    session.run(*cmd, *session.posargs)
Ejemplo n.º 5
0
def check_dependencies(session: nox.Session) -> None:
    """Verify that all the dependencies declared in pyproject.toml are up to date."""
    import httpx

    # Note: this can be linked to a specific hash by adding it between raw and {file.name} as another route segment.
    with httpx.Client() as client:
        requirements = client.get(
            "https://gist.githubusercontent.com/FasterSpeeding/13e3d871f872fa09cf7bdc4144d62b2b/raw/requirements.json"
        ).json()

        # Note: this can be linked to a specific hash by adding it between raw and {file.name} as another route segment.
        code = client.get(
            "https://gist.githubusercontent.com/FasterSpeeding/13e3d871f872fa09cf7bdc4144d62b2b/raw/check_dependency.py"
        ).read()

    session.install(*requirements)
    # This is saved to a temporary file to avoid the source showing up in any of the output.

    # A try, finally is used to delete the file rather than relying on delete=True behaviour
    # as on Windows the file cannot be accessed by other processes if delete is True.
    file = tempfile.NamedTemporaryFile(delete=False)
    try:
        with file:
            file.write(code)

        session.run("python", file.name)

    finally:
        pathlib.Path(file.name).unlink(missing_ok=False)
Ejemplo n.º 6
0
def bump(session: nox.Session) -> None:
    """
    Bump the major/minor/patch version (if nothing given, just shows the version).
    """

    session.install("tomli")
    output = session.run(
        "python",
        "-c",
        "import tomli, pathlib; p = pathlib.Path('pyproject.toml'); print(tomli.loads(p.read_text())['project']['version'])",
        silent=True,
    )
    current_version = output.strip()

    if not session.posargs:
        session.log(f"Current version: {current_version}")
        return

    new_version = session.posargs[0]
    session.log(f"Bumping from {current_version} to {new_version}")

    replace_version(
        Path("src/uhi/__init__.py"),
        '__version__ = "{version}"',
        current_version,
        new_version,
    )
    replace_version(Path("pyproject.toml"), 'version = "{version}"',
                    current_version, new_version)

    print(f"git switch -c chore/bump/{new_version}")
    print("git add -u src/uhi/__init__.py pyproject.toml")
    print(f"git commit -m 'chore: bump version to {new_version}'")
    print("gh pr create --fill")
Ejemplo n.º 7
0
def lint(session: nox.Session) -> None:
    """
    Run the linter.
    """
    session.install("pre-commit")
    session.run("pre-commit", "run", "--all-files", "--hook-stage=manual",
                *session.posargs)
Ejemplo n.º 8
0
def tests(session: nox.Session) -> str:
    """
    Run the tests.
    """
    wheel = build(session)
    session.install(f"./dist/{wheel}[test]")
    session.run("pytest", *session.posargs)
Ejemplo n.º 9
0
def black(session: nox.Session) -> None:
    """Run black, a code formatter and format checker."""
    session.install(BLACK_PINNED_VERSION)
    if session.posargs:
        session.run("python", "-m", "black", *session.posargs)
    else:
        session.run("python", "-m", "black", *DEFAULT_LINT_ARGUMENTS)
Ejemplo n.º 10
0
def build(session: nox.Session) -> None:
    """
    Build an SDist and wheel.
    """

    session.install("build")
    session.run("python", "-m", "build")
Ejemplo n.º 11
0
def build_release(session: nox.Session) -> None:
    version = release.get_version_from_arguments(session)
    if not version:
        session.error("Usage: nox -s build-release -- YY.N[.P]")

    session.log("# Ensure no files in dist/")
    if release.have_files_in_folder("dist"):
        session.error(
            "There are files in dist/. Remove them and try again. "
            "You can use `git clean -fxdi -- dist` command to do this")

    session.log("# Install dependencies")
    session.install("setuptools", "wheel", "twine")

    with release.isolated_temporary_checkout(session, version) as build_dir:
        session.log(
            "# Start the build in an isolated, "
            f"temporary Git checkout at {build_dir!s}", )
        with release.workdir(session, build_dir):
            tmp_dists = build_dists(session)

        tmp_dist_paths = (build_dir / p for p in tmp_dists)
        session.log(f"# Copying dists from {build_dir}")
        os.makedirs("dist", exist_ok=True)
        for dist, final in zip(tmp_dist_paths, tmp_dists):
            session.log(f"# Copying {dist} to {final}")
            shutil.copy(dist, final)
Ejemplo n.º 12
0
def tests_packaging(session: nox.Session) -> None:
    """
    Run the packaging tests.
    """

    session.install("-r", "tests/requirements.txt", "--prefer-binary")
    session.run("pytest", "tests/extra_python_package")
Ejemplo n.º 13
0
def upload_release(session: nox.Session) -> None:
    version = release.get_version_from_arguments(session)
    if not version:
        session.error("Usage: nox -s upload-release -- YY.N[.P]")

    session.log("# Install dependencies")
    session.install("twine")

    distribution_files = glob.glob("dist/*")
    session.log(f"# Distribution files: {distribution_files}")

    # Sanity check: Make sure there's 2 distribution files.
    count = len(distribution_files)
    if count != 2:
        session.error(
            f"Expected 2 distribution files for upload, got {count}. "
            f"Remove dist/ and run 'nox -s build-release -- {version}'")
    # Sanity check: Make sure the files are correctly named.
    distfile_names = (os.path.basename(fn) for fn in distribution_files)
    expected_distribution_files = [
        f"pip-{version}-py3-none-any.whl",
        f"pip-{version}.tar.gz",
    ]
    if sorted(distfile_names) != sorted(expected_distribution_files):
        session.error(
            f"Distribution files do not seem to be for {version} release.")

    session.log("# Upload distributions")
    session.run("twine", "upload", *distribution_files)
Ejemplo n.º 14
0
def publish(session: Session) -> None:
    """
    Publish a package to pypi
    """

    session.install("poetry", "poetry-dynamic-versioning")
    session.run("poetry", "publish", "--build")
Ejemplo n.º 15
0
def dev(session: nox.Session) -> None:
    """Build a development environment and optionally run a command given as extra args"""
    session.install(*test_deps)
    session.install(*dev_deps)
    session.install("-e", ".")
    if session.posargs:
        session.run(*session.posargs, external=True)
Ejemplo n.º 16
0
def pylint(session: nox.Session) -> None:
    """
    Run pylint.
    """

    session.install("pylint", ".")
    session.run("pylint", "cibuildwheel", *session.posargs)
Ejemplo n.º 17
0
def check_manifest(session: nox.Session) -> None:
    """
    Ensure all needed files are included in the manifest.
    """

    session.install("check-manifest")
    session.run("check-manifest", *session.posargs)
Ejemplo n.º 18
0
def update(session: nox.Session) -> None:
    """
    Get the latest (or given) version of cmake and update the copy with it.
    """

    if session.posargs:
        (version, ) = session.posargs
    else:
        session.install("lastversion")
        version = session.run("lastversion",
                              "kitware/cmake",
                              log=False,
                              silent=True).strip()

    cmake_url = f"https://raw.githubusercontent.com/Kitware/CMake/v{version}/Utilities/Sphinx/cmake.py"
    colors_url = f"https://raw.githubusercontent.com/Kitware/CMake/v{version}/Utilities/Sphinx/colors.py"

    urllib.request.urlretrieve(cmake_url,
                               "sphinxcontrib/moderncmakedomain/cmake.py")
    urllib.request.urlretrieve(colors_url,
                               "sphinxcontrib/moderncmakedomain/colors.py")

    session.install("bump2version")
    session.run("bumpversion", "--allow-dirty", "--new-version", version,
                "patch", "setup.cfg")
Ejemplo n.º 19
0
def check_wheel(session: nox.Session) -> None:
    """Check the wheel, should not be used directly."""
    session.install("wheel", "twine")
    session.chdir(f"{session.cache_dir}/dist")
    session.run("twine", "check", "*", external=True)
    session.install(glob.glob("*.whl")[0])
    session.run("python", "-m", "gcovr", "--help", external=True)
Ejemplo n.º 20
0
def tests_pipenv(session: nox.Session):
    """
    Run test suite with pipenv sync.
    """
    tmp_dir = session.create_tmp()
    for to_copy in (package_name, tests_name, pipfile_lock, notebooks_name):
        if Path(to_copy).is_dir():
            copytree(to_copy, Path(tmp_dir) / to_copy)
        elif Path(to_copy).is_file():
            copy2(to_copy, tmp_dir)
        elif Path(to_copy).exists():
            ValueError("File not dir or file.")
        else:
            logging.error(f"Expected {to_copy} to exist.")
    session.chdir(tmp_dir)
    session.install("pipenv")
    session.run("pipenv", "--rm", success_codes=[0, 1])
    session.run(
        "pipenv",
        "sync",
        "--python",
        f"{session.python}",
        "--dev",
        "--bare",
    )
    session.run(
        "pipenv",
        "run",
        "pytest",
    )
Ejemplo n.º 21
0
def doctest(session: nox.Session) -> None:
    """Execute script `run_doctests.py` and measure code coverage.

    You can define arguments specific to the doctest session.  The `doctest` session
    passes them to the `run_doctests.py` script.  For example, to restrict testing to
    module `armatools.py` in Cython mode, write:

    nox -s doctest -- --file_doctests=armatools.py --python-mode=false

    Or shorter:

    nox -s doctest -- -f armatools.py -p f

    The `doctest` session only measures code coverage when no session-specific
    arguments are given, due to the mentioned restrictions inevitably resulting in
    incomplete code coverage measurements.
    """
    _install_hydpy(session)
    session.install("coverage")
    session.chdir(_get_sitepackagepath(session))
    session.run("python", "hydpy/docs/enable_autodoc.py")
    if not session.posargs:
        shutil.copy("hydpy/tests/hydpydoctestcustomize.py",
                    "hydpydoctestcustomize.py")
        shutil.copy("hydpy/tests/hydpydoctestcustomize.pth",
                    "hydpydoctestcustomize.pth")
    with _clean_environment(session):
        session.run("python", "hydpy/tests/run_doctests.py", *session.posargs)
    if not session.posargs:
        session.run("coverage", "combine")
        session.run("coverage", "report", "-m", "--skip-covered",
                    "--fail-under=100")
Ejemplo n.º 22
0
def sphinx(session: nox.Session) -> None:
    """Build the HTML documentation and report warnings as errors.

    The `sphinx` session is more about building than testing.  However, it also checks
    for completeness, substitutions' correctness, and things like that.  Hence, we
    leave it here until we find a strong reason for moving it somewhere else.

    This session passes session-specific arguments to `sphinx-build`.  For example,
    when building the official documentation on Travis-CI, we want to ensure that
    everything is correct, so we pass the `-W` flag to convert warnings into errors:

    nox -s sphinx -- -W
    """
    _install_hydpy(session)
    session.install(
        "docutils",
        "sphinx",
        "sphinxcontrib-fulltoc",
        "sphinxprettysearchresults",
        "sphinxcontrib.bibtex<2",
    )
    session.chdir(_get_sitepackagepath(session))
    with _clean_environment(session):
        session.run("python", "hydpy/tests/run_doctests.py",
                    "--python-mode=false")
    session.run("python", "hydpy/docs/enable_autodoc.py")
    session.run("python", "hydpy/docs/prepare.py")
    session.run("sphinx-build", "hydpy/docs/auto", "hydpy/docs/auto/build",
                *session.posargs)
    session.run("python", "hydpy/docs/modify_html.py")
Ejemplo n.º 23
0
def docs(session: nox.Session) -> None:
    session.install("-e", ".")
    session.install("-r", REQUIREMENTS["docs"])

    def get_sphinx_build_command(kind: str) -> List[str]:
        # Having the conf.py in the docs/html is weird but needed because we
        # can not use a different configuration directory vs source directory
        # on RTD currently. So, we'll pass "-c docs/html" here.
        # See https://github.com/rtfd/readthedocs.org/issues/1543.
        # fmt: off
        return [
            "sphinx-build",
            "-W",
            "-c",
            "docs/html",  # see note above
            "-d",
            "docs/build/doctrees/" + kind,
            "-b",
            kind,
            "docs/" + kind,
            "docs/build/" + kind,
        ]
        # fmt: on

    session.run(*get_sphinx_build_command("html"))
    session.run(*get_sphinx_build_command("man"))
Ejemplo n.º 24
0
def mypy(session: nox.Session) -> None:
    """Run mypy."""
    session.install("-r", "mypy-requirements.txt")
    session.run("mypy", "--version")
    session.run(
        "mypy",
        "dummyserver",
        "noxfile.py",
        "src/urllib3",
        "test/__init__.py",
        "test/with_dummyserver/test_connectionpool.py",
        "test/with_dummyserver/test_chunked_transfer.py",
        "test/with_dummyserver/test_https.py",
        "test/with_dummyserver/test_no_ssl.py",
        "test/with_dummyserver/test_poolmanager.py",
        "test/with_dummyserver/test_proxy_poolmanager.py",
        "test/conftest.py",
        "test/contrib/test_pyopenssl_dependencies.py",
        "test/contrib/test_socks.py",
        "test/port_helpers.py",
        "test/test_collections.py",
        "test/test_compatibility.py",
        "test/test_connection.py",
        "test/test_exceptions.py",
        "test/test_fields.py",
        "test/test_filepost.py",
        "test/test_no_ssl.py",
        "test/test_poolmanager.py",
        "test/test_proxymanager.py",
        "test/test_queue_monkeypatch.py",
        "test/test_retry.py",
        "test/test_ssl.py",
        "test/test_wait.py",
        "test/tz_stub.py",
    )
Ejemplo n.º 25
0
def dev_test_sim(
    session: nox.Session,
    sim: Optional[str],
    toplevel_lang: Optional[str],
    gpi_interface: Optional[str],
) -> None:
    """Test a development version of cocotb against a simulator."""

    session.env["CFLAGS"] = "-Werror -Wno-deprecated-declarations -g --coverage"
    session.env["COCOTB_LIBRARY_COVERAGE"] = "1"
    session.env["CXXFLAGS"] = "-Werror"
    session.env["LDFLAGS"] = "--coverage"

    session.install(*test_deps, *coverage_deps)
    session.install("-e", ".")

    env = env_vars_for_test(sim, toplevel_lang, gpi_interface)
    config_str = stringify_dict(env)

    # Remove a potentially existing coverage file from a previous run for the
    # same test configuration.
    coverage_file = Path(f".coverage.test.sim-{sim}-{toplevel_lang}-{gpi_interface}")
    with suppress(FileNotFoundError):
        coverage_file.unlink()

    session.log(f"Running 'make test' against a simulator {config_str}")
    session.run("make", "test", external=True, env=env)

    session.log(f"Running simulator-specific tests against a simulator {config_str}")
    session.run(
        "pytest",
        "-v",
        "--cov=cocotb",
        "--cov-branch",
        # Don't display coverage report here
        "--cov-report=",
        "-k",
        "simulator_required",
    )
    Path(".coverage").rename(".coverage.pytest")

    session.log(f"All tests passed with configuration {config_str}!")

    # Combine coverage produced during the test runs, and place it in a file
    # with a name specific to this invocation of dev_test_sim().
    coverage_files = glob.glob("**/.coverage.cocotb", recursive=True)
    if not coverage_files:
        session.error(
            "No coverage files found. Something went wrong during the test execution."
        )
    coverage_files.append(".coverage.pytest")
    session.run("coverage", "combine", "--append", *coverage_files)
    Path(".coverage").rename(coverage_file)

    session.log(f"Stored Python coverage for this test run in {coverage_file}.")

    # Combine coverage from all nox sessions as last step after all sessions
    # have completed.
    session.notify("dev_coverage_combine")
Ejemplo n.º 26
0
def build(session: nox.Session) -> None:
    """
    Build SDists and wheels.
    """

    session.install("build")
    session.run("python", "-m", "build")
    session.run("python", "-m", "build", env={"PYBIND11_GLOBAL_SDIST": "1"})
Ejemplo n.º 27
0
def docs(session: nox.Session) -> None:
    session.install("-r", "docs/requirements.txt")
    session.install(".[socks,secure,brotli]")

    session.chdir("docs")
    if os.path.exists("_build"):
        shutil.rmtree("_build")
    session.run("sphinx-build", "-b", "html", "-W", ".", "_build/html")
Ejemplo n.º 28
0
def tests(session: nox.Session) -> None:
    """
    Run the unit and regular tests.
    """

    shutil.rmtree("build", ignore_errors=True)
    session.install(".[test]")
    session.run("pytest", *session.posargs)
Ejemplo n.º 29
0
def conda_tests(session: nox.Session) -> None:
    """Run test suite with pytest."""
    session.create_tmp()  # Fixes permission errors on Windows
    session.conda_install(
        "--file", "requirements-conda-test.txt", "--channel", "conda-forge"
    )
    session.install("-e", ".", "--no-deps")
    session.run("pytest", *session.posargs)
Ejemplo n.º 30
0
def pylint(session: nox.Session) -> None:
    """
    Run pylint.
    """

    session.install("pylint")
    session.install("-e", ".")
    session.run("pylint", "src", *session.posargs)