disnake
/
noxfile.py
250 строк · 7.3 Кб
1# SPDX-License-Identifier: MIT
2
3from __future__ import annotations
4
5import os
6import pathlib
7from itertools import chain
8from typing import TYPE_CHECKING, Callable, Dict, List, Tuple, TypeVar
9
10import nox
11
12if TYPE_CHECKING:
13from typing_extensions import Concatenate, ParamSpec
14
15P = ParamSpec("P")
16T = TypeVar("T")
17
18NoxSessionFunc = Callable[Concatenate[nox.Session, P], T]
19
20
21# see https://pdm.fming.dev/latest/usage/advanced/#use-nox-as-the-runner
22os.environ.update(
23{
24"PDM_IGNORE_SAVED_PYTHON": "1",
25},
26)
27
28
29nox.options.error_on_external_run = True
30nox.options.reuse_existing_virtualenvs = True
31nox.options.sessions = [
32"lint",
33"check-manifest",
34"slotscheck",
35"pyright",
36"test",
37]
38nox.needs_version = ">=2022.1.7"
39
40
41# used to reset cached coverage data once for the first test run only
42reset_coverage = True
43
44
45@nox.session
46def docs(session: nox.Session) -> None:
47"""Build and generate the documentation.
48
49If running locally, will build automatic reloading docs.
50If running in CI, will build a production version of the documentation.
51"""
52session.run_always("pdm", "install", "--prod", "-G", "docs", external=True)
53with session.chdir("docs"):
54args = ["-b", "html", "-n", ".", "_build/html", *session.posargs]
55if session.interactive:
56session.run(
57"sphinx-autobuild",
58"--ignore",
59"_build",
60"--watch",
61"../disnake",
62"--watch",
63"../changelog",
64"--port",
65"8009",
66"-j",
67"auto",
68*args,
69)
70else:
71session.run(
72"sphinx-build",
73"-aE",
74*args,
75)
76
77
78@nox.session
79def lint(session: nox.Session) -> None:
80"""Check all files for linting errors"""
81session.run_always("pdm", "install", "-G", "tools", external=True)
82
83session.run("pre-commit", "run", "--all-files", *session.posargs)
84
85
86@nox.session(name="check-manifest")
87def check_manifest(session: nox.Session) -> None:
88"""Run check-manifest."""
89# --no-self is provided here because check-manifest builds disnake. There's no reason to build twice, so we don't.
90session.run_always("pdm", "install", "--no-self", "-dG", "tools", external=True)
91session.run("check-manifest", "-v")
92
93
94@nox.session()
95def slotscheck(session: nox.Session) -> None:
96"""Run slotscheck."""
97session.run_always("pdm", "install", "-dG", "tools", external=True)
98session.run("python", "-m", "slotscheck", "--verbose", "-m", "disnake")
99
100
101@nox.session
102def autotyping(session: nox.Session) -> None:
103"""Run autotyping.
104
105Because of the nature of changes that autotyping makes, and the goal design of examples,
106this runs on each folder in the repository with specific settings.
107"""
108session.run_always("pdm", "install", "-dG", "codemod", external=True)
109
110base_command = ["python", "-m", "libcst.tool", "codemod", "autotyping.AutotypeCommand"]
111if not session.interactive:
112base_command += ["--hide-progress"]
113
114dir_options: Dict[Tuple[str, ...], Tuple[str, ...]] = {
115(
116"disnake",
117"scripts",
118"tests",
119"test_bot",
120"noxfile.py",
121): ("--aggressive",),
122("examples",): (
123"--scalar-return",
124"--bool-param",
125"--bool-param",
126"--int-param",
127"--float-param",
128"--str-param",
129"--bytes-param",
130),
131}
132
133if session.posargs:
134# short circuit with the provided arguments
135# if there's just one file argument, give it the defaults that we normally use
136posargs = session.posargs.copy()
137if len(posargs) == 1 and not (path := posargs[0]).startswith("--"):
138path = pathlib.Path(path).absolute()
139try:
140path = path.relative_to(pathlib.Path.cwd())
141except ValueError:
142pass
143else:
144module = path.parts[0]
145for modules, options in dir_options.items():
146if module in modules:
147posargs += options
148break
149
150session.run(
151*base_command,
152*posargs,
153)
154return
155
156# run the custom fixers
157for module, options in dir_options.items():
158session.run(
159*base_command,
160*module,
161*options,
162)
163
164
165@nox.session(name="codemod")
166def codemod(session: nox.Session) -> None:
167"""Run libcst codemods."""
168session.run_always("pdm", "install", "-dG", "codemod", external=True)
169
170base_command = ["python", "-m", "libcst.tool"]
171base_command_codemod = base_command + ["codemod"]
172if not session.interactive:
173base_command_codemod += ["--hide-progress"]
174
175if (session.posargs and session.posargs[0] == "run-all") or not session.interactive:
176# run all of the transformers on disnake
177session.log("Running all transformers.")
178
179session.run(*base_command_codemod, "combined.CombinedCodemod", "disnake")
180elif session.posargs:
181if len(session.posargs) < 2:
182session.posargs.append("disnake")
183
184session.run(*base_command_codemod, *session.posargs)
185else:
186session.run(*base_command, "list")
187return # don't run autotyping in this case
188
189session.notify("autotyping", posargs=[])
190
191
192@nox.session()
193def pyright(session: nox.Session) -> None:
194"""Run pyright."""
195session.run_always("pdm", "install", "-d", "-Gspeed", "-Gdocs", "-Gvoice", external=True)
196env = {
197"PYRIGHT_PYTHON_IGNORE_WARNINGS": "1",
198}
199try:
200session.run("python", "-m", "pyright", *session.posargs, env=env)
201except KeyboardInterrupt:
202pass
203
204
205@nox.session(python=["3.8", "3.9", "3.10", "3.11", "3.12"])
206@nox.parametrize(
207"extras",
208[
209[],
210# NOTE: disabled while there are no tests that would require these dependencies
211# ["speed"],
212# ["voice"],
213],
214)
215def test(session: nox.Session, extras: List[str]) -> None:
216"""Run tests."""
217# shell splitting is not done by nox
218extras = list(chain(*(["-G", extra] for extra in extras)))
219
220session.run_always("pdm", "install", "-dG", "test", "-dG", "typing", *extras, external=True)
221
222pytest_args = ["--cov", "--cov-context=test"]
223global reset_coverage # noqa: PLW0603
224if reset_coverage:
225# don't use `--cov-append` for first run
226reset_coverage = False
227else:
228# use `--cov-append` in all subsequent runs
229pytest_args.append("--cov-append")
230
231# TODO: only run tests that depend on the different dependencies
232session.run(
233"pytest",
234*pytest_args,
235*session.posargs,
236)
237
238
239@nox.session()
240def coverage(session: nox.Session) -> None:
241"""Display coverage information from the tests."""
242session.run_always("pdm", "install", "-dG", "test", external=True)
243if "html" in session.posargs or "serve" in session.posargs:
244session.run("coverage", "html", "--show-contexts")
245if "serve" in session.posargs:
246session.run(
247"python", "-m", "http.server", "8012", "--directory", "htmlcov", "--bind", "127.0.0.1"
248)
249if "erase" in session.posargs:
250session.run("coverage", "erase")
251