Skip to content

Commit

Permalink
ENH: use uv pip compile if possible (#22)
Browse files Browse the repository at this point in the history
* ENH: install `uv` in action
* ENH: print when resolving with `pip-tools`
  • Loading branch information
redeboer authored Mar 5, 2024
1 parent d043dcd commit ef3aa0d
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
"codecov",
"commitlint",
"compwa",
"elif",
"prereleased",
"pyproject",
"redeboer",
"venv"
],
Expand Down
24 changes: 23 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,30 @@ runs:
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
- run: pip install git+https://github.com/ComPWA/update-pip-constraints@main

- name: Determine package configuration file
run: |
if [ -f pyproject.toml ]; then
if grep -q "\[project\]" pyproject.toml; then
echo 'SETUP_FILE=pyproject.toml' | tee -a $GITHUB_ENV
fi
elif [ -f setup.cfg ]; then
if grep -q "\[metadata\]" setup.cfg && grep -q "\[options\]" setup.cfg; then
echo 'SETUP_FILE=setup.cfg' | tee -a $GITHUB_ENV
fi
fi
shell: bash

- if: env.SETUP_FILE == 'setup.cfg'
run: |
pip install update-pip-constraints@git+https://github.com/ComPWA/update-pip-constraints@v1
shell: bash
- if: env.SETUP_FILE == 'pyproject.toml'
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
uv pip install --system update-pip-constraints@git+https://github.com/ComPWA/update-pip-constraints@v1
shell: bash

- run: update-pip-constraints
shell: bash
- uses: actions/upload-artifact@v4
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ install_requires =
importlib-metadata; python_version <"3.8.0"
pip-tools >=6.2.0 # strip-extras and extras_require
toml
uv; python_version >="3.8.0"
packages = find:
package_dir =
=src
Expand Down
100 changes: 74 additions & 26 deletions src/update_pip_constraints/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,51 @@
# fmt: off
import warnings # noqa: I001
warnings.filterwarnings("ignore", category=UserWarning)

from setuptools import find_packages # noqa: I001 # import setuptools first!
# fmt: on

import shutil
import os
import sys
from configparser import ConfigParser
from pathlib import Path
from typing import List, Optional

from typing import List, Optional, Sequence
from argparse import ArgumentParser
import toml
from piptools.scripts import compile # type: ignore[import]

if sys.version_info < (3, 8):
from importlib_metadata import version
else:
from importlib.metadata import version


def main() -> None:
python_version = _get_python_version()
def main(argv: Optional[Sequence[str]] = None) -> int:
parser = ArgumentParser(description="Update pip constraints file")
parser.add_argument(
"-p",
"--python-version",
default=_get_python_version(),
help="Python version to use. E.g. 3.9, 3.10, 3.11, etc.",
type=str,
)
args = parser.parse_args(argv)
python_version = args.python_version
output_file = _form_constraint_file_path(python_version)
unsafe_packages = None
if not os.path.exists("setup.cfg"):
unsafe_packages = _get_main_packages()
unsafe_packages.insert(0, "setuptools")
unsafe_packages.insert(0, "pip")
if update_constraints_file(output_file, unsafe_packages):
excludes: List[str] = []
if shutil.which("uv") is None or not __uses_pyproject():
excludes = [
"pip",
"setuptools",
*_get_main_packages(),
]
exit_code = update_constraints_file_py36(output_file, excludes)
else:
excludes = ["setuptools"]
exit_code = update_constraints_file(output_file, python_version, excludes)
if exit_code != 0:
msg = "There were issues running pip-compile"
raise RuntimeError(msg)
return exit_code


def _get_python_version() -> str:
version = sys.version_info
return f"{version.major}.{version.minor}"
v = sys.version_info
return f"{v.major}.{v.minor}"


def _get_main_packages() -> List[str]:
Expand Down Expand Up @@ -86,14 +96,53 @@ def __get_package_directory() -> str:
return "."


def __uses_pyproject() -> bool:
with open("pyproject.toml") as f:
pyproject = toml.load(f) # type: ignore[arg-type]
return pyproject.get("project", {}).get("name", None) is not None


def _form_constraint_file_path(python_version: str) -> Path:
constraints_dir = Path(".constraints")
return constraints_dir / f"py{python_version}.txt"


def update_constraints_file(
output_file: Path, unsafe_packages: Optional[List[str]] = None
output_file: Path, python_version: str, unsafe_packages: List[str]
) -> int:
import subprocess # noqa: PLC0415, S404

if not __uses_pyproject():
msg = "Package has to be configured with pyproject.toml"
raise ValueError(msg)
output_file.parent.mkdir(exist_ok=True)
command_arguments = [
"uv",
"pip",
"compile",
"pyproject.toml",
"-o",
str(output_file),
"--all-extras",
"--no-annotate",
f"--python-version={python_version}",
"--upgrade",
]
for package in unsafe_packages:
command_arguments.append("--no-emit-package")
command_arguments.append(package)
return subprocess.check_call(command_arguments) # noqa: S603


def update_constraints_file_py36(output_file: Path, unsafe_packages: List[str]) -> int:
from piptools.scripts import compile # type: ignore[import] # noqa: PLC0415

if sys.version_info < (3, 8):
from importlib_metadata import version # noqa: PLC0415
else:
from importlib.metadata import version # noqa: PLC0415

print("Resolving dependencies with pip-tools...") # noqa: T201
output_file.parent.mkdir(exist_ok=True)
command_arguments = [
"-o",
Expand All @@ -107,12 +156,11 @@ def update_constraints_file(
major, minor, *_ = (int(i) for i in version("pip-tools").split("."))
if (major, minor) >= (6, 8):
command_arguments.append("--resolver=backtracking")
if unsafe_packages is not None:
for package in unsafe_packages:
command_arguments.append("--unsafe-package")
command_arguments.append(package)
for package in unsafe_packages:
command_arguments.append("--unsafe-package")
command_arguments.append(package)
return compile.cli(command_arguments) # type: ignore[misc]


if "__main__" in __name__:
main()
if __name__ == "__main__":
raise SystemExit(main())
6 changes: 3 additions & 3 deletions tests/test_update_pip_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from update_pip_constraints import (
_form_constraint_file_path, # pyright: ignore[reportPrivateUsage]
_get_python_version, # pyright: ignore[reportPrivateUsage]
update_constraints_file,
update_constraints_file_py36,
)


Expand All @@ -22,13 +22,13 @@ def test_get_python_version():


@pytest.mark.slow()
def test_update_constraints_file():
def test_update_constraints_file_py36():
if "CI" in os.environ:
pytest.skip()
this_directory = Path(__file__).parent.absolute()
output_file = this_directory / "constraints.txt"
with pytest.raises(SystemExit) as error:
update_constraints_file(output_file)
update_constraints_file_py36(output_file, unsafe_packages=[])
assert error.type is SystemExit
assert error.value.code == 0
with open(output_file) as stream:
Expand Down

0 comments on commit ef3aa0d

Please sign in to comment.