Skip to content

Commit cd190ae

Browse files
authored
chore(template): accept new copier update (#60)
Co-authored-by: wpk-nist-gov <5348008+wpk-nist-gov@users.noreply.github.com>
1 parent 26ec046 commit cd190ae

12 files changed

Lines changed: 186 additions & 125 deletions

File tree

.copier-answers.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
2-
_commit: v0.11.0-7-g0d0a7bc
2+
_commit: v0.12.0-3-gfa0bc11
33
_src_path: https://github.com/usnistgov/cookiecutter-nist-python.git
44
command_line_interface: typer
55
conda_channel: conda-forge

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ repos:
176176
- id: check-github-actions
177177
alias: actions
178178
- repo: https://github.com/rhysd/actionlint
179-
rev: v1.7.11
179+
rev: v1.7.12
180180
hooks:
181181
- id: actionlint
182182
alias: actions

justfile

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ sync *options: (_requirements "--sync" options)
149149
[group("requirements")]
150150
lock *options: (_requirements "--lock" options)
151151

152-
# Rebuild requirements, lock requirements, and run uv sync if .venv exists or uv lock if not. Pass --upgrade/-U to upgrade
152+
# Rebu ild requirements, lock requirements, and run uv sync if .venv exists or uv lock if not. Pass --upgrade/-U to upgrade
153153
[group("requirements")]
154154
requirements *options: (_requirements "--sync-or-lock" options)
155155

@@ -196,8 +196,17 @@ pyrefly *options: (_typecheck "-cpyrefly" options)
196196
# Run pylint (with optional args)
197197
[group("lint")]
198198
[group("typecheck")]
199-
pylint *options="src tests":
200-
{{ UVRUN }} {{ TYPECHECK_UVRUN_OPTS }} pylint {{ PYLINT_OPTS }} {{ options }}
199+
pylint:
200+
#!/usr/bin/env sh
201+
set -exu
202+
possible=("src" "tests" "noxfile.py" "tools" "scripts")
203+
options=()
204+
for d in "${possible[@]}"; do
205+
if [ -e "$d" ]; then
206+
options+=("$d")
207+
fi
208+
done
209+
{{ UVRUN }} {{ TYPECHECK_UVRUN_OPTS }} pylint {{ PYLINT_OPTS }} "${options[@]}"
201210

202211
# Run all checkers (with optional directories)
203212
[group("typecheck")]
@@ -207,8 +216,7 @@ typecheck *options: (_typecheck "-cmypy[faster-cache] -cbasedpyright -cpyrefly -
207216
[group("tools")]
208217
[group("typecheck")]
209218
@typecheck-tools *files="noxfile.py tools/*.py":
210-
-just TYPECHECK_UVRUN_OPTS="--only-group=nox --only-group=typecheck-runner" mypy -- --strict {{ files }}
211-
just TYPECHECK_UVRUN_OPTS="--only-group=nox --only-group=typecheck-runner" basedpyright -- {{ files }}
219+
-just TYPECHECK_UVRUN_OPTS="--only-group=nox --only-group=typecheck-runner" _typecheck "-c'mypy[faster-cache] --strict' -cbasedpyright -cpyrefly -cty" {{ files }}
212220
just TYPECHECK_UVRUN_OPTS="--only-group=nox --only-group=pylint" pylint {{ files }}
213221

214222
# ** typecheck all

noxfile.py

Lines changed: 85 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ def install_package(
361361
installpkg: str | None = None,
362362
) -> None:
363363
"""Install current package."""
364+
run: Callable[..., Any]
364365
if installpkg is not None:
365366
run = session.run
366367
opts = [*args, installpkg]
@@ -382,50 +383,59 @@ def install_package(
382383
)
383384

384385

385-
def get_package_wheel(
386-
session: Session,
387-
opts: str | Iterable[str] | None = None,
388-
extras: str | Iterable[str] | None = None,
389-
reuse: bool = True,
390-
) -> str:
391-
"""
392-
Build the package in return the build location.
386+
class _GetPackageWheel:
387+
"""Interface to get_package_wheel"""
393388

394-
This is similar to how tox does isolated builds.
389+
def __init__(self) -> None:
390+
self._called = False
395391

396-
Note that the first time this is called,
392+
def __call__(
393+
self,
394+
session: Session,
395+
opts: str | Iterable[str] | None = None,
396+
extras: str | Iterable[str] | None = None,
397+
reuse: bool = True,
398+
) -> str:
399+
"""
400+
Build the package in return the build location.
397401
398-
Should be straightforward to extend this to isolated builds
399-
that depend on python version (something like have session build-3.11 ....)
400-
"""
401-
dist_location = Path(session.cache_dir) / "dist"
402-
if reuse and getattr(get_package_wheel, "_called", False):
403-
session.log("Reuse isolated build")
404-
else:
405-
shutil.rmtree(dist_location, ignore_errors=True)
406-
session.run_always("uv", "build", f"--out-dir={dist_location}", "--wheel")
402+
This is similar to how tox does isolated builds.
403+
404+
Note that the first time this is called,
405+
406+
Should be straightforward to extend this to isolated builds
407+
that depend on python version (something like have session build-3.11 ....)
408+
"""
409+
dist_location = Path(session.cache_dir) / "dist"
410+
if reuse and self._called:
411+
session.log("Reuse isolated build")
412+
else:
413+
shutil.rmtree(dist_location, ignore_errors=True)
414+
session.run_always("uv", "build", f"--out-dir={dist_location}", "--wheel")
415+
416+
# save that this was called:
417+
if reuse:
418+
self._called = True
407419

408-
# save that this was called:
409-
if reuse:
410-
get_package_wheel._called = True # type: ignore[attr-defined] # pyright: ignore[reportFunctionMemberAccess] # noqa: SLF001 # pylint: disable=protected-access
420+
paths = list(dist_location.glob("*.whl"))
421+
if len(paths) != 1:
422+
msg = f"something wonky with paths {paths}"
423+
raise ValueError(msg)
411424

412-
paths = list(dist_location.glob("*.whl"))
413-
if len(paths) != 1:
414-
msg = f"something wonky with paths {paths}"
415-
raise ValueError(msg)
425+
path = f"{PACKAGE_NAME}@{paths[0]}"
426+
if extras:
427+
if not isinstance(extras, str):
428+
extras = ",".join(extras)
429+
path = f"{path}[{extras}]"
416430

417-
path = f"{PACKAGE_NAME}@{paths[0]}"
418-
if extras:
419-
if not isinstance(extras, str):
420-
extras = ",".join(extras)
421-
path = f"{path}[{extras}]"
431+
if opts:
432+
if not isinstance(opts, str):
433+
opts = " ".join(opts)
434+
path = f"{path} {opts}"
435+
return path
422436

423-
if opts:
424-
if not isinstance(opts, str):
425-
opts = " ".join(opts)
426-
path = f"{path} {opts}"
427437

428-
return path
438+
get_package_wheel = _GetPackageWheel()
429439

430440

431441
# * uvx runner ----------------------------------------------------------------
@@ -442,7 +452,7 @@ def uvx_run(
442452
session: Session, *args: str | PathLike[str], locked: bool = True, **kwargs: Any
443453
) -> Any:
444454
"""Run command using uvx"""
445-
return session.run("uvx", *get_uvx_constraint_args(locked), *args, **kwargs)
455+
return session.run("uvx", *get_uvx_constraint_args(locked), *args, **kwargs) # pyright: ignore[reportUnknownVariableType]
446456

447457

448458
def pre_commit_run(
@@ -735,7 +745,7 @@ def lint(
735745
# ** type checking
736746
@nox.session(name="typecheck", **ALL_KWS)
737747
@add_opts
738-
def typecheck(
748+
def typecheck( # noqa: PLR0912
739749
session: nox.Session,
740750
opts: SessionParams,
741751
) -> None:
@@ -745,10 +755,16 @@ def typecheck(
745755

746756
cmd = opts.typecheck or []
747757
if not opts.typecheck_run and not cmd:
748-
cmd = ["mypy", "basedpyright", "pyrefly", "ty"]
758+
cmd = ["all"]
749759

750760
if "all" in cmd:
751-
cmd = ["mypy", "basedpyright", "pyrefly", "ty", "pylint"]
761+
cmd = [
762+
"mypy",
763+
"basedpyright",
764+
"pyrefly",
765+
"ty",
766+
"pylint",
767+
]
752768

753769
# set the cache directory for mypy
754770
session.env["MYPY_CACHE_DIR"] = str(Path(session.create_tmp()) / ".mypy_cache")
@@ -757,38 +773,50 @@ def typecheck(
757773
cmd = list(cmd)
758774
cmd.remove("clean")
759775

760-
for name in (".mypy_cache", ".pytype"):
776+
for name in (".mypy_cache",):
761777
p = Path(session.create_tmp()) / name
762778
if p.exists():
763779
session.log(f"removing cache {p}")
764780
shutil.rmtree(p)
765781

766-
if not isinstance(session.python, str):
767-
raise TypeError
768-
782+
# do all typecheckers in one go
783+
typecheckers: list[str] = []
784+
othercheckers: list[str] = []
769785
for c in cmd:
770786
if c in {"mypy", "pyright", "basedpyright", "ty", "pyrefly"}:
771-
checker = "mypy[faster-cache]" if c == "mypy" else c
772-
session.run(
773-
"typecheck-runner",
774-
*get_uvx_constraint_args(),
775-
"--verbose",
776-
f"--check={checker}",
777-
"--allow-errors",
778-
external=False,
779-
)
780-
elif c == "pylint":
787+
typecheckers.append(f"--check={'mypy[faster-cache]' if c == 'mypy' else c}")
788+
else:
789+
othercheckers.append(c)
790+
791+
if typecheckers:
792+
session.run(
793+
"typecheck-runner",
794+
*get_uvx_constraint_args(),
795+
"--verbose",
796+
*typecheckers,
797+
"--",
798+
external=False,
799+
)
800+
801+
for other in othercheckers:
802+
if other == "pylint":
803+
paths = [
804+
x
805+
for x in ("src", "tests", "noxfile.py", "scripts", "tools")
806+
if Path(x).exists()
807+
]
781808
session.run(
782809
"pylint",
783810
# A bit dangerous, but needed to allow pylint
784811
# to work across versions.
785812
"--disable=unrecognized-option",
786813
"--enable-all-extensions",
787-
"src",
788-
"tests",
814+
*paths,
789815
)
816+
elif other.endswith("-notebook"):
817+
uvx_run(session, "--from=rust-just", "just", other)
790818
else:
791-
session.log(f"Skipping unknown command {c}")
819+
session.log(f"Skipping unknown command {other}")
792820

793821

794822
# ** Dist conda

pyproject.toml

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ test = [
6464
]
6565
type = [
6666
"types-click",
67+
{ include-group = "nox" },
6768
{ include-group = "pylint" },
6869
{ include-group = "pytest" },
6970
{ include-group = "typecheck-runner" },
@@ -159,17 +160,12 @@ CPY = "CPY"
159160

160161
# * typecheck ---------------------------------------------------------------------
161162
[tool.mypy]
162-
exclude = [
163-
".eggs",
164-
".nox",
165-
".numba_cache",
166-
".tox",
167-
".venv",
168-
"docs",
169-
]
170163
files = [
171164
"src",
172165
"tests",
166+
# tools
167+
"noxfile.py",
168+
"tools",
173169
]
174170
strict = true
175171
# options
@@ -186,7 +182,14 @@ warn_unused_ignores = true
186182

187183
[tool.pyrefly]
188184
enabled-ignores = [ "pyrefly" ]
189-
project-includes = [ "src", "tests" ]
185+
project-includes = [
186+
"src",
187+
"tests",
188+
# tools
189+
"noxfile.py",
190+
"tools",
191+
]
192+
search-path = [ "." ]
190193

191194
[tool.pyright]
192195
exclude = [
@@ -203,6 +206,9 @@ exclude = [
203206
include = [
204207
"src",
205208
"tests",
209+
# tools
210+
"noxfile.py",
211+
"tools",
206212
]
207213
strict = [
208214
"noxfile.py",
@@ -243,7 +249,13 @@ reportUnusedCallResult = false
243249
[tool.ty]
244250
# Disable support for `type: ignore` comments
245251
analysis.respect-type-ignore-comments = false
246-
src.include = [ "src", "tests" ]
252+
src.include = [
253+
"src",
254+
"tests",
255+
# tools
256+
"noxfile.py",
257+
"tools",
258+
]
247259

248260
# * Testing --------------------------------------------------------------------
249261
[tool.pytest.ini_options]

0 commit comments

Comments
 (0)