Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 9 additions & 19 deletions django/core/serializers/xml_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,27 +416,17 @@ def _get_model_from_node(self, node, attr):


def getInnerText(node):
"""Get all the inner text of a DOM node (recursively)."""
inner_text_list = getInnerTextList(node)
return "".join(inner_text_list)


def getInnerTextList(node):
"""Return a list of the inner texts of a DOM node (recursively)."""
"""Get the inner text of a DOM node and any children one level deep."""
# inspired by
# https://mail.python.org/pipermail/xml-sig/2005-March/011022.html
result = []
for child in node.childNodes:
if (
child.nodeType == child.TEXT_NODE
or child.nodeType == child.CDATA_SECTION_NODE
):
result.append(child.data)
elif child.nodeType == child.ELEMENT_NODE:
result.extend(getInnerTextList(child))
else:
pass
return result
return "".join(
[
element.data
for child in node.childNodes
for element in (child, *child.childNodes)
if element.nodeType in (element.TEXT_NODE, element.CDATA_SECTION_NODE)
]
)


# Below code based on Christian Heimes' defusedxml
Expand Down
2 changes: 1 addition & 1 deletion docs/howto/auth-remote-user.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ instead of :class:`django.contrib.auth.middleware.RemoteUserMiddleware`::
This warning doesn't apply to ``RemoteUserMiddleware`` in its default
configuration with ``header = 'REMOTE_USER'``, since a key that doesn't
start with ``HTTP_`` in ``request.META`` can only be set by your WSGI
server, not directly from an HTTP request header.
or ASGI server, not directly from an HTTP request header.

If you need more control, you can create your own authentication backend
that inherits from :class:`~django.contrib.auth.backends.RemoteUserBackend` and
Expand Down
Binary file added docs/internals/_images/contribution_process.pdf
Binary file not shown.
12 changes: 10 additions & 2 deletions docs/ref/contrib/contenttypes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,16 @@ The ``ContentTypeManager``
:class:`~django.contrib.contenttypes.models.ContentType` to keep track
of models for which it has created
:class:`~django.contrib.contenttypes.models.ContentType` instances. You
probably won't ever need to call this method yourself; Django will call
it automatically when it's needed.
probably won't need to call this method in application code yourself;
Django will call it automatically when it's needed.

You may need to clear the cache when testing, to reset between tests,
or after preparing test state. For example::

class ContentTypesTests(TestCase):
def setUp(self):
ContentType.objects.clear_cache()
self.addCleanup(ContentType.objects.clear_cache)

.. method:: get_for_id(id)

Expand Down
3 changes: 3 additions & 0 deletions docs/ref/contrib/postgres/aggregates.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ General-purpose aggregation functions

.. deprecated:: 6.0

The PostgreSQL ``StringAgg`` class is deprecated in favor of the
generally available :class:`~django.db.models.StringAgg` class.

Returns the input values concatenated into a string, separated by
the ``delimiter`` string, or ``default`` if there are no values.

Expand Down
2 changes: 1 addition & 1 deletion docs/ref/request-response.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ Methods
.. method:: HttpResponse.close()

This method is called at the end of the request directly by the WSGI
server.
or ASGI server.

.. method:: HttpResponse.write(content)

Expand Down
10 changes: 10 additions & 0 deletions tests/fixtures/fixtures/invalid_deeply_nested_elements.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">

<object pk="1" model="fixtures.person">
<field type="CharField" name="name">
<natural>Django <em>pony</em></natural>
</field>
</object>

</django-objects>
9 changes: 9 additions & 0 deletions tests/fixtures/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
CircularA,
CircularB,
NaturalKeyThing,
Person,
PrimaryKeyUUIDModel,
ProxySpy,
Spy,
Expand Down Expand Up @@ -520,6 +521,14 @@ def test_loading_and_dumping(self):
natural_foreign_keys=True,
)

def test_deeply_nested_elements(self):
"""Text inside deeply-nested tags is skipped."""
management.call_command(
"loaddata", "invalid_deeply_nested_elements.xml", verbosity=0
)
person = Person.objects.get(pk=1)
self.assertEqual(person.name, "Django") # not "Django pony"

def test_dumpdata_with_excludes(self):
# Load fixture1 which has a site, two articles, and a category
Site.objects.all().delete()
Expand Down
25 changes: 9 additions & 16 deletions tests/runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,6 @@

TEMPLATE_DIR = os.path.join(RUNTESTS_DIR, "templates")

# Create a specific subdirectory for the duration of the test suite.
TMPDIR = tempfile.mkdtemp(prefix="django_")
# Set the TMPDIR environment variable in addition to tempfile.tempdir
# so that children processes inherit it.
tempfile.tempdir = os.environ["TMPDIR"] = TMPDIR

# Removing the temporary TMPDIR.
atexit.register(shutil.rmtree, TMPDIR)

# Add variables enabling coverage to trace code in subprocesses.
os.environ["RUNTESTS_DIR"] = RUNTESTS_DIR
os.environ["COVERAGE_PROCESS_START"] = os.path.join(RUNTESTS_DIR, ".coveragerc")
Expand Down Expand Up @@ -197,6 +188,7 @@ def _module_match_label(module_name, label):


def setup_collect_tests(start_at, start_after, test_labels=None):
TMPDIR = os.environ["TMPDIR"]
state = {
"INSTALLED_APPS": settings.INSTALLED_APPS,
"ROOT_URLCONF": getattr(settings, "ROOT_URLCONF", ""),
Expand Down Expand Up @@ -324,13 +316,6 @@ def no_available_apps(cls):

def teardown_run_tests(state):
teardown_collect_tests(state)
# Discard the multiprocessing.util finalizer that tries to remove a
# temporary directory that's already removed by this script's
# atexit.register(shutil.rmtree, TMPDIR) handler. Prevents
# FileNotFoundError at the end of a test run (#27890).
from multiprocessing.util import _finalizer_registry

_finalizer_registry.pop((-100, 0), None)
del os.environ["RUNNING_DJANGOS_TEST_SUITE"]


Expand Down Expand Up @@ -531,6 +516,14 @@ def paired_tests(paired_test, options, test_labels, start_at, start_after):


if __name__ == "__main__":
# Create a specific subdirectory for the duration of the test suite.
TMPDIR = tempfile.mkdtemp(prefix="django_")
# Set the TMPDIR environment variable in addition to tempfile.tempdir
# so that children processes inherit it.
tempfile.tempdir = os.environ["TMPDIR"] = TMPDIR
# Remove the temporary TMPDIR.
atexit.register(shutil.rmtree, TMPDIR)

parser = argparse.ArgumentParser(description="Run the Django test suite.")
parser.add_argument(
"modules",
Expand Down
25 changes: 20 additions & 5 deletions tests/utils_tests/test_html.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import math
import os
import sys
from datetime import datetime
Expand Down Expand Up @@ -122,14 +123,25 @@ def test_strip_tags(self):
# The check below is temporary until all supported Python versions and
# CI workers include the fix. See:
# https://github.com/python/cpython/commit/6eb6c5db
min_fixed = {
min_fixed_security = {
(3, 13): (3, 13, 6),
(3, 12): (3, 12, 12),
}
# Similarly, there was a fix for terminating incomplete entities. See:
# https://github.com/python/cpython/commit/95296a9d
min_fixed_incomplete_entities = {
(3, 14): (3, 14, 1),
(3, 13): (3, 13, 10),
(3, 12): (3, 12, math.inf), # not fixed in 3.12.
}
major_version = sys.version_info[:2]
htmlparser_fixed = sys.version_info >= min_fixed.get(
htmlparser_fixed_security = sys.version_info >= min_fixed_security.get(
major_version, major_version
)
htmlparser_fixed_incomplete_entities = (
sys.version_info
>= min_fixed_incomplete_entities.get(major_version, major_version)
)
items = (
(
"<p>See: &#39;&eacute; is an apostrophe followed by e acute</p>",
Expand All @@ -156,16 +168,19 @@ def test_strip_tags(self):
# https://bugs.python.org/issue20288
("&gotcha&#;<>", "&gotcha&#;<>"),
("<sc<!-- -->ript>test<<!-- -->/script>", "ript>test"),
("<script>alert()</script>&h", "alert()h"),
(
"<script>alert()</script>&h",
"alert()&h;" if htmlparser_fixed_incomplete_entities else "alert()h",
),
(
"><!" + ("&" * 16000) + "D",
">" if htmlparser_fixed else "><!" + ("&" * 16000) + "D",
">" if htmlparser_fixed_security else "><!" + ("&" * 16000) + "D",
),
("X<<<<br>br>br>br>X", "XX"),
("<" * 50 + "a>" * 50, ""),
(
">" + "<a" * 500 + "a",
">" if htmlparser_fixed else ">" + "<a" * 500 + "a",
">" if htmlparser_fixed_security else ">" + "<a" * 500 + "a",
),
("<a" * 49 + "a" * 951, "<a" * 49 + "a" * 951),
("<" + "a" * 1_002, "<" + "a" * 1_002),
Expand Down