chore: unify packaging around uv

This commit is contained in:
Hadrian Burkhardt
2026-04-30 23:59:56 +00:00
parent b0fc264cb2
commit bfe72b4f77
17 changed files with 43 additions and 1310 deletions
+3
View File
@@ -9,6 +9,9 @@ jobs:
- image: cimg/python:3.13 - image: cimg/python:3.13
steps: steps:
- checkout - checkout
- run:
name: Install uv
command: python -m pip install uv
- run: - run:
name: Install Dependencies name: Install Dependencies
command: make dependencies command: make dependencies
+2
View File
@@ -3,8 +3,10 @@
.pytest_cache .pytest_cache
/.coverage /.coverage
/htmlcov /htmlcov
*.egg-info/
*.pyc *.pyc
.venv .venv
__pycache__ __pycache__
.devcontainer .devcontainer
.vscode .vscode
.codex
+7 -6
View File
@@ -9,7 +9,7 @@ ARG DEPLOY_DIR
ARG USERNAME ARG USERNAME
# Install dependencies # Install dependencies
RUN pip install pipenv RUN pip install --no-cache-dir uv
# Add app user # Add app user
RUN adduser --disabled-password ${USERNAME} RUN adduser --disabled-password ${USERNAME}
@@ -27,8 +27,9 @@ WORKDIR ${DEPLOY_DIR}
COPY stw_potsdam/ ./stw_potsdam COPY stw_potsdam/ ./stw_potsdam
COPY tests ./tests COPY tests ./tests
COPY Makefile . COPY Makefile .
COPY Pipfile . COPY README.md .
COPY Pipfile.lock . COPY pyproject.toml .
COPY uv.lock .
# Apply app user to app folder # Apply app user to app folder
RUN chown -R ${USERNAME} . RUN chown -R ${USERNAME} .
@@ -48,7 +49,7 @@ RUN apt-get update && apt-get install -y build-essential python3-dev
# Install environment # Install environment
USER ${USERNAME} USER ${USERNAME}
RUN pipenv install --dev RUN uv sync --frozen --extra dev
# Run tests # Run tests
RUN make test RUN make test
@@ -58,7 +59,7 @@ RUN rm -rf .venv
RUN rm -rf ./tests ./Makefile RUN rm -rf ./tests ./Makefile
# Install production environment # Install production environment
RUN pipenv install --deploy RUN uv sync --frozen --no-dev
### Production container ### Production container
@@ -82,6 +83,6 @@ ENV LISTEN_PORT=${LISTEN_PORT}
ENV LISTEN=0.0.0.0:${LISTEN_PORT} ENV LISTEN=0.0.0.0:${LISTEN_PORT}
EXPOSE ${LISTEN_PORT} EXPOSE ${LISTEN_PORT}
CMD ["pipenv", "run", "uwsgi", "--master", "--http11-socket", "$LISTEN", "--plugins", "python", "--protocol", "uwsgi", "--wsgi", "stw_potsdam.views:app", "--virtualenv", "./.venv"] CMD ["sh", "-c", "uv run uwsgi --master --http11-socket \"$LISTEN\" --plugins python --protocol uwsgi --wsgi stw_potsdam.views:app --virtualenv ./.venv"]
HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://127.0.0.1:$LISTEN_PORT/health_check || exit 1 HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://127.0.0.1:$LISTEN_PORT/health_check || exit 1
+11 -12
View File
@@ -1,34 +1,33 @@
RUN=uv run flask --app stw_potsdam.views run
RUN=FLASK_APP="stw_potsdam.views" pipenv run flask run
dependencies: dependencies:
pipenv sync --dev uv sync --extra dev
run: run:
$(RUN) $(RUN)
debug: debug:
FLASK_ENV=development $(RUN) --debug uv run flask --app stw_potsdam.views --debug run
test: test:
pipenv run python -m pytest -vv --cov-branch --cov stw_potsdam --cov-report term --cov-report html uv run --extra dev python -m pytest -vv --cov-branch --cov stw_potsdam --cov-report term --cov-report html
test_debug: test_debug:
pipenv run python -m pytest -v --trace uv run --extra dev python -m pytest -v --trace
coverage_publish: coverage_publish:
pipenv run python -m coveralls uv run --extra dev python -m coveralls
coverage_report: coverage_report:
pipenv run python -m coverage report --fail-under 90 uv run --extra dev python -m coverage report --fail-under 90
lint: lint:
pipenv run pycodestyle stw_potsdam tests uv run --extra dev pycodestyle stw_potsdam tests
pipenv run pydocstyle stw_potsdam tests uv run --extra dev pydocstyle stw_potsdam tests
pipenv run pylint stw_potsdam tests uv run --extra dev pylint stw_potsdam tests
clean: clean:
pipenv run python -m coverage erase uv run --extra dev python -m coverage erase
rm -rf .pytest_cache .cache rm -rf .pytest_cache .cache
.PHONY: dependencies run debug test test_debug coverage_publish coverage_report lint clean .PHONY: dependencies run debug test test_debug coverage_publish coverage_report lint clean
-21
View File
@@ -1,21 +0,0 @@
[packages]
requests = "*"
pyopenmensa = "*"
flask = "*"
cachetools = "*"
uwsgi = "*"
[dev-packages]
pytest = "*"
coveralls = "*"
pytest-cov = "*"
httpretty = "*"
pycodestyle = "*"
pydocstyle = "*"
pylint = "*"
sphinx = "*"
sphinx-autobuild = "*"
sphinx-rtd-theme = "*"
[requires]
python_version = "3.13"
Generated
-1073
View File
File diff suppressed because it is too large Load Diff
+1 -6
View File
@@ -25,14 +25,9 @@ Recommended: Python 3.12+.
$ python -m venv .venv $ python -m venv .venv
$ . .venv/bin/activate $ . .venv/bin/activate
$ pip install -r requirements-dev.txt $ pip install -e ".[dev]"
$ FLASK_APP=stw_potsdam.views flask run $ FLASK_APP=stw_potsdam.views flask run
**Legacy (Pipenv)** ::
$ pipenv install --dev
$ make run
**Contributions** are always welcome, in particular if the response format of the canteens change. Feel free to file a PR with improvements. **Contributions** are always welcome, in particular if the response format of the canteens change. Feel free to file a PR with improvements.
**Deployment** If in need of a deployment, file a PR to this fork: [kaifabian/om-parser-potsdam-v2][kai]. Kai is currently in charge of running an instance of the parser and the registration on the OpenMensa platform. **Deployment** If in need of a deployment, file a PR to this fork: [kaifabian/om-parser-potsdam-v2][kai]. Kai is currently in charge of running an instance of the parser and the registration on the OpenMensa platform.
+8 -10
View File
@@ -6,9 +6,9 @@ Because the parser may break on changes to the canteen website, it should be eas
Quickstart Quickstart
~~~~~~~~~~ ~~~~~~~~~~
Use `Pipenv <https://pipenv.readthedocs.io/en/latest/>`_ to setup the environment and start coding: :: Use `uv <https://docs.astral.sh/uv/>`_ to setup the environment and start coding: ::
$ pipenv install --dev # Create venv $ uv sync --extra dev # Create venv and install dependencies
$ make test # Check setup by running tests $ make test # Check setup by running tests
$ make debug # Start app instance with debugger and pretty printing of JSON $ make debug # Start app instance with debugger and pretty printing of JSON
$ make run # Start app without debugger $ make run # Start app without debugger
@@ -17,7 +17,7 @@ Use `Pipenv <https://pipenv.readthedocs.io/en/latest/>`_ to setup the environmen
The list of available canteens is available at the ``/canteens`` endpoint. The ``/canteens/<name>`` endpoint provides the XML feed for individual canteens, e.g., ``/canteens/griebnitzsee``. The list of available canteens is available at the ``/canteens`` endpoint. The ``/canteens/<name>`` endpoint provides the XML feed for individual canteens, e.g., ``/canteens/griebnitzsee``.
Given the default configuration, http://127.0.0.1:5000/canteens/griebnitzsee will display the `OpenMensa` meta-feed for the Griebnitzsee canteen, and http://127.0.0.1:5000/canteens/griebnitzsee/menu will render the menu feed. Given the default configuration, http://127.0.0.1:5000/canteens/griebnitzsee will display the `OpenMensa` feed for the Griebnitzsee canteen.
Main Module Entry Points Main Module Entry Points
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -29,16 +29,15 @@ Generating a new `OpenMensa` feed starts by reading the configured canteens. Som
.. autoclass:: stw_potsdam.config.Canteen .. autoclass:: stw_potsdam.config.Canteen
Use the canteen data to assemble the menu parameters in order to download the menu JSON. The menu parameters are also used as cache key: it should uniquely identify the retrieved menu. Use the canteen data to select matching upstream outlets, download the required menu JSON, and render the OpenMensa XML.
.. autoclass:: stw_potsdam.canteen_api.MenuParams .. autoclass:: stw_potsdam.swp_webspeiseplan_api.SWPWebspeiseplanAPI
.. autofunction:: stw_potsdam.canteen_api.download_menu .. autoclass:: stw_potsdam.swp_webspeiseplan_parser.SWPWebspeiseplanParser
The render module contains methods for converting the JSON response into valid `OpenMensa` menu and meta feeds, respectively: The XML type modules contain the OpenMensa rendering objects:
.. autofunction:: stw_potsdam.feed.render_menu .. autoclass:: stw_potsdam.xml_types.builder.Builder
.. autofunction:: stw_potsdam.feed.render_meta
Tests Tests
~~~~~ ~~~~~
@@ -58,4 +57,3 @@ The first invocation runs tests whose outcome can solely be determined by the te
Setting the environment variable ``ENABLE_API_QUERY`` enables tests which require querying the canteen API. Because third-party services are queried, those are more suited to manual execution. Developers can quickly check if their change is applicable to today's menu. Setting the environment variable ``ENABLE_API_QUERY`` enables tests which require querying the canteen API. Because third-party services are queried, those are more suited to manual execution. Developers can quickly check if their change is applicable to today's menu.
@@ -1,74 +0,0 @@
Metadata-Version: 2.4
Name: om-parser-stw-potsdam-v2
Version: 2.0.1
Summary: OpenMensa parser components for Studentenwerk Potsdam.
Requires-Python: >=3.12
Description-Content-Type: text/markdown
Requires-Dist: requests
Requires-Dist: pyopenmensa
Requires-Dist: flask
Requires-Dist: cachetools
Requires-Dist: uwsgi
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: coveralls; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: httpretty; extra == "dev"
Requires-Dist: pycodestyle; extra == "dev"
Requires-Dist: pydocstyle; extra == "dev"
Requires-Dist: pylint; extra == "dev"
Requires-Dist: sphinx; extra == "dev"
Requires-Dist: sphinx-autobuild; extra == "dev"
Requires-Dist: sphinx-rtd-theme; extra == "dev"
# OpenMensa Parser STW Potsdam
[![CircleCI](https://dl.circleci.com/status-badge/img/gh/f4lco/om-parser-stw-potsdam-v2/tree/master.svg?style=shield)](https://dl.circleci.com/status-badge/redirect/gh/f4lco/om-parser-stw-potsdam-v2/tree/master)
[![Coverage Status](https://coveralls.io/repos/github/f4lco/om-parser-stw-potsdam-v2/badge.svg?branch=master)](https://coveralls.io/github/f4lco/om-parser-stw-potsdam-v2?branch=master)
[![Read the Docs](https://readthedocs.org/projects/om-parser-stw-potsdam-v2/badge/?version=latest&style=flat)](https://om-parser-stw-potsdam-v2.readthedocs.io/en/latest/)
[OpenMensa][om] parser components query canteen websites for menus and transform them into OpenMensa's data format.
This project came to life after the website of the canteens of the Studentenwerk Potsdam changed, and is therefore the successor to [kaifabian/om-parser-potsdam][prev-parser] (hence the "-v2").
Among others, OpenMensa powers the popular [Mensa Uni Potsdam][steppschuh] Android app.
The current application is built with [Python][py], [PyOpenMensa][pom], and [Flask][flask]. Learn more about the technical details at [Read the Docs][rtd].
## Local development (modern)
Recommended: Python 3.12+.
**Option A (uv, recommended)** ::
$ uv venv
$ uv pip install -e ".[dev]"
$ uv run flask --app stw_potsdam.views run
**Option B (venv + pip)** ::
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install -r requirements-dev.txt
$ FLASK_APP=stw_potsdam.views flask run
**Legacy (Pipenv)** ::
$ pipenv install --dev
$ make run
**Contributions** are always welcome, in particular if the response format of the canteens change. Feel free to file a PR with improvements.
**Deployment** If in need of a deployment, file a PR to this fork: [kaifabian/om-parser-potsdam-v2][kai]. Kai is currently in charge of running an instance of the parser and the registration on the OpenMensa platform.
**Where to go next** maybe use this parser or the OpenMensa API to source a new dataset for training a predictor for your favorite lunch?
**License** Just assume this project is licensed in terms of [WTFPL](http://www.wtfpl.net/) ;)
[om]: https://openmensa.org
[prev-parser]: https://github.com/kaifabian/om-parser-potsdam
[rtd]: https://om-parser-stw-potsdam-v2.readthedocs.io/en/latest/
[steppschuh]: https://steppschuh.net/blog/?p=951
[py]: http://python.org
[pom]: https://github.com/mswart/pyopenmensa
[flask]: https://palletsprojects.com/p/flask/
[kai]: https://github.com/kaifabian/om-parser-stw-potsdam-v2
@@ -1,22 +0,0 @@
README.md
pyproject.toml
om_parser_stw_potsdam_v2.egg-info/PKG-INFO
om_parser_stw_potsdam_v2.egg-info/SOURCES.txt
om_parser_stw_potsdam_v2.egg-info/dependency_links.txt
om_parser_stw_potsdam_v2.egg-info/requires.txt
om_parser_stw_potsdam_v2.egg-info/top_level.txt
stw_potsdam/__init__.py
stw_potsdam/config.py
stw_potsdam/swp_webspeiseplan_api.py
stw_potsdam/swp_webspeiseplan_parser.py
stw_potsdam/views.py
stw_potsdam/xml_types/__init__.py
stw_potsdam/xml_types/builder.py
stw_potsdam/xml_types/canteen_xml.py
stw_potsdam/xml_types/feed_xml.py
stw_potsdam/xml_types/meal_xml.py
stw_potsdam/xml_types/openmensa_xml.py
stw_potsdam/xml_types/times_xml.py
tests/test_consistency.py
tests/test_retrieval.py
tests/test_views.py
@@ -1 +0,0 @@
@@ -1,17 +0,0 @@
requests
pyopenmensa
flask
cachetools
uwsgi
[dev]
pytest
coveralls
pytest-cov
httpretty
pycodestyle
pydocstyle
pylint
sphinx
sphinx-autobuild
sphinx-rtd-theme
@@ -1 +0,0 @@
stw_potsdam
+10
View File
@@ -1,3 +1,7 @@
[build-system]
requires = ["setuptools>=69"]
build-backend = "setuptools.build_meta"
[project] [project]
name = "om-parser-stw-potsdam-v2" name = "om-parser-stw-potsdam-v2"
version = "2.0.1" version = "2.0.1"
@@ -26,3 +30,9 @@ dev = [
"sphinx-autobuild", "sphinx-autobuild",
"sphinx-rtd-theme", "sphinx-rtd-theme",
] ]
[tool.setuptools.packages.find]
include = ["stw_potsdam*"]
[tool.setuptools.package-data]
stw_potsdam = ["canteens.ini"]
-51
View File
@@ -1,51 +0,0 @@
-r requirements.txt
alabaster==1.0.0; python_version >= '3.10'
anyio==4.6.2.post1; python_version >= '3.9'
astroid==3.3.5; python_full_version >= '3.9.0'
babel==2.16.0; python_version >= '3.8'
certifi==2024.8.30; python_version >= '3.6'
charset-normalizer==3.4.0; python_full_version >= '3.7.0'
click==8.1.7; python_version >= '3.7'
colorama==0.4.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'
coverage[toml]==6.5.0; python_version >= '3.7'
coveralls==3.3.1; python_version >= '3.5'
dill==0.3.9; python_version >= '3.8'
docopt==0.6.2
docutils==0.21.2; python_version >= '3.9'
h11==0.14.0; python_version >= '3.7'
httpretty==1.1.4; python_version >= '3'
idna==3.10; python_version >= '3.6'
imagesize==1.4.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
iniconfig==2.0.0; python_version >= '3.7'
isort==5.13.2; python_full_version >= '3.8.0'
jinja2==3.1.4; python_version >= '3.7'
markupsafe==3.0.2; python_version >= '3.9'
mccabe==0.7.0; python_version >= '3.6'
packaging==24.2; python_version >= '3.8'
platformdirs==4.3.6; python_version >= '3.8'
pluggy==1.5.0; python_version >= '3.8'
pycodestyle==2.12.1; python_version >= '3.8'
pydocstyle==6.3.0; python_version >= '3.6'
pygments==2.18.0; python_version >= '3.8'
pylint==3.3.1; python_full_version >= '3.9.0'
pytest-cov==5.0.0; python_version >= '3.8'
pytest==8.3.3; python_version >= '3.8'
requests==2.32.3; python_version >= '3.8'
sniffio==1.3.1; python_version >= '3.7'
snowballstemmer==2.2.0
sphinx-autobuild==2024.10.3; python_version >= '3.9'
sphinx-rtd-theme==3.0.2; python_version >= '3.8'
sphinx==8.1.3; python_version >= '3.10'
sphinxcontrib-applehelp==2.0.0; python_version >= '3.9'
sphinxcontrib-devhelp==2.0.0; python_version >= '3.9'
sphinxcontrib-htmlhelp==2.1.0; python_version >= '3.9'
sphinxcontrib-jquery==4.1; python_version >= '2.7'
sphinxcontrib-jsmath==1.0.1; python_version >= '3.5'
sphinxcontrib-qthelp==2.0.0; python_version >= '3.9'
sphinxcontrib-serializinghtml==2.0.0; python_version >= '3.9'
starlette==0.41.2; python_version >= '3.8'
tomlkit==0.13.2; python_version >= '3.8'
urllib3==2.2.3; python_version >= '3.8'
uvicorn==0.32.0; python_version >= '3.8'
watchfiles==0.24.0; python_version >= '3.8'
websockets==14.1; python_version >= '3.9'
-15
View File
@@ -1,15 +0,0 @@
blinker==1.9.0; python_version >= '3.9'
cachetools==5.5.0; python_version >= '3.7'
certifi==2024.8.30; python_version >= '3.6'
charset-normalizer==3.4.0; python_full_version >= '3.7.0'
click==8.1.7; python_version >= '3.7'
flask==3.1.0; python_version >= '3.9'
idna==3.10; python_version >= '3.6'
itsdangerous==2.2.0; python_version >= '3.8'
jinja2==3.1.4; python_version >= '3.7'
markupsafe==3.0.2; python_version >= '3.9'
pyopenmensa==0.95.0
requests==2.32.3; python_version >= '3.8'
urllib3==2.2.3; python_version >= '3.8'
uwsgi==2.0.28
werkzeug==3.1.3; python_version >= '3.9'
Generated
+1 -1
View File
@@ -423,7 +423,7 @@ wheels = [
[[package]] [[package]]
name = "om-parser-stw-potsdam-v2" name = "om-parser-stw-potsdam-v2"
version = "2.0.1" version = "2.0.1"
source = { virtual = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "cachetools" }, { name = "cachetools" },
{ name = "flask" }, { name = "flask" },