Package: src:python-django Version: 3:5.2.17-1 User: [email protected] Usertags: python3.15 Tags: patch, ftbfs, forky, sid
Hi! While rebuilding the python related packages against the Python 3.15rc1 version we found that python-django fails to build from source [1]. There are three separate issues related to python 3.15. First, tests failing with `NameError: name 'SomeType' is not defined. Did you mean: 'TokenType'?`. This was fixed upstream with Commit e7f539f [2]. Second, the error message for `test_invalid_choice_db_option` has changed. To fix this, it required applying a few upstream patches [3] [4]. Third, test_strip_tags failed with `sys.version_info >= min_fixed_security[sys.version_info[:2]] KeyError: (3, 15)`, this is caused by line 136 of tests/utils_tests/test_html.py, which defines htmlparser_fixed_security but that's never used and it's later recrated in line 151 in a way that avoids the error, the related upstream fix about this is in [5], but backporting the fix is actually only deleting the line 136. I applied the upstream fixes in the sandbox [5] to be able to build the packages that depend on python-django, please consider applying the patch to support the upcoming 3.15 version. Happy hacking, [1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4415709/raw/python-django_5.2.17-1+py315.1_amd64-2026-08-22T01:25:30Z.build [2]: https://github.com/django/django/commit/e7f539f813bd56a71ca3c1fbf379f47691002086 [3]: https://github.com/django/django/pull/20021 [4]: https://github.com/django/django/commit/ed13a58bf63df94508c8a0fe779da0b6a2bc26bb [5]: https://github.com/django/django/commit/185b049 [6]: https://debusine.debian.net/debian/r-python-python3.15/ -- "Can you imagine what I would do if I could do all I can?" -- Sun Tzu Saludos /\/\ /\ >< `/
From: Jacob Walls <[email protected]> Date: Wed, 6 May 2026 15:39:41 -0400 Subject: [PATCH] Refs #36712, #36664 -- Used annotation_format parameter of getfullargspec() on Python 3.15. https://github.com/python/cpython/pull/149457 Origin: upstream, https://github.com/django/django/commit/e7f539f813bd56a71ca3c1fbf379f47691002086 --- django/contrib/admin/templatetags/base.py | 9 +++------ django/template/base.py | 5 ++--- django/template/library.py | 23 ++++++++++------------- django/utils/inspect.py | 27 ++++++++++++++++++++++----- 4 files changed, 37 insertions(+), 27 deletions(-) Index: python-django/django/contrib/admin/templatetags/base.py =================================================================== --- python-django.orig/django/contrib/admin/templatetags/base.py +++ python-django/django/contrib/admin/templatetags/base.py @@ -1,7 +1,5 @@ -from inspect import getfullargspec - from django.template.library import InclusionNode, parse_bits -from django.utils.inspect import lazy_annotations +from django.utils.inspect import getfullargspec class InclusionAdminNode(InclusionNode): @@ -12,10 +10,9 @@ class InclusionAdminNode(InclusionNode): def __init__(self, parser, token, func, template_name, takes_context=True): self.template_name = template_name - with lazy_annotations(): - params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = ( - getfullargspec(func) - ) + params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec( + func + ) bits = token.split_contents() args, kwargs = parse_bits( parser, Index: python-django/django/template/base.py =================================================================== --- python-django.orig/django/template/base.py +++ python-django/django/template/base.py @@ -58,7 +58,7 @@ from enum import Enum from django.template.context import BaseContext from django.utils.formats import localize from django.utils.html import conditional_escape -from django.utils.inspect import lazy_annotations, signature +from django.utils.inspect import getfullargspec, signature from django.utils.regex_helper import _lazy_re_compile from django.utils.safestring import SafeData, SafeString, mark_safe from django.utils.text import get_text_list, smart_split, unescape_string_literal @@ -761,8 +761,7 @@ class FilterExpression: # Check to see if a decorator is providing the real function. func = inspect.unwrap(func) - with lazy_annotations(): - args, _, _, defaults, _, _, _ = inspect.getfullargspec(func) + args, _, _, defaults, _, _, _ = getfullargspec(func) alen = len(args) dlen = len(defaults or []) # Not enough OR Too many Index: python-django/django/template/library.py =================================================================== --- python-django.orig/django/template/library.py +++ python-django/django/template/library.py @@ -1,10 +1,10 @@ from collections.abc import Iterable from functools import wraps from importlib import import_module -from inspect import getfullargspec, unwrap +from inspect import unwrap from django.utils.html import conditional_escape -from django.utils.inspect import lazy_annotations +from django.utils.inspect import getfullargspec from .base import Node, Template, token_kwargs from .exceptions import TemplateSyntaxError @@ -110,16 +110,15 @@ class Library: """ def dec(func): - with lazy_annotations(): - ( - params, - varargs, - varkw, - defaults, - kwonly, - kwonly_defaults, - _, - ) = getfullargspec(unwrap(func)) + ( + params, + varargs, + varkw, + defaults, + kwonly, + kwonly_defaults, + _, + ) = getfullargspec(unwrap(func)) function_name = name or func.__name__ @wraps(func) @@ -166,16 +165,15 @@ class Library: def dec(func): nonlocal end_name - with lazy_annotations(): - ( - params, - varargs, - varkw, - defaults, - kwonly, - kwonly_defaults, - _, - ) = getfullargspec(unwrap(func)) + ( + params, + varargs, + varkw, + defaults, + kwonly, + kwonly_defaults, + _, + ) = getfullargspec(unwrap(func)) function_name = name or func.__name__ if end_name is None: @@ -250,16 +248,15 @@ class Library: """ def dec(func): - with lazy_annotations(): - ( - params, - varargs, - varkw, - defaults, - kwonly, - kwonly_defaults, - _, - ) = getfullargspec(unwrap(func)) + ( + params, + varargs, + varkw, + defaults, + kwonly, + kwonly_defaults, + _, + ) = getfullargspec(unwrap(func)) function_name = name or func.__name__ @wraps(func) Index: python-django/django/utils/inspect.py =================================================================== --- python-django.orig/django/utils/inspect.py +++ python-django/django/utils/inspect.py @@ -3,16 +3,17 @@ import inspect import threading from contextlib import contextmanager -from django.utils.version import PY314 +from django.utils.version import PY314, PY315 if PY314: import annotationlib - lock = threading.Lock() - safe_signature_from_callable = functools.partial( - inspect._signature_from_callable, - annotation_format=annotationlib.Format.FORWARDREF, - ) + if not PY315: + lock = threading.Lock() + safe_signature_from_callable = functools.partial( + inspect._signature_from_callable, + annotation_format=annotationlib.Format.FORWARDREF, + ) @functools.lru_cache(maxsize=512) @@ -96,12 +97,12 @@ def lazy_annotations(): compatibility with Python 3.14+ deferred evaluation, patch the module-level helper to provide the annotation_format that we are using elsewhere. - This private helper could be removed when there is an upstream solution for - https://github.com/python/cpython/issues/141560. + This private helper should only be used for Python 3.14, as + https://github.com/python/cpython/issues/141560 was fixed in 3.15. This context manager is not reentrant. """ - if not PY314: + if PY315 or not PY314: yield return with lock: @@ -113,6 +114,22 @@ def lazy_annotations(): inspect._signature_from_callable = original_helper +def getfullargspec(*args, annotation_format=None, **kwargs): + """ + A wrapper around inspect.getfullargspec that leaves deferred annotations + unevaluated on Python 3.14+, since they are not used in our case. + """ + if PY315: + return inspect.getfullargspec( + *args, **kwargs, annotation_format=annotationlib.Format.FORWARDREF + ) + if PY314: + with lazy_annotations(): + return inspect.getfullargspec(*args, **kwargs) + else: + return inspect.getfullargspec(*args, **kwargs) + + def signature(obj): """ A wrapper around inspect.signature that leaves deferred annotations
From: kihuni <[email protected]> Date: Sun, 2 Nov 2025 08:50:45 +0300 Subject: [PATCH] Fixed #36321 -- Defaulted suggest_on_error=True in management commands. Python 3.15 defaults suggest_on_error=True, but the feature is available from 3.14, so this change opts in earlier. This change can be reverted when Python 3.15 is the minimum supported version. Origin: upstream, https://github.com/django/django/commit/b1a65eac7c09250d36e12464fc8fff2a401246b6 --- django/core/management/base.py | 3 +++ django/utils/version.py | 1 + tests/admin_scripts/tests.py | 8 +++++++- tests/user_commands/tests.py | 16 ++++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) Index: python-django/django/core/management/base.py =================================================================== --- python-django.orig/django/core/management/base.py +++ python-django/django/core/management/base.py @@ -15,7 +15,7 @@ from django.core import checks from django.core.exceptions import ImproperlyConfigured from django.core.management.color import color_style, no_style from django.db import DEFAULT_DB_ALIAS, connections -from django.utils.version import PY314 +from django.utils.version import PY314, PY315 ALL_CHECKS = "__all__" @@ -58,6 +58,8 @@ class CommandParser(ArgumentParser): ): self.missing_args_message = missing_args_message self.called_from_command_line = called_from_command_line + if PY314 and not PY315: + kwargs.setdefault("suggest_on_error", True) if PY314: if os.environ.get("DJANGO_COLORS") == "nocolor" or "--no-color" in sys.argv: kwargs.setdefault("color", False) Index: python-django/django/utils/version.py =================================================================== --- python-django.orig/django/utils/version.py +++ python-django/django/utils/version.py @@ -20,6 +20,7 @@ PY311 = sys.version_info >= (3, 11) PY312 = sys.version_info >= (3, 12) PY313 = sys.version_info >= (3, 13) PY314 = sys.version_info >= (3, 14) +PY315 = sys.version_info >= (3, 15) def get_version(version=None): Index: python-django/tests/admin_scripts/tests.py =================================================================== --- python-django.orig/tests/admin_scripts/tests.py +++ python-django/tests/admin_scripts/tests.py @@ -38,7 +38,7 @@ from django.db.migrations.recorder impor from django.test import LiveServerTestCase, SimpleTestCase, TestCase, override_settings from django.test.utils import captured_stderr, captured_stdout from django.urls import path -from django.utils.version import PY313, get_docs_version +from django.utils.version import PY313, PY314, get_docs_version from django.views.static import serve from . import urls @@ -2405,10 +2405,16 @@ class Discovery(SimpleTestCase): class CommandDBOptionChoiceTests(SimpleTestCase): def test_invalid_choice_db_option(self): - expected_error = ( - r"Error: argument --database: invalid choice: 'deflaut' " - r"\(choose from '?default'?, '?other'?\)" - ) + if PY314: + expected_error = ( + r"Error: argument --database: invalid choice: 'deflaut', " + r"maybe you meant 'default'\? \(choose from default, other\)" + ) + else: + expected_error = ( + r"Error: argument --database: invalid choice: 'deflaut' " + r"\(choose from '?default'?, '?other'?\)" + ) args = [ "changepassword", "createsuperuser",
From: kasey <[email protected]> Date: Tue, 12 May 2026 00:15:15 -0500 Subject: [PATCH] Fixed #37096 -- Fixed test_invalid_choice_db_option on Python 3.14.5+. Origin: upstream, https://github.com/django/django/commit/ed13a58bf63df94508c8a0fe779da0b6a2bc26bb --- tests/admin_scripts/tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) Index: python-django/tests/admin_scripts/tests.py =================================================================== --- python-django.orig/tests/admin_scripts/tests.py +++ python-django/tests/admin_scripts/tests.py @@ -2408,7 +2408,8 @@ class CommandDBOptionChoiceTests(SimpleT if PY314: expected_error = ( r"Error: argument --database: invalid choice: 'deflaut', " - r"maybe you meant 'default'\? \(choose from default, other\)" + r"maybe you meant 'default'\? " + r"\(choose from '?default'?, '?other'?\)" ) else: expected_error = (
From: Mariusz Felisiak <[email protected]> Date: Wed, 22 Oct 2025 10:04:38 +0200 Subject: [PATCH] Refs #36499 -- Made TestUtilsHtml.test_strip_tags() assume behavior change in X.Y.0 version for Python 3.14+. This also removes unsupported versions of Python from the test dict. Origin: upstream, https://github.com/django/django/commit/185b049e9e72a5ff4b07e33605e10eb4f52ca74c --- tests/utils_tests/test_html.py | 11 ----------- 1 file changed, 11 deletions(-) Index: python-django/tests/utils_tests/test_html.py =================================================================== --- python-django.orig/tests/utils_tests/test_html.py +++ python-django/tests/utils_tests/test_html.py @@ -126,16 +126,9 @@ class TestUtilsHtml(SimpleTestCase): # Python versions and CI workers include the fix. See: # https://github.com/python/cpython/commit/6eb6c5db min_fixed_security = { - (3, 14): (3, 14), (3, 13): (3, 13, 6), (3, 12): (3, 12, 12), - (3, 11): (3, 11, 14), - (3, 10): (3, 10, 19), - (3, 9): (3, 9, 24), } - htmlparser_fixed_security = ( - sys.version_info >= min_fixed_security[sys.version_info[:2]] - ) # Similarly, there was a fix for terminating incomplete entities. See: # https://github.com/python/cpython/commit/95296a9d min_fixed_incomplete_entities = {

