You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"""Nox configuration and automation tasks for Python projects.This noxfile provides a comprehensive set of development, testing, and maintenance tasks.All sessions can be run using: `uv run nox -s session_name`Available Sessions:-----------------Testing & Quality: test Run pytest test suite Usage: uv run nox -s test [-- tests/specific_test.py] coverage Run tests with coverage reporting Usage: uv run nox -s coverage integration_tests Run integration test suite Usage: uv run nox -s integration_testsCode Quality: format Format code using ruff Usage: uv run nox -s format [-- path/to/format] lint Run ruff linter Usage: uv run nox -s lint [-- path/to/lint] type_check Run mypy type checking Usage: uv run nox -s type_check [-- path/to/check] security Run bandit security checks Usage: uv run nox -s security pre_commit Run all pre-commit hooks Usage: uv run nox -s pre_commitDocumentation: build_docs Build documentation using MkDocs Usage: uv run nox -s build_docsBuild & Release: build Build package distributions Usage: uv run nox -s build [-- --wheel] clean Remove build artifacts Usage: uv run nox -s clean publish Check and upload package to PyPI Usage: uv run nox -s publishDevelopment Tools: generate_requirements Generate requirements.txt files Usage: uv run nox -s requirements [-- --format requirements-txt] benchmark Run performance benchmarks Usage: uv run nox -s benchmark dependency_check Check dependencies for security issues Usage: uv run nox -s dependency_checkDocker: docker_build Build Docker image Usage: uv run nox -s docker_buildNotes:- Most sessions support additional arguments after `--`- Sessions with dependency groups automatically install required packages- Default Python version is determined by .python-version file or falls back to 3.13- All sessions use UV as the virtual environment backendExamples: # Run specific test file uv run nox -s test -- tests/test_specific.py # Format specific directory uv run nox -s format -- src/ # Build wheel only uv run nox -s build -- --wheel # Generate requirements with specific format uv run nox -s requirements -- --format pip-compile"""fromfunctoolsimportwrapsimportnoxfromnoximportSessionimportloggingimportsysfrompathlibimportPathfromtypingimport (
Any,
Callable,
Dict,
Generator,
Literal,
Optional,
Sequence,
List,
Tuple,
TypeVar,
Union,
)
fromdataclassesimportdataclassifsys.version_info>= (3, 11):
importtomllibastoml_libelse:
try:
importtomliastoml_libexceptImportError:
raiseImportError(
"For Python versions < 3.11, please install 'tomli' using pip: pip install tomli"
)
# Set up logginglogging.basicConfig(level=logging.DEBUG)
logger=logging.getLogger(__name__)
T_co=TypeVar("T_co", covariant=True)
AnyCallable=Callable[..., Any]
SessionDecorator=Union[AnyCallable, Callable[[AnyCallable], AnyCallable]]
@dataclass(frozen=True)classConstants:
# Pure constantsDOT="."# Dependency-related constantsDEPENDENCIES_GROUP_KEY: str="dependency-groups"DEPENDENCIES_KEY: str="dependencies"PROJECT_KEY: str="project"DEV_KEY: str="dev"TESTS_KEY: str="tests"DOCS_KEY: str="docs"RELEASE_KEY: str="release"# Dependency keys pathsDEV_DEPENDENCIES_KEYS: Tuple[str, ...] = (DEPENDENCIES_GROUP_KEY, DEV_KEY)
RELEASE_DEPENDENCIES_KEYS: Tuple[str, ...] = (PROJECT_KEY, DEPENDENCIES_KEY)
DOCS_DEPENDENCIES_KEYS: Tuple[str, ...] = (DEPENDENCIES_GROUP_KEY, DOCS_KEY)
TESTS_DEPENDENCIES_KEYS: Tuple[str, ...] = (DEPENDENCIES_GROUP_KEY, TESTS_KEY)
# Python version constantsDEFAULT_PYTHON_VERSION: str="3.13"MINIMALLY_SUPPORTED_PYTHON_VERSION: str="3.8"@propertydefALL_SUPPORTED_PYTHON_VERSIONS(self) ->Generator[str, None, None]:
min_version=int(self.MINIMALLY_SUPPORTED_PYTHON_VERSION.split(".")[1])
max_version=int(self.DEFAULT_PYTHON_VERSION.split(".")[1])
return (f"3.{i}"foriinrange(min_version, max_version+1))
@dataclass(frozen=True)classBinaryCommand:
RUFF: str="ruff"PYTEST: str="pytest"PYTHON: str="python"MYPY: str="mypy"BANDIT: str="bandit"MKDOCS: str="mkdocs"SPHINX_BUILD: str="sphinx-build"COVERAGE: str="coverage"PRE_COMMIT: str="pre-commit"RM: str="rm"TWINE: str="twine"PIP_COMPILE: str="pip-compile"DOCKER: str="docker"SAFETY: str="safety"BUILD: str="build"UV: str="uv"@dataclass(frozen=True)classDirectories:
TESTS: str=Constants.TESTS_KEYDOCS: str=Constants.DOCS_KEYSRC: str="src"BUILD: str=BinaryCommand.BUILDDIST: str="dist"CWD: str="."NOX_OPTIONS_ACROSS_ALL_SESSIONS= {
"reuse_venv": True,
"venv_backend": "uv|virtualenv",
}
BASE_NOX_SESSION: Callable[[str], Callable[[Callable], SessionDecorator]] = (
lambdaname: nox.session(
name=name,
python=CURRENT_PYTHON_VERSION,
**NOX_OPTIONS_ACROSS_ALL_SESSIONS,
)
)
DEFAULT_UNNAMED_NOX_SESSION: Callable[
[str, Optional[str], Optional[Tuple[str, ...]]],
Callable[[Callable], SessionDecorator],
] = (
lambdaname,
group_deps_name=None,
default_posargs=(): lambdafunc: BASE_NOX_SESSION(name)(
(
alter_session_run(func, default_posargs),
install_group_deps(group_deps_name)(
alter_session_run(func, default_posargs)
),
)[int(group_deps_nameisnotNone)]
)
)
"""Standard Nox Session decorator that creates a named session with configurable behavior.This decorator wraps around the base Nox session decorator to provide three functionalities:1. Creates a Nox session with a specified name2. Optionally installs dependency groups before running the session3. Allows specification of default positional argumentsArgs: name (str): The name to use for the Nox session group_deps_name (str, optional): The name of the dependency group to install before running the session. If None, no additional dependencies will be installed. default_posargs (Tuple[str, ...], optional): Default positional arguments to be used when no command-line arguments are provided.Examples: ```python # Basic usage with just a session name @DEFAULT_UNNAMED_NOX_SESSION('testing') def run_tests(session): session.run('pytest') # Usage with dependency group installation @DEFAULT_UNNAMED_NOX_SESSION('testing', group_deps_name='test-deps') def run_tests(session): session.run('pytest') # Usage with default positional arguments @DEFAULT_UNNAMED_NOX_SESSION('lint', default_posargs=('src/', 'tests/')) def run_lint(session): session.run('flake8', *session.posargs) # Combined usage @DEFAULT_UNNAMED_NOX_SESSION('pytest', group_deps_name='test-deps', default_posargs=('tests/',)) def run_tests(session): session.run('pytest', *session.posargs) ```Notes: - The decorated function becomes a Nox session that can be discovered and run by Nox - Session names must be unique across all sessions in the noxfile - Dependencies are installed via Poetry's group feature when group_deps_name is provided - Default positional arguments (default_posargs) are used only when no command-line arguments are given - Access runtime arguments within the session using session.posargs - Command-line arguments override default_posargs when providedReturns: SessionDecorator: A decorated function that Nox recognizes as a session"""DEFAULT_NAMED_NOX_SESSION: Callable[
[AnyCallable, Optional[Tuple[str, ...]]],
Union[AnyCallable, Callable[[AnyCallable], AnyCallable]],
] =lambdagroup_deps_name, default_posargs=(): (
# if `group_deps_name` is callable, means decorating a function, directly return the decorator `DEFAULT_UNNAMED_NOX_SESSION`DEFAULT_UNNAMED_NOX_SESSION(
group_deps_name.__name__.replace("_", "-"), default_posargs=default_posargs
)(group_deps_name)
ifcallable(group_deps_name)
else ...,
# if `group_deps_name` is str, return lambdalambdafunc: DEFAULT_UNNAMED_NOX_SESSION(
func.__name__.replace("_", "-"), default_posargs=default_posargs
)(install_group_deps(group_deps_name)(func)),
)[int(isinstance(group_deps_name, str))] # not callable => 0, callable => 1"""A flexible Nox session decorator that automatically derives the session name from the function name.This decorator serves as a higher-level wrapper around DEFAULT_UNNAMED_NOX_SESSION with two usage patterns:1. As a simple decorator (@DEFAULT_NAMED_NOX_SESSION) that uses the function name as the session name2. As a decorator factory (@DEFAULT_NAMED_NOX_SESSION("group")) that installs dependencies before runningThe session name is automatically generated by replacing underscores with hyphens in the function name.Args: group_deps_name (Union[str, Callable]): Either: - A function to decorate (when used as @DEFAULT_NAMED_NOX_SESSION) - A string specifying the dependency group name (when used as @DEFAULT_NAMED_NOX_SESSION("group")) default_posargs (Tuple[str, ...], optional): Default positional arguments to use when no command-line arguments are provided.Examples: ```python # Simple usage - session name will be "run-tests" @DEFAULT_NAMED_NOX_SESSION def run_tests(session): session.run('pytest') # With dependency group - session name will be "integration-tests" @DEFAULT_NAMED_NOX_SESSION('test-deps') def integration_tests(session): session.run('pytest', 'tests/integration') # With default arguments - session name will be "run-lint" @DEFAULT_NAMED_NOX_SESSION def run_lint(session): session.run('flake8', *session.posargs) # Combined usage - session name will be "run-all-tests" @DEFAULT_NAMED_NOX_SESSION('test-deps', default_posargs=('tests/',)) def run_all_tests(session): session.run('pytest', *session.posargs) ```Notes: - Session names are automatically generated from the function name by replacing '_' with '-' - When used with a group name, dependencies are installed via Poetry's group feature - Default positional arguments are used only when no command-line arguments are provided - Access runtime arguments within the session using session.posargs - Command-line arguments take precedence over default_posargsReturns: Union[AnyCallable, Callable[[AnyCallable], AnyCallable]]: Either: - The decorated session function (when used as simple decorator) - A decorator that will create the session (when used with arguments)"""TESTS_DEPS_NAMED_NOX_SESSION=lambdadefault_posargs=(): DEFAULT_NAMED_NOX_SESSION(
"tests", default_posargs
)
"""A decorator that will set up a Nox session with all the group = 'tests' dependencies installed."""DEV_DEPS_NAMED_NOX_SESSION=lambdadefault_posargs=(): DEFAULT_NAMED_NOX_SESSION(
"dev", default_posargs
)
"""A decorator that will set up a Nox session with all the group = 'dev' dependencies installed."""DOCS_DEPS_NAMED_NOX_SESSION=lambdadefault_posargs=(): DEFAULT_NAMED_NOX_SESSION(
"docs", default_posargs
)
"""A decorator that will set up a Nox session with all the group = 'docs' dependencies installed."""RELEASE_DEPS_NAMED_NOX_SESSION=lambdadefault_posargs=(): DEFAULT_NAMED_NOX_SESSION(
"release", default_posargs
)
"""A decorator that will set up a Nox session with all the 'release' dependencies installed."""defalter_session_run(func: Callable[..., Any], default_posargs: Tuple[str, ...] = ()):
@wraps(func)defwrapper(session: Session, *args, **kwargs):
ifsession.posargsordefault_posargs:
classSessionWithNoSlots(Session):
__dict__= {**session.__dict__}
defrun(self, *args, **kwargs):
args= [*args, *(session.posargsordefault_posargs)]
returnsession.run(*args, **kwargs)
new_session=object.__new__(SessionWithNoSlots)
fork, vinsession.__dict__.items():
setattr(new_session, k, v)
returnfunc(new_session, *args, **kwargs)
returnfunc(session, *args, **kwargs)
returnwrapperdefinstall_group_deps(group_deps_name: str):
defdecorator(func: Callable[..., Any]):
@wraps(func)defwrapper(session: Session, *args, **kwargs):
logger.debug(f"Installing dependencies for group: {group_deps_name}")
nox_session_install_deps_in_group(
session, group_deps_nameifgroup_deps_nameelseNone
)
returnfunc(session, *args, **kwargs)
returnwrapperreturndecoratordeffind_any_file(file_name_with_extension: str) ->Callable[[], Optional[Path]]:
try:
fromtypingimportcastfromloggingimportLoggerlogger=cast(Logger, logger)
exceptNameError:
logger=type("nothing", (), {"debug": lambda*_args, **_kwargs: None})()
try:
file_name, extension=file_name_with_extension.split(".")
exceptValueError:
returnlambda: Nonedeffind_the_file() ->Optional[Path]:
logger.debug(f"Entering `find_{file_name}_{extension}` function")
curr_dir=Path(__file__).parentlogger.debug(f"Starting search from directory: {curr_dir}")
whilecurr_dir!=curr_dir.parent:
logger.debug(f"Checking directory: {curr_dir}")
file_path=curr_dir/f"{file_name}.{extension}"iffile_path.is_file():
logger.debug(f"Found {file_name}.{extension} at: {file_path}")
returnfile_pathcurr_dir=curr_dir.parentlogger.debug(f"Moving up to parent directory: {curr_dir}")
logger.debug(f"{file_name}.{extension} not found in any parent directory")
returnNonefind_any_file.__name__=f"find_{file_name}_{extension}"returnfind_the_filefind_pyproject_toml=find_any_file("pyproject.toml")
find_dot_python_version=find_any_file(".python-version")
defget_min_python_version(requires_python: str):
importredefparse_version(version_str: str):
returntuple(map(int, version_str.split(".")))
# Remove any whitespacerequires_python=requires_python.replace(" ", "")
# Initialize with the lowest possible Python 3 versionmin_version= (3, 0)
# Split by commas to handle multiple conditionsconditions=requires_python.split(",")
forconditioninconditions:
match=re.match(r"(>=|>|<|<=|==|~=|\^)?(\d+(\.\d+)*)", condition)
ifmatch:
operator, version=match.groups()[:2]
version=parse_version(version)
ifoperatorin (">=", "==", "~=", "^") oroperatorisNone:
ifversion>min_version:
min_version=versionelifoperator==">":
next_version=version[:-1] + (version[-1] +1,)
ifnext_version>min_version:
min_version=next_versionreturn".".join(map(str, min_version))
defimmediately_invoke(f: Callable[[], T_co]) ->T_co:
returnf()
@immediately_invokedefCURRENT_PYTHON_VERSION() ->str:
PYTHON_VERSION=Constants.DEFAULT_PYTHON_VERSIONtry:
DOT_PYTHON_VERSION_FILE=find_dot_python_version()
ifDOT_PYTHON_VERSION_FILE:
logger.debug("found `.python-version`")
withopen(str(DOT_PYTHON_VERSION_FILE), mode="r") asf:
PYTHON_VERSION=f.readline().replace("\n", "")
except (IOError, FileNotFoundError) aserr:
logger.error(
f"error encountered when attempting to read `.python-version`; error: {err}"
)
returnPYTHON_VERSIONlogger.debug(f"`CURRENT_PYTHON_VERSION` is set to '{PYTHON_VERSION}'")
returnPYTHON_VERSIONdefget_pyproject_toml_data() ->Optional[Dict[str, str]]:
logger.debug("Attempting to find `pyproject.toml` file")
pyproject_toml_file=find_pyproject_toml()
ifpyproject_toml_fileisNone:
logger.debug("`pyproject.toml` file not found")
returnNonelogger.debug(f"Reading `pyproject.toml` from {pyproject_toml_file}")
pyproject_data=Nonetry:
withopen(pyproject_toml_file, "rb") asf:
pyproject_data=toml_lib.load(f)
logger.debug(f"Successfully loaded `pyproject.toml` data: {pyproject_data}")
exceptExceptionase:
logger.debug(f"Error loading `pyproject.toml`: {str(e)}")
ifnotpyproject_data:
logger.debug("`pyproject.toml` data is empty")
returnNonereturnpyproject_datadefget_value_through_keys_path(
dictionary: Dict[str, str], keys_path: Sequence[str]
) ->Optional[Any]:
logger.debug(f"Searching through dictionary using keys path: {keys_path}")
value=Noneiftype(dictionary) isnotdictornothasattr(dictionary, "get"):
logger.debug("Input is not a valid dictionary")
returnNoneiftype(keys_path) isstr:
logger.debug("Converting single string key to list")
keys_path= [keys_path]
forkeyinkeys_path:
logger.debug(f"Accessing key: {key}")
value=dictionary.get(key)
logger.debug(f"Value found for key {key}: {value}")
iftype(value) isdict:
logger.debug("Value is a dictionary, continuing search")
dictionary=valueelse:
logger.debug("Value is not a dictionary, search complete")
breakreturnvaluedefget_dependencies(group: Literal["tests", "dev", "docs", None] =None) ->List[str]:
logger.debug(f"Getting dependencies for group: {group}")
group=groupor"prod"logger.debug(f"Effective group: {group}")
pyproject_toml_data=get_pyproject_toml_data()
ifnotpyproject_toml_data:
logger.debug("No pyproject.toml data available")
return []
group_keys_path_mapping: dict[
Optional[Literal["tests", "dev", "docs", "prod"]], List[str]
] = {
"dev": Constants.DEV_DEPENDENCIES_KEYS,
"docs": Constants.DOCS_DEPENDENCIES_KEYS,
"tests": Constants.TESTS_DEPENDENCIES_KEYS,
"prod": Constants.RELEASE_DEPENDENCIES_KEYS,
}
keys_path=group_keys_path_mapping[group]
logger.debug(f"Keys path for group {group}: {keys_path}")
ifnotkeys_path:
logger.debug("No keys path found for group")
return [""]
list_deps=get_value_through_keys_path(pyproject_toml_data, keys_path)
logger.debug(f"Dependencies found: {list_deps}")
ifisinstance(list_deps, str):
logger.debug("Dependencies is a single string, converting to list")
return [list_deps]
ifnotall(isinstance(s, str) forsinlist_deps):
logger.debug("Not all dependencies are strings, returning empty list")
return [""]
returnlist_depsdefnox_session_install_deps(nox: Session, dependencies: List[str]):
logger.debug(f"Installing dependencies: {dependencies}")
iftype(dependencies) isstr:
logger.debug("Converting single string dependency to tuple")
dependencies= (dependencies,)
fordepindependencies:
logger.debug(f"Installing dependency: {dep}")
nox.install(dep)
defnox_session_install_deps_in_group(
nox: Session, group: Literal["tests", "dev", "docs", None] =None
):
logger.debug(f"Installing dependencies for group: {group}")
dependencies=get_dependencies(group)
logger.debug(f"Dependencies for group {group}: {dependencies}")
returnnox_session_install_deps(nox, dependencies)
# ========== NOX SESSIONS ==========@DEV_DEPS_NAMED_NOX_SESSION(default_posargs=(Constants.DOT,))defformat(nox: Session) ->None:
"""Format Python code using Ruff formatter. Usage: `uv run nox -s format`. Automatically formats all Python files in the project using Ruff's opinionated formatter. By default, formats the entire project directory. Args: nox (Session): Nox session object """nox.run(BinaryCommand.RUFF, "format")
@DEV_DEPS_NAMED_NOX_SESSION(default_posargs=(Constants.DOT,))deflint(nox: Session) ->None:
"""Run Ruff linter to check code quality. Usage: `uv run nox -s lint`. Performs static code analysis to identify potential issues, style violations, and other code quality concerns. Args: nox (Session): Nox session object """nox.run(BinaryCommand.RUFF, "check")
@DEV_DEPS_NAMED_NOX_SESSION(default_posargs=(Constants.DOT,))deftype_check(nox: Session) ->None:
"""Run MyPy static type checker. Usage: `uv run nox -s type-check`. Performs static type checking on Python code to catch type-related errors before runtime. Args: nox (Session): Nox session object """nox.run(BinaryCommand.MYPY)
@DEV_DEPS_NAMED_NOX_SESSIONdefsecurity(nox: Session) ->None:
"""Run Bandit security checker. Usage: `uv run nox -s security`. Scans Python code for common security issues and vulnerabilities. Focuses on the src directory by default. Args: nox (Session): Nox session object """nox.run(BinaryCommand.BANDIT, "-r", Directories.SRC)
@DOCS_DEPS_NAMED_NOX_SESSIONdefbuild_docs(nox: Session) ->None:
"""Build project documentation using MkDocs. Usage: `uv run nox -s build-docs`. Generates static documentation site from markdown files. Args: nox (Session): Nox session object """nox.run(BinaryCommand.MKDOCS, "build")
@TESTS_DEPS_NAMED_NOX_SESSIONdefcoverage(nox: Session) ->None:
"""Run tests with coverage reporting. Usage: `uv run nox -s coverage`. Executes test suite and generates a coverage report showing which parts of the code were executed during testing. Args: nox (Session): Nox session object """nox.run(BinaryCommand.COVERAGE, "run", "-m", "pytest")
nox.run(BinaryCommand.COVERAGE, "report", "-m")
@DEV_DEPS_NAMED_NOX_SESSIONdefpre_commit(nox: Session) ->None:
"""Run all pre-commit hooks. Usage: `uv run nox -s pre-commit`. Executes all configured pre-commit hooks against all files in the repository. Useful for checking code before committing. Args: nox (Session): Nox session object """nox.run(BinaryCommand.PRE_COMMIT, "run", "--all-files")
@DEV_DEPS_NAMED_NOX_SESSION(default_posargs=("--wheel",))defbuild(nox: Session) ->None:
"""Build package distributions using UV. Usage: `uv run nox -s build`. Creates distribution packages (wheel by default) for the project. Args: nox (Session): Nox session object """nox.run(BinaryCommand.UV, "build")
@DEFAULT_NAMED_NOX_SESSIONdefclean(nox: Session) ->None:
"""Clean build artifacts. Usage: `uv run nox -s clean`. Removes all build artifacts including: - build/ directory - dist/ directory - *.egg-info directories Args: nox (Session): Nox session object """nox.run(BinaryCommand.RM, "-rf", "build", "dist", "*.egg-info")
@DEV_DEPS_NAMED_NOX_SESSIONdefpublish(nox: Session) ->None:
"""Publish package to PyPI. Usage: `uv run nox -s publish`. Checks distribution files for issues and uploads them to PyPI. Requires proper PyPI credentials to be configured. Args: nox (Session): Nox session object """nox.run(BinaryCommand.TWINE, "check", "dist/*")
nox.run(BinaryCommand.TWINE, "upload", "dist/*")
@DEFAULT_UNNAMED_NOX_SESSION("requirements", "dev", default_posargs=("--format", "requirements-txt"))defgenerate_requirements(nox: Session) ->None:
"""Generate requirements files using UV. Usage: `uv run nox -s requirements`. Exports dependencies from pyproject.toml to requirements.txt format. By default, generates requirements-txt format. Args: nox (Session): Nox session object """nox.run(BinaryCommand.UV, "export")
@DEFAULT_NAMED_NOX_SESSION("dev")defbenchmark(nox: Session) ->None:
"""Run performance benchmarks. Usage: `uv run nox -s benchmark`. Executes benchmark tests and compares results with previous runs. Benchmarks should be located in the benchmarks/ directory. Args: nox (Session): Nox session object """nox.run(BinaryCommand.PYTHON, "-m", "pytest", "benchmarks/", "--benchmark-compare")
@DEFAULT_NAMED_NOX_SESSIONdefdocker_build(nox: Session) ->None:
"""Build Docker image for the project. Usage: `uv run nox -s docker-build`. Creates a Docker image tagged as 'myproject:latest' using the project's Dockerfile. Args: nox (Session): Nox session object """nox.run(BinaryCommand.DOCKER, "build", "-t", "myproject:latest", ".")
@DEFAULT_NAMED_NOX_SESSIONdefintegration_tests(nox: Session) ->None:
"""Run integration tests. Usage: `uv run nox -s integration_tests`. Executes integration tests located in the tests/integration directory. Installs test dependencies before running. Args: nox (Session): Nox session object """nox_session_install_deps_in_group(nox, "tests")
nox.run(
BinaryCommand.PYTHON,
"-m",
BinaryCommand.PYTEST,
f"{Directories.TESTS}/integration/",
"-s",
"-vv",
)
@DEFAULT_NAMED_NOX_SESSION("dev", default_posargs=("check", "--full-report", ))defdependency_check(nox: Session) ->None:
"""Check dependencies for known security vulnerabilities. Usage: `uv run nox -s dependency-check`. Uses Safety to scan project dependencies against known security advisories. Generates a full report of findings. Args: nox (Session): Nox session object Example: """nox.run(BinaryCommand.SAFETY,)
Describe the solution you'd like
Basically, some of the benefits with this noxfile.py is that:
it runs from Python 3.8.
you can always pass in additional position arguments to Nox, e.g. nox -s test -- tests/test_stmt.py -s -vv, and presumably pytest will test a single file instead of the default testing of tests/ directory. (Session.run is modified by the decorator)
The decorators will install the group dependencies using pyproject.toml and nox.Session.
Describe alternatives you've considered
Not that I know of.
Anything else?
No response
The text was updated successfully, but these errors were encountered:
How would this feature be useful?
This is the
noxfile.py
.Describe the solution you'd like
Basically, some of the benefits with this
noxfile.py
is that:Nox
, e.g.nox -s test -- tests/test_stmt.py -s -vv
, and presumablypytest
will test a single file instead of the default testing oftests/
directory. (Session.run
is modified by the decorator)pyproject.toml
andnox.Session
.Describe alternatives you've considered
Not that I know of.
Anything else?
No response
The text was updated successfully, but these errors were encountered: