From 58bba92650b21c5d67bf4fb077b18fcea45bfff0 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 23 Feb 2026 18:24:43 -0500 Subject: [PATCH] build(pyproject): migrate to uv --- .github/CONTRIBUTING.md | 80 +++++++++++++--------------- .github/dependabot.yml | 2 +- .github/workflows/docs.yml | 11 ++-- .github/workflows/lint.yml | 17 +++--- .github/workflows/release-please.yml | 23 +++----- .github/workflows/test.yml | 64 ++++++++-------------- .gitignore | 2 +- .pre-commit-config.yaml | 10 ++-- README.md | 26 ++++----- pyproject.toml | 7 +++ 10 files changed, 102 insertions(+), 140 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a27506d..3d92166 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -17,34 +17,22 @@ cd python-cli-template ## Install -Install [Python](https://www.python.org/): +Install [uv](https://docs.astral.sh/uv/): ```sh -brew install python +brew install uv ``` -Create the virtual environment: +Install development dependencies: ```sh -python3 -m venv .venv -``` - -Activate the virtual environment: - -```sh -source .venv/bin/activate -``` - -Install the dependencies: - -```sh -pip install -e '.[build,docs,lint,test]' +uv sync --all-extras ``` Install pre-commit into your git hooks: ```sh -pre-commit install +uv run pre-commit install ``` ## Develop @@ -74,38 +62,38 @@ Things that will improve the chance that your pull request will be accepted: ## Test -Install the dependencies: +Install test dependencies: ```sh -pip install -e '.[test]' +uv sync --extra test ``` Run the tests: ```sh -pytest +uv run pytest ``` Run the tests with [coverage](https://coverage.readthedocs.io/): ```sh -coverage run -m pytest +uv run coverage run -m pytest ``` Generate a coverage report: ```sh -coverage report +uv run coverage report ``` ```sh -coverage html +uv run coverage html ``` -Install the package with [pipx](https://pipx.pypa.io/): +Install the package with [uv](https://docs.astral.sh/uv/): ```sh -pipx install . --force +uv tool install . --force ``` Test the command: @@ -116,80 +104,88 @@ python-cli-template --help ## Lint -Install the dependencies: +Install lint dependencies: ```sh -pip install -e '.[lint]' +uv sync --extra lint ``` Update pre-commit hooks to the latest version: ```sh -pre-commit autoupdate +uv run pre-commit autoupdate ``` Run all pre-commit hooks: ```sh -pre-commit run --all-files +uv run pre-commit run --all-files +``` + +Lint all files: + +```sh +uv run ruff check # --fix ``` -Lint all files in the current directory: +Format all files: ```sh -ruff check +uv run ruff format ``` -Format all files in the current directory: +## Run + +Run the CLI: ```sh -ruff format +uv run python-cli-template ``` ## Build -Install the dependencies: +Install build dependencies: ```sh -pip install -e '.[build]' +uv sync --extra build ``` Generate the distribution packages: ```sh -python3 -m build +uv build ``` Upload all of the archives under `dist`: ```sh -twine upload --repository testpypi dist/* +uv publish --repository testpypi ``` Install the package: ```sh -pip install --index-url https://test.pypi.org/simple/ --no-deps python-cli-template +uv tool install --index-url testpypi python-cli-template ``` Bundle the package with [PyInstaller](https://pyinstaller.org/): ```sh -pyinstaller src/python-cli-template/cli.py --name python-cli-template +uv run pyinstaller python_cli_template.cli --name python-cli-template ``` ## Docs -Install the dependencies: +Install docs dependencies: ```sh -pip install -e '.[docs]' +uv sync --extra docs ``` Generate the docs with [pdoc](https://pdoc.dev/): ```sh -pdoc src/python_cli_template/ +uv run pdoc src/python_cli_template/ ``` ## Release diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2809951..34a263e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ version: 2 updates: - - package-ecosystem: 'pip' + - package-ecosystem: 'uv' directory: '/' schedule: interval: 'daily' diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a4491ac..683eb43 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -11,17 +11,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Use Python - uses: actions/setup-python@v6 - with: - cache: pip - python-version-file: pyproject.toml + - name: Install uv + uses: astral-sh/setup-uv@v7 - name: Install dependencies - run: pip install -e .[docs] + run: uv sync --extra docs - name: Build docs - run: pdoc src/python_cli_template/ -o docs + run: uv run pdoc src/python_cli_template/ -o docs - name: Deploy if: github.ref_name == 'master' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7c67ea4..ca4ab13 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,23 +11,20 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Use Python - uses: actions/setup-python@v6 - with: - cache: pip - python-version-file: pyproject.toml + - name: Install uv + uses: astral-sh/setup-uv@v7 - name: Install dependencies - run: pip install -e .[lint] + run: uv sync --extra lint - name: Type check - run: mypy . + run: uv run mypy . - name: Run Black - run: black --check . + run: uv run black --check . - name: Run Ruff - run: ruff check + run: uv run ruff check - name: Run pre-commit - run: pre-commit run --all-files + run: uv run pre-commit run --all-files diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index b7ea730..214286c 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -36,19 +36,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Use Python - uses: actions/setup-python@v6 - with: - python-version-file: pyproject.toml - - - name: Install build - run: python -m pip install build + - name: Install uv + uses: astral-sh/setup-uv@v7 - name: Build package - run: python -m build + run: uv build - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + run: uv publish upload: needs: release @@ -64,16 +59,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Use Python - uses: actions/setup-python@v6 - with: - python-version-file: pyproject.toml + - name: Install uv + uses: astral-sh/setup-uv@v7 - name: Install dependencies - run: pip install -e '.[build]' + run: uv sync --extra build - name: Build executable - run: pyinstaller src/python_cli_template/cli.py --name python-cli-template --onefile --clean + run: uv run pyinstaller python_cli_template.cli --name python-cli-template --onefile --clean - name: Compress executable shell: bash diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5bcaa98..5518878 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,53 +11,23 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Use Python - uses: actions/setup-python@v6 - with: - cache: pip - python-version-file: pyproject.toml + - name: Install uv + uses: astral-sh/setup-uv@v7 - name: Install dependencies - run: pip install -e .[test] + run: uv sync --extra test - name: Run tests and collect coverage run: | - coverage run -m pytest - coverage report - coverage xml + uv run coverage run -m pytest + uv run coverage report + uv run coverage xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} - install: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Use Python - uses: actions/setup-python@v6 - with: - cache: pip - python-version-file: pyproject.toml - - - name: Install package - run: pipx install . - - - name: Check version - run: | - version=$(grep version src/python_cli_template/__init__.py | cut -d'"' -f 2) - echo $version - python-cli-template --version - set -e - [[ $(python-cli-template --version) == $version ]] - [[ $(python-cli-template -v) == $version ]] - - - name: Get help - run: python-cli-template --help - integration: runs-on: ubuntu-latest strategy: @@ -69,14 +39,22 @@ jobs: - name: Checkout repository uses: actions/checkout@v6 - - name: Use Python - uses: actions/setup-python@v6 - with: - cache: pip - python-version-file: pyproject.toml + - name: Install uv + uses: astral-sh/setup-uv@v7 - - name: Install package - run: pipx install . + - name: Install tool + run: uv tool install . - name: Run command run: ${{ matrix.command }} + + - name: Get version + run: | + VERSION=$(grep version src/python_cli_template/__init__.py | cut -d'"' -f 2) + echo "VERSION=$VERSION" >> $GITHUB_ENV + + - name: Check version + run: | + set -e + [[ $(python-cli-template --version) == "$VERSION" ]] + [[ $(python-cli-template -v) == "$VERSION" ]] diff --git a/.gitignore b/.gitignore index 95fd8b2..c967276 100644 --- a/.gitignore +++ b/.gitignore @@ -98,7 +98,7 @@ ipython_config.py # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. -#uv.lock +uv.lock # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 79a081b..65cdc3f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-added-large-files - id: check-case-conflict @@ -16,18 +16,18 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 25.1.0 + rev: 26.1.0 hooks: - id: black - repo: https://github.com/PyCQA/isort - rev: 6.0.1 + rev: 8.0.0 hooks: - id: isort - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.2 + rev: v0.15.2 hooks: - id: ruff - args: [ --fix ] + args: [--fix] - id: ruff-format diff --git a/README.md b/README.md index 35091f5..c2b4d62 100644 --- a/README.md +++ b/README.md @@ -17,16 +17,22 @@ pipx run python-cli-template --name world ## Prerequisites - [Python](https://www.python.org/) -- [pipx](https://pipx.pypa.io/) +- [pipx](https://pipx.pypa.io/) or [uv](https://docs.astral.sh/uv/) ## CLI -Install the CLI: +Install with pipx: ```sh pipx install python-cli-template ``` +Or install with uv: + +```sh +uv tool install python-cli-template +``` + ### `--name` **Optional**: Name to greet. Defaults to `World`. @@ -51,22 +57,10 @@ python-cli-template --help # python-cli-template -h ## Script -Create a virtual environment: - -```sh -python3 -m venv .venv -``` - -Activate the virtual environment: - -```sh -source .venv/bin/activate -``` - Install the package: ```sh -pip install python-cli-template +uv add python-cli-template ``` Greet a name: @@ -81,7 +75,7 @@ print(hello("Bob")) Run the script: ```sh -python script.py +uv run script.py ``` ## License diff --git a/pyproject.toml b/pyproject.toml index 11fbcad..4e29397 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,9 @@ python-cli-template = "python_cli_template.cli:main" [project.entry-points."pipx.run"] python-cli-template = "python_cli_template.cli:main" +[project.entry-points."uv.run"] +python-cli-template = "python_cli_template.cli:main" + [project.optional-dependencies] build = [ "build==1.4.0", @@ -46,6 +49,10 @@ test = [ Homepage = "https://github.com/remarkablemark/python-cli-template" Issues = "https://github.com/remarkablemark/python-cli-template/issues" +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + [tool.black] fast = true