Nox 秘籍

什么?

很多人和很多项目都使用 Nox 的 python 自动化能力。

这些会话中有些是经典的(”run pytest and linting”),有些是更独特、更有趣的!

Nox 秘籍是这些会话的集合。

Nox超级容易上手,而且开箱即用,超级强大。但是,当事情变得复杂或者你想把一些更强大的任务串联起来时,往往可以在 GitHub 上找到唯一的例子来猎取新颖的会话。

那种让你觉得 “我不知道你能做到这一点!” 的会话。

这本秘籍旨在成为一个集中的、由社区驱动的、令人敬畏的 Nox 会话库,作为灵感来源和 Nox 用户的参考指南。如果你正在用 Nox 做一些很酷的事情,为什么不在这里添加你的会话呢?

贡献会话

任何人都可以为秘籍贡献会话。然而,有几条指导原则你应该牢记:

  • 你的会话应该是有趣的或独特的,它应该做一些不寻常的事情或其他有趣的事情。

  • 你应该简要地解释它的作用,以及为什么它很有趣。

关于如何为 Nox 做贡献的一般建议,请参见 贡献 指南

绝技

即时开发环境

在为 Python 项目做贡献时,常见的症结(尤其是对于初学者)是处理虚拟环境和安装依赖的问题。

进入 dev nox 会话:

import os

import nox

# It's a good idea to keep your dev session out of the default list
# so it's not run twice accidentally
nox.options.sessions = [...] # Sessions other than 'dev'

@nox.session
def dev(session: nox.Session) -> None:
    """
    Sets up a python development environment for the project.

    This session will:
    - Create a python virtualenv for the session
    - Install the `virtualenv` cli tool into this environment
    - Use `virtualenv` to create a global project virtual environment
    - Invoke the python interpreter from the global project environment to install
      the project and all it's development dependencies.
    """

    session.install("virtualenv")
    # VENV_DIR here is a pathlib.Path location of the project virtualenv
    # e.g. .venv
    session.run("virtualenv", os.fsdecode(VENV_DIR), silent=True)

    python = os.fsdecode(VENV_DIR.joinpath("bin/python"))

    # Use the venv's interpreter to install the project along with
    # all it's dev dependencies, this ensures it's installed in the right way
    session.run(python, "-m", "pip", "install", "-e", ".[dev]", external=True)

有了这个,用户只需运行 nox -s dev,就能自动设置好他们的整个环境!

自动发布

发布开源项目的新版本可能是真正的痛苦,有很多复杂的步骤。像 Bump2Version 这样的工具在这里确实有帮助。

洒上 Nox 后更是如此:

import nox

@nox.session
def release(session: nox.Session) -> None:
    """
    Kicks off an automated release process by creating and pushing a new tag.

    Invokes bump2version with the posarg setting the version.

    Usage:
    $ nox -s release -- [major|minor|patch]
    """
    parser = argparse.ArgumentParser(description="Release a semver version.")
    parser.add_argument(
        "version",
        type=str,
        nargs=1,
        help="The type of semver release to make.",
        choices={"major", "minor", "patch"},
    )
    args: argparse.Namespace = parser.parse_args(args=session.posargs)
    version: str = args.version.pop()

    # If we get here, we should be good to go
    # Let's do a final check for safety
    confirm = input(
        f"You are about to bump the {version!r} version. Are you sure? [y/n]: "
    )

    # Abort on anything other than 'y'
    if confirm.lower().strip() != "y":
        session.error(f"You said no when prompted to bump the {version!r} version.")


    session.install("bump2version")

    session.log(f"Bumping the {version!r} version")
    session.run("bump2version", version)

    session.log("Pushing the new tag")
    session.run("git", "push", external=True)
    session.run("git", "push", "--tags", external=True)

现在,简单的 nox -s release -- patch 就能自动发布(前提是你已经设置了 Bump2Version 来改变你的文件)。如果你设置了 CI/CD 管道,这就特别强大!