Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: use uv pip compile if possible #22

Merged
merged 7 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading