From 375611bbdd1c405ebbcc1bd1dfcc7583e6cb93ca Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 16:34:44 +0000 Subject: [PATCH 1/5] chore(template): apply TODO.md template cleanups Co-authored-by: buddingengineers12345 --- copier.yml | 22 ++---- scripts/sync_skip_if_exists.py | 4 +- template/.github/workflows/release.yml.jinja | 4 +- ... if include_docs %}ci.md{% endif %}.jinja} | 0 ... include_docs %}index.md{% endif %}.jinja} | 0 .../common}/bump_version.py.jinja | 0 .../logging_config.py.jinja | 34 --------- ... if include_cli %}cli.py{% endif %}.jinja} | 2 - ...nclude_docs %}mkdocs.yml{% endif %}.jinja} | 2 - ...e_git_cliff %}cliff.toml{% endif %}.jinja} | 0 tests/test_template.py | 71 +++++++------------ 11 files changed, 32 insertions(+), 107 deletions(-) rename template/docs/{ci.md.jinja => {% if include_docs %}ci.md{% endif %}.jinja} (100%) rename template/docs/{index.md.jinja => {% if include_docs %}index.md{% endif %}.jinja} (100%) rename template/{scripts => src/{{ package_name }}/common}/bump_version.py.jinja (100%) delete mode 100644 template/src/{{ package_name }}/logging_config.py.jinja rename template/src/{{ package_name }}/{cli.py.jinja => {% if include_cli %}cli.py{% endif %}.jinja} (91%) rename template/{mkdocs.yml.jinja => {% if include_docs %}mkdocs.yml{% endif %}.jinja} (92%) rename template/{cliff.toml.jinja => {% if include_git_cliff %}cliff.toml{% endif %}.jinja} (100%) diff --git a/copier.yml b/copier.yml index 6305ba4..deee888 100644 --- a/copier.yml +++ b/copier.yml @@ -34,7 +34,7 @@ _skip_if_exists: - mkdocs.yml - pyproject.toml - README.md - - scripts/bump_version.py + - src/{{ package_name }}/common/bump_version.py - SECURITY.md - src/{{ package_name }}/__init__.py @@ -140,15 +140,10 @@ include_cli: help: Generate a Typer-based CLI entry point and console script? default: false -include_logging_setup: - type: bool - help: Add a logging_config module with configure_logging() (stdlib logging + structlog)? - default: false - include_git_cliff: type: bool help: Add git-cliff, cliff.toml, and a just changelog recipe for release notes? - default: false + default: true # ------------------------------------------------------------------------- # Computed values @@ -182,7 +177,7 @@ github_actions_python_versions: # when the host Python lacks `ensurepip`/`pip` (common on minimal distro Pythons). # - To avoid template generation failing on machines without `uv`, we bootstrap `uv` first. # We try `pip` if available; otherwise we fall back to Astral's installer script. -# - Keep tasks idempotent. It's okay if `uv self update` fails (offline / restricted envs). +# - Keep tasks idempotent. # # Copy vs update: these tasks run after both `copier copy` and `copier update` (not gated # with _copier_operation) so the lockfile and local env stay aligned with the template after @@ -226,7 +221,6 @@ _tasks: command -v uv >/dev/null 2>&1 ' - - command: uv self update || true - command: uv lock - command: >- uv sync --frozen --extra dev --extra test @@ -236,15 +230,7 @@ _tasks: - command: uv run pre-commit install --hook-type pre-push - command: uv run ruff check --fix --unsafe-fixes . - command: uv run basedpyright - - command: rm -f cliff.toml - when: "{{ not include_git_cliff }}" - - command: rm -f src/{{ package_name }}/logging_config.py - when: "{{ not include_logging_setup }}" - - command: rm -f src/{{ package_name }}/cli.py - when: "{{ not include_cli }}" - - command: rm -f mkdocs.yml - when: "{{ not include_docs }}" - - command: sh -c 'rm -f docs/index.md docs/ci.md 2>/dev/null; rmdir docs 2>/dev/null || true' + - command: sh -c 'rmdir docs 2>/dev/null || true' when: "{{ not include_docs }}" - command: echo "✅ Project {{ project_name }} created successfully!" - command: echo "📁 Location $(pwd)" diff --git a/scripts/sync_skip_if_exists.py b/scripts/sync_skip_if_exists.py index 5d49b9c..f93c55b 100644 --- a/scripts/sync_skip_if_exists.py +++ b/scripts/sync_skip_if_exists.py @@ -27,7 +27,7 @@ "template/.github/CODE_OF_CONDUCT.md.jinja": ".github/CODE_OF_CONDUCT.md", "template/.github/ISSUE_TEMPLATE/bug_report.md.jinja": ".github/ISSUE_TEMPLATE/bug_report.md", "template/.github/ISSUE_TEMPLATE/feature_request.md.jinja": ".github/ISSUE_TEMPLATE/feature_request.md", - "template/scripts/bump_version.py.jinja": "scripts/bump_version.py", + "template/src/{{ package_name }}/common/bump_version.py.jinja": "src/{{ package_name }}/common/bump_version.py", } # Always include these (user customization hotspots even if not in the map above). @@ -44,7 +44,7 @@ ".github/CODE_OF_CONDUCT.md", ".github/ISSUE_TEMPLATE/bug_report.md", ".github/ISSUE_TEMPLATE/feature_request.md", - "scripts/bump_version.py", + "src/{{ package_name }}/common/bump_version.py", ] # Paths touched at least this often in recent history are added to the skip list. diff --git a/template/.github/workflows/release.yml.jinja b/template/.github/workflows/release.yml.jinja index 1d984cf..3e91802 100644 --- a/template/.github/workflows/release.yml.jinja +++ b/template/.github/workflows/release.yml.jinja @@ -92,9 +92,9 @@ jobs: fi if [ -n "{% raw %}${{ inputs.version }}{% endraw %}" ]; then - NEW_VERSION="$(uv run python scripts/bump_version.py --new-version "{% raw %}${{ inputs.version }}{% endraw %}")" + NEW_VERSION="$(uv run python src/{{ package_name }}/common/bump_version.py --new-version "{% raw %}${{ inputs.version }}{% endraw %}")" else - NEW_VERSION="$(uv run python scripts/bump_version.py --bump "{% raw %}${{ inputs.bump }}{% endraw %}")" + NEW_VERSION="$(uv run python src/{{ package_name }}/common/bump_version.py --bump "{% raw %}${{ inputs.bump }}{% endraw %}")" fi echo "version=${NEW_VERSION}" >> "${GITHUB_OUTPUT}" diff --git a/template/docs/ci.md.jinja b/template/docs/{% if include_docs %}ci.md{% endif %}.jinja similarity index 100% rename from template/docs/ci.md.jinja rename to template/docs/{% if include_docs %}ci.md{% endif %}.jinja diff --git a/template/docs/index.md.jinja b/template/docs/{% if include_docs %}index.md{% endif %}.jinja similarity index 100% rename from template/docs/index.md.jinja rename to template/docs/{% if include_docs %}index.md{% endif %}.jinja diff --git a/template/scripts/bump_version.py.jinja b/template/src/{{ package_name }}/common/bump_version.py.jinja similarity index 100% rename from template/scripts/bump_version.py.jinja rename to template/src/{{ package_name }}/common/bump_version.py.jinja diff --git a/template/src/{{ package_name }}/logging_config.py.jinja b/template/src/{{ package_name }}/logging_config.py.jinja deleted file mode 100644 index 556e114..0000000 --- a/template/src/{{ package_name }}/logging_config.py.jinja +++ /dev/null @@ -1,34 +0,0 @@ -{% if include_logging_setup %} -"""Central logging configuration (stdlib logging + structlog).""" - -from __future__ import annotations - -import logging -import sys - -import structlog - - -def configure_logging(level: str = "INFO") -> None: - """Configure stdlib logging and structlog for console output. - - Args: - level: Root log level name (e.g. ``INFO``, ``DEBUG``). - """ - lvl = getattr(logging, level.upper(), logging.INFO) - logging.basicConfig(format="%(message)s", stream=sys.stdout, level=lvl) - structlog.configure( - wrapper_class=structlog.make_filtering_bound_logger(lvl), - processors=[ - structlog.contextvars.merge_contextvars, - structlog.processors.add_log_level, - structlog.processors.StackInfoRenderer(), - structlog.dev.set_exc_info, - structlog.processors.TimeStamper(fmt="iso"), - structlog.dev.ConsoleRenderer(), - ], - context_class=dict, - logger_factory=structlog.PrintLoggerFactory(file=sys.stdout), - cache_logger_on_first_use=False, - ) -{% endif %} diff --git a/template/src/{{ package_name }}/cli.py.jinja b/template/src/{{ package_name }}/{% if include_cli %}cli.py{% endif %}.jinja similarity index 91% rename from template/src/{{ package_name }}/cli.py.jinja rename to template/src/{{ package_name }}/{% if include_cli %}cli.py{% endif %}.jinja index ba704b9..b425f25 100644 --- a/template/src/{{ package_name }}/cli.py.jinja +++ b/template/src/{{ package_name }}/{% if include_cli %}cli.py{% endif %}.jinja @@ -1,4 +1,3 @@ -{% if include_cli %} """Command-line interface for **{{ project_name }}**.""" from __future__ import annotations @@ -16,4 +15,3 @@ def hello() -> None: if __name__ == "__main__": app() -{% endif %} diff --git a/template/mkdocs.yml.jinja b/template/{% if include_docs %}mkdocs.yml{% endif %}.jinja similarity index 92% rename from template/mkdocs.yml.jinja rename to template/{% if include_docs %}mkdocs.yml{% endif %}.jinja index 4936538..46052d1 100644 --- a/template/mkdocs.yml.jinja +++ b/template/{% if include_docs %}mkdocs.yml{% endif %}.jinja @@ -1,4 +1,3 @@ -{% if include_docs %} site_name: "{{ project_name }}" site_description: "{{ project_description }}" repo_url: "https://github.com/{{ github_username }}/{{ project_slug }}" @@ -18,4 +17,3 @@ plugins: python: options: docstring_style: google -{% endif %} diff --git a/template/cliff.toml.jinja b/template/{% if include_git_cliff %}cliff.toml{% endif %}.jinja similarity index 100% rename from template/cliff.toml.jinja rename to template/{% if include_git_cliff %}cliff.toml{% endif %}.jinja diff --git a/tests/test_template.py b/tests/test_template.py index 3960b28..5ee1a01 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -113,17 +113,9 @@ def _remove_empty_optional_artifacts(dest: Path, data: dict[str, str | bool]) -> pkg = data.get("package_name") if not isinstance(pkg, str): return - pairs: list[tuple[bool, Path]] = [ - (not bool(data.get("include_cli", False)), dest / "src" / pkg / "cli.py"), - ( - not bool(data.get("include_logging_setup", False)), - dest / "src" / pkg / "logging_config.py", - ), - (not bool(data.get("include_git_cliff", False)), dest / "cliff.toml"), - ] - for should_drop, path in pairs: - if should_drop and path.is_file() and path.stat().st_size == 0: - path.unlink() + # Optional artifacts are now conditionally named in the template, so Copier won't + # emit empty files for disabled features. Keep this hook as a no-op for now + # (it remains useful if we add any future optional whole-file templates). def copy_with_data( @@ -272,8 +264,7 @@ def test_generate_defaults_only_cli(tmp_path: Path) -> None: { "package_name": "my_library", "include_cli": False, - "include_logging_setup": False, - "include_git_cliff": False, + "include_git_cliff": True, }, ) @@ -325,7 +316,6 @@ def test_computed_values_not_recorded_in_answers_file(tmp_path: Path) -> None: { "package_name": "my_library", "include_cli": False, - "include_logging_setup": False, "include_git_cliff": False, }, ) @@ -343,7 +333,6 @@ def test_answers_file_warns_never_edit_manually(tmp_path: Path) -> None: { "package_name": "my_library", "include_cli": False, - "include_logging_setup": False, "include_git_cliff": False, }, ) @@ -367,7 +356,6 @@ def test_generate_programmatic_run_copy_local(tmp_path: Path) -> None: { "package_name": "my_library", "include_cli": False, - "include_logging_setup": False, "include_git_cliff": False, }, ) @@ -404,7 +392,6 @@ def test_generate_from_vcs_git_file_url(tmp_path: Path) -> None: { "package_name": "my_library", "include_cli": False, - "include_logging_setup": False, "include_git_cliff": False, }, ) @@ -665,7 +652,6 @@ def test_copier_update_exits_zero_after_copy_and_commit(tmp_path: Path) -> None: { "package_name": "update_smoke_test", "include_cli": False, - "include_logging_setup": False, "include_git_cliff": False, }, ) @@ -702,7 +688,6 @@ def test_answers_file_matches_explicit_copy_data(tmp_path: Path) -> None: "include_pandas_support": True, "include_numpy": True, "include_cli": False, - "include_logging_setup": False, "include_git_cliff": False, } copy_with_data(test_dir, expected) @@ -801,25 +786,6 @@ def test_include_git_cliff_adds_dependency_group(tmp_path: Path) -> None: assert "git-cliff" in raw -def test_include_logging_setup_adds_module(tmp_path: Path) -> None: - """``include_logging_setup=true`` must ship ``logging_config.py`` with configure_logging.""" - test_dir = tmp_path / "with_logging" - copy_with_data( - test_dir, - { - "project_name": "Log Project", - "package_name": "log_project", - "include_docs": False, - "include_logging_setup": True, - }, - ) - mod = test_dir / "src" / "log_project" / "logging_config.py" - assert mod.is_file() - text = mod.read_text(encoding="utf-8") - assert "configure_logging" in text - assert "structlog" in text - - def test_root_contributing_and_security_rendered(tmp_path: Path) -> None: """Repository root should include ``CONTRIBUTING.md`` and ``SECURITY.md``.""" test_dir = tmp_path / "contrib_sec" @@ -852,7 +818,10 @@ def test_docs_ci_page_when_docs_enabled(tmp_path: Path) -> None: def test_generated_pyproject_basedpyright_standard_mode(tmp_path: Path) -> None: """Generated projects should configure basedpyright in standard mode (per template contract).""" test_dir = tmp_path / "bp_std" - copy_with_data(test_dir, {"project_name": "BP Test", "include_docs": False}) + copy_with_data( + test_dir, + {"project_name": "BP Test", "include_docs": False, "include_git_cliff": False}, + ) raw = (test_dir / "pyproject.toml").read_text(encoding="utf-8") assert 'typeCheckingMode = "standard"' in raw assert "reportMissingImports = true" in raw @@ -861,7 +830,10 @@ def test_generated_pyproject_basedpyright_standard_mode(tmp_path: Path) -> None: def test_generated_pre_commit_includes_detect_secrets(tmp_path: Path) -> None: """Pre-commit config in generated projects should run detect-secrets with a baseline.""" test_dir = tmp_path / "secrets_hook" - copy_with_data(test_dir, {"project_name": "Secrets Hook", "include_docs": False}) + copy_with_data( + test_dir, + {"project_name": "Secrets Hook", "include_docs": False, "include_git_cliff": False}, + ) cfg = (test_dir / ".pre-commit-config.yaml").read_text(encoding="utf-8") assert "detect-secrets" in cfg assert ".secrets.baseline" in cfg @@ -871,7 +843,10 @@ def test_generated_pre_commit_includes_detect_secrets(tmp_path: Path) -> None: def test_generated_renovate_enables_pre_commit(tmp_path: Path) -> None: """Renovate should manage pre-commit hook revisions in generated projects.""" test_dir = tmp_path / "renovate_pc" - copy_with_data(test_dir, {"project_name": "Renovate Test", "include_docs": False}) + copy_with_data( + test_dir, + {"project_name": "Renovate Test", "include_docs": False, "include_git_cliff": False}, + ) import json data = json.loads((test_dir / ".github" / "renovate.json").read_text(encoding="utf-8")) @@ -886,7 +861,6 @@ def test_generated_renovate_enables_pre_commit(tmp_path: Path) -> None: "include_numpy": True, "include_pandas_support": False, "include_cli": True, - "include_logging_setup": True, "include_git_cliff": True, }, { @@ -894,7 +868,6 @@ def test_generated_renovate_enables_pre_commit(tmp_path: Path) -> None: "include_numpy": False, "include_pandas_support": True, "include_cli": False, - "include_logging_setup": False, "include_git_cliff": False, }, ], @@ -954,7 +927,9 @@ def test_release_workflow_generated_by_default(tmp_path: Path) -> None: assert release_yml.is_file(), "release.yml must exist when include_release_workflow=true" content = release_yml.read_text(encoding="utf-8") assert "${{ true }}" in content, "release job must be enabled" - assert "bump_version.py" in content, "release.yml must reference bump_version.py" + assert ( + "src/release_default/common/bump_version.py" in content + ), "release.yml must reference src//common/bump_version.py" assert "--generate-notes" in content, ( "release must use gh --generate-notes (no CHANGELOG.md required)" ) @@ -1102,7 +1077,7 @@ def test_pre_commit_update_workflow_generated(tmp_path: Path) -> None: def test_scripts_bump_version_generated(tmp_path: Path) -> None: - """scripts/bump_version.py must exist in the generated project.""" + """src//common/bump_version.py must exist in the generated project.""" test_dir = tmp_path / "bump_version" copy_with_data( test_dir, @@ -1112,8 +1087,10 @@ def test_scripts_bump_version_generated(tmp_path: Path) -> None: "include_docs": False, }, ) - bump_script = test_dir / "scripts" / "bump_version.py" - assert bump_script.is_file(), "scripts/bump_version.py must exist in generated projects" + bump_script = test_dir / "src" / "bump_version" / "common" / "bump_version.py" + assert bump_script.is_file(), ( + "src//common/bump_version.py must exist in generated projects" + ) content = bump_script.read_text(encoding="utf-8") assert "BumpKind" in content, "bump_version.py must contain BumpKind type alias" assert "[project]" in content, "bump_version.py must look for [project] section" From db5120525ade5476ce6062ea412404c374a78496 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 16:38:11 +0000 Subject: [PATCH 2/5] test: use git+file:// for copier runs Co-authored-by: buddingengineers12345 --- tests/test_template.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/test_template.py b/tests/test_template.py index 5ee1a01..0278627 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -59,7 +59,7 @@ def get_default_command_list(test_dir: Path) -> list[str]: return [ "copier", "copy", - ".", + "git+file://.", str(test_dir), "--data", "project_name=Test Project", @@ -258,7 +258,9 @@ def test_generate_defaults_only_cli(tmp_path: Path) -> None: Pass explicit ``--data`` when you need a different distribution name. """ test_dir = tmp_path / "defaults_only" - _ = run_command(["copier", "copy", ".", str(test_dir), "--trust", "--defaults", "--skip-tasks"]) + _ = run_command( + ["copier", "copy", "git+file://.", str(test_dir), "--trust", "--defaults", "--skip-tasks"] + ) _remove_empty_optional_artifacts( test_dir, { @@ -310,7 +312,9 @@ def test_package_name_validator_rejects_leading_digit(tmp_path: Path) -> None: def test_computed_values_not_recorded_in_answers_file(tmp_path: Path) -> None: """Questions with ``when: false`` must not be stored in the answers file.""" test_dir = tmp_path / "computed_answers" - _ = run_command(["copier", "copy", ".", str(test_dir), "--trust", "--defaults", "--skip-tasks"]) + _ = run_command( + ["copier", "copy", "git+file://.", str(test_dir), "--trust", "--defaults", "--skip-tasks"] + ) _remove_empty_optional_artifacts( test_dir, { @@ -327,7 +331,9 @@ def test_computed_values_not_recorded_in_answers_file(tmp_path: Path) -> None: def test_answers_file_warns_never_edit_manually(tmp_path: Path) -> None: """Generated answers file should match Copier docs banner text.""" test_dir = tmp_path / "answers_banner" - _ = run_command(["copier", "copy", ".", str(test_dir), "--trust", "--defaults", "--skip-tasks"]) + _ = run_command( + ["copier", "copy", "git+file://.", str(test_dir), "--trust", "--defaults", "--skip-tasks"] + ) _remove_empty_optional_artifacts( test_dir, { @@ -927,9 +933,9 @@ def test_release_workflow_generated_by_default(tmp_path: Path) -> None: assert release_yml.is_file(), "release.yml must exist when include_release_workflow=true" content = release_yml.read_text(encoding="utf-8") assert "${{ true }}" in content, "release job must be enabled" - assert ( - "src/release_default/common/bump_version.py" in content - ), "release.yml must reference src//common/bump_version.py" + assert "src/release_default/common/bump_version.py" in content, ( + "release.yml must reference src//common/bump_version.py" + ) assert "--generate-notes" in content, ( "release must use gh --generate-notes (no CHANGELOG.md required)" ) From b7f3fb725a6674258b8e9a8737555e7c13d60840 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 16:41:15 +0000 Subject: [PATCH 3/5] test: fix git+file template URI Co-authored-by: buddingengineers12345 --- tests/test_template.py | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/tests/test_template.py b/tests/test_template.py index 0278627..1f1e723 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -19,6 +19,8 @@ import yaml from copier import run_copy +TEMPLATE_GIT_SRC = f"git+{Path('.').resolve().as_uri()}" + def run_command( cmd: list[str], @@ -59,7 +61,7 @@ def get_default_command_list(test_dir: Path) -> list[str]: return [ "copier", "copy", - "git+file://.", + TEMPLATE_GIT_SRC, str(test_dir), "--data", "project_name=Test Project", @@ -259,7 +261,15 @@ def test_generate_defaults_only_cli(tmp_path: Path) -> None: """ test_dir = tmp_path / "defaults_only" _ = run_command( - ["copier", "copy", "git+file://.", str(test_dir), "--trust", "--defaults", "--skip-tasks"] + [ + "copier", + "copy", + TEMPLATE_GIT_SRC, + str(test_dir), + "--trust", + "--defaults", + "--skip-tasks", + ] ) _remove_empty_optional_artifacts( test_dir, @@ -313,7 +323,15 @@ def test_computed_values_not_recorded_in_answers_file(tmp_path: Path) -> None: """Questions with ``when: false`` must not be stored in the answers file.""" test_dir = tmp_path / "computed_answers" _ = run_command( - ["copier", "copy", "git+file://.", str(test_dir), "--trust", "--defaults", "--skip-tasks"] + [ + "copier", + "copy", + TEMPLATE_GIT_SRC, + str(test_dir), + "--trust", + "--defaults", + "--skip-tasks", + ] ) _remove_empty_optional_artifacts( test_dir, @@ -332,7 +350,15 @@ def test_answers_file_warns_never_edit_manually(tmp_path: Path) -> None: """Generated answers file should match Copier docs banner text.""" test_dir = tmp_path / "answers_banner" _ = run_command( - ["copier", "copy", "git+file://.", str(test_dir), "--trust", "--defaults", "--skip-tasks"] + [ + "copier", + "copy", + TEMPLATE_GIT_SRC, + str(test_dir), + "--trust", + "--defaults", + "--skip-tasks", + ] ) _remove_empty_optional_artifacts( test_dir, From 2170abf3561aba7b0e2cc775e25aff8ba8c06d69 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 16:43:01 +0000 Subject: [PATCH 4/5] test: render template via git+file in all paths Co-authored-by: buddingengineers12345 --- tests/test_template.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_template.py b/tests/test_template.py index 1f1e723..39d3fb7 100644 --- a/tests/test_template.py +++ b/tests/test_template.py @@ -141,7 +141,7 @@ def copy_with_data( "copy", "--vcs-ref", "HEAD", - ".", + TEMPLATE_GIT_SRC, str(dest), "--trust", "--defaults", @@ -306,7 +306,7 @@ def test_package_name_validator_rejects_leading_digit(tmp_path: Path) -> None: "copy", "--vcs-ref", "HEAD", - ".", + TEMPLATE_GIT_SRC, str(test_dir), "--trust", "--defaults", @@ -376,7 +376,7 @@ def test_generate_programmatic_run_copy_local(tmp_path: Path) -> None: """Render programmatically with :func:`copier.run_copy` from a local path.""" test_dir = tmp_path / "programmatic_local" _worker = run_copy( - ".", + TEMPLATE_GIT_SRC, test_dir, defaults=True, unsafe=True, From bd8fc583738250ebf8cbc05690e52c7a216196ab Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 8 Apr 2026 16:44:57 +0000 Subject: [PATCH 5/5] chore(just): run pip-audit via uv tool run Co-authored-by: buddingengineers12345 --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index d8dce07..936b44f 100644 --- a/justfile +++ b/justfile @@ -91,7 +91,7 @@ precommit: # Dependency audit matching .github/workflows/security.yml (pip-audit) audit: - @uv export --frozen --format requirements-txt --extra dev | uvx pip-audit --requirement /dev/stdin + @uv export --frozen --format requirements-txt --extra dev | uv tool run pip-audit --requirement /dev/stdin # ------------------------------------------------------------------------- # Dependency management