Skip to content

Commit

Permalink
Switch to uv
Browse files Browse the repository at this point in the history
  • Loading branch information
jedie committed Nov 11, 2024
1 parent c1e51f8 commit f5aa38e
Show file tree
Hide file tree
Showing 12 changed files with 1,709 additions and 1,751 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ default_install_hook_types:

repos:
- repo: https://github.com/jedie/cli-base-utilities
rev: v0.11.0
rev: v0.13.1
hooks:
- id: update-readme-history
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ Usage: ./dev-cli.py [OPTIONS] COMMAND [ARGS]...
│ coverage Run tests and show coverage report. │
│ fix-code-style Fix code style of all manageprojects source code files via darker │
│ git-hooks Setup our "pre-commit" git hooks │
│ install Run pip-sync and install 'manageprojects' via pip as editable. │
│ install Install requirements and 'manageprojects' via pip as editable. │
│ mypy Run Mypy (configured in pyproject.toml) │
│ pip-audit Run pip-audit check against current requirements files │
│ publish Build and upload this project to PyPi │
Expand Down Expand Up @@ -347,7 +347,8 @@ See also git tags: https://github.com/jedie/manageprojects/tags

[comment]: <> (✂✂✂ auto generated history start ✂✂✂)

* [**dev**](https://github.com/jedie/manageprojects/compare/v0.19.2...main)
* [v0.20.0](https://github.com/jedie/manageprojects/compare/v0.19.2...v0.20.0)
* 2024-11-11 - Switch to uv
* 2024-09-25 - Add: test_pre_commit_hooks()
* 2024-09-25 - Move git pre-commit hook from dev-cli.py to update command
* [v0.19.2](https://github.com/jedie/manageprojects/compare/v0.19.1...v0.19.2)
Expand Down
16 changes: 10 additions & 6 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""

import hashlib
import os
import shlex
import subprocess
import sys
Expand Down Expand Up @@ -50,9 +51,9 @@ def print_no_pip_error():
BIN_PATH = VENV_PATH / BIN_NAME
PYTHON_PATH = BIN_PATH / f'python3{FILE_EXT}'
PIP_PATH = BIN_PATH / f'pip{FILE_EXT}'
PIP_SYNC_PATH = BIN_PATH / f'pip-sync{FILE_EXT}'
UV_PATH = BIN_PATH / f'uv{FILE_EXT}'

DEP_LOCK_PATH = BASE_PATH / 'requirements.txt'
DEP_LOCK_PATH = BASE_PATH / 'uv.lock'
DEP_HASH_PATH = VENV_PATH / '.dep_hash'

# script file defined in pyproject.toml as [console_scripts]
Expand Down Expand Up @@ -91,15 +92,18 @@ def main(argv):
builder = venv.EnvBuilder(symlinks=True, upgrade=True, with_pip=True)
builder.create(env_dir=VENV_PATH)

# Set environment variable for uv to use '.venv-app' as project environment:
os.environ['UV_PROJECT_ENVIRONMENT'] = str(VENV_PATH.absolute())

if not PROJECT_SHELL_SCRIPT.is_file() or not venv_up2date():
# Update pip
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'pip')

# Install pip-tools
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'pip-tools')
# Install uv
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'uv')

# install requirements via "pip-sync"
verbose_check_call(PIP_SYNC_PATH, str(DEP_LOCK_PATH))
# install requirements
verbose_check_call(UV_PATH, 'sync', '--frozen', '--no-dev')

# install project
verbose_check_call(PIP_PATH, 'install', '--no-deps', '-e', '.')
Expand Down
12 changes: 6 additions & 6 deletions dev-cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ def print_no_pip_error():
BIN_PATH = VENV_PATH / BIN_NAME
PYTHON_PATH = BIN_PATH / f'python3{FILE_EXT}'
PIP_PATH = BIN_PATH / f'pip{FILE_EXT}'
PIP_SYNC_PATH = BIN_PATH / f'pip-sync{FILE_EXT}'
UV_PATH = BIN_PATH / f'uv{FILE_EXT}'

DEP_LOCK_PATH = BASE_PATH / 'requirements.dev.txt'
DEP_LOCK_PATH = BASE_PATH / 'uv.lock'
DEP_HASH_PATH = VENV_PATH / '.dep_hash'

# script file defined in pyproject.toml as [console_scripts]
Expand Down Expand Up @@ -95,11 +95,11 @@ def main(argv):
# Update pip
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'pip')

# Install pip-tools
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'pip-tools')
# Install uv
verbose_check_call(PYTHON_PATH, '-m', 'pip', 'install', '-U', 'uv')

# install requirements via "pip-sync"
verbose_check_call(PIP_SYNC_PATH, str(DEP_LOCK_PATH))
# install requirements
verbose_check_call(UV_PATH, 'sync')

# install project
verbose_check_call(PIP_PATH, 'install', '--no-deps', '-e', '.')
Expand Down
2 changes: 1 addition & 1 deletion manageprojects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"""

# See https://packaging.python.org/en/latest/specifications/version-specifiers/
__version__ = '0.19.2'
__version__ = '0.20.0'
__author__ = 'Jens Diemer <[email protected]>'
106 changes: 63 additions & 43 deletions manageprojects/cli_dev/packaging.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,64 @@
import sys
from pathlib import Path
import logging
import tempfile

import click
from bx_py_utils.pyproject_toml import get_pyproject_config
from cli_base.cli_tools.dev_tools import run_unittest_cli
from cli_base.cli_tools.subprocess_utils import verbose_check_call
from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE
from cli_base.run_pip_audit import run_pip_audit
from cli_base.cli_tools.subprocess_utils import ToolsExecutor
from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE, setup_logging

import manageprojects
from manageprojects.cli_dev import PACKAGE_ROOT, cli
from manageprojects.utilities.publish import publish_package


logger = logging.getLogger(__name__)


@cli.command()
def install():
"""
Run pip-sync and install 'manageprojects' via pip as editable.
Install requirements and 'manageprojects' via pip as editable.
"""
verbose_check_call('pip-sync', PACKAGE_ROOT / 'requirements.dev.txt')
verbose_check_call('pip', 'install', '--no-deps', '-e', '.')
tools_executor = ToolsExecutor(cwd=PACKAGE_ROOT)
tools_executor.verbose_check_call('uv', 'sync')
tools_executor.verbose_check_call('pip', 'install', '--no-deps', '-e', '.')


def run_pip_audit(verbosity: int):
tools_executor = ToolsExecutor(cwd=PACKAGE_ROOT)

with tempfile.NamedTemporaryFile(prefix='requirements', suffix='.txt') as temp_file:
tools_executor.verbose_check_call(
'uv',
'export',
'--no-header',
'--frozen',
'--no-editable',
'--no-emit-project',
'-o',
temp_file.name,
)

config: dict = get_pyproject_config(
section=('tool', 'cli_base', 'pip_audit'),
base_path=PACKAGE_ROOT,
)
logger.debug('pip_audit config: %r', config)
assert isinstance(config, dict), f'Expected a dict: {config=}'

popenargs = ['pip-audit', '--strict', '--require-hashes']

if verbosity:
popenargs.append(f'-{"v" * verbosity}')

for vulnerability_id in config.get('ignore-vuln', []):
popenargs.extend(['--ignore-vuln', vulnerability_id])

popenargs.extend(['-r', temp_file.name])

logger.debug('pip_audit args: %s', popenargs)
tools_executor.verbose_check_call(*popenargs)


@cli.command()
Expand All @@ -27,51 +67,31 @@ def pip_audit(verbosity: int):
"""
Run pip-audit check against current requirements files
"""
run_pip_audit(base_path=PACKAGE_ROOT, verbosity=verbosity)
setup_logging(verbosity=verbosity)
run_pip_audit(verbosity=verbosity)


@cli.command()
def update():
@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE)
def update(verbosity: int):
"""
Update "requirements*.txt" dependencies files
"""
bin_path = Path(sys.executable).parent

verbose_check_call(bin_path / 'pip', 'install', '-U', 'pip')
verbose_check_call(bin_path / 'pip', 'install', '-U', 'pip-tools')

extra_env = dict(
CUSTOM_COMPILE_COMMAND='./dev-cli.py update',
)

pip_compile_base = [bin_path / 'pip-compile', '--verbose', '--upgrade']

# Only "prod" dependencies:
verbose_check_call(
*pip_compile_base,
'pyproject.toml',
'--output-file',
'requirements.txt',
extra_env=extra_env,
)

# dependencies + "dev"-optional-dependencies:
verbose_check_call(
*pip_compile_base,
'pyproject.toml',
'--extra=dev',
'--output-file',
'requirements.dev.txt',
extra_env=extra_env,
)

run_pip_audit(base_path=PACKAGE_ROOT)
setup_logging(verbosity=verbosity)

tools_executor = ToolsExecutor(cwd=PACKAGE_ROOT)

tools_executor.verbose_check_call('pip', 'install', '-U', 'pip')
tools_executor.verbose_check_call('pip', 'install', '-U', 'uv')
tools_executor.verbose_check_call('uv', 'lock', '--upgrade')

run_pip_audit(verbosity=verbosity)

# Install new dependencies in current .venv:
verbose_check_call(bin_path / 'pip-sync', 'requirements.dev.txt')
tools_executor.verbose_check_call('uv', 'sync')

# Update git pre-commit hooks:
verbose_check_call(bin_path / 'pre_commit', 'autoupdate')
tools_executor.verbose_check_call('pre-commit', 'autoupdate')


@cli.command()
Expand Down
3 changes: 1 addition & 2 deletions manageprojects/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

from manageprojects.cli_app import manage
from manageprojects.cli_app.manage import start_project, update_project
from manageprojects.cli_dev import PACKAGE_ROOT
from manageprojects.cli_dev import cli as dev_cli
from manageprojects.constants import PY_BIN_PATH
from manageprojects.data_classes import CookiecutterResult
Expand Down Expand Up @@ -80,7 +79,7 @@ def test_install(self):
self.assertEqual(
call_mock.get_popenargs(rstrip_paths=(PY_BIN_PATH,)),
[
['.../pip-sync', f'{PACKAGE_ROOT}/requirements.dev.txt'],
['.../uv', 'sync'],
['.../pip', 'install', '--no-deps', '-e', '.'],
],
)
26 changes: 6 additions & 20 deletions manageprojects/tests/test_readme_history.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
import os
from unittest import TestCase, skipIf

from bx_py_utils.auto_doc import assert_readme_block
from cli_base.cli_tools.git_history import get_git_history

import manageprojects
from manageprojects.cli_dev import PACKAGE_ROOT
from cli_base.cli_tools.constants import GITHUB_ACTION
from cli_base.cli_tools.git_history import update_readme_history


class ReadmeHistoryTestCase(TestCase):
@skipIf(
# After a release the history may be "changed" because of version bump
# and we should not block merge requests because of this.
'GITHUB_ACTION' in os.environ,
# After a release the history may be "changed" because of version bump.
# We should not block merge requests because of this.
GITHUB_ACTION,
reason='Skip on github actions',
)
def test_readme_history(self):
git_history = get_git_history(
current_version=manageprojects.__version__,
add_author=False,
)
history = '\n'.join(git_history)
assert_readme_block(
readme_path=PACKAGE_ROOT / 'README.md',
text_block=f'\n{history}\n',
start_marker_line='[comment]: <> (✂✂✂ auto generated history start ✂✂✂)',
end_marker_line='[comment]: <> (✂✂✂ auto generated history end ✂✂✂)',
)
update_readme_history(raise_update_error=True)
43 changes: 16 additions & 27 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ dependencies = [
"rich-click", # https://github.com/ewels/rich-click
"rich", # https://github.com/Textualize/rich
]
[project.optional-dependencies]

[dependency-groups]
dev = [
"python-gnupg", # https://github.com/vsajip/python-gnupg
"bx_py_utils", # https://github.com/boxine/bx_py_utils
"urllib3", # for deny_requests.deny_any_real_request() in tests
"pip-tools", # https://github.com/jazzband/pip-tools/
"uv", # https://github.com/astral-sh/uv
"tox", # https://github.com/tox-dev/tox
"tox-uv", # https://github.com/tox-dev/tox-uv
"coverage", # https://github.com/nedbat/coveragepy
"autopep8", # https://github.com/hhatto/autopep8
"pyupgrade", # https://github.com/asottile/pyupgrade
Expand All @@ -67,15 +69,6 @@ dev = [
'backports.tarfile', # via jaraco-context -> keyring -> twine
]

[tool.pip-tools.compile]
index-url="https://pypi.org/simple"
extra-index-url=["https://www.piwheels.org/simple"] # Add hashes of piwheels packages, too!
generate-hashes = true
# https://pip-tools.readthedocs.io/en/stable/#deprecations
allow-unsafe = true
resolver="backtracking"
strip-extras = true

[project.urls]
Documentation = "https://github.com/jedie/manageprojects"
Source = "https://github.com/jedie/manageprojects"
Expand Down Expand Up @@ -163,21 +156,16 @@ exclude_lines = [


[tool.tox] # https://tox.wiki/en/latest/config.html#pyproject-toml
legacy_tox_ini = """
[tox]
isolated_build = True
envlist = py{313,312,311}
skip_missing_interpreters = True
[testenv]
passenv = *
skip_install = true
commands_pre =
pip install -U pip-tools
pip-sync requirements.dev.txt
commands =
python3 -m coverage run --context='{envname}'
"""
isolated_build = true
env_list = ["3.13", "3.12", "3.11"]
skip_missing_interpreters = true

[tool.tox.testenv]
runner = "uv-venv-lock-runner"
with_dev = true
commands = [
["python3", "-m", "coverage", "run", "--context='{envname}'"]
]


[tool.mypy]
Expand All @@ -193,7 +181,7 @@ exclude = ['.venv', 'tests']
initial_revision = "8438598"
initial_date = 2022-11-20T20:01:37+01:00
cookiecutter_template = "https://github.com/jedie/cookiecutter_templates"
cookiecutter_directory = "piptools-python"
cookiecutter_directory = "uv-python"
applied_migrations = [
"cf44769", # 2023-01-11T08:15:06+01:00
"cd164cd", # 2023-02-18T11:55:57+01:00
Expand All @@ -214,6 +202,7 @@ applied_migrations = [
"f8be3e0", # 2024-07-16T19:35:26+02:00
"2cdc1d8", # 2024-08-25T19:00:41+02:00
"56c3caa", # 2024-09-22T16:52:30+02:00
"ff48b81", # 2024-11-09T19:08:01+01:00
]

[manageprojects.cookiecutter_context.cookiecutter]
Expand Down
Loading

0 comments on commit f5aa38e

Please sign in to comment.