From abb636c1af7b2fd00a624985f60b7aff07374580 Mon Sep 17 00:00:00 2001
From: Tom <tom@tomforb.es>
Date: Fri, 13 Oct 2017 02:02:04 +0100
Subject: [PATCH] Improved performance of utils.html.escape().

---
 django/utils/functional.py |  3 ++-
 django/utils/html.py       | 13 +++++++++----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/django/utils/functional.py b/django/utils/functional.py
index 71e5238c1e..af49322559 100644
--- a/django/utils/functional.py
+++ b/django/utils/functional.py
@@ -1,4 +1,5 @@
 import copy
+import itertools
 import operator
 from functools import total_ordering, wraps
 
@@ -189,7 +190,7 @@ def keep_lazy(*resultclasses):
 
         @wraps(func)
         def wrapper(*args, **kwargs):
-            for arg in list(args) + list(kwargs.values()):
+            for arg in itertools.chain(args, kwargs.values()):
                 if isinstance(arg, Promise):
                     break
             else:
diff --git a/django/utils/html.py b/django/utils/html.py
index e365cd41f6..4fefbc6355 100644
--- a/django/utils/html.py
+++ b/django/utils/html.py
@@ -30,6 +30,14 @@ simple_url_re = re.compile(r'^https?://\[?\w', re.IGNORECASE)
 simple_url_2_re = re.compile(r'^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$', re.IGNORECASE)
 simple_email_re = re.compile(r'^\S+@\S+\.\S+$')
 
+_html_escapes = {
+    ord('&'): '&amp;',
+    ord('<'): '&lt;',
+    ord('>'): '&gt;',
+    ord('"'): '&quot;',
+    ord("'"): '&#39;',
+}
+
 
 @keep_lazy(str, SafeText)
 def escape(text):
@@ -41,10 +49,7 @@ def escape(text):
     This may result in double-escaping. If this is a concern, use
     conditional_escape() instead.
     """
-    return mark_safe(
-        str(text).replace('&', '&amp;').replace('<', '&lt;')
-        .replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;')
-    )
+    return mark_safe(str(text).translate(_html_escapes))
 
 
 _js_escapes = {