diff --git a/INSTALL b/INSTALL
index be64877..dda9b4c 100644
a
|
b
|
|
1 | 1 | Thanks for downloading Django. |
2 | 2 | |
3 | | To install it, make sure you have Python 3.4 or greater installed. Then run |
| 3 | To install it, make sure you have Python 3.5 or greater installed. Then run |
4 | 4 | this command from the command prompt: |
5 | 5 | |
6 | 6 | python setup.py install |
diff --git a/django/http/cookie.py b/django/http/cookie.py
index 52dff78..5c3fb94 100644
a
|
b
|
|
1 | | import sys |
2 | 1 | from http import cookies |
3 | 2 | |
4 | | # Cookie pickling bug is fixed in Python 3.4.3+ |
5 | | # http://bugs.python.org/issue22775 |
6 | | if sys.version_info >= (3, 4, 3): |
7 | | SimpleCookie = cookies.SimpleCookie |
8 | | else: |
9 | | Morsel = cookies.Morsel |
10 | | |
11 | | class SimpleCookie(cookies.SimpleCookie): |
12 | | def __setitem__(self, key, value): |
13 | | if isinstance(value, Morsel): |
14 | | # allow assignment of constructed Morsels (e.g. for pickling) |
15 | | dict.__setitem__(self, key, value) |
16 | | else: |
17 | | super().__setitem__(key, value) |
| 3 | # For backwards compatibility in Django 2.X. |
| 4 | SimpleCookie = cookies.SimpleCookie |
18 | 5 | |
19 | 6 | |
20 | 7 | def parse_cookie(cookie): |
diff --git a/django/test/html.py b/django/test/html.py
index 900aa3d..d2e6efe 100644
a
|
b
|
Comparing two html documents.
|
3 | 3 | """ |
4 | 4 | |
5 | 5 | import re |
6 | | |
7 | | from django.utils.html_parser import HTMLParseError, HTMLParser |
| 6 | from html.parser import HTMLParser |
8 | 7 | |
9 | 8 | WHITESPACE = re.compile(r'\s+') |
10 | 9 | |
… |
… |
class RootElement(Element):
|
140 | 139 | return ''.join(str(c) for c in self.children) |
141 | 140 | |
142 | 141 | |
| 142 | class HTMLParseError(Exception): |
| 143 | pass |
| 144 | |
| 145 | |
143 | 146 | class Parser(HTMLParser): |
144 | 147 | SELF_CLOSING_TAGS = ( |
145 | 148 | 'br', 'hr', 'input', 'img', 'meta', 'spacer', 'link', 'frame', 'base', |
… |
… |
class Parser(HTMLParser):
|
147 | 150 | ) |
148 | 151 | |
149 | 152 | def __init__(self): |
150 | | HTMLParser.__init__(self) |
| 153 | HTMLParser.__init__(self, convert_charrefs=False) |
151 | 154 | self.root = RootElement() |
152 | 155 | self.open_tags = [] |
153 | 156 | self.element_positions = {} |
diff --git a/django/utils/html.py b/django/utils/html.py
index 18c650f..fb847a8 100644
a
|
b
|
|
1 | 1 | """HTML utilities suitable for global use.""" |
2 | 2 | |
3 | 3 | import re |
| 4 | from html.parser import HTMLParser |
4 | 5 | from urllib.parse import ( |
5 | 6 | parse_qsl, quote, unquote, urlencode, urlsplit, urlunsplit, |
6 | 7 | ) |
… |
… |
from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS
|
11 | 12 | from django.utils.safestring import SafeData, SafeText, mark_safe |
12 | 13 | from django.utils.text import normalize_newlines |
13 | 14 | |
14 | | from .html_parser import HTMLParseError, HTMLParser |
15 | | |
16 | 15 | # Configuration for urlize() function. |
17 | 16 | TRAILING_PUNCTUATION_RE = re.compile( |
18 | 17 | '^' # Beginning of word |
… |
… |
def linebreaks(value, autoescape=False):
|
131 | 130 | |
132 | 131 | class MLStripper(HTMLParser): |
133 | 132 | def __init__(self): |
134 | | HTMLParser.__init__(self) |
| 133 | HTMLParser.__init__(self, convert_charrefs=False) |
135 | 134 | self.reset() |
136 | 135 | self.fed = [] |
137 | 136 | |
… |
… |
def _strip_once(value):
|
153 | 152 | Internal tag stripping utility used by strip_tags. |
154 | 153 | """ |
155 | 154 | s = MLStripper() |
156 | | try: |
157 | | s.feed(value) |
158 | | except HTMLParseError: |
159 | | return value |
160 | | try: |
161 | | s.close() |
162 | | except HTMLParseError: |
163 | | return s.get_data() + s.rawdata |
164 | | else: |
165 | | return s.get_data() |
| 155 | s.feed(value) |
| 156 | s.close() |
| 157 | return s.get_data() |
166 | 158 | |
167 | 159 | |
168 | 160 | @keep_lazy_text |
diff --git a/django/utils/html_parser.py b/django/utils/html_parser.py
deleted file mode 100644
index 6b46ddc..0000000
+
|
-
|
|
1 | | import html.parser |
2 | | |
3 | | try: |
4 | | HTMLParseError = html.parser.HTMLParseError |
5 | | except AttributeError: |
6 | | # create a dummy class for Python 3.5+ where it's been removed |
7 | | class HTMLParseError(Exception): |
8 | | pass |
9 | | |
10 | | |
11 | | class HTMLParser(html.parser.HTMLParser): |
12 | | """Explicitly set convert_charrefs to be False. |
13 | | |
14 | | This silences a deprecation warning on Python 3.4. |
15 | | """ |
16 | | def __init__(self, convert_charrefs=False, **kwargs): |
17 | | html.parser.HTMLParser.__init__(self, convert_charrefs=convert_charrefs, **kwargs) |
diff --git a/docs/intro/install.txt b/docs/intro/install.txt
index 7a338ee..eda052c 100644
a
|
b
|
your operating system's package manager.
|
29 | 29 | You can verify that Python is installed by typing ``python`` from your shell; |
30 | 30 | you should see something like:: |
31 | 31 | |
32 | | Python 3.4.x |
| 32 | Python 3.x.y |
33 | 33 | [GCC 4.x] on linux |
34 | 34 | Type "help", "copyright", "credits" or "license" for more information. |
35 | 35 | >>> |
diff --git a/docs/intro/tutorial01.txt b/docs/intro/tutorial01.txt
index 05ee9c3..cbb5b73 100644
a
|
b
|
in a shell prompt (indicated by the $ prefix):
|
23 | 23 | If Django is installed, you should see the version of your installation. If it |
24 | 24 | isn't, you'll get an error telling "No module named django". |
25 | 25 | |
26 | | This tutorial is written for Django |version| and Python 3.4 or later. If the |
| 26 | This tutorial is written for Django |version| and Python 3.5 or later. If the |
27 | 27 | Django version doesn't match, you can refer to the tutorial for your version |
28 | 28 | of Django by using the version switcher at the bottom right corner of this |
29 | 29 | page, or update Django to the newest version. If you are still using Python |
diff --git a/docs/ref/applications.txt b/docs/ref/applications.txt
index be3f554..9fd2a41 100644
a
|
b
|
Configurable attributes
|
192 | 192 | .. attribute:: AppConfig.path |
193 | 193 | |
194 | 194 | Filesystem path to the application directory, e.g. |
195 | | ``'/usr/lib/python3.4/dist-packages/django/contrib/admin'``. |
| 195 | ``'/usr/lib/pythonX.Y/dist-packages/django/contrib/admin'``. |
196 | 196 | |
197 | 197 | In most cases, Django can automatically detect and set this, but you can |
198 | 198 | also provide an explicit override as a class attribute on your |
diff --git a/setup.py b/setup.py
index e9cfa4f..a936760 100644
a
|
b
|
setup(
|
62 | 62 | 'Operating System :: OS Independent', |
63 | 63 | 'Programming Language :: Python', |
64 | 64 | 'Programming Language :: Python :: 3', |
65 | | 'Programming Language :: Python :: 3.4', |
66 | 65 | 'Programming Language :: Python :: 3.5', |
67 | 66 | 'Programming Language :: Python :: 3.6', |
68 | 67 | 'Topic :: Internet :: WWW/HTTP', |
diff --git a/tests/mail/tests.py b/tests/mail/tests.py
index 63737b3..ade8993 100644
a
|
b
|
class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
|
1138 | 1138 | def __init__(self, *args, **kwargs): |
1139 | 1139 | threading.Thread.__init__(self) |
1140 | 1140 | # New kwarg added in Python 3.5; default switching to False in 3.6. |
1141 | | if sys.version_info >= (3, 5): |
1142 | | kwargs['decode_data'] = True |
| 1141 | # Setting a value only silences a deprecation warning in PY35. |
| 1142 | kwargs['decode_data'] = True |
1143 | 1143 | smtpd.SMTPServer.__init__(self, *args, **kwargs) |
1144 | 1144 | self._sink = [] |
1145 | 1145 | self.active = False |
diff --git a/tests/sessions_tests/tests.py b/tests/sessions_tests/tests.py
index 9654c7d..de7e41f 100644
a
|
b
|
import base64
|
2 | 2 | import os |
3 | 3 | import shutil |
4 | 4 | import string |
5 | | import sys |
6 | 5 | import tempfile |
7 | 6 | import unittest |
8 | 7 | from datetime import timedelta |
… |
… |
class SessionMiddlewareTests(TestCase):
|
726 | 725 | # A deleted cookie header looks like: |
727 | 726 | # Set-Cookie: sessionid=; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/ |
728 | 727 | self.assertEqual( |
729 | | 'Set-Cookie: {}={}; expires=Thu, 01-Jan-1970 00:00:00 GMT; ' |
| 728 | 'Set-Cookie: {}=""; expires=Thu, 01-Jan-1970 00:00:00 GMT; ' |
730 | 729 | 'Max-Age=0; Path=/'.format( |
731 | 730 | settings.SESSION_COOKIE_NAME, |
732 | | '""' if sys.version_info >= (3, 5) else '', |
733 | 731 | ), |
734 | 732 | str(response.cookies[settings.SESSION_COOKIE_NAME]) |
735 | 733 | ) |
… |
… |
class SessionMiddlewareTests(TestCase):
|
756 | 754 | # expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; |
757 | 755 | # Path=/example/ |
758 | 756 | self.assertEqual( |
759 | | 'Set-Cookie: {}={}; Domain=.example.local; expires=Thu, ' |
| 757 | 'Set-Cookie: {}=""; Domain=.example.local; expires=Thu, ' |
760 | 758 | '01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/example/'.format( |
761 | 759 | settings.SESSION_COOKIE_NAME, |
762 | | '""' if sys.version_info >= (3, 5) else '', |
763 | 760 | ), |
764 | 761 | str(response.cookies[settings.SESSION_COOKIE_NAME]) |
765 | 762 | ) |
diff --git a/tests/test_runner/test_debug_sql.py b/tests/test_runner/test_debug_sql.py
index 1b36fbc..c73b260 100644
a
|
b
|
|
1 | | import sys |
2 | 1 | import unittest |
3 | 2 | from io import StringIO |
4 | 3 | |
… |
… |
class TestDebugSQL(unittest.TestCase):
|
68 | 67 | ] |
69 | 68 | |
70 | 69 | verbose_expected_outputs = [ |
71 | | # Output format changed in Python 3.5+ |
72 | | x.format('' if sys.version_info < (3, 5) else 'TestDebugSQL.') for x in [ |
73 | | 'runTest (test_runner.test_debug_sql.{}FailingTest) ... FAIL', |
74 | | 'runTest (test_runner.test_debug_sql.{}ErrorTest) ... ERROR', |
75 | | 'runTest (test_runner.test_debug_sql.{}PassingTest) ... ok', |
76 | | ] |
| 70 | 'runTest (test_runner.test_debug_sql.TestDebugSQL.FailingTest) ... FAIL', |
| 71 | 'runTest (test_runner.test_debug_sql.TestDebugSQL.ErrorTest) ... ERROR', |
| 72 | 'runTest (test_runner.test_debug_sql.TestDebugSQL.PassingTest) ... ok', |
77 | 73 | ] + [ |
78 | 74 | ('''SELECT COUNT(*) AS "__count" ''' |
79 | 75 | '''FROM "test_runner_person" WHERE ''' |
diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py
index 19ef405..baedf05 100644
a
|
b
|
|
1 | 1 | import os |
2 | | import sys |
3 | 2 | import unittest |
4 | 3 | from io import StringIO |
5 | 4 | |
… |
… |
class HTMLEqualTests(SimpleTestCase):
|
646 | 645 | error_msg = ( |
647 | 646 | "First argument is not valid HTML:\n" |
648 | 647 | "('Unexpected end tag `div` (Line 1, Column 6)', (1, 6))" |
649 | | ) if sys.version_info >= (3, 5) else ( |
650 | | "First argument is not valid HTML:\n" |
651 | | "Unexpected end tag `div` (Line 1, Column 6), at line 1, column 7" |
652 | 648 | ) |
653 | 649 | with self.assertRaisesMessage(AssertionError, error_msg): |
654 | 650 | self.assertHTMLEqual('< div></ div>', '<div></div>') |