From d9ba8f61104aab387e6439616606a5e313e40e34 Mon Sep 17 00:00:00 2001 From: Kevin Weiss Date: Tue, 24 Mar 2026 17:16:38 +0100 Subject: [PATCH] chore: update with copier template v0.0.4 --- .copier-answers.yml | 2 +- .github/agents/pr-review.agent.md | 68 ++++++++++++++++++ .github/copilot-instructions.md | 15 ++++ .../lobaro-template.instructions.md | 40 +++++++++++ .github/workflows/ci.yml | 53 ++++++++------ .pre-commit-config.yaml | 70 +++++++++++-------- pyproject.toml | 25 +++---- pyrightconfig.json | 11 +++ tests/test_lob_hlpr.py | 1 + tox.ini | 27 ++++--- 10 files changed, 238 insertions(+), 74 deletions(-) create mode 100644 .github/agents/pr-review.agent.md create mode 100644 .github/copilot-instructions.md create mode 100644 .github/instructions/lobaro-template.instructions.md create mode 100644 pyrightconfig.json diff --git a/.copier-answers.yml b/.copier-answers.yml index 5290225..a426247 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: v0.0.2 +_commit: v0.0.4 _src_path: ../template-python/ author: Kevin Weiss author_email: weiss.kevin604@gmail.com diff --git a/.github/agents/pr-review.agent.md b/.github/agents/pr-review.agent.md new file mode 100644 index 0000000..e7c7a2f --- /dev/null +++ b/.github/agents/pr-review.agent.md @@ -0,0 +1,68 @@ +--- +description: Review PR commits against master — check architecture, bugs, test coverage and commit messages, apply fixup commits, then propose a PR title and summary. +--- + +You are a thorough PR reviewer for Lobaro Python projects. Work through the +steps below in order. Be specific about problems and their locations. Do not +skip a step even if the previous one passed cleanly. + +## Step 1 — Map the branch + +``` +git log master..HEAD --oneline +``` + +List every commit on the branch. Then for each commit, run `git show ` to +read its diff in full before forming any opinion. + +## Step 2 — Review each commit + +For each commit evaluate the four areas below. Collect all findings before +making any changes. + +**Architecture / intent** +Does the change make sense at the design level? Is the approach sound? Does it +fit the project structure and direction? + +**Bugs** +Any logic errors, off-by-ones, unhandled edge-cases, thread-safety issues, or +resource leaks? Would the code fail for any valid input? + +**Test coverage** +Are the changed code paths exercised by tests? Are edge-cases and error paths +covered? New behaviour without tests is a finding. + +**Commit message** +Must be a valid [Conventional Commit](https://www.conventionalcommits.org/): +`type(scope): description` — lower-case description, no trailing period. +Common types: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `build`. +Check that the type, scope, and description accurately reflect the diff. + +Present a summary of all findings before moving on. + +## Step 3 — Fix problems one by one + +For each finding, in order: + +1. Apply the fix to the source files. +2. Run `tox -e lint` — fix any issues and repeat until it passes cleanly. +3. Run `tox` — fix any failures and repeat until it passes cleanly. +4. Create the smallest accurate commit: + - If the fix belongs squarely to an existing commit: `git commit --fixup=` + - If it is genuinely new work (e.g. additional tests, a separate bug): + use a new conventional commit message. + +**Never amend or rebase the user's existing commits. Only add new commits.** + +Iterate through all findings until all are resolved. + +## Step 4 — Propose a PR summary + +Once all findings are addressed, output: + +1. The updated commit list: `git log master..HEAD --oneline` +2. A recommended PR title in conventional commit format. +3. A short PR body (3–8 sentences) explaining what changed, why, and any + migration or review notes. + +Pause here and wait for the user to review each commit before they squash. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..f4c02a9 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,15 @@ +# GitHub Copilot Instructions — helpers + + + +Simple python based helpers for lobaro tools. +This is a Lobaro Python library (`lob-hlpr`), module `lob_hlpr`. + +Instructions generic information based off the +[Lobaro Python template](https://github.com/lobaro/template-python) +(layout, patterns, workflow, CLI) is defined in +[lobaro-template.instructions.md](.github/instructions/lobaro-template.instructions.md). + diff --git a/.github/instructions/lobaro-template.instructions.md b/.github/instructions/lobaro-template.instructions.md new file mode 100644 index 0000000..9a9aacb --- /dev/null +++ b/.github/instructions/lobaro-template.instructions.md @@ -0,0 +1,40 @@ +--- +applyTo: "**" +--- +# Lobaro Project Instructions + +## Project layout + +- Source: `src/lob_hlpr/` — all library/app code lives here +- Tests: `tests/` +- Config: `pyproject.toml`, if configs can be in different files, prefer that (e.g. `tox.ini`, `pytest.ini`) +- Versioning: `setuptools-scm` — version comes from git tags, never hardcode it +- Dependencies: loose version bounds in `pyproject.toml`; pinned snapshots in `requirements*.txt` + +## Python version + +Python ≥ 3.10. Always use built-in generics — `list[X]`, `dict[K, V]`, `X | None` — never `typing.List` etc. + +## Validation workflow + +Always run lint first, fix all issues, then run the full test suite: + +``` +tox -e lint # check and fix all style issues +tox # full test suite across Python versions +``` + +If lint passes but tests fail, diagnose the test failure — do not bypass checks. + +## Code patterns + +- Use `dataclasses.dataclass` for data containers — never Pydantic (not a dependency) +- Use `logging` in every module — never `print` in library code +- Prefer named functions over lambdas +- Follow PEP 8 and PEP 257 +- Type-hint all public functions and methods +- Try not to add third-party dependencies unless necessary — prefer built-in features + +## Agents + +- PR review agent: [instructions](../agents/pr-review.agent.md) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b50d69a..d7ff92e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,35 +17,48 @@ concurrency: cancel-in-progress: true env: - TOX_VERSION: "4.24.1" + TOX_VERSION: "4.49.1" + TOX_UV_VERSION: "1.33.4" + UV_VERSION: "0.10.11" MIN_PYTHON_VERSION: "3.10" - MAX_PYTHON_VERSION: "3.12" + MAX_PYTHON_VERSION: "3.13" jobs: + check-commits: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # deep clone for setuptools-scm + - name: Prevent fixup/squash/WIP commits + run: | + BASE_SHA=$(git merge-base origin/main HEAD 2>/dev/null || git merge-base origin/master HEAD) + git log $BASE_SHA..HEAD --pretty=%s | grep -E '^(fixup!|squash!|WIP|wip)' && exit 1 || echo "✅ ok" + prepare: runs-on: ubuntu-24.04 outputs: wheel-distribution: ${{ steps.wheel-distribution.outputs.path }} VERSION: ${{ steps.get_version.outputs.VERSION }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 # deep clone for setuptools-scm - - uses: actions/setup-python@v5 - id: setup-python + - uses: astral-sh/setup-uv@v7 with: + version: ${{ env.UV_VERSION }} python-version: ${{ env.MIN_PYTHON_VERSION }} - name: Run static analysis and format checkers run: >- - pipx run - --python '${{ steps.setup-python.outputs.python-path }}' - --spec tox==${{ env.TOX_VERSION }} + uv tool run + --from "tox==${{ env.TOX_VERSION }}" + --with "tox-uv==${{ env.TOX_UV_VERSION }}" tox -e lint - name: Build package distribution files run: >- - pipx run - --python '${{ steps.setup-python.outputs.python-path }}' - --spec tox==${{ env.TOX_VERSION }} + uv tool run + --from "tox==${{ env.TOX_VERSION }}" + --with "tox-uv==${{ env.TOX_UV_VERSION }}" tox -e clean,build - name: Record the path of wheel distribution id: wheel-distribution @@ -59,7 +72,7 @@ jobs: - name: Store the distribution files for use in other stages # `tests` and `publish` will use the same pre-built distributions, # so we make sure to release the exact same package that was tested - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: python-distribution-files path: dist/ @@ -71,26 +84,26 @@ jobs: matrix: python: - "3.10" - - "3.12" + - "3.13" platform: - ubuntu-24.04 runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - id: setup-python + - uses: actions/checkout@v6 + - uses: astral-sh/setup-uv@v7 with: + version: ${{ env.UV_VERSION }} python-version: ${{ matrix.python }} - name: Retrieve pre-built distribution files - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: python-distribution-files path: dist/ - name: Run tests run: >- - pipx run - --python '${{ steps.setup-python.outputs.python-path }}' - --spec tox==${{ env.TOX_VERSION }} + uv tool run + --from "tox==${{ env.TOX_VERSION }}" + --with "tox-uv==${{ env.TOX_UV_VERSION }}" tox --installpkg '${{ needs.prepare.outputs.wheel-distribution }}' -- -rFEx --durations 10 --color yes diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ec247aa..3b60563 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,48 +1,62 @@ exclude: '^docs/conf.py' +default_install_hook_types: [pre-commit, commit-msg] + repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: "v6.0.0" hooks: - - id: check-added-large-files - args: ['--maxkb=16384'] - - id: check-ast - - id: check-case-conflict - - id: check-illegal-windows-names - - id: check-json - - id: check-merge-conflict - - id: check-symlinks - - id: check-toml - - id: check-xml - - id: check-yaml - - id: debug-statements - - id: destroyed-symlinks - - id: end-of-file-fixer - - id: pretty-format-json - args: ['--autofix'] - - id: requirements-txt-fixer - - id: sort-simple-yaml - - id: trailing-whitespace + - id: check-added-large-files + args: ['--maxkb=16384'] + - id: check-ast + - id: check-case-conflict + - id: check-illegal-windows-names + - id: check-json + - id: check-merge-conflict + - id: check-symlinks + - id: check-toml + - id: check-xml + - id: check-yaml + - id: debug-statements + - id: destroyed-symlinks + - id: end-of-file-fixer + - id: pretty-format-json + args: ['--autofix'] + - id: requirements-txt-fixer + - id: sort-simple-yaml + - id: trailing-whitespace - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.0" + rev: "v2.18.1" hooks: - id: pyproject-fmt - repo: https://github.com/codespell-project/codespell - rev: v2.4.1 + rev: "v2.4.2" hooks: - - id: codespell + - id: codespell + stages: [commit-msg, pre-commit] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.3 + rev: "v0.15.6" hooks: # Run the linter. - - id: ruff + - id: ruff-check # Run the formatter. - id: ruff-format -- repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v1.14.1' +- repo: https://github.com/DetachHead/basedpyright-prek-mirror + rev: "1.38.2" + hooks: + - id: basedpyright + +- repo: https://github.com/gitleaks/gitleaks + rev: "v8.24.2" + hooks: + - id: gitleaks + +- repo: https://github.com/compilerla/conventional-pre-commit + rev: "v4.4.0" hooks: - - id: mypy + - id: conventional-pre-commit + stages: [commit-msg] diff --git a/pyproject.toml b/pyproject.toml index e6f4771..0581bd7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,16 +1,15 @@ [build-system] build-backend = "setuptools.build_meta" - requires = [ - "setuptools>=64", - "setuptools-scm[toml]>=8", + "setuptools>=77", + "setuptools-scm[toml]>=9", ] [project] name = "lob-hlpr" description = "Simple python based helpers for lobaro tools." readme = "README.md" -license = { file = "LICENSE" } +license-files = [ "LICENSE" ] authors = [ { name = "Kevin Weiss", email = "weiss.kevin604@gmail.com" }, ] @@ -22,27 +21,23 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] dynamic = [ "version" ] - dependencies = [ + # ] - optional-dependencies.testing = [ - "pytest~=8.3.4", - "pytest-cov~=6.0.0", + "pytest~=9.0.2", + "pytest-cov~=7.0.0", ] [tool.setuptools] include-package-data = true - -[tool.setuptools.packages.find] -where = [ "src" ] - -[tool.setuptools.package-data] -lob_hlpr = [ +package-data.lob_hlpr = [ "py.typed", ] +packages.find.where = [ "src" ] [tool.setuptools_scm] # For smarter version schemes and other configuration options, @@ -50,4 +45,4 @@ lob_hlpr = [ version_scheme = "no-guess-dev" [tool.pyproject-fmt] -max_supported_python = "3.12" +max_supported_python = "3.13" diff --git a/pyrightconfig.json b/pyrightconfig.json new file mode 100644 index 0000000..33cf201 --- /dev/null +++ b/pyrightconfig.json @@ -0,0 +1,11 @@ +{ + "reportImplicitOverride": "none", + "reportImplicitStringConcatenation": "none", + "reportMissingImports": "none", + "reportMissingModuleSource": "none", + "reportMissingTypeArgument": "none", + "reportOptionalMemberAccess": "none", + "reportUnannotatedClassAttribute": "none", + "reportUnusedCallResult": "none", + "typeCheckingMode": "basic" +} diff --git a/tests/test_lob_hlpr.py b/tests/test_lob_hlpr.py index 2e422e8..d68d175 100644 --- a/tests/test_lob_hlpr.py +++ b/tests/test_lob_hlpr.py @@ -265,6 +265,7 @@ def test_fw_id_from_fw_file_passes(): # Test with a valid firmware file test_file = "tests/files/fw-test-file.hex" res = hlp.fw_id_from_fw_file(test_file, contains="app-nrf9160-wmbus") + assert res.name is not None assert "app-nrf9160-wmbus" in res.name diff --git a/tox.ini b/tox.ini index 86fa92c..091068a 100644 --- a/tox.ini +++ b/tox.ini @@ -28,29 +28,36 @@ commands = description = Perform static analysis and style checks skip_install = True deps = - pre-commit==4.1.0 + prek==0.3.5 passenv = HOMEPATH PROGRAMDATA SETUPTOOLS_* commands = - pre-commit run --all-files {posargs:--show-diff-on-failure} + prek run --all-files {posargs:--show-diff-on-failure} -[testenv:{build,clean}] -description = - build: Build the package in isolation according to PEP517, see https://github.com/pypa/build - clean: Remove old distribution files and temporary build artifacts (./build and ./dist) +[testenv:clean] +description = Remove old distribution files and temporary build artifacts (./build and ./dist) +skip_install = True +changedir = {toxinidir} +deps = +passenv = + SETUPTOOLS_* +commands = + python -c 'import shutil; [shutil.rmtree(p, True) for p in ("build", "dist", "docs/_build")]' + python -c 'import pathlib, shutil; [shutil.rmtree(p, True) for p in pathlib.Path("src").glob("*.egg-info")]' + +[testenv:build] +description = Build the package in isolation according to PEP517, see https://github.com/pypa/build # https://setuptools.pypa.io/en/stable/build_meta.html#how-to-use-it skip_install = True changedir = {toxinidir} deps = - build: build[virtualenv] + build[virtualenv] passenv = SETUPTOOLS_* commands = - clean: python -c 'import shutil; [shutil.rmtree(p, True) for p in ("build", "dist", "docs/_build")]' - clean: python -c 'import pathlib, shutil; [shutil.rmtree(p, True) for p in pathlib.Path("src").glob("*.egg-info")]' - build: python -m build {posargs} + python -m build {posargs} # By default, both `sdist` and `wheel` are built. If your sdist is too big or you don't want # to make it available, consider running: `tox -e build -- --wheel`