[Django] #30399: Use Python stdlib html.escape() to in django.utils.html.escape()

113 views
Skip to first unread message

Django

unread,
Apr 24, 2019, 8:33:18 AM4/24/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
------------------------------------------------+------------------------
Reporter: Jon Dufresne | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Utilities | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------------+------------------------
The function `django.utils.html.escape()` partially duplicates the Python
stdlib function `html.escape()`. We can replace this duplication with
wider community developed version.

`html.escape()` has been available since Python 3.2:

https://docs.python.org/3/library/html.html#html.escape

This function is also faster than Django's. As Python bug
https://bugs.python.org/issue18020 concludes, using `.replace()` can be
faster than `.translate()`. This function gets called numerous times when
rendering templates. After making the change locally, I saw the following
improvement:

master:

{{{
$ python -m timeit -s 'from django.utils.html import escape'
'escape(copyright)'
50000 loops, best of 5: 4.03 usec per loop
}}}

branch:

{{{
$ python -m timeit -s 'from django.utils.html import escape'
'escape(copyright)'
100000 loops, best of 5: 2.45 usec per loop
}}}

One small concern, `html.escape()` converts `'` to `&#x27` rather than
`&#39`. These values are functionally equivalent HTML, but I'll mention it
as a backwards incompatible change as the literal text has changed

--
Ticket URL: <https://code.djangoproject.com/ticket/30399>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 24, 2019, 9:15:55 AM4/24/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Utilities | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jon Dufresne):

* has_patch: 0 => 1


Comment:

https://github.com/django/django/pull/11276

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:1>

Django

unread,
Apr 24, 2019, 12:44:30 PM4/24/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Utilities | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Claude Paroz):

Partially related, wouldn't we take advantage of this and change most
usages of the single quote inside strings by the typographic quote (`’`,
also `“…”`) where appropriate?

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:2>

Django

unread,
Apr 24, 2019, 12:49:36 PM4/24/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
--------------------------------------+------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Utilities | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------
Changes (by Claude Paroz):

* stage: Unreviewed => Accepted


--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:3>

Django

unread,
Apr 25, 2019, 12:09:44 AM4/25/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
--------------------------------------+------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Utilities | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------

Comment (by Jon Dufresne):

> Partially related, wouldn't we take advantage of this and change most
usages of the single quote inside strings by the typographic quote (’,
also “…”) where appropriate?

I like this idea but feel it is a different objective so I've followed
through with in ticket #30400

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:4>

Django

unread,
Apr 25, 2019, 6:05:54 AM4/25/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Utilities | Version: master
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Claude Paroz):

* stage: Accepted => Ready for checkin


--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:5>

Django

unread,
Apr 25, 2019, 9:08:52 AM4/25/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Utilities | Version: master

Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Carlton Gibson):

Super. Thanks all!

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:6>

Django

unread,
Apr 25, 2019, 9:09:57 AM4/25/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: closed
Cleanup/optimization |
Component: Utilities | Version: master
Severity: Normal | Resolution: fixed

Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson <carlton.gibson@…>):

* status: new => closed
* resolution: => fixed


Comment:

In [changeset:"8d76443aba863b75ad3b1392ca7e1d59bad84dc4" 8d76443a]:
{{{
#!CommitTicketReference repository=""
revision="8d76443aba863b75ad3b1392ca7e1d59bad84dc4"
Fixed #30399 -- Changed django.utils.html.escape()/urlize() to use
html.escape()/unescape().
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:7>

Django

unread,
May 8, 2019, 3:33:02 AM5/8/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: closed
Cleanup/optimization |
Component: Utilities | Version: master

Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Claude Paroz):

> One small concern, html.escape() converts ' to &#x27 rather than &#39.

It's annoying, as `assertHTMLEqual` seems to make a difference between
those two equivalent representations, and that means different code paths
in apps testing with different Django versions. That's something we should
try to solve in `django.test.html`.

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:8>

Django

unread,
May 8, 2019, 9:31:47 AM5/8/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: closed
Cleanup/optimization |
Component: Utilities | Version: master

Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Jon Dufresne):

> It's annoying, as `assertHTMLEqual` seems to make a difference between
those two equivalent representations, and that means different code paths
in apps testing with different Django versions. That's something we should
try to solve in `django.test.html`.

Good idea. I added a [https://github.com/django/django/pull/11343 PR] for
this.

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:9>

Django

unread,
May 9, 2019, 9:56:30 AM5/9/19
to django-...@googlegroups.com
#30399: Use Python stdlib html.escape() to in django.utils.html.escape()
-------------------------------------+-------------------------------------

Reporter: Jon Dufresne | Owner: nobody
Type: | Status: closed
Cleanup/optimization |
Component: Utilities | Version: master

Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Carlton Gibson <carlton.gibson@…>):

In [changeset:"48235ba807483fe349d2dc66aaeddc0d03f8b0d4" 48235ba8]:
{{{
#!CommitTicketReference repository=""
revision="48235ba807483fe349d2dc66aaeddc0d03f8b0d4"
Refs #30399 -- Made assertHTMLEqual normalize character and entity
references.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/30399#comment:10>

Reply all
Reply to author
Forward
0 new messages