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

[uv] pip compile: dependencies in pyproject.toml, lockfile mechanism #711

Merged
merged 13 commits into from
Apr 13, 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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
requirements.*.txt linguist-generated=true
27 changes: 20 additions & 7 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,27 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- name: print information about pip cache
run: pip cache info && pip cache list
- name: ensure presence of `wheel`
run: pip install wheel
- name: install pip dependencies
run: pip install -r requirements.txt -r requirements.dev.txt
# cache: 'pip'
- name: set up `uv`
run: pip install uv && uv pip list
- name: restore uv cache
uses: actions/cache/restore@v4
id: cache-uv-restore
with:
path: ~/.cache/uv
key: uv
- name: install pip dependencies with uv
run: >
uv pip sync --system requirements.dev.txt
&& uv pip install --system . deps/wtforms-widgets
&& uv pip list --system
id: pip-install
- name: save uv cache
uses: actions/cache/save@v4
id: cache-uv-save
with:
path: ~/.cache/uv
key: uv
# now come the tests
- name: Execute ruff
run: ruff check --output-format=github .
Expand Down
15 changes: 15 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ repos:
rev: 'v0.3.2'
hooks:
- id: ruff
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.1.29
hooks:
- id: pip-compile
name: "pip-compile: requirements.txt"
args: [pyproject.toml, --generate-hashes, --quiet, -o, requirements.txt]
files: ^(pyproject.toml|requirements.txt)$
- id: pip-compile
name: "pip-compile: requirements.dev.txt"
args: [pyproject.toml, --generate-hashes, --extra, dev, --quiet, -o, requirements.dev.txt]
files: ^(pyproject.toml|requirements.dev.txt)$
- id: pip-compile
name: "pip-compile: requirements.prod.txt"
args: [pyproject.toml, --generate-hashes, --extra, prod, --quiet, -o, requirements.prod.txt]
files: ^(pyproject.toml|requirements.prod.txt)$
- repo: https://github.com/returntocorp/semgrep
rev: 'v1.31.2'
hooks:
Expand Down
2 changes: 1 addition & 1 deletion doc/guides/git.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ environment) with:

::

docker compose run --rm dev-app pip install -r requirements.txt
docker compose run --rm dev-app pip sync requirements.txt

The production build also uses the submodules. Make sure to update the
commit hash of the submodule HEAD if you change something. This will be
Expand Down
9 changes: 3 additions & 6 deletions doc/guides/setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ Using a python virtual environment (venv)
-----------------------------------------

Prerequisites
* `virtualenvwrapper <https://virtualenvwrapper.readthedocs.io/en/latest/>`_
(`arch:python-virtualenvwrapper <https://archlinux.org/packages/?name=python-virtualenvwrapper>`_,
`debian:virtualenvwrapper <https://packages.debian.org/bullseye/virtualenvwrapper>`_)
* installed `uv <https://github.com/astral-sh/uv>`_

If you only want to build the documentation or run tests,
you only need to do the following:
Expand All @@ -42,8 +40,7 @@ you only need to do the following:
#. Set up a virtual environment

.. code:: shell

mkvirtualenv -a . -r requirements.txt -r requirements.dev.txt pycroft
pip install -r requirements.txt -r requirements.dev.txt
uv venv
uv pip sync requirements.dev.txt && uv pip install -e deps/wtforms-widgets -e '.[dev]'

#. Run tests / Build docs / …
2 changes: 1 addition & 1 deletion doc/guides/troubleshooting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Reinstall the pip requirements

.. code:: sh

drc run --rm dev-app pip install -r requirements.txt
drc run --rm dev-app pip sync requirements.txt

I need to downgrade the schema
------------------------------
Expand Down
11 changes: 8 additions & 3 deletions docker/base.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ ENV LANG=C.UTF-8 DEBIAN_FRONTEND=noninteractive
COPY etc/apt /etc/apt

# Install Debian packages
RUN apt-get update && apt-get install -y --no-install-recommends \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get install -y --no-install-recommends \
bash \
libpq5 \
&& apt-get clean
Expand All @@ -25,8 +27,11 @@ WORKDIR /opt/pycroft
# - Create a virtual environment
# - Upgrade pip, setuptools and wheel
# - Create app directory
RUN python3 -m venv /opt/pycroft/venv \
&& /opt/pycroft/venv/bin/pip install -U pip setuptools wheel \
ENV VIRTUAL_ENV=/opt/pycroft/venv
RUN --mount=type=cache,target=/opt/pycroft/.cache,uid=$UID,gid=$GID\
python3 -m venv /opt/pycroft/venv \
&& /opt/pycroft/venv/bin/pip install -U uv \
&& /opt/pycroft/venv/bin/uv pip install -U setuptools wheel \
&& mkdir /opt/pycroft/app /opt/pycroft/wheel

COPY --link . /
Expand Down
4 changes: 3 additions & 1 deletion docker/dev.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ COPY etc/apt /etc/apt

# Install Debian packages
# Build-essential is needed For compiling things in pip
RUN apt-get update \
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update \
&& apt-get install -y --no-install-recommends \
bash \
bash-completion \
Expand Down
4 changes: 2 additions & 2 deletions docker/dev/container/commands/pip
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ set -euo pipefail
readonly USAGE=("<command> [options]")

readonly DESCRIPTION=(
"Run the pip of the virtual environment in the project root directory."
"Run `uv pip` of the virtual environment in the project root directory."
)

run() {
cd /opt/pycroft/app
/opt/pycroft/venv/bin/pip "$@"
/opt/pycroft/venv/bin/uv pip "$@"
}

[[ "$0" == "$BASH_SOURCE" ]] && run "$@" || :
14 changes: 8 additions & 6 deletions docker/dev/container/hooks/init/10_venv
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ LOCKDIR=/opt/pycroft/venv
. /container/common/locking.sh

function execute_hook() {
PIP="/opt/pycroft/venv/bin/pip"
set -x
PIP="/opt/pycroft/venv/bin/uv pip"
UV="/opt/pycroft/venv/bin/uv"
PY="/opt/pycroft/venv/bin/python"

if [[ ! -f /opt/pycroft/venv/bin/activate ]]; then
Expand All @@ -20,15 +22,15 @@ function execute_hook() {
fi

$PY -m ensurepip
$PY -m pip install uv
$PIP install wheel

echo "No pip packages found, installing requirements"
cd /opt/pycroft/app
$PIP install --upgrade pip
$PIP cache info
$PIP cache list
$PIP install -r requirements.txt -r requirements.dev.txt
$PIP install -e .
$PIP install --upgrade uv
ls `$UV cache dir`
$PIP sync requirements.dev.txt
$PIP install -e '.[dev]' 'wtforms-widgets @ ./deps/wtforms-widgets'
}

[[ -d $LOCKDIR ]] || mkdir $LOCKDIR
Expand Down
4 changes: 3 additions & 1 deletion docker/prod.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ WORKDIR /opt/pycroft/app
# Download or build wheels of requirements
COPY --chown=pycroft:pycroft requirements.txt .
COPY --chown=pycroft:pycroft ./deps ./deps
RUN /opt/pycroft/venv/bin/pip wheel --wheel-dir /opt/pycroft/wheel -r requirements.txt
RUN /opt/pycroft/venv/bin/pip wheel --wheel-dir /opt/pycroft/wheel -r requirements.txt \
&& rm /opt/pycroft/wheel/wtforms_widgets*.whl \
&& /opt/pycroft/venv/bin/pip wheel --wheel-dir /opt/pycroft/wheel --no-deps ./deps/wtforms-widgets

# Download JS/CSS dependencies
COPY --chown=pycroft:pycroft package.json package-lock.json ./
Expand Down
102 changes: 102 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,108 @@ requires = [
]
build-backend = "setuptools.build_meta"

# PROJECT METADATA
[project]
name = "pycroft"
version = "0.1.0"
authors = [{name = "The Pycroft Authors"}]
license = {text = "Apache Software License"}
description = "AG DSN user management software"
readme = "README.md"
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Web Environment",
"Framework :: Flask",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.11",
"Topic :: Internet",
]
urls = {Homepage = "http://github.com/agdsn/pycroft/"}
requires-python = ">= 3.11"
dependencies = [
"alembic ~= 1.9.2",
"babel >= 2.12.1",
"blinker ~= 1.4",
"celery ~= 5.2.1",
"Click ~= 8.0",
"email-validator ~= 1.1.1",
"fints ~= 3.1.0",
"Flask ~= 2.3.2",
"Flask-Babel ~= 3.1.0",
"Flask-Login ~= 0.6.2",
"Flask-RESTful ~= 0.3.7",
"Flask-WTF ~= 1.1.1",
"GitPython ~= 2.1.7",
"ipaddr ~= 2.2.0",
"Jinja2 ~= 3.0",
"jsonschema ~= 3.2.0",
"ldap3 ~= 2.5.1", # only needed for ldap caching
"mac-vendor-lookup ~= 0.1.11",
"MarkupSafe ~= 2.0",
"marshmallow ~= 3.20.1",
"mt-940 ~= 4.19.0",
"passlib ~= 1.7.1",
"pillow ~= 8.4.0", # usersheet generation
"psycopg2-binary ~= 2.9.4",
"pydantic ~= 2.0.0",
"python-dotenv ~= 0.21.0",
"reportlab ~= 3.6.2",
"sentry-sdk[Flask] ~= 1.29.2",
"simplejson ~= 3.11.1", # decimal serialization
"SQLAlchemy >= 2.0.1",
"webargs ~= 8.3.0",
"Werkzeug ~= 2.3.6",
"wrapt ~= 1.14.1",
"WTForms ~= 2.3.3",
"wtforms-widgets", # note: use `pip install -e deps/wtforms-widgets` for development
]

[project.optional-dependencies]
prod = [
"uwsgi ~= 2.0.21",
"uwsgitop ~= 0.11",
]
schemadisplay = [
"sqlalchemy-schemadisplay @ git+https://github.com/lukasjuhrich/sqlalchemy_schemadisplay.git@master",
]
dev = [
"celery-types ~= 0.9.3",
"coverage ~= 6.5.0",
"factory-boy ~= 3.2.0",
"Flask-Testing ~= 0.8.1",
"guzzle-sphinx-theme @ git+https://github.com/agdsn/guzzle_sphinx_theme.git@977d49fcbdf2b3df9660d813d4b33369391923e1",
"mypy ~= 1.8.0",
"pydot ~= 1.4.1",
"pyinstrument ~= 4.2.0",
"pytest ~= 7.0.0",
"pytest-cov ~= 4.0.0",
"pytest-timeout ~= 2.1.0",
# required for pycharm „run with coverage“ reporting
"ruff ~= 0.3.2",
"sphinx ~= 5.1.1",
"sphinx-autobuild ~= 2021.3.14",
"sphinxcontrib-fulltoc ~= 1.2.0",
"sphinxcontrib-httpdomain ~= 1.8.0",
"sphinx-paramlinks ~= 0.6.0",
"types-jsonschema ~= 4.3.0",
"types-passlib ~= 1.7.7",
"watchdog ~= 2.3.1",
]

[project.scripts]
pycroft = "scripts.server_run:main"
pycroft_ldap_sync = "ldap_sync.__main__:main"
alembic_wrapper = "scripts.alembic_wrapper:cli"

[tool.setuptools]
include-package-data = true

[tool.setuptools.packages]
find = {namespaces = false}

# TOOLS
[tool.black]
line-length = 100

Expand Down
Loading
Loading