Conversation
Replace Poetry with uv for faster dependency resolution and installation. This follows the same migration pattern used in python-web-service-boilerplate. Migration includes: - Convert pyproject.toml from Poetry format to PEP 621 standard - Replace poetry.lock with uv.lock - Update GitHub Actions workflows to use uv - Update pre-commit hooks to use 'uv run' instead of 'poetry run' - Modernize Dockerfile to use uv - Update README.md with uv setup and usage instructions All tests and linting pass with uv.
There was a problem hiding this comment.
Pull request overview
Migrates the project from Poetry-based dependency management to uv, updating packaging metadata to PEP 621 and modernizing local tooling, CI, and Docker builds to use uv workflows.
Changes:
- Replaced Poetry configuration/lock usage with PEP 621
[project]metadata anduv.lock. - Updated pre-commit hooks and GitHub Actions to run tooling via
uv run/uv sync. - Modernized Docker build to use a multi-stage
uv sync --frozenapproach.
Reviewed changes
Copilot reviewed 8 out of 10 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
uv.lock |
Adds uv lockfile for reproducible installs. |
pyproject.toml |
Moves to PEP 621 metadata and switches build backend; updates Ruff config. |
src/python_boilerplate/configuration/application_configuration.py |
Updates pyproject metadata lookup from Poetry keys to PEP 621 keys. |
src/python_boilerplate/__main__.py |
Updates version lookup from Poetry keys to PEP 621 keys. |
README.md |
Updates setup and command docs to reference uv instead of Poetry. |
Dockerfile |
Replaces Poetry-based multi-stage build with uv sync-based build. |
.pre-commit-config.yaml |
Reworks local hooks to run ruff/mypy/pytest via uv. |
.github/workflows/python-ci-with-uv.yml |
Updates CI commands to run via uv. |
.github/actions/project-environment-setup/action.yml |
Replaces Poetry install/setup with uv setup and uv sync. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
README.md
Outdated
| ### Run Python Script | ||
|
|
||
| **Append your project’s root directory to** `PYTHONPATH` — In any environment you wish to run your Python application such as Docker, vagrant or your virtual environment i.e. in bin/activate, run the below command: | ||
|
|
||
| > [How to Fix ModuleNotFoundError and ImportError](https://towardsdatascience.com/how-to-fix-modulenotfounderror-and-importerror-248ce5b69b1c) |
There was a problem hiding this comment.
There are now two "Run Python Script" sections back-to-back, and the later one still contains poetry run ... commands. This is inconsistent with the uv migration and likely to confuse users; remove the duplicated Poetry section or update it to uv so there is a single authoritative set of commands.
| pytest-monitor = "==1.6.6" | ||
| requires = ["setuptools>=61.0", "wheel"] | ||
| build-backend = "setuptools.build_meta" | ||
|
|
There was a problem hiding this comment.
Switching the build backend to setuptools without configuring package discovery for the src/ layout will produce an empty/incorrect wheel (e.g., python_boilerplate won’t be included) and can break pip install . / packaging. Add setuptools configuration (e.g., package-dir pointing to src and package discovery via packages.find), or use a backend that auto-handles the current layout.
| [tool.setuptools] | |
| package-dir = {"" = "src"} | |
| [tool.setuptools.packages.find] | |
| where = ["src"] |
pyproject.toml
Outdated
| show-fixes = true | ||
| src = ["src", ] | ||
| src = ["src", "tests"] | ||
| target-version = "py39" |
There was a problem hiding this comment.
target-version = "py39" conflicts with requires-python = ">=3.13.1,<3.14". Ruff will lint/format assuming Python 3.9 semantics, which can hide/introduce issues for 3.13-only code. Align Ruff’s target-version with the supported runtime (e.g., py313).
| target-version = "py39" | |
| target-version = "py313" |
| .venv/| | ||
| .sqlite3 | ||
| )$^ |
There was a problem hiding this comment.
The top-level exclude regex ends with $^, which makes it impossible to match anything (end-of-string immediately followed by start-of-string). This likely means .venv/ and sqlite files will not be excluded from hooks. Fix the regex terminator (e.g., )$) and ensure the sqlite pattern matches the intended filenames (e.g., .*\.sqlite3$).
| .venv/| | |
| .sqlite3 | |
| )$^ | |
| \.venv/| | |
| .*\.sqlite3 | |
| )$ |
…errors - Change 'import test_python_boilerplate' to fully-qualified module imports in test_debounce_throttle.py and test_apscheduler_configuration.py so mypy can resolve the attr-defined references for mocker.spy() - Add PLW0406 to per-file-ignores for tests/ since fully-qualified self-imports trigger the module-imports-itself warning
…ame__] The test modules were importing themselves (e.g., import test_python_boilerplate.common.test_debounce_throttle) solely to pass the module to mocker.spy(). This triggered PLW0406 (module-imports-itself) and PLC0415 (import-not-at-top-level) lint suppressions. Replace with the idiomatic sys.modules[__name__] pattern and remove the now-unnecessary PLW0406/PLC0415 entries from pyproject.toml per-file-ignores.
pyinstrument 5.1.2 uses a C-level ProfilerState object via sys.setprofile() that is not a callable Python function. pytest-benchmark's PauseInstrumentation saves and restores the profiler via sys.setprofile(), which fails with TypeError on the non-callable ProfilerState. Skip the auto_profile fixture for tests using the benchmark fixture, since profiling during benchmarks is counterproductive anyway (adds overhead that corrupts measurements).
…deferred side effects - Adopt PEP 695 type parameter syntax in profiling.py and debounce_throttle.py - Remove unnecessary `from __future__ import annotations` in asynchronization.py and debounce_throttle.py - Extract _make_profile_decorator factory to DRY elapsed_time, mem_profile, and cpu_profile - Defer loguru handler setup into configure() and SMTP login into init_smtp() - Rename retain_log_files to _retain_log_files (private, called only by configure) - Fix stale README: consolidate black/isort/flake8 references to Ruff, remove duplicate poetry section, fix Python badge - Bump actions/checkout v2/v3 to v4, docker-build-with-cache-action v2 to v6 - Add py.typed marker for PEP 561 compliance
Changes Included:
Verification:
All existing functionality has been verified:
This migration maintains full backward compatibility in terms of functionality while providing a more modern and efficient development experience.
External References Used