From 8bdcd415bc188c79567a9ef062138caa4b7d0ae4 Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Mon, 19 Jan 2026 12:59:12 +0100 Subject: [PATCH] make version specific install req --- .pre-commit-config.yaml | 4 + docs/requirements.txt | 4 +- pyproject.toml | 2 +- src/backend/requirements-3.14.txt | 483 ++++++++++++++++++++++++++++++ src/backend/requirements-dev.txt | 2 + src/backend/requirements.txt | 4 + tasks.py | 69 +++-- 7 files changed, 535 insertions(+), 33 deletions(-) create mode 100644 src/backend/requirements-3.14.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4894553a9a..b0b4b878b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,6 +39,10 @@ repos: name: pip-compile requirements.txt args: [src/backend/requirements.in, -o, src/backend/requirements.txt] files: src/backend/requirements\.(in|txt)$ + - id: pip-compile + name: pip-compile requirements.txt 3.14 + args: [src/backend/requirements.in, -o, src/backend/requirements-3.14.txt, --python-version=3.14] + files: src/backend/requirements\.(in|txt)$ - id: pip-compile name: pip-compile requirements.txt args: [contrib/dev_reqs/requirements.in, -o, contrib/dev_reqs/requirements.txt, -b, src/backend/requirements.txt] diff --git a/docs/requirements.txt b/docs/requirements.txt index 5031d04cf1..2f0bcff4e0 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -187,7 +187,9 @@ super-collections==0.6.2 termcolor==3.3.0 # via mkdocs-macros-plugin typing-extensions==4.15.0 - # via beautifulsoup4 + # via + # anyio + # beautifulsoup4 urllib3==2.6.3 # via requests watchdog==6.0.0 diff --git a/pyproject.toml b/pyproject.toml index 3169165d6b..037916b12b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,7 @@ skip-magic-trailing-comma = true line-ending = "auto" [tool.uv.pip] -python-version = "3.14" +python-version = "3.11" no-strip-extras=true # generate-hashes=true diff --git a/src/backend/requirements-3.14.txt b/src/backend/requirements-3.14.txt new file mode 100644 index 0000000000..4603b71215 --- /dev/null +++ b/src/backend/requirements-3.14.txt @@ -0,0 +1,483 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile src/backend/requirements.in -o src/backend/requirements-3.14.txt --python-version=3.14 +asgiref==3.11.0 + # via + # django + # django-allauth + # django-cors-headers + # django-structlog +attrs==25.4.0 + # via + # jsonschema + # referencing +babel==2.17.0 + # via py-moneyed +bcrypt==5.0.0 + # via paramiko +bleach[css]==6.3.0 + # via django-markdownify +blessed==1.25.0 + # via -r src/backend/requirements.in +boto3==1.42.30 + # via + # django-anymail + # django-storages +botocore==1.42.30 + # via + # boto3 + # s3transfer +brotli==1.2.0 + # via fonttools +certifi==2026.1.4 + # via + # requests + # sentry-sdk +cffi==2.0.0 + # via + # cryptography + # pynacl + # weasyprint +charset-normalizer==3.4.4 + # via requests +cryptography==46.0.3 + # via + # -r src/backend/requirements.in + # django-anymail + # djangorestframework-simplejwt + # fido2 + # jwcrypto + # paramiko + # pyjwt +cssselect2==0.8.0 + # via weasyprint +defusedxml==0.7.1 + # via python3-openid +django==5.2.10 + # via + # -r src/backend/requirements.in + # django-allauth + # django-anymail + # django-cors-headers + # django-dbbackup + # django-error-report-2 + # django-filter + # django-flags + # django-ical + # django-js-asset + # django-markdownify + # django-money + # django-oauth-toolkit + # django-otp + # django-picklefield + # django-q2 + # django-recurrence + # django-redis + # django-sesame + # django-sql-utils + # django-sslserver + # django-stdimage + # django-storages + # django-structlog + # django-taggit + # django-xforwardedfor-middleware + # djangorestframework + # djangorestframework-simplejwt + # drf-spectacular +django-allauth[headless, mfa, openid, saml, socialaccount]==65.14.0 + # via -r src/backend/requirements.in +django-anymail[amazon-ses, postal]==14.0 + # via -r src/backend/requirements.in +django-cleanup==9.0.0 + # via -r src/backend/requirements.in +django-cors-headers==4.9.0 + # via -r src/backend/requirements.in +django-dbbackup==5.1.2 + # via -r src/backend/requirements.in +django-error-report-2==0.4.2 + # via -r src/backend/requirements.in +django-filter==25.2 + # via -r src/backend/requirements.in +django-flags==5.1.0 + # via -r src/backend/requirements.in +django-ical==1.9.2 + # via -r src/backend/requirements.in +django-ipware==7.0.1 + # via django-structlog +django-js-asset==3.1.2 + # via django-mptt +django-mailbox==4.10.1 + # via -r src/backend/requirements.in +django-maintenance-mode==0.22.0 + # via -r src/backend/requirements.in +django-markdownify==0.9.6 + # via -r src/backend/requirements.in +django-money==3.5.4 + # via -r src/backend/requirements.in +django-mptt==0.18.0 + # via -r src/backend/requirements.in +django-oauth-toolkit==3.2.0 + # via -r src/backend/requirements.in +django-otp==1.3.0 + # via -r src/backend/requirements.in +django-picklefield==3.4.0 + # via django-q2 +django-q-sentry==0.1.6 + # via -r src/backend/requirements.in +django-q2==1.9.0 + # via -r src/backend/requirements.in +django-recurrence==1.14 + # via django-ical +django-redis==6.0.0 + # via -r src/backend/requirements.in +django-sesame==3.2.3 + # via -r src/backend/requirements.in +django-sql-utils==0.7.0 + # via -r src/backend/requirements.in +django-sslserver==0.22 + # via -r src/backend/requirements.in +django-stdimage==6.0.2 + # via -r src/backend/requirements.in +django-storages[s3, sftp]==1.14.6 + # via -r src/backend/requirements.in +django-structlog==10.0.0 + # via -r src/backend/requirements.in +django-taggit==6.1.0 + # via -r src/backend/requirements.in +django-xforwardedfor-middleware==2.0 + # via -r src/backend/requirements.in +djangorestframework==3.16.1 + # via + # -r src/backend/requirements.in + # djangorestframework-simplejwt + # drf-spectacular +djangorestframework-simplejwt[crypto]==5.5.1 + # via -r src/backend/requirements.in +docutils==0.22.4 + # via -r src/backend/requirements.in +drf-spectacular==0.29.0 + # via -r src/backend/requirements.in +dulwich==1.0.0 + # via -r src/backend/requirements.in +et-xmlfile==2.0.0 + # via openpyxl +feedparser==6.0.12 + # via -r src/backend/requirements.in +fido2==2.1.1 + # via django-allauth +flexcache==0.3 + # via pint +flexparser==0.4 + # via pint +fonttools[woff]==4.61.1 + # via weasyprint +googleapis-common-protos==1.72.0 + # via + # opentelemetry-exporter-otlp-proto-grpc + # opentelemetry-exporter-otlp-proto-http +grpcio==1.76.0 + # via + # -r src/backend/requirements.in + # opentelemetry-exporter-otlp-proto-grpc +gunicorn==23.0.0 + # via -r src/backend/requirements.in +icalendar==6.3.2 + # via django-ical +idna==3.11 + # via + # django-anymail + # requests +importlib-metadata==8.7.1 + # via opentelemetry-api +inflection==0.5.1 + # via drf-spectacular +invoke==2.2.1 + # via paramiko +isodate==0.7.2 + # via python3-saml +jinja2==3.1.6 + # via -r src/backend/requirements.in +jmespath==1.0.1 + # via + # boto3 + # botocore +jsonschema==4.26.0 + # via drf-spectacular +jsonschema-specifications==2025.9.1 + # via jsonschema +jwcrypto==1.5.6 + # via django-oauth-toolkit +lxml==6.0.2 + # via + # python3-saml + # xmlsec +markdown==3.10 + # via django-markdownify +markupsafe==3.0.3 + # via jinja2 +oauthlib==3.3.1 + # via + # django-allauth + # django-oauth-toolkit +openpyxl==3.1.5 + # via tablib +opentelemetry-api==1.39.1 + # via + # -r src/backend/requirements.in + # opentelemetry-exporter-otlp-proto-grpc + # opentelemetry-exporter-otlp-proto-http + # opentelemetry-instrumentation + # opentelemetry-instrumentation-dbapi + # opentelemetry-instrumentation-django + # opentelemetry-instrumentation-psycopg + # opentelemetry-instrumentation-pymysql + # opentelemetry-instrumentation-redis + # opentelemetry-instrumentation-requests + # opentelemetry-instrumentation-sqlite3 + # opentelemetry-instrumentation-system-metrics + # opentelemetry-instrumentation-wsgi + # opentelemetry-sdk + # opentelemetry-semantic-conventions +opentelemetry-exporter-otlp==1.39.1 + # via -r src/backend/requirements.in +opentelemetry-exporter-otlp-proto-common==1.39.1 + # via + # opentelemetry-exporter-otlp-proto-grpc + # opentelemetry-exporter-otlp-proto-http +opentelemetry-exporter-otlp-proto-grpc==1.39.1 + # via opentelemetry-exporter-otlp +opentelemetry-exporter-otlp-proto-http==1.39.1 + # via opentelemetry-exporter-otlp +opentelemetry-instrumentation==0.60b1 + # via + # opentelemetry-instrumentation-dbapi + # opentelemetry-instrumentation-django + # opentelemetry-instrumentation-psycopg + # opentelemetry-instrumentation-pymysql + # opentelemetry-instrumentation-redis + # opentelemetry-instrumentation-requests + # opentelemetry-instrumentation-sqlite3 + # opentelemetry-instrumentation-system-metrics + # opentelemetry-instrumentation-wsgi +opentelemetry-instrumentation-dbapi==0.60b1 + # via + # opentelemetry-instrumentation-psycopg + # opentelemetry-instrumentation-pymysql + # opentelemetry-instrumentation-sqlite3 +opentelemetry-instrumentation-django==0.60b1 + # via -r src/backend/requirements.in +opentelemetry-instrumentation-psycopg==0.60b1 + # via -r src/backend/requirements.in +opentelemetry-instrumentation-pymysql==0.60b1 + # via -r src/backend/requirements.in +opentelemetry-instrumentation-redis==0.60b1 + # via -r src/backend/requirements.in +opentelemetry-instrumentation-requests==0.60b1 + # via -r src/backend/requirements.in +opentelemetry-instrumentation-sqlite3==0.60b1 + # via -r src/backend/requirements.in +opentelemetry-instrumentation-system-metrics==0.60b1 + # via -r src/backend/requirements.in +opentelemetry-instrumentation-wsgi==0.60b1 + # via + # -r src/backend/requirements.in + # opentelemetry-instrumentation-django +opentelemetry-proto==1.39.1 + # via + # opentelemetry-exporter-otlp-proto-common + # opentelemetry-exporter-otlp-proto-grpc + # opentelemetry-exporter-otlp-proto-http +opentelemetry-sdk==1.39.1 + # via + # -r src/backend/requirements.in + # opentelemetry-exporter-otlp-proto-grpc + # opentelemetry-exporter-otlp-proto-http +opentelemetry-semantic-conventions==0.60b1 + # via + # opentelemetry-instrumentation + # opentelemetry-instrumentation-dbapi + # opentelemetry-instrumentation-django + # opentelemetry-instrumentation-redis + # opentelemetry-instrumentation-requests + # opentelemetry-instrumentation-wsgi + # opentelemetry-sdk +opentelemetry-util-http==0.60b1 + # via + # opentelemetry-instrumentation-django + # opentelemetry-instrumentation-requests + # opentelemetry-instrumentation-wsgi +packaging==25.0 + # via + # gunicorn + # opentelemetry-instrumentation +paramiko==4.0.0 + # via django-storages +pdf2image==1.17.0 + # via -r src/backend/requirements.in +pillow==12.1.0 + # via + # -r src/backend/requirements.in + # django-stdimage + # pdf2image + # python-barcode + # qrcode + # weasyprint +pint==0.25.2 + # via -r src/backend/requirements.in +pip-licenses==5.5.0 + # via -r src/backend/requirements.in +platformdirs==4.5.1 + # via pint +ppf-datamatrix==0.2 + # via -r src/backend/requirements.in +prettytable==3.17.0 + # via pip-licenses +protobuf==6.33.4 + # via + # googleapis-common-protos + # opentelemetry-proto +psutil==7.2.1 + # via opentelemetry-instrumentation-system-metrics +py-moneyed==3.0 + # via django-money +pycparser==2.23 + # via cffi +pydyf==0.12.1 + # via weasyprint +pyjwt[crypto]==2.10.1 + # via + # django-allauth + # djangorestframework-simplejwt +pynacl==1.6.2 + # via paramiko +pypdf==6.6.0 + # via -r src/backend/requirements.in +pyphen==0.17.2 + # via weasyprint +python-barcode[images]==0.16.1 + # via -r src/backend/requirements.in +python-dateutil==2.9.0.post0 + # via + # botocore + # django-recurrence + # icalendar +python-dotenv==1.2.1 + # via -r src/backend/requirements.in +python-fsutil==0.16.0 + # via django-maintenance-mode +python-ipware==3.0.0 + # via django-ipware +python3-openid==3.2.0 + # via django-allauth +python3-saml==1.16.0 + # via django-allauth +pyyaml==6.0.3 + # via + # -r src/backend/requirements.in + # drf-spectacular + # tablib +qrcode[pil]==8.2 + # via + # -r src/backend/requirements.in + # django-allauth +rapidfuzz==3.14.3 + # via -r src/backend/requirements.in +redis==7.1.0 + # via django-redis +referencing==0.37.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.5 + # via + # django-allauth + # django-anymail + # django-oauth-toolkit + # opentelemetry-exporter-otlp-proto-http +rpds-py==0.30.0 + # via + # jsonschema + # referencing +s3transfer==0.16.0 + # via boto3 +sentry-sdk==2.49.0 + # via + # -r src/backend/requirements.in + # django-q-sentry +setuptools==80.9.0 + # via + # -r src/backend/requirements.in + # django-money +sgmllib3k==1.0.0 + # via feedparser +six==1.17.0 + # via python-dateutil +sqlparse==0.5.5 + # via + # django + # django-sql-utils +structlog==25.5.0 + # via django-structlog +tablib[xls, xlsx, yaml]==3.9.0 + # via -r src/backend/requirements.in +tinycss2==1.4.0 + # via + # bleach + # cssselect2 + # weasyprint +tinyhtml5==2.0.0 + # via weasyprint +typing-extensions==4.15.0 + # via + # flexcache + # flexparser + # grpcio + # jwcrypto + # opentelemetry-api + # opentelemetry-exporter-otlp-proto-grpc + # opentelemetry-exporter-otlp-proto-http + # opentelemetry-sdk + # opentelemetry-semantic-conventions + # pint + # py-moneyed +tzdata==2025.3 + # via icalendar +uritemplate==4.2.0 + # via drf-spectacular +urllib3==2.6.3 + # via + # botocore + # django-anymail + # dulwich + # requests + # sentry-sdk +wcwidth==0.2.14 + # via + # blessed + # prettytable +weasyprint==66.0 + # via -r src/backend/requirements.in +webencodings==0.5.1 + # via + # bleach + # cssselect2 + # tinycss2 + # tinyhtml5 +whitenoise==6.11.0 + # via -r src/backend/requirements.in +wrapt==1.17.3 + # via + # opentelemetry-instrumentation + # opentelemetry-instrumentation-dbapi + # opentelemetry-instrumentation-redis +xlrd==2.0.2 + # via tablib +xlwt==1.3.0 + # via tablib +xmlsec==1.3.17 + # via + # -r src/backend/requirements.in + # python3-saml +zipp==3.23.0 + # via importlib-metadata +zopfli==0.4.0 + # via fonttools diff --git a/src/backend/requirements-dev.txt b/src/backend/requirements-dev.txt index 234c51d1dd..23ed43c57d 100644 --- a/src/backend/requirements-dev.txt +++ b/src/backend/requirements-dev.txt @@ -134,6 +134,8 @@ sqlparse==0.5.5 # -c src/backend/requirements.txt # django # django-silk +tomli==2.4.0 + # via coverage ty==0.0.1a21 # via -r src/backend/requirements-dev.in types-psycopg2==2.9.21.20251012 diff --git a/src/backend/requirements.txt b/src/backend/requirements.txt index 207847199b..cd4831a799 100644 --- a/src/backend/requirements.txt +++ b/src/backend/requirements.txt @@ -6,6 +6,8 @@ asgiref==3.11.0 # django-allauth # django-cors-headers # django-structlog +async-timeout==5.0.1 + # via redis attrs==25.4.0 # via # jsonschema @@ -428,6 +430,7 @@ tinyhtml5==2.0.0 # via weasyprint typing-extensions==4.15.0 # via + # dulwich # flexcache # flexparser # grpcio @@ -439,6 +442,7 @@ typing-extensions==4.15.0 # opentelemetry-semantic-conventions # pint # py-moneyed + # referencing tzdata==2025.3 # via icalendar uritemplate==4.2.0 diff --git a/tasks.py b/tasks.py index da042c4489..fe9abc4233 100644 --- a/tasks.py +++ b/tasks.py @@ -417,6 +417,32 @@ def manage(c, cmd, pty: bool = False, env=None): run(c, f'python3 manage.py {cmd}', manage_py_dir(), pty, env) +def run_install(c, uv, install_file, run_preflight=True): + """Run the installation of python packages from a requirements file.""" + info(f"Installing required python packages from '{install_file}'") + if not Path(install_file).is_file(): + raise FileNotFoundError(f"Requirements file '{install_file}' not found") + + # Install required Python packages with PIP + if not uv: + if run_preflight: + run( + c, + 'pip3 install --no-cache-dir --disable-pip-version-check -U pip setuptools', + ) + run( + c, + f'pip3 install --no-cache-dir --disable-pip-version-check -U -r {install_file}', + ) + else: + if run_preflight: + run( + c, + 'pip3 install --no-cache-dir --disable-pip-version-check -U uv setuptools', + ) + run(c, f'uv pip install -U -r {install_file}') + + def yarn(c, cmd): """Runs a given command against the yarn package manager. @@ -492,16 +518,7 @@ def plugins(c, uv=False): get_plugin_file, ) - plugin_file = get_plugin_file() - - info(f"Installing plugin packages from '{plugin_file}'") - - # Install the plugins - if not uv: - run(c, f"pip3 install --disable-pip-version-check -U -r '{plugin_file}'") - else: - run(c, 'pip3 install --no-cache-dir --disable-pip-version-check uv') - run(c, f"uv pip install -r '{plugin_file}'") + run_install(c, uv, get_plugin_file(), run_preflight=False) # Collect plugin static files manage(c, 'collectplugins') @@ -517,29 +534,19 @@ def plugins(c, uv=False): def install(c, uv=False, skip_plugins=False): """Installs required python packages.""" # Ensure path is relative to *this* directory - INSTALL_FILE = local_dir().joinpath('src/backend/requirements.txt') + install_file = local_dir().joinpath('src/backend/requirements.txt') - info(f"Installing required python packages from '{INSTALL_FILE}'") + # Test if there is a version specific requirements file + sys_ver_s = python_version().split('.') + sys_string = f'{sys_ver_s[0]}.{sys_ver_s[1]}' + install_file_vers = local_dir().joinpath( + f'src/backend/requirements-{sys_string}.txt' + ) + if install_file_vers.exists(): + install_file = install_file_vers + info(f'Using version-specific requirements file: {install_file_vers}') - if not Path(INSTALL_FILE).is_file(): - raise FileNotFoundError(f"Requirements file '{INSTALL_FILE}' not found") - - # Install required Python packages with PIP - if not uv: - run( - c, - 'pip3 install --no-cache-dir --disable-pip-version-check -U pip setuptools', - ) - run( - c, - f'pip3 install --no-cache-dir --disable-pip-version-check -U -r {INSTALL_FILE}', - ) - else: - run( - c, - 'pip3 install --no-cache-dir --disable-pip-version-check -U uv setuptools', - ) - run(c, f'uv pip install -U -r {INSTALL_FILE}') + run_install(c, uv, install_file) # Run plugins install if not skip_plugins: