Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • hub/hub
  • cyroxx/hub
  • myigel/hub
  • thomasdotwtf/hub
4 results
Select Git revision
Show changes
Commits on Source (244)
...@@ -10,3 +10,9 @@ src/hub/.settings.secret ...@@ -10,3 +10,9 @@ src/hub/.settings.secret
# local media files # local media files
src/media/ src/media/
.tools/
.vscode/
.venv*/
**/*_cache
...@@ -13,5 +13,5 @@ trim_trailing_whitespace = true ...@@ -13,5 +13,5 @@ trim_trailing_whitespace = true
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[*.py] [*.py, *.toml]
indent_size = 4 indent_size = 4
...@@ -83,15 +83,6 @@ db.sqlite3-journal ...@@ -83,15 +83,6 @@ db.sqlite3-journal
profile_default/ profile_default/
ipython_config.py ipython_config.py
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
.pdm-python
# Environments # Environments
.env .env
.venv .venv
......
...@@ -29,10 +29,14 @@ workflow: ...@@ -29,10 +29,14 @@ workflow:
# Use build cache to speed up CI # Use build cache to speed up CI
default: default:
cache: cache:
- key:
files:
- uv.lock
paths:
- $UV_CACHE_DIR
- key: "python-default" - key: "python-default"
paths: paths:
- .cache/pip - .cache/pip
- .cache/pdm
- key: - key:
files: files:
- src/plainui/yarn.lock - src/plainui/yarn.lock
...@@ -68,6 +72,7 @@ default: ...@@ -68,6 +72,7 @@ default:
POSTGRES_USER: ci POSTGRES_USER: ci
SSO_SECRET_GENERATE: "True" SSO_SECRET_GENERATE: "True"
STORAGE_TYPE: local STORAGE_TYPE: local
UV_CACHE_DIR: .uv-cache
# Kaniko build setup # Kaniko build setup
.build: .build:
...@@ -111,6 +116,8 @@ default: ...@@ -111,6 +116,8 @@ default:
"ci": true "ci": true
} }
EOF EOF
after_script:
- uv cache prune --ci
# Crane setup # Crane setup
.crane: .crane:
...@@ -122,29 +129,32 @@ default: ...@@ -122,29 +129,32 @@ default:
before_script: before_script:
- '[ -n "$DOCKER_CONFIG" ] || export DOCKER_CONFIG=$HOME/.docker' - '[ -n "$DOCKER_CONFIG" ] || export DOCKER_CONFIG=$HOME/.docker'
- crane auth login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - crane auth login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
meta_build: meta_build:
stage: prepare stage: prepare
extends: .build extends: .build
variables: variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" UV_CACHE_DIR: .uv-cache
script: script:
- /kaniko/executor - /kaniko/executor
$KANIKO_ARGS $KANIKO_ARGS
$KANIKO_CACHE_ARGS $KANIKO_CACHE_ARGS
--dockerfile $CI_PROJECT_DIR/Dockerfile --dockerfile $CI_PROJECT_DIR/Dockerfile
--target base --target meta
--destination $CI_REGISTRY_IMAGE/build_image:bi-$CI_PIPELINE_ID --destination $CI_REGISTRY_IMAGE/meta_image:mi-$CI_PIPELINE_ID
rules: rules:
- when: always - when: always
.test: .test:
extends: extends:
- .django_runner_settings - .django_runner_settings
image: $CI_REGISTRY_IMAGE/build_image:bi-$CI_PIPELINE_ID image: $CI_REGISTRY_IMAGE/meta_image:mi-$CI_PIPELINE_ID
variables: variables:
PDM_CACHE_DIR: .cache/pdm UV_CACHE_DIR: .uv-cache
needs: needs:
- meta_build - meta_build
after_script:
- uv cache prune --ci
app_version: app_version:
stage: test stage: test
...@@ -155,8 +165,8 @@ app_version: ...@@ -155,8 +165,8 @@ app_version:
DATABASE_URL: "postgis://ci:runner@db_server/migrations" DATABASE_URL: "postgis://ci:runner@db_server/migrations"
script: script:
- python3 -V - python3 -V
- pdm sync -d --no-editable -G dev - uv sync
- pdm app_version - uv run task app_version
allow_failure: true allow_failure: true
rules: rules:
- when: always - when: always
...@@ -166,8 +176,7 @@ lint: ...@@ -166,8 +176,7 @@ lint:
extends: .test extends: .test
script: script:
- python3 -V - python3 -V
- pdm sync -d --no-editable -G dev - tox -e py-lint,html-lint
- pdm run lint
allow_failure: true allow_failure: true
rules: rules:
- when: always - when: always
...@@ -177,8 +186,7 @@ format: ...@@ -177,8 +186,7 @@ format:
extends: .test extends: .test
script: script:
- python3 -V - python3 -V
- pdm sync -d --no-editable -G dev - tox -e py-format,html-format
- pdm run format
- git diff --exit-code -- . ':!src/version.json' - git diff --exit-code -- . ':!src/version.json'
allow_failure: true allow_failure: true
rules: rules:
...@@ -191,11 +199,11 @@ format_prettier: ...@@ -191,11 +199,11 @@ format_prettier:
before_script: before_script:
- apk add --no-cache git - apk add --no-cache git
- corepack enable - corepack enable
- 'echo "cacheFolder: \".yarn/cache/\"" > .yarnrc.yml' - 'echo "cacheFolder: \".yarn/cache/\"" >> .yarnrc.yml'
- yarn install --immutable - yarn install --immutable
script: script:
- yarn format - yarn format
- git diff --exit-code -- . ':!src/version.json' - git diff --exit-code -- . ':!src/version.json' ':!.yarnrc.yml'
allow_failure: true allow_failure: true
rules: rules:
- when: always - when: always
...@@ -209,8 +217,8 @@ migration_check: ...@@ -209,8 +217,8 @@ migration_check:
DATABASE_URL: "postgis://ci:runner@db_server/migrations" DATABASE_URL: "postgis://ci:runner@db_server/migrations"
script: script:
- python3 -V - python3 -V
- pdm sync -d --no-editable -G dev - uv run task manage makemigrations --check
- pdm run check-migrations - uv run task manage makemigrations --dry-run
translations_check: translations_check:
stage: test stage: test
...@@ -222,8 +230,8 @@ translations_check: ...@@ -222,8 +230,8 @@ translations_check:
allow_failure: true allow_failure: true
script: script:
- python3 -V - python3 -V
- pdm install --no-editable --prod - uv sync
- pdm manage makemessages - uv run task manage makemessages
- git diff --exit-code -- . ':!src/version.json' - git diff --exit-code -- . ':!src/version.json'
requirements_export: requirements_export:
...@@ -231,16 +239,16 @@ requirements_export: ...@@ -231,16 +239,16 @@ requirements_export:
extends: .test extends: .test
script: script:
- python3 -V - python3 -V
- pdm lock --check - uv lock --check
- pdm export --no-hashes -o requirements.txt --prod - uv export --frozen -o=requirements.dev.txt --no-hashes --all-groups
- pdm export --no-hashes -o requirements.dev.txt --de - uv export --frozen -o=requirements.txt --no-hashes --no-dev
- git diff --exit-code -- . ':!src/version.json' - git diff --exit-code -- . ':!src/version.json'
rules: rules:
- changes: - changes:
- requirements.txt - requirements.txt
- requirements.dev.txt - requirements.dev.txt
- project.toml - project.toml
- pdm.lock - uv.lock
django-tests: django-tests:
stage: test stage: test
...@@ -256,16 +264,18 @@ django-tests: ...@@ -256,16 +264,18 @@ django-tests:
DATABASE_URL: "postgis://ci:runner@db_server/self_test" DATABASE_URL: "postgis://ci:runner@db_server/self_test"
script: script:
- python3 -V - python3 -V
- pdm sync -d --no-editable -G dev - tox -e django-test
- pdm run test - tox -e coverage-report
- pdm run coverage xml -i
- pdm run coverage report
coverage: '/(?i)total(?:\s+\d+){4}\s+(\d+)%/' coverage: '/(?i)total(?:\s+\d+){4}\s+(\d+)%/'
artifacts: artifacts:
reports: reports:
coverage_report: coverage_report:
coverage_format: cobertura coverage_format: cobertura
path: .tools/coverage/coverage.xml path: .tools/coverage/report.xml
paths:
- .tools/coverage/html_report/
expire_in: 1 week
expose_as: "HTML Coverage Report"
build_nginx: build_nginx:
stage: build stage: build
...@@ -515,7 +525,7 @@ cleanup-ci-images: ...@@ -515,7 +525,7 @@ cleanup-ci-images:
- crane delete $CI_REGISTRY_IMAGE/ci/hub:ci-${CI_PIPELINE_ID} - crane delete $CI_REGISTRY_IMAGE/ci/hub:ci-${CI_PIPELINE_ID}
- crane delete $CI_REGISTRY_IMAGE/ci/nginx:ci-${CI_PIPELINE_ID} - crane delete $CI_REGISTRY_IMAGE/ci/nginx:ci-${CI_PIPELINE_ID}
- crane delete $CI_REGISTRY_IMAGE/ci/hub:ci-${CI_PIPELINE_ID}-test - crane delete $CI_REGISTRY_IMAGE/ci/hub:ci-${CI_PIPELINE_ID}-test
- crane delete $CI_REGISTRY_IMAGE/build_image:bi-$CI_PIPELINE_ID - crane delete $CI_REGISTRY_IMAGE/meta_image:mi-$CI_PIPELINE_ID
needs: needs:
- job: publish-production - job: publish-production
optional: true optional: true
......
...@@ -9,7 +9,7 @@ repos: ...@@ -9,7 +9,7 @@ repos:
- id: check-merge-conflict - id: check-merge-conflict
- id: check-ast - id: check-ast
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0 rev: v0.9.7
hooks: hooks:
- id: ruff - id: ruff
args: [--fix] args: [--fix]
...@@ -18,37 +18,40 @@ repos: ...@@ -18,37 +18,40 @@ repos:
rev: v1.0.0 rev: v1.0.0
hooks: hooks:
- id: check-json5 - id: check-json5
- repo: https://github.com/pdm-project/pdm
rev: 2.20.1
hooks:
- name: check production requirements
id: pdm-export
args: ["-o", "requirements.txt", "--without-hashes", "--prod"]
files: ^pdm.lock$
- repo: https://github.com/pdm-project/pdm
rev: 2.20.1
hooks:
- name: check development requirements
id: pdm-export
args: ["-o", "requirements.dev.txt", "--without-hashes", "--dev"]
files: ^pdm.lock$
- repo: https://github.com/pdm-project/pdm
rev: 2.20.1
hooks:
- id: pdm-lock-check
- repo: https://github.com/djlint/djLint - repo: https://github.com/djlint/djLint
rev: v1.36.2 rev: v1.36.4
hooks: hooks:
- id: djlint-reformat-django - id: djlint-reformat-django
- id: djlint-reformat-jinja - id: djlint-reformat-jinja
- id: djlint-django - id: djlint-django
- id: djlint-jinja - id: djlint-jinja
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.6.2
hooks:
- id: uv-lock
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.6.2
hooks:
- name: uv-export-prod
id: uv-export
args:
- --frozen
- -o=requirements.txt
- --no-hashes
- --no-dev
- name: uv-export-dev
id: uv-export
args:
- --frozen
- -o=requirements.dev.txt
- --no-hashes
- --all-groups
- repo: local - repo: local
hooks: hooks:
- name: Check for uncreated migrations. - name: Check for uncreated migrations.
id: migrations-check id: migrations-check
language: system language: system
entry: sh -c "pdm manage makemigrations --check --dry-run" entry: sh -c "uv run task manage makemigrations --check --dry-run"
files: "models/.*.py$" files: "models/.*.py$"
types: types:
- python - python
......
**/*.html **/*.html
**/*.j2 **/*.j2
.yarn .yarn
.yarnrc.yml
.venv*
static.dist/ static.dist/
**/vendor/**/* **/vendor/**/*
......
...@@ -2,8 +2,6 @@ activitypub ...@@ -2,8 +2,6 @@ activitypub
Andi Andi
ASGI ASGI
backoffice backoffice
bigbluebutton
BIGBLUEBUTTON
blocktranslate blocktranslate
clonbares clonbares
CLUBFRIENDS CLUBFRIENDS
......
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
yarnPath: .yarn/releases/yarn-4.6.0.cjs
...@@ -50,11 +50,10 @@ Um eine andere Demo Datei zu laden kann die Umgebungsvariable `DJANGO_LOAD_FIXTU ...@@ -50,11 +50,10 @@ Um eine andere Demo Datei zu laden kann die Umgebungsvariable `DJANGO_LOAD_FIXTU
- Linux: Pakete `python3`, `postgresql` und `gettext` - Linux: Pakete `python3`, `postgresql` und `gettext`
- Mac: `brew install python3 postgresql gettext` bzw. https://postgresapp.com/ - Mac: `brew install python3 postgresql gettext` bzw. https://postgresapp.com/
- Windows: [latest stable Python 3 release](https://www.python.org/downloads/windows/) und [PostgreSQL Installer](https://www.postgresql.org/download/windows/) und [gettext binaries](https://mlocati.github.io/articles/gettext-iconv-windows.html) - Windows: [latest stable Python 3 release](https://www.python.org/downloads/windows/) und [PostgreSQL Installer](https://www.postgresql.org/download/windows/) und [gettext binaries](https://mlocati.github.io/articles/gettext-iconv-windows.html)
- Python Paketmanager: `pdm`: - Python Paketmanager: `uv`:
Kann mit OS Installationsmitteln, mit `pip install pdm` oder `pipx install pdm` installiert werden. Kann mit OS Installationsmitteln, mit `pip install uv` oder `pipx install uv` installiert werden. (Siehe die [Offizielle Dokumentation](https://docs.astral.sh/uv/getting-started/installation/))
1. Klone dieses Repository an beliebigen Ort. 1. Klone dieses Repository an beliebigen Ort.
1. Erstelle die virtuelle Umgebung mit `pdm info` 1. Installiere die python dependencies mit `uv sync`
1. Installiere die python dependencies mit `pdm install`
1. (falls nicht bereits vorhanden) lege einen PostgreSQL-User an (`createuser -P hub_app`) sowie eine Datenbank (`createdb -O hub_app hub`) - unter Linux ggf. via `sudo -u postgres` 1. (falls nicht bereits vorhanden) lege einen PostgreSQL-User an (`createuser -P hub_app`) sowie eine Datenbank (`createdb -O hub_app hub`) - unter Linux ggf. via `sudo -u postgres`
1. Konfiguriere deine Instanz mittels: 1. Konfiguriere deine Instanz mittels:
- Umgebungsvariablen (z.B. direnv, oder env Datei) - Umgebungsvariablen (z.B. direnv, oder env Datei)
...@@ -84,18 +83,17 @@ DATABASES = { ...@@ -84,18 +83,17 @@ DATABASES = {
} }
``` ```
8. Lege die Datenbanktabellen an: `pdm manage migrate` 8. Lege die Datenbanktabellen an: `uv run task manage migrate`
9. Richte einen Admin-Nutzer (für die Anwendung) ein: `pdm manage createsuperuser` 9. Richte einen Admin-Nutzer (für die Anwendung) ein: `uv run task manage createsuperuser`
10. optional: Import von Demo-Daten: `pdm manage.py loaddata .src/core/fixtures/rc3_2021.json` 10. optional: Import von Demo-Daten: `uv run task.py loaddata .src/core/fixtures/rc3_2021.json`
11. optional: Für deinen Adminuser via [Admin-Seite](http://localhost:8000/c3admin/) einen `ConferenceMember` anlegen um den User für das Frontend freizuschalten 11. optional: Für deinen Adminuser via [Admin-Seite](http://localhost:8000/c3admin/) einen `ConferenceMember` anlegen um den User für das Frontend freizuschalten
## Nutzung ## Nutzung
1. Aktiviere das virtual env `pdm venv activate` 2. Wende ggf. vorhandene DB-Migrations an (wenn du gerade aus dem Git geupdatet hast): `uv run task manage migrate`
2. Wende ggf. vorhandene DB-Migrations an (wenn du gerade aus dem Git geupdatet hast): `pdm manage migrate` 3. Stelle sicher dass alle Translations aktuell sind: `uv run task manage compilemessages`
3. Stelle sicher dass alle Translations aktuell sind: `pdm manage compilemessages` 4. Lasse alle staticfiles einsammeln: `uv run task manage collectstatic --noinput`
4. Lasse alle staticfiles einsammeln: `pdm manage collectstatic --noinput` 5. Starte den Dev-Server: `uv run task manage runserver`
5. Starte den Dev-Server: `pdm manage runserver`
6. Besuche die lokale Instanz: [Admin-Seite](http://localhost:8000/c3admin/), [API](http://localhost:8000/api/) und [plainui-Frontend](http://localhost:8000/) 6. Besuche die lokale Instanz: [Admin-Seite](http://localhost:8000/c3admin/), [API](http://localhost:8000/api/) und [plainui-Frontend](http://localhost:8000/)
## PlainUI Development Tipps ## PlainUI Development Tipps
...@@ -136,26 +134,26 @@ Wiederverwendbare Elemente können als Komponenten integriert werden. Dafür gib ...@@ -136,26 +134,26 @@ Wiederverwendbare Elemente können als Komponenten integriert werden. Dafür gib
### Abhängigkeitsverwaltung ### Abhängigkeitsverwaltung
Zur Verwaltung der verwendeten python Abhängigkeiten wir der [Paketmanager PDM](https://pdm-project.org/en/latest/) verwendet. Zur Verwaltung der verwendeten python Abhängigkeiten wir der [Paketmanager UV](https://docs.astral.sh/uv/) verwendet.
Mittels diesem werden die `requirements.txt` und die `requirements.dev.txt` erzeugt. Mittels diesem werden die `requirements.txt` und die `requirements.dev.txt` erzeugt.
#### Installation der aktuellen Abhängigkeiten #### Installation der aktuellen Abhängigkeiten
Um die aktuellen python Abhängigkeiten zu installieren kann das Kommando `pdm install` verwendet werden. Um die aktuellen python Abhängigkeiten zu installieren kann das Kommando `uv sync` verwendet werden.
Mit dem Kommando `pdm sync --clean` kann sichergestellt werden, dass genau die Versionen aus dem pdm lock file installiert werden. Mit dem Kommando `ur sync --frozen` kann sichergestellt werden, dass genau die Versionen aus dem uv lock file installiert werden.
_Achtung_: **Nicht in der Lock Datei enthaltene python Pakete werden deinstalliert!** _Achtung_: **Nicht in der Lock Datei enthaltene python Pakete werden deinstalliert!**
#### Hinzufügen von neuen Abhängigkeiten #### Hinzufügen von neuen Abhängigkeiten
Um neue Abhängigkeiten hinzuzufügen kann das Kommando `pdm add` verwendet werden. Mit dem Parameter `--dev` kann eine Abhängigkeit als Entwicklungs-Abhängigkeit deklariert werden. Diese wird dann in den Produktivinstanzen nicht installiert. Um neue Abhängigkeiten hinzuzufügen kann das Kommando `uv add` verwendet werden. Mit dem Parameter `--dev` kann eine Abhängigkeit als Entwicklungs-Abhängigkeit deklariert werden. Diese wird dann in den Produktivinstanzen nicht installiert.
Anschließend müssen die `requirements.txt` und `requirements.dev.txt` angepasst werden. Anschließend müssen die `requirements.txt` und `requirements.dev.txt` angepasst werden.
Wenn `pre-commit` verwendet wird, passiert dies automatisch beim commit. Wenn `pre-commit` verwendet wird, passiert dies automatisch beim commit.
Alternativ können die folgenden Kommandos verwendet werden Alternativ können die folgenden Kommandos verwendet werden
```bash ```bash
pdm export --no-hashes -o requirements.txt --prod uv export --format requirements-txt --no-hashes -o requirements.txt --no-dev
pdm export --no-hashes -o requirements.dev.txt --dev uv export --format requirements-txt --no-hashes -o requirements.dev.txt --all-groups
``` ```
### Debugging DJANGO ### Debugging DJANGO
...@@ -177,9 +175,9 @@ oder: ...@@ -177,9 +175,9 @@ oder:
### Übersetzungen extrahieren & compilieren ### Übersetzungen extrahieren & compilieren
- `pdm manage makemessages` - `uv run task manage makemessages`
- Die Übersetzungsdateien in `<app>/locale/<sprache>/LC_MESSAGES/django.po` wurden um alle neuen Übersetzungsstrings erweitert. Bearbeiten und jeweils bei `msgstr` die Übersetzungen einfügen! - Die Übersetzungsdateien in `<app>/locale/<sprache>/LC_MESSAGES/django.po` wurden um alle neuen Übersetzungsstrings erweitert. Bearbeiten und jeweils bei `msgstr` die Übersetzungen einfügen!
- `pdm manage compilemessages` - `uv run task manage compilemessages`
- Zum Ausprobieren müsst ihr django neu starten um die neuen Übersetzungsdateien zu laden - Zum Ausprobieren müsst ihr django neu starten um die neuen Übersetzungsdateien zu laden
### Übersetzungen definineren ### Übersetzungen definineren
...@@ -189,7 +187,7 @@ oder: ...@@ -189,7 +187,7 @@ oder:
### Static Files einsammeln lassen ### Static Files einsammeln lassen
- `pdm manage collectstatic` - `uv run task manage collectstatic`
- ohne dies brechen u.a. Unittests mit Fehlern wie "Missing staticfiles manifest entry" ab - ohne dies brechen u.a. Unittests mit Fehlern wie "Missing staticfiles manifest entry" ab
### Tests ### Tests
...@@ -216,8 +214,8 @@ self.assertEqual(translation, "NoTIcket_trans") ...@@ -216,8 +214,8 @@ self.assertEqual(translation, "NoTIcket_trans")
Um die Tests ausführen zu können muss der Datenbanknutzer das Recht haben neue Datenbaken anzulegen. Um die Tests ausführen zu können muss der Datenbanknutzer das Recht haben neue Datenbaken anzulegen.
Dafür mit `psql postgres` die Datenbankkonsole starten. Dort `ALTER USER hub_app CREATEDB;` ausführen (ggf. `hub_app` durch den gewählten Nutzernamen ersetzen). Am Ende mit `Strg-D` Konsole wieder schließen. Dafür mit `psql postgres` die Datenbankkonsole starten. Dort `ALTER USER hub_app CREATEDB;` ausführen (ggf. `hub_app` durch den gewählten Nutzernamen ersetzen). Am Ende mit `Strg-D` Konsole wieder schließen.
Um die Django Tests auszuführen kann das Kommando `pdm test` verwendet werden. \ Um die Django Tests auszuführen kann das Kommando `uv run tox -e django-test` verwendet werden. \
Um nur die Tests einer App auszuführen stattdessen `pdm test -- <app>.tests` ausführen. \ Um nur die Tests einer App auszuführen stattdessen `uv run tox -e django-test -- <app>.tests` ausführen. \
Hilfreiche Argumente sind `-v 2` um die ausgeführten Tests anzuzeigen, `--failfast` um nach dem ersten Fehler abzubrechen, und `--keepdb` um nicht jedes mal die Migrationen durchführen zu müssen. \ Hilfreiche Argumente sind `-v 2` um die ausgeführten Tests anzuzeigen, `--failfast` um nach dem ersten Fehler abzubrechen, und `--keepdb` um nicht jedes mal die Migrationen durchführen zu müssen. \
Für weitere Infos zu dem Befehl ist https://docs.djangoproject.com/en/3.1/ref/django-admin/#django-admin-test hilfreich. Für weitere Infos zu dem Befehl ist https://docs.djangoproject.com/en/3.1/ref/django-admin/#django-admin-test hilfreich.
...@@ -244,7 +242,7 @@ Dieses hat die folgenden Kommandos: ...@@ -244,7 +242,7 @@ Dieses hat die folgenden Kommandos:
- `ruff check`: Diess Kommando checkt auf häufige Fehler in python code und hat auch teilweise Möglichkeiten diese zu beheben - `ruff check`: Diess Kommando checkt auf häufige Fehler in python code und hat auch teilweise Möglichkeiten diese zu beheben
- `ruff format`: Dieses Kommando re-formatiert alle python dateien nach einem voregebenen Code-Style - `ruff format`: Dieses Kommando re-formatiert alle python dateien nach einem voregebenen Code-Style
### djLink ### djLint
**Leider ist es nicht möglich djLint so zu konfigurieren, dass es automatisch die richtigen Profile verwendet.** **Leider ist es nicht möglich djLint so zu konfigurieren, dass es automatisch die richtigen Profile verwendet.**
**Wenn eine Integration in einen Editor gewünscht ist, muss dies berücksichtigt werden!** **Wenn eine Integration in einen Editor gewünscht ist, muss dies berücksichtigt werden!**
......
ARG REGISTRY="" ARG REGISTRY=""
FROM ${REGISTRY}python:3.13-bookworm AS base FROM ${REGISTRY}python:3.13-bookworm AS base
COPY --from=ghcr.io/astral-sh/uv:0.5.21 /uv /uvx /bin/
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
ENV PDM_CHECK_UPDATE=false # Set up uv environment
ENV UV_LINK_MODE=copy UV_COMPILE_BYTECODE=1 UV_TOOL_BIN_DIR=/opt/uv-bin/
RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/99-unattended-minimal && \ RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/99-unattended-minimal && \
echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf.d/99-unattended-minimal && \ echo 'APT::Install-Suggests "false";' >> /etc/apt/apt.conf.d/99-unattended-minimal && \
...@@ -10,7 +12,6 @@ RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/99-unattended- ...@@ -10,7 +12,6 @@ RUN echo 'APT::Install-Recommends "false";' > /etc/apt/apt.conf.d/99-unattended-
RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \ RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \
--mount=target=/var/cache/apt/archives/,type=cache,sharing=locked \ --mount=target=/var/cache/apt/archives/,type=cache,sharing=locked \
--mount=target=/root/.cache/pip,type=cache,sharing=locked \
# Prevent apt cache cleaning # Prevent apt cache cleaning
rm -f /etc/apt/apt.conf.d/docker-clean && \ rm -f /etc/apt/apt.conf.d/docker-clean && \
apt-get update && \ apt-get update && \
...@@ -21,12 +22,16 @@ RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \ ...@@ -21,12 +22,16 @@ RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \
dpkg-reconfigure locales && \ dpkg-reconfigure locales && \
locale-gen C.UTF-8 && \ locale-gen C.UTF-8 && \
/usr/sbin/update-locale LANG=C.UTF-8 && \ /usr/sbin/update-locale LANG=C.UTF-8 && \
pip install -U pdm && \
# Fix caching issue with kaniko see: https://github.com/GoogleContainerTools/kaniko/issues/3246 # Fix caching issue with kaniko see: https://github.com/GoogleContainerTools/kaniko/issues/3246
mkdir -p /app/plainui mkdir -p /app/plainui
# Add path for future pdm location # Add path for future uv location
ENV PATH="/install/.venv/bin:$PATH" ENV PATH="/install/.venv/bin:/opt/uv-bin:$PATH"
######################################### [meta] #############################
FROM base AS meta
RUN uv tool install tox --with tox-uv
######################################### [build] ############################# ######################################### [build] #############################
...@@ -38,25 +43,24 @@ RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \ ...@@ -38,25 +43,24 @@ RUN --mount=target=/var/lib/apt/lists/,type=cache,sharing=locked \
--mount=target=/var/cache/apt/archives/,type=cache,sharing=locked \ --mount=target=/var/cache/apt/archives/,type=cache,sharing=locked \
apt-get update && \ apt-get update && \
apt-get install \ apt-get install \
build-essential \ build-essential && \
yarnpkg && \
/usr/bin/yarnpkg global bin corepack enable &&\
mkdir /install mkdir /install
WORKDIR /install WORKDIR /install
COPY pyproject.toml pdm.lock README.md /install/ COPY pyproject.toml uv.lock README.md /install/
RUN --mount=target=/root/.cache/pdm,type=cache,sharing=locked \ RUN --mount=type=cache,target=/root/.cache/uv \
pdm install --check --prod --no-editable uv sync --frozen --no-install-project --no-editable
######################################### [build-dev] ######################### ######################################### [build-dev] #########################
FROM build AS build-dev FROM build AS build-dev
WORKDIR /install WORKDIR /install
RUN --mount=target=/root/.cache/pdm,type=cache,sharing=locked \ RUN --mount=type=cache,target=/root/.cache/uv \
pdm install --check --dev --no-editable uv sync --frozen --no-install-project --no-editable
######################################### [node-build] ######################## ######################################### [node-build] ########################
FROM ${REGISTRY}node:20-alpine AS node-base FROM ${REGISTRY}node:20-alpine AS node-base
RUN mkdir -p /app/plainui/ RUN mkdir -p /app/plainui/
...@@ -68,16 +72,6 @@ RUN corepack enable && \ ...@@ -68,16 +72,6 @@ RUN corepack enable && \
/usr/local/bin/yarnpkg set version stable && \ /usr/local/bin/yarnpkg set version stable && \
/usr/local/bin/yarnpkg install /usr/local/bin/yarnpkg install
######################################### [nginx-forwarder] ###################
FROM ${REGISTRY}nginx:1-alpine-slim AS nginx-forwarder
ENV APP_SOCKET="/run/hub/app.sock"
ENV SCRIPT_NAME=""
COPY deployment/docker/index.html deployment/docker/error_*.html /www/default/
COPY deployment/docker/nginx.conf /etc/nginx/templates/default.conf.template
######################################### [webworker-base] #################### ######################################### [webworker-base] ####################
FROM base AS webworker-base FROM base AS webworker-base
...@@ -96,7 +90,6 @@ COPY deployment/docker/app.sh /usr/local/bin/app ...@@ -96,7 +90,6 @@ COPY deployment/docker/app.sh /usr/local/bin/app
COPY deployment/docker/check_django.sh /usr/local/bin/hub_healthcheck COPY deployment/docker/check_django.sh /usr/local/bin/hub_healthcheck
COPY deployment/docker/check_psql.py /usr/local/bin/postgres_healthcheck COPY deployment/docker/check_psql.py /usr/local/bin/postgres_healthcheck
COPY --from=build /install/.venv /install/.venv
ENV PATH="/install/.venv/bin:$PATH" ENV PATH="/install/.venv/bin:$PATH"
RUN install -d -m 0755 -o appuser -g appuser /app/hub /data /app/media /run/hub && \ RUN install -d -m 0755 -o appuser -g appuser /app/hub /data /app/media /run/hub && \
...@@ -133,7 +126,12 @@ RUN export DJANGO_SETTINGS_MODULE='hub.settings.build' && \ ...@@ -133,7 +126,12 @@ RUN export DJANGO_SETTINGS_MODULE='hub.settings.build' && \
######################################### [nginx] ############################# ######################################### [nginx] #############################
FROM nginx-forwarder AS nginx FROM ${REGISTRY}nginx:1-alpine-slim AS nginx
ENV APP_SOCKET="/run/hub/app.sock"
ENV SCRIPT_NAME=""
COPY deployment/docker/index.html deployment/docker/error_*.html /www/default/
COPY deployment/docker/nginx.conf /etc/nginx/templates/default.conf.template
COPY --from=build-static /app/static.dist /www/static COPY --from=build-static /app/static.dist /www/static
...@@ -141,6 +139,7 @@ COPY --from=build-static /app/static.dist /www/static ...@@ -141,6 +139,7 @@ COPY --from=build-static /app/static.dist /www/static
FROM webworker-base AS webworker FROM webworker-base AS webworker
COPY --from=build /install/.venv /install/.venv
COPY --from=build-static --chown=appuser /app /app COPY --from=build-static --chown=appuser /app /app
USER appuser USER appuser
......
...@@ -39,9 +39,18 @@ Prodinstanz: <https://api.events.ccc.de/congress/2024/> ...@@ -39,9 +39,18 @@ Prodinstanz: <https://api.events.ccc.de/congress/2024/>
| Kategorie | Endpunkt | GET | POST | PUT | DEL | Beschreibung | | Kategorie | Endpunkt | GET | POST | PUT | DEL | Beschreibung |
| ---------- | ---------------------------------------- | --- | ---- | --- | --- | ----------------------------------------------------- | | ---------- | ---------------------------------------- | --- | ---- | --- | --- | ----------------------------------------------------- |
| Auth | `/auth/get-token` | | x | | | Ausstellen eines API-Tokens |
| Persönlich | `/me` | x | | x | | eigenes Profil / Settings | | Persönlich | `/me` | x | | x | | eigenes Profil / Settings |
| Persönlich | `/me/friends` | x | | x | x | Liste der Buddies |
| Persönlich | `/me/badges` | x | | | | Liste aller Badges/Achievements | | Persönlich | `/me/badges` | x | | | | Liste aller Badges/Achievements |
| Persönlich | `/me/events` | x | | | | Favorisierte Events |
| Persönlich | `/me/events/<uuid>/` | | | x | x | Events (ent-)favorisieren |
| Persönlich | `/me/friends` | x | | x | x | Liste der Buddies |
| Persönlich | `/me/received-messages/` | x | | | | Übersicht empfangener PN |
| Persönlich | `/me/received-messages/<uuid>` | x | | | | Details einer empfangenen PN |
| Persönlich | `/me/send-message` | | x | | | Send a new PN |
| Persönlich | `/me/sent-messages/` | x | | | | Übersicht gesendeter PN |
| Persönlich | `/me/sent-messages/<uuid>` | x | | | | Details einer gesendeten PN |
| Persönlich | `/me/delete-message/<uuid>` | x | | | | PN löschen |
| Konferenz | `/` | x | | | | Metadaten des Konferenz | | Konferenz | `/` | x | | | | Metadaten des Konferenz |
| Konferenz | `/tags` | x | | | | Liste aller Tags auf der Konferenz | | Konferenz | `/tags` | x | | | | Liste aller Tags auf der Konferenz |
| Konferenz | `/tracks` | x | x | | | Liste der Tracks | | Konferenz | `/tracks` | x | x | | | Liste der Tracks |
...@@ -64,6 +73,20 @@ Prodinstanz: <https://api.events.ccc.de/congress/2024/> ...@@ -64,6 +73,20 @@ Prodinstanz: <https://api.events.ccc.de/congress/2024/>
Per POST werden neue Einträge angelegt, per PUT bestehende verändert. Per POST werden neue Einträge angelegt, per PUT bestehende verändert.
Details zu den einzelnen Endpunkten folgen in Kürze™. Details zu den einzelnen Endpunkten folgen in Kürze™.
### API-Beispiel mit cURL
Zuerst einen Token generieren:
```bash
curl https://{API_URL}/api/auth/get-token -H "Content-Type: application/json" -X POST --data '{"username": "{USERNAME}", "password": "{PASSWORD}"}'
```
Mit diesem Token können dann Endpunkte aufgerufen werden die eine Authentifizierung erfordern:
```bash
curl https://{API_URL}/api/me -H "Content-Type: application/json" -H "Authorization: Token {API_TOKEN}"
```
## Development ## Development
see [Development.md](./Development.md) see [Development.md](./Development.md)
...@@ -45,6 +45,8 @@ if [ ! -e "$HOME/$ADMIN_CREATED" -a -n "$DJANGO_CREATE_ADMIN_PASSWORD" ]; then ...@@ -45,6 +45,8 @@ if [ ! -e "$HOME/$ADMIN_CREATED" -a -n "$DJANGO_CREATE_ADMIN_PASSWORD" ]; then
touch $HOME/$ADMIN_CREATED touch $HOME/$ADMIN_CREATED
fi fi
touch $HOME/PREPARATION_DONE
if [ "$1" == "webworker" -o "$STARTMODE" == "webworker" ]; then if [ "$1" == "webworker" -o "$STARTMODE" == "webworker" ]; then
# start gunicorn (might be called indirectly via supervisor when started with 'all') # start gunicorn (might be called indirectly via supervisor when started with 'all')
gunicorn_params=() gunicorn_params=()
...@@ -75,12 +77,7 @@ if [ "$1" == "shell" -o "$1" == "createsuperuser" -o "$1" == "test" ]; then ...@@ -75,12 +77,7 @@ if [ "$1" == "shell" -o "$1" == "createsuperuser" -o "$1" == "test" ]; then
fi fi
if [ "$1" == "housekeeping" ]; then if [ "$1" == "housekeeping" ]; then
interval="${HOUSEKEEPING_SLEEP_SECONDS:-300}" python3 $APP_HOME/manage.py housekeeping --forever
if [ "$interval" -gt 0 ]; then
python3 $APP_HOME/manage.py housekeeping --forever --forever-delay="$interval"
else
python3 $APP_HOME/manage.py housekeeping
fi
fi fi
cat <<EOD cat <<EOD
......
...@@ -21,7 +21,7 @@ TOKEN = env('API_TOKEN') ...@@ -21,7 +21,7 @@ TOKEN = env('API_TOKEN')
PER_PAGE = 100 PER_PAGE = 100
DELETE_ALL = datetime.now(tz=UTC) - timedelta(weeks=env('THRESHOLD_ALL')) DELETE_ALL = datetime.now(tz=UTC) - timedelta(weeks=env('THRESHOLD_ALL'))
DELETE_FAILED = datetime.now(tz=UTC) - timedelta(weeks=env('THRESHOLD_FAILED')) DELETE_FAILED = datetime.now(tz=UTC) - timedelta(weeks=env('THRESHOLD_FAILED'))
BASE_URL = f'{env('CI_API_V4_URL')}/projects/{env("CI_PROJECT_ID")}' BASE_URL = f'{env("CI_API_V4_URL")}/projects/{env("CI_PROJECT_ID")}'
if TOKEN is None: if TOKEN is None:
raise ValueError('API_TOKEN is required') raise ValueError('API_TOKEN is required')
......
{ {
"name": "hub", "name": "hub",
"packageManager": "yarn@4.5.0", "packageManager": "yarn@4.6.0",
"devDependencies": { "devDependencies": {
"@cspell/dict-de-de": "^4.0.3", "@cspell/dict-de-de": "^4.0.3",
"@cspell/dict-python": "^4.2.12", "@cspell/dict-python": "^4.2.12",
......
This diff is collapsed.
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
name = "hub" name = "hub"
dynamic = ["version"] dynamic = ["version"]
description = "Management tool for chaos events." description = "Management tool for chaos events."
authors = [ authors = [{ name = "Hub Team", email = "hub@cccv.de" }]
{name = "Roang", email = "lucas@brandstaetter.tech"},
]
dependencies = [ dependencies = [
"babel~=2.16", "babel~=2.16",
"bleach~=6.1", "bleach~=6.1",
...@@ -39,69 +37,58 @@ dependencies = [ ...@@ -39,69 +37,58 @@ dependencies = [
"segno~=1.6.1", "segno~=1.6.1",
"sentry-sdk>=2.17.0,<3", "sentry-sdk>=2.17.0,<3",
"tzdata~=2024.2", "tzdata~=2024.2",
"pdm>=2.11.2",
"psycopg[binary,pool]>=3.2.3", "psycopg[binary,pool]>=3.2.3",
"gunicorn>=23.0.0", "gunicorn>=23.0.0",
"pydantic>=2.9.2", "pydantic>=2.9.2",
"django-rich>=1.13.0", "django-rich>=1.13.0",
"django-csp>=3.8", "django-csp>=3.8",
"rules>=3.5", "rules>=3.5",
"django-ical>=1.9.2",
"django-stubs-ext>=5.1.2",
"ipython>=8.31.0",
"django-extensions>=3.2.3",
] ]
requires-python = "==3.13.*" requires-python = "==3.13.*"
readme = "README.md" readme = "README.md"
license = { text = "MIT" } license = { text = "MIT" }
[project.optional-dependencies] [dependency-groups]
watchfiles = [
"django-watchfiles>=1.0.0",
]
[tool.pdm]
distribution = false
[tool.pdm.version]
source = "scm"
write_to = "version.txt"
[tool.pdm.dev-dependencies]
lint = [
"ruff>=0.1.11",
"djlint>=1.35.4",
]
local = [
"debugpy>=1.8.0",
"icecream>=2.1.3",
]
dev = [ dev = [
"tox>=4.11.4",
"coverage>=7.4.0", "coverage>=7.4.0",
"tox-pdm>=0.7.2",
"pre-commit>=3.6.0",
"docutils>=0.21.2", "docutils>=0.21.2",
"pre-commit>=3.6.0",
"tblib>=3.0.0",
"tox-uv>=1.19.0",
"tox>=4.11.4",
"taskipy>=1.14.1",
] ]
lint = ["ruff>=0.1.11", "djlint>=1.35.4"]
local = ["debugpy>=1.8.0", "icecream>=2.1.3"]
typing = [ typing = [
"django-stubs[mypy-compatible]>=5.1.1", "pyright>=1.1.392.post0",
] "djangorestframework-stubs[compatible-mypy]>=1.4.0",
static-analysis = [ "django-stubs>=5.1.2",
"pylint>=3.3.1",
"pylint-django>=2.6.1",
] ]
static-analysis = ["pylint>=3.3.1", "pylint-django>=2.6.1"]
watchfiles = ["django-watchfiles>=1.0.0"]
[tool.pdm.scripts] # uv currently has no task runner, use taskipy instead.
# Generic scripts # Ref: https://github.com/astral-sh/uv/issues/5903
whoami = { shell = "echo `{pdm} -V` was called as '{pdm} -V'" } [tool.taskipy.tasks]
# Application version # Application version
app_version = "./src/manage.py appversion" app_version = "./src/manage.py appversion"
# Django scripts # Django scripts
start = "./src/manage.py runserver" start = { cmd = "./src/manage.py runserver", cwd = "." }
shell = "./src/manage.py shell" shell = { cmd = "./src/manage.py shell_plus", cwd = "." }
manage = "./src/manage.py" manage = { cmd = "./src/manage.py", cwd = "." }
compilemessages = { cmd = "./manage.py compilemessages", cwd = "./src" }
# TOX scripts # TOX scripts
all = "tox" all = "tox"
check-migrations = "tox -e migrations" check-migrations = "tox -e migrations"
coverage-report = "tox -e coverage-report" coverage-report = "tox -e coverage-report"
style-check = {composite = ["format", "lint"]} style-check = "task format && task lint"
format = {composite = ["py-format", "html-format"]} format = "tox -e py-format,html-format"
lint = {composite = ["py-lint", "html-lint"]} lint = "tox -e py-lint,html-lint"
py-format = "tox -e py-format" py-format = "tox -e py-format"
py-lint = "tox -e py-lint" py-lint = "tox -e py-lint"
html-format = "tox -e html-format" html-format = "tox -e html-format"
...@@ -112,15 +99,20 @@ live-test = "tox -e live-test" ...@@ -112,15 +99,20 @@ live-test = "tox -e live-test"
[tool.coverage.run] [tool.coverage.run]
data_file = ".tools/coverage/coverage" data_file = ".tools/coverage/coverage"
dynamic_context = "test_function" dynamic_context = "test_function"
omit =[ omit = ["*/migrations/*"]
"*/migrations/*"]
branch = true branch = true
[tool.coverage.report] [tool.coverage.report]
show_missing = true show_missing = true
exclude_also = [
"def __repr__",
"if settings.DEBUG",
"if TYPE_CHECKING:",
"raise NotImplementedError",
]
[tool.coverage.xml] [tool.coverage.xml]
output = ".tools/coverage/coverage.xml" output = ".tools/coverage/report.xml"
[tool.coverage.html] [tool.coverage.html]
directory = ".tools/coverage/html_report" directory = ".tools/coverage/html_report"
...@@ -130,10 +122,187 @@ indent = 2 ...@@ -130,10 +122,187 @@ indent = 2
ignore = "H006,H013,H021,H022,H030,H031" ignore = "H006,H013,H021,H022,H030,H031"
linter_output_format = "{filename}:{line}: {code} {message} {match}" linter_output_format = "{filename}:{line}: {code} {message} {match}"
preserve_blank_lines = true preserve_blank_lines = true
extend_exclude=".tools" # We neeed to override the default settings for the GitLab CI
# Ref: https://github.com/djlint/djLint/issues/1028
exclude = ".venv"
extend_exclude = "__pypackages__,_build,.bzr,.direnv,.eggs,.git,.git-rewrite,.hg,.ipynb_checkpoints,.mypy_cache,.nox,.pants.d,.pytest_cache,.pytype,.ruff_cache,.svn,.tox,.venv,.vscode,buck-out,dist,node_modules,venv,.tools"
[tool.mypy] [tool.mypy]
plugins = ["mypy_django_plugin.main"] plugins = ["mypy_django_plugin.main"]
[tool.django-stubs] [tool.django-stubs]
django_settings_module = "hub.settings.base" django_settings_module = "hub.settings.base"
[tool.tox]
requires = ["tox>=4"]
env_list = [
"py-lint",
"py-format",
"html-lint",
"html-format",
"django-test",
"coverage-repor",
]
work_dir = ".tools/tox"
[tool.tox.env_run_base]
runner = "uv-venv-lock-runner"
skip_install = true
[tool.tox.env.hub.set_env]
ALLOWED_HOSTS = { replace = "env", name = "ALLOWED_HOSTS" }
DATABASE_URL = { replace = "env", name = "DATABASE_URL" }
DJANGO_DEBUG = "I_KNOW_WHAT_I_AM_DOING"
DJANGO_SETTINGS_MODULE = "hub.settings.test"
DISABLE_REQUEST_LOGGING = "True"
SERVE_API = "True"
SERVE_BACKOFFICE = "True"
SERVE_FRONTEND = "True"
SSO_SECRET_GENERATE = "True"
STORAGE_TYPE = "local"
USE_PLAIN_STATICFILES = "True"
METRICS_SERVER_IPS = "127.0.0.1,localhost"
[tool.tox.env.py-lint]
uv_sync_flags = ["--only-group=lint"]
commands = [["ruff", "check", "."]]
[tool.tox.env.py-format]
uv_sync_flags = ["--only-group=lint"]
commands = [["ruff", "format", ".", "--diff"]]
[tool.tox.env.html-lint]
uv_sync_flags = ["--only-group=lint"]
commands = [
[
"djlint",
"--profile",
"jinja",
"-e",
"j2",
"--lint",
".",
],
[
"djlint",
"--profile",
"django",
"-e",
"html",
"--lint",
".",
],
]
[tool.tox.env.html-format]
uv_sync_flags = ["--only-group=lint"]
commands = [
[
"djlint",
"--profile",
"jinja",
"-e",
"j2",
"--reformat",
".",
],
[
"djlint",
"--profile",
"django",
"-e",
"html",
"--reformat",
".",
],
]
[tool.tox.env.django-test]
set_env = [
{ replace = "ref", of = [
"tool",
"tox",
"env",
"hub",
"set_env",
] },
{ PYTHONWARNINGS = "always" },
]
allowlist_externals = ["coverage"]
extras = ["dev"]
commands = [
[
"coverage",
"run",
"--concurrency=multiprocessing",
"{toxinidir}/src/manage.py",
"test",
"-v",
"2",
"--parallel=8",
'src',
{ replace = "posargs", extend = true },
],
[
"coverage",
"combine",
],
]
[tool.tox.env.django-test-single]
set_env = [
{ replace = "ref", of = [
"tool",
"tox",
"env",
"hub",
"set_env",
] },
{ PYTHONWARNINGS = "always" },
]
extras = ["dev"]
change_dir = "{toxinidir}/src"
allowlist_externals = ["coverage"]
commands = [
[
"coverage",
"run",
"./manage.py",
"test",
"-v",
"2",
{ replace = "posargs", extend = true },
],
]
[tool.tox.env.live-test]
groups = "dev"
change_dir = "{toxinidir}"
commands = [["python", "-m", "unittest", "{posargs}"]]
[tool.tox.env.live-test.set_env]
PYTHONWARNINGS = "always"
SERVE_API = "yes"
[tool.tox.env.coverage-report]
deps = ["coverage"]
commands = [["coverage", "report"], ["coverage", "xml"], ["coverage", "html"]]
[tool.pyright]
include = ["src"]
exclude = [
"**/node_modules",
"**/dist",
"**/build",
"**/.venv",
"**/.vscode",
"**/.tools",
]
venvPath = "."
venv = ".venv"
verboseOutput = true
reportMissingTypeArgument = "information"
reportPrivateUsage = "information"
typeCheckingMode = "standard" # "off", "basic", "standard", "strict"
# This file is @generated by PDM. # This file was autogenerated by uv via the following command:
# Please do not edit it manually. # uv export --frozen -o=requirements.dev.txt --no-hashes --all-groups
annotated-types==0.7.0 annotated-types==0.7.0
anyio==4.6.2.post1 anyio==4.8.0
asgiref==3.8.1 asgiref==3.8.1
astroid==3.3.5 astroid==3.3.8
asttokens==2.4.1 asttokens==3.0.0
babel==2.16.0 babel==2.17.0
beautifulsoup4==4.12.3 beautifulsoup4==4.13.3
bleach==6.2.0 bleach==6.2.0
blinker==1.9.0 boto3==1.36.26
boto3==1.35.71 botocore==1.36.26
botocore==1.35.71 cachetools==5.5.2
cachetools==5.5.0 certifi==2025.1.31
certifi==2024.8.30 cffi==1.17.1 ; platform_python_implementation != 'PyPy'
cffi==1.17.1; platform_python_implementation != "PyPy"
cfgv==3.4.0 cfgv==3.4.0
chardet==5.2.0 chardet==5.2.0
charset-normalizer==3.4.0 charset-normalizer==3.4.1
click==8.1.7 click==8.1.8
colorama==0.4.6 colorama==0.4.6
coverage==7.6.8 coverage==7.6.12
cryptography==43.0.3 cryptography==44.0.1
cssbeautifier==1.15.1 cssbeautifier==1.15.3
debugpy==1.8.9 debugpy==1.8.12
decorator==5.2.0
defusedxml==0.7.1 defusedxml==0.7.1
dep-logic==0.4.9 dill==0.3.9
dill==0.3.9; python_version >= "3.11"
distlib==0.3.9 distlib==0.3.9
django==5.1.3 django==5.1.6
django-bootstrap5==24.3 django-bootstrap5==24.3
django-cors-headers==4.6.0 django-cors-headers==4.7.0
django-csp==3.8 django-csp==3.8
django-debug-toolbar==4.4.6 django-debug-toolbar==4.4.6
django-environ==0.11.2 django-environ==0.11.2
django-modeltranslation==0.19.11 django-extensions==3.2.3
django-ical==1.9.2
django-modeltranslation==0.19.12
django-oauth-toolkit==3.0.1 django-oauth-toolkit==3.0.1
django-ratelimit==4.1.0 django-ratelimit==4.1.0
django-recurrence==1.11.1
django-redis==5.4.0 django-redis==5.4.0
django-rich==1.13.0 django-rich==1.14.0
django-storages==1.14.4 django-storages==1.14.5
django-stubs-ext==5.1.1 django-stubs==5.1.3
django-stubs[mypy-compatible]==5.1.1 django-stubs-ext==5.1.3
django-timezone-field==7.0 django-timezone-field==7.0
django-watchfiles==1.1.0
django-widget-tweaks==1.5.0 django-widget-tweaks==1.5.0
djangorestframework==3.15.2 djangorestframework==3.15.2
djlint==1.36.2 djangorestframework-stubs==3.15.3
djlint==1.36.4
docutils==0.21.2 docutils==0.21.2
editorconfig==0.12.4 editorconfig==0.17.0
et-xmlfile==2.0.0 et-xmlfile==2.0.0
executing==2.1.0 executing==2.2.0
filelock==3.16.1 filelock==3.17.0
findpython==0.6.2
freezegun==1.5.1 freezegun==1.5.1
gunicorn==23.0.0 gunicorn==23.0.0
h11==0.14.0 icalendar==6.1.1
hishel==0.0.33 icecream==2.1.4
httpcore==1.0.7 identify==2.6.7
httpx[socks]==0.27.2
icecream==2.1.3
identify==2.6.2
idna==3.10 idna==3.10
installer==0.7.0 ipython==8.32.0
isort==5.13.2 isort==6.0.0
jinja2==3.1.4 jedi==0.19.2
jinja2==3.1.5
jmespath==1.0.1 jmespath==1.0.1
jsbeautifier==1.15.1 jsbeautifier==1.15.3
json5==0.9.28 json5==0.10.0
jwcrypto==1.5.6 jwcrypto==1.5.6
lxml==5.3.0 lxml==5.3.1
markdown-it-py==3.0.0 markdown-it-py==3.0.0
markdownify==0.13.1 markdownify==0.13.1
markupsafe==3.0.2 markupsafe==3.0.2
matplotlib-inline==0.1.7
mccabe==0.7.0 mccabe==0.7.0
mdurl==0.1.2 mdurl==0.1.2
mistletoe==1.4.0 mistletoe==1.4.0
msgpack==1.1.0 mslex==1.3.0 ; sys_platform == 'win32'
mypy==1.15.0
mypy-extensions==1.0.0
nodeenv==1.9.1 nodeenv==1.9.1
numpy==2.1.3; python_version >= "3.12" numpy==2.2.3
oauthlib==3.2.2 oauthlib==3.2.2
odfpy==1.4.1 odfpy==1.4.1
openpyxl==3.1.5 openpyxl==3.1.5
ordered-set==4.1.0 ordered-set==4.1.0
packaging==24.2 packaging==24.2
pandas==2.2.3 pandas==2.2.3
parso==0.8.4
pathspec==0.12.1 pathspec==0.12.1
pbs-installer==2024.10.16 pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pdm==2.21.0
pillow==10.4.0 pillow==10.4.0
platformdirs==4.3.6 platformdirs==4.3.6
pluggy==1.5.0 pluggy==1.5.0
pre-commit==4.0.1 pre-commit==4.1.0
psycopg-binary==3.2.3; implementation_name != "pypy" prompt-toolkit==3.0.50
psycopg-pool==3.2.4 psutil==6.1.1
psycopg[binary,pool]==3.2.3 psycopg==3.2.4
pycparser==2.22; platform_python_implementation != "PyPy" psycopg-binary==3.2.4 ; implementation_name != 'pypy'
pydantic==2.10.2 psycopg-pool==3.2.5
pydantic-core==2.27.1 ptyprocess==0.7.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pygments==2.18.0 pure-eval==0.2.3
pycparser==2.22 ; platform_python_implementation != 'PyPy'
pydantic==2.10.6
pydantic-core==2.27.2
pygments==2.19.1
pyjwt==2.9.0 pyjwt==2.9.0
pylint==3.3.1 pylint==3.3.4
pylint-django==2.6.1 pylint-django==2.6.1
pylint-plugin-utils==0.8.2 pylint-plugin-utils==0.8.2
pyproject-api==1.8.0 pyproject-api==1.9.0
pyproject-hooks==1.2.0 pyright==1.1.394
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
python-dotenv==1.0.1 pytz==2025.1
pytz==2024.2
pyyaml==6.0.2 pyyaml==6.0.2
redis==5.2.0 redis==5.2.1
regex==2024.11.6 regex==2024.11.6
requests==2.32.3 requests==2.32.3
requests-file==2.1.0 requests-file==2.1.0
resolvelib==1.1.0
rich==13.9.4 rich==13.9.4
ruff==0.8.0 ruff==0.9.7
rules==3.5 rules==3.5
s3transfer==0.10.4 s3transfer==0.11.2
segno==1.6.1 segno==1.6.1
sentry-sdk==2.19.0 sentry-sdk==2.22.0
shellingham==1.5.4 six==1.17.0
six==1.16.0
sniffio==1.3.1 sniffio==1.3.1
socksio==1.0.0
soupsieve==2.6 soupsieve==2.6
sqlparse==0.5.2 sqlparse==0.5.3
stack-data==0.6.3
taskipy==1.14.1
tblib==3.0.0
tomli==2.2.1
tomlkit==0.13.2 tomlkit==0.13.2
tox==4.23.2 tox==4.24.1
tox-pdm==0.7.2 tox-uv==1.25.0
tqdm==4.67.1 tqdm==4.67.1
truststore==0.10.0; python_version >= "3.10" traitlets==5.14.3
types-pyyaml==6.0.12.20240917 types-pyyaml==6.0.12.20241230
types-requests==2.32.0.20241016
typing-extensions==4.12.2 typing-extensions==4.12.2
tzdata==2024.2 tzdata==2024.2
unearth==0.17.2 urllib3==2.3.0
urllib3==2.2.3 uv==0.6.2
virtualenv==20.27.1 virtualenv==20.29.2
watchfiles==1.0.4
wcwidth==0.2.13
webencodings==0.5.1 webencodings==0.5.1
# This file is @generated by PDM. # This file was autogenerated by uv via the following command:
# Please do not edit it manually. # uv export --frozen -o=requirements.txt --no-hashes --no-dev
annotated-types==0.7.0 annotated-types==0.7.0
anyio==4.6.2.post1
asgiref==3.8.1 asgiref==3.8.1
babel==2.16.0 asttokens==3.0.0
beautifulsoup4==4.12.3 babel==2.17.0
beautifulsoup4==4.13.3
bleach==6.2.0 bleach==6.2.0
blinker==1.9.0 boto3==1.36.26
boto3==1.35.71 botocore==1.36.26
botocore==1.35.71 certifi==2025.1.31
certifi==2024.8.30 cffi==1.17.1 ; platform_python_implementation != 'PyPy'
cffi==1.17.1; platform_python_implementation != "PyPy" charset-normalizer==3.4.1
charset-normalizer==3.4.0 colorama==0.4.6 ; sys_platform == 'win32'
cryptography==43.0.3 cryptography==44.0.1
decorator==5.2.0
defusedxml==0.7.1 defusedxml==0.7.1
dep-logic==0.4.9 django==5.1.6
distlib==0.3.9
django==5.1.3
django-bootstrap5==24.3 django-bootstrap5==24.3
django-cors-headers==4.6.0 django-cors-headers==4.7.0
django-csp==3.8 django-csp==3.8
django-debug-toolbar==4.4.6 django-debug-toolbar==4.4.6
django-environ==0.11.2 django-environ==0.11.2
django-modeltranslation==0.19.11 django-extensions==3.2.3
django-ical==1.9.2
django-modeltranslation==0.19.12
django-oauth-toolkit==3.0.1 django-oauth-toolkit==3.0.1
django-ratelimit==4.1.0 django-ratelimit==4.1.0
django-recurrence==1.11.1
django-redis==5.4.0 django-redis==5.4.0
django-rich==1.13.0 django-rich==1.14.0
django-storages==1.14.4 django-storages==1.14.5
django-stubs-ext==5.1.3
django-timezone-field==7.0 django-timezone-field==7.0
django-widget-tweaks==1.5.0 django-widget-tweaks==1.5.0
djangorestframework==3.15.2 djangorestframework==3.15.2
et-xmlfile==2.0.0 et-xmlfile==2.0.0
filelock==3.16.1 executing==2.2.0
findpython==0.6.2
freezegun==1.5.1 freezegun==1.5.1
gunicorn==23.0.0 gunicorn==23.0.0
h11==0.14.0 icalendar==6.1.1
hishel==0.0.33
httpcore==1.0.7
httpx[socks]==0.27.2
idna==3.10 idna==3.10
installer==0.7.0 ipython==8.32.0
jinja2==3.1.4 jedi==0.19.2
jinja2==3.1.5
jmespath==1.0.1 jmespath==1.0.1
jwcrypto==1.5.6 jwcrypto==1.5.6
lxml==5.3.0 lxml==5.3.1
markdown-it-py==3.0.0 markdown-it-py==3.0.0
markdownify==0.13.1 markdownify==0.13.1
markupsafe==3.0.2 markupsafe==3.0.2
matplotlib-inline==0.1.7
mdurl==0.1.2 mdurl==0.1.2
mistletoe==1.4.0 mistletoe==1.4.0
msgpack==1.1.0 numpy==2.2.3
numpy==2.1.3; python_version >= "3.12"
oauthlib==3.2.2 oauthlib==3.2.2
odfpy==1.4.1 odfpy==1.4.1
openpyxl==3.1.5 openpyxl==3.1.5
ordered-set==4.1.0 ordered-set==4.1.0
packaging==24.2 packaging==24.2
pandas==2.2.3 pandas==2.2.3
pbs-installer==2024.10.16 parso==0.8.4
pdm==2.21.0 pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pillow==10.4.0 pillow==10.4.0
platformdirs==4.3.6 prompt-toolkit==3.0.50
psycopg-binary==3.2.3; implementation_name != "pypy" psycopg==3.2.4
psycopg-pool==3.2.4 psycopg-binary==3.2.4 ; implementation_name != 'pypy'
psycopg[binary,pool]==3.2.3 psycopg-pool==3.2.5
pycparser==2.22; platform_python_implementation != "PyPy" ptyprocess==0.7.0 ; sys_platform != 'emscripten' and sys_platform != 'win32'
pydantic==2.10.2 pure-eval==0.2.3
pydantic-core==2.27.1 pycparser==2.22 ; platform_python_implementation != 'PyPy'
pygments==2.18.0 pydantic==2.10.6
pydantic-core==2.27.2
pygments==2.19.1
pyjwt==2.9.0 pyjwt==2.9.0
pyproject-hooks==1.2.0
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
python-dotenv==1.0.1 pytz==2025.1
pytz==2024.2 redis==5.2.1
redis==5.2.0
requests==2.32.3 requests==2.32.3
requests-file==2.1.0 requests-file==2.1.0
resolvelib==1.1.0
rich==13.9.4 rich==13.9.4
rules==3.5 rules==3.5
s3transfer==0.10.4 s3transfer==0.11.2
segno==1.6.1 segno==1.6.1
sentry-sdk==2.19.0 sentry-sdk==2.22.0
shellingham==1.5.4 six==1.17.0
six==1.16.0
sniffio==1.3.1
socksio==1.0.0
soupsieve==2.6 soupsieve==2.6
sqlparse==0.5.2 sqlparse==0.5.3
tomlkit==0.13.2 stack-data==0.6.3
truststore==0.10.0; python_version >= "3.10" traitlets==5.14.3
typing-extensions==4.12.2 typing-extensions==4.12.2
tzdata==2024.2 tzdata==2024.2
unearth==0.17.2 urllib3==2.3.0
urllib3==2.2.3 wcwidth==0.2.13
virtualenv==20.27.1
webencodings==0.5.1 webencodings==0.5.1
from typing import Optional
from django_ical.views import ICalFeed
from django.utils.text import slugify
from core.models import (
Conference,
Event,
)
class EventICalFeed(ICalFeed):
"""
EventICalFeed serializes Events to an iCal response.
"""
def __init__(self, events: list[Event], name: Optional[str] = None, conference: Optional[Conference] = None):
super().__init__()
self.name = name
self.conference = conference
self.events = events
def product_id(self) -> str:
issuer = self.conference.name if self.conference else 'Hub'
product = self.name if self.name else 'iCal export'
return f'-//{issuer}//{product}'
def title(self) -> str:
if self.name:
return self.name
return 'Hub iCal export'
def items(self) -> list[Event]:
return self.events
def item_title(self, item) -> str:
return item.name
def item_description(self, item) -> str:
return item.description
def item_start_datetime(self, item):
return item.schedule_start
def item_end_datetime(self, item):
return item.schedule_end
def item_location(self, item) -> str:
if item.room:
return item.room.name
if item.location:
return item.location
return ''
def item_guid(self, item) -> str:
return item.pk
def item_categories(self, item) -> list[str]:
categories = []
if item.recording == Event.Recording.YES:
categories.append('recorded')
elif item.recording == Event.Recording.NO:
categories.append('not recorded')
if item.kind == Event.Kind.OFFICIAL or item.assembly.is_official:
categories.append('official')
if item.track:
categories.append(item.track.name)
return categories
def file_name(self) -> str:
return slugify(self.title()) + '.ics'