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>') |