2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-07-04 06:00:38 +00:00

!feat(backend): bump minimum python version (#12223)

* bump ci versions

* bump installer version

* bump tooling version ref

* bump doc refs

* bump / refactor code refs

* bump debug ref

* remove now unneeded deps

* bump release version

* remove distutils

* fix finder call

* remove old compat code

* add changelog entry

* lower cov target for now
This commit is contained in:
Matthias Mair
2026-06-24 09:42:35 +02:00
committed by GitHub
parent 09f11a27d9
commit de736ee5de
30 changed files with 49 additions and 126 deletions
+2 -2
View File
@@ -3,7 +3,7 @@
# In contrast with the "production" image (which is based on an Alpine image)
# we use a Debian-based image for the devcontainer
FROM mcr.microsoft.com/devcontainers/python:3.11-bookworm@sha256:e754c29c4e3ffcf6c794c1020e36a0812341d88ec9569a34704b975fa89e8848
FROM mcr.microsoft.com/devcontainers/python:3.12-trixie@sha256:5440cb68898d190ad6c6e8a4634ce89d0645bea47f9c8beb75612bb8e3983711
# InvenTree paths
ENV INVENTREE_HOME="/home/inventree"
@@ -25,7 +25,7 @@ RUN chmod +x init.sh
# Install required base packages
RUN apt update && apt install -y \
python3.11-dev python3.11-venv \
python3.12-dev python3.12-venv \
postgresql-client \
libldap2-dev libsasl2-dev \
libpango1.0-0 libcairo2 \
+1 -1
View File
@@ -14,7 +14,7 @@ pool:
strategy:
matrix:
Python39:
PYTHON_VERSION: '3.11'
PYTHON_VERSION: 3.12
maxParallel: 3
steps:
+1 -1
View File
@@ -9,7 +9,7 @@ on:
- l10
env:
python_version: 3.11
python_version: 3.12
permissions:
contents: read
+3 -3
View File
@@ -62,7 +62,7 @@ jobs:
contents: read
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: "3.11"
python_version: 3.12
runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps:
@@ -134,7 +134,7 @@ jobs:
contents: read
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: "3.11"
python_version: 3.12
runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps:
@@ -158,7 +158,7 @@ jobs:
id-token: write
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
python_version: "3.11"
python_version: 3.12
runs-on: ubuntu-latest # in the future we can try to use alternative runners here
steps:
+1 -1
View File
@@ -13,7 +13,7 @@ on:
branches-ignore: ["l10*"]
env:
python_version: 3.11
python_version: 3.12
node_version: 24
# The OS version must be set per job
server_start_sleep: 60
+1 -1
View File
@@ -15,7 +15,7 @@ permissions:
contents: read
env:
python_version: 3.11
python_version: 3.12
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+2 -2
View File
@@ -9,7 +9,7 @@ on:
branches-ignore: ["l10*"]
env:
python_version: 3.11
python_version: 3.12
node_version: 24
# The OS version must be set per job
server_start_sleep: 60
@@ -379,7 +379,7 @@ jobs:
continue-on-error: true # continue if a step fails so that coverage gets pushed
strategy:
matrix:
python_version: [3.11, 3.14]
python_version: [3.12, 3.14]
env:
INVENTREE_DB_NAME: ./inventree.sqlite
+3 -3
View File
@@ -7,7 +7,7 @@ on:
permissions:
contents: read
env:
python_version: 3.11
python_version: 3.12
jobs:
stable:
@@ -151,9 +151,9 @@ jobs:
fail-fast: false
matrix:
target:
- ubuntu:22.04
- ubuntu:24.04
- debian:12
- ubuntu:26.04
- debian:13
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # pin@v6.0.3
+1 -1
View File
@@ -6,7 +6,7 @@ on:
- master
env:
python_version: 3.11
python_version: 3.12
node_version: 24
permissions:
+5 -5
View File
@@ -21,9 +21,9 @@ before:
dependencies:
- curl
- poppler-utils
- "python3.11 | python3.12 | python3.13 | python3.14"
- "python3.11-venv | python3.12-venv | python3.13-venv | python3.14-venv"
- "python3.11-dev | python3.12-dev | python3.13-dev | python3.14-dev"
- "python3.12 | python3.13 | python3.14"
- "python3.12-venv | python3.13-venv | python3.14-venv"
- "python3.12-dev | python3.13-dev | python3.14-dev"
- python3-pip
- python3-cffi
- python3-brotli
@@ -36,6 +36,6 @@ dependencies:
- jq
- "libffi7 | libffi8"
targets:
ubuntu-22.04: true
ubuntu-24.04: true
debian-12: true
ubuntu-26.04: true
debian-13: true
+1 -1
View File
@@ -97,4 +97,4 @@ repos:
rev: 0.4.3
hooks:
- id: teyit
language_version: python3.11
language_version: python3.12
+1 -1
View File
@@ -47,7 +47,7 @@
"name": "InvenTree invoke schema",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/.venv/lib/python3.11/site-packages/invoke/__main__.py",
"program": "${workspaceFolder}/.venv/lib/python3.12/site-packages/invoke/__main__.py",
"cwd": "${workspaceFolder}",
"args": [
"dev.schema","--ignore-warnings"
+2
View File
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Breaking Changes
- [#12223](https://github.com/inventree/InvenTree/pull/12223) removes support for python 3.11 and stops providing packages for Debian 11 and Ubuntu 20.04.
### Added
### Changed
+1 -1
View File
@@ -24,7 +24,7 @@ flag_management:
carryforward: true
statuses:
- type: project
target: 40%
target: 38%
- name: web
carryforward: true
statuses:
+1 -1
View File
@@ -79,7 +79,7 @@ function detect_python() {
echo "${On_Red}"
echo "# POI07| Python ${SETUP_PYTHON} not found - aborting!"
echo "# POI07| Please ensure python can be executed with the command '$SETUP_PYTHON' by the current user '$USER'."
echo "# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.11'."
echo "# POI07| If you are using a different python version, please set the environment variable SETUP_PYTHON to the correct command - eg. 'python3.12'."
echo "${Color_Off}"
exit 1
fi
+1 -1
View File
@@ -26,7 +26,7 @@ export DATA_DIR=${APP_HOME}/data
export SETUP_NGINX_FILE=${SETUP_NGINX_FILE:-/etc/nginx/sites-enabled/inventree.conf}
export SETUP_ADMIN_PASSWORD_FILE=${CONF_DIR}/admin_password.txt
export SETUP_NO_CALLS=${SETUP_NO_CALLS:-false}
export SETUP_PYTHON=${SETUP_PYTHON:-python3.11}
export SETUP_PYTHON=${SETUP_PYTHON:-python3.12}
export SETUP_ADMIN_NOCREATION=${SETUP_ADMIN_NOCREATION:-false}
# SETUP_DEBUG can be set to get debug info
# SETUP_EXTRA_PIP can be set to install extra pip packages
+2 -2
View File
@@ -4,10 +4,10 @@ import json
import os
import re
from datetime import datetime
from distutils.version import StrictVersion # type: ignore[import]
from pathlib import Path
import requests
from packaging.version import Version
here = Path(__file__).parent
@@ -57,7 +57,7 @@ def fetch_rtd_versions():
print('No RTD token found - skipping RTD version fetch')
# Sort versions by version number
versions = sorted(versions, key=lambda x: StrictVersion(x['version']), reverse=True)
versions = sorted(versions, key=lambda x: Version(x['version']), reverse=True)
# Add "latest" version first
if not any(x['title'] == 'latest' for x in versions):
+1 -1
View File
@@ -325,7 +325,7 @@ ARG INVENTREE_TAG
# prebuild stage - needs a lot of build dependencies
# make sure, the alpine and python version matches the version used in the inventree base image
FROM python:3.11-alpine3.18 as prebuild
FROM python:3.12-alpine3.18 as prebuild
# Install whatever development dependency is needed (e.g. cups-dev, gcc, the musl-dev build tools and the pip pycups package)
RUN apk add --no-cache cups-dev gcc musl-dev && \
+1 -1
View File
@@ -366,7 +366,7 @@ extra:
# provider: google
# property: UA-143467500-1
min_python_version: 3.11
min_python_version: 3.12
min_invoke_version: 2.0.0
django_version: 5.2
docker_postgres_version: 17
+1 -1
View File
@@ -97,7 +97,7 @@ skip-magic-trailing-comma = true
line-ending = "auto"
[tool.uv.pip]
python-version = "3.11"
python-version = "3.12"
no-strip-extras=true
generate-hashes=true
+2 -2
View File
@@ -9,9 +9,9 @@ python:
- requirements: src/backend/requirements.txt
build:
os: "ubuntu-22.04"
os: "ubuntu-24.04"
tools:
python: "3.11"
python: "3.12"
jobs:
post_install:
- pip install -U invoke
+1 -1
View File
@@ -18,7 +18,7 @@ from .api_version import INVENTREE_API_TEXT, INVENTREE_API_VERSION
INVENTREE_SW_VERSION = '1.5.0 dev'
# Minimum supported Python version
MIN_PYTHON_VERSION = (3, 11)
MIN_PYTHON_VERSION = (3, 12)
logger = logging.getLogger('inventree')
+1 -13
View File
@@ -1,19 +1,7 @@
"""Types for settings."""
import sys
from collections.abc import Callable
from typing import Any, TypedDict
if sys.version_info >= (3, 11):
from typing import NotRequired # pragma: no cover
else:
class NotRequired: # pragma: no cover
"""NotRequired type helper is only supported with Python 3.11+."""
def __class_getitem__(cls, item):
"""Return the item."""
return item
from typing import Any, NotRequired, TypedDict
class SettingsKeyType(TypedDict, total=False):
+5 -10
View File
@@ -108,9 +108,6 @@ def handle_error(error, do_raise: bool = True, do_log: bool = True, log_name: st
def get_entrypoints():
"""Returns list for entrypoints for InvenTree plugins."""
# on python before 3.12, we need to use importlib_metadata
if sys.version_info < (3, 12):
return entry_points().get('inventree_plugins', [])
return entry_points(group='inventree_plugins')
@@ -190,13 +187,11 @@ def get_modules(pkg, path=None):
continue
try:
if sys.version_info < (3, 12):
module = finder.find_module(name).load_module(name)
else:
spec = finder.find_spec(name)
module = module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
spec = finder.find_spec(name, path)
module = module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
pkg_names = getattr(module, '__all__', None)
for k, v in vars(module).items():
if not k.startswith('_') and (pkg_names is None or k in pkg_names):
+1 -2
View File
@@ -117,8 +117,7 @@ def plugins_file_hash():
try:
with pf.open('rb') as f:
# Note: Once we support 3.11 as a minimum, we can use hashlib.file_digest
return hashlib.sha256(f.read()).hexdigest()
return hashlib.file_digest(f, 'sha256').hexdigest()
except Exception:
log_error('plugins_file_hash', scope='plugins')
return None
+3 -4
View File
@@ -7,6 +7,7 @@ import warnings
from datetime import datetime
from importlib.metadata import PackageNotFoundError, metadata
from pathlib import Path
from sysconfig import get_path
from typing import Optional
from django.conf import settings
@@ -517,7 +518,6 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase):
return InvenTree.helpers.pui_url(f'/settings/admin/plugin/{config.pk}/')
return InvenTree.helpers.pui_url('/settings/admin/plugin/')
# region package info
@mark_final
def _get_package_commit(self):
"""Get last git commit for the plugin."""
@@ -527,10 +527,9 @@ class InvenTreePlugin(VersionMixin, MixinBase, MetaBase):
@mark_final
def is_editable(cls):
"""Returns if the current part is editable."""
from distutils.sysconfig import get_python_lib
pkg_name = cls.__name__.split('.')[0]
dist_info = list(Path(get_python_lib()).glob(f'{pkg_name}-*.dist-info'))
py_lib = get_path('platlib')
dist_info = list(Path(py_lib).glob(f'{pkg_name}-*.dist-info'))
return bool(len(dist_info) == 1)
@classmethod
+3 -9
View File
@@ -585,15 +585,9 @@ class PluginsRegistry:
# Gather Modules
if parent_path:
# On python 3.12 use new loader method
if sys.version_info < (3, 12):
raw_module = _load_source(
plugin_dir, str(parent_obj.joinpath('__init__.py'))
)
else:
raw_module = SourceFileLoader(
plugin_dir, str(parent_obj.joinpath('__init__.py'))
).load_module()
raw_module = SourceFileLoader(
plugin_dir, str(parent_obj.joinpath('__init__.py'))
).load_module()
else:
raw_module = importlib.import_module(plugin_dir)
-49
View File
@@ -594,55 +594,6 @@ sqlparse==0.5.5 \
# -c src/backend/requirements.txt
# django
# django-silk
tomli==2.4.1 \
--hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \
--hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
--hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
--hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \
--hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \
--hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \
--hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \
--hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \
--hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
--hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
--hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \
--hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \
--hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \
--hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
--hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \
--hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
--hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
--hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
--hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
--hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \
--hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \
--hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
--hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
--hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \
--hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \
--hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \
--hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \
--hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
--hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \
--hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \
--hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \
--hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
--hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
--hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \
--hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \
--hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \
--hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
--hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \
--hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \
--hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
--hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \
--hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \
--hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
--hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
--hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
# via coverage
ty==0.0.51 \
--hash=sha256:08adbe53fb8bc9e7f00e89bf1d3c875a02cda76d83f109d2e6ab1ff35a7bfa8c \
--hash=sha256:25a5b31e6f23fd5dc63ad29087ded09932409e4154e2fe07bbaed015035990bb \
-5
View File
@@ -8,10 +8,6 @@ asgiref==3.11.1 \
# django-allauth
# django-cors-headers
# django-structlog
async-timeout==5.0.1 \
--hash=sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c \
--hash=sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3
# via redis
attrs==26.1.0 \
--hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \
--hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32
@@ -1929,7 +1925,6 @@ typing-extensions==4.15.0 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via
# django-redis
# dulwich
# flexcache
# flexparser
# grpcio
+1 -1
View File
@@ -7,7 +7,7 @@
[build.environment]
VITE_DEMO = "true"
PYTHON_VERSION = "3.11"
PYTHON_VERSION = "3.12"
# Send requests to subpath