[Python-modules-commits] [python-django] 01/01: Unapply patches and disable git-dpm
Raphaël Hertzog
hertzog at moszumanska.debian.org
Sat May 20 14:02:52 UTC 2017
This is an automated email from the git hooks/post-receive script.
hertzog pushed a commit to branch debian/jessie
in repository python-django.
commit 3e5ffc824466e56ff04c17ce97f0c26f6c1029aa
Author: Raphaël Hertzog <hertzog at debian.org>
Date: Sat May 20 15:55:45 2017 +0200
Unapply patches and disable git-dpm
---
debian/.git-dpm | 11 ---
debian/gbp.conf | 2 +-
django/contrib/auth/hashers.py | 77 ++++++--------------
django/contrib/auth/tests/test_hashers.py | 60 ----------------
django/contrib/gis/geoip/base.py | 19 +++--
django/http/cookie.py | 29 ++++----
django/utils/http.py | 13 +---
django/views/debug.py | 4 +-
docs/conf.py | 5 +-
docs/man/django-admin.1 | 6 +-
docs/topics/auth/passwords.txt | 113 ------------------------------
tests/admin_views/admin.py | 3 +-
tests/admin_views/models.py | 4 --
tests/httpwrappers/tests.py | 50 +------------
tests/requests/tests.py | 5 +-
tests/utils_tests/test_http.py | 25 -------
16 files changed, 57 insertions(+), 369 deletions(-)
diff --git a/debian/.git-dpm b/debian/.git-dpm
deleted file mode 100644
index 7b6f2ec..0000000
--- a/debian/.git-dpm
+++ /dev/null
@@ -1,11 +0,0 @@
-# see git-dpm(1) from git-dpm package
-NONE
-b66a3bcd305248e7e246884fd7906a75d69ffc94
-2d07f4b16101fcc8973128c4e4920b41f87175ee
-2d07f4b16101fcc8973128c4e4920b41f87175ee
-python-django_1.7.11.orig.tar.gz
-f9abaf7eacec73bc1c5e6080e2778a7174ebf9d4
-7586798
-debianTag="debian/%e%v"
-patchedTag="patched/%e%v"
-upstreamTag="upstream/%e%u"
diff --git a/debian/gbp.conf b/debian/gbp.conf
index 9e794e3..c08fd3f 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,3 +1,3 @@
[DEFAULT]
upstream-branch=upstream/1.7.x
-debian-branch=debian/sid
+debian-branch=debian/jessie
diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index 1ad4bcb..e459f39 100644
--- a/django/contrib/auth/hashers.py
+++ b/django/contrib/auth/hashers.py
@@ -5,7 +5,6 @@ import binascii
from collections import OrderedDict
import hashlib
import importlib
-import warnings
from django.dispatch import receiver
from django.conf import settings
@@ -56,17 +55,10 @@ def check_password(password, encoded, setter=None, preferred='default'):
preferred = get_hasher(preferred)
hasher = identify_hasher(encoded)
- hasher_changed = hasher.algorithm != preferred.algorithm
- must_update = hasher_changed or preferred.must_update(encoded)
+ must_update = hasher.algorithm != preferred.algorithm
+ if not must_update:
+ must_update = preferred.must_update(encoded)
is_correct = hasher.verify(password, encoded)
-
- # If the hasher didn't change (we don't protect against enumeration if it
- # does) and the password should get updated, try to close the timing gap
- # between the work factor of the current encoded password and the default
- # work factor.
- if not is_correct and not hasher_changed and must_update:
- hasher.harden_runtime(password, encoded)
-
if setter and is_correct and must_update:
setter(password)
return is_correct
@@ -225,19 +217,6 @@ class BasePasswordHasher(object):
def must_update(self, encoded):
return False
- def harden_runtime(self, password, encoded):
- """
- Bridge the runtime gap between the work factor supplied in `encoded`
- and the work factor suggested by this hasher.
-
- Taking PBKDF2 as an example, if `encoded` contains 20000 iterations and
- `self.iterations` is 30000, this method should run password through
- another 10000 iterations of PBKDF2. Similar approaches should exist
- for any hasher that has a work factor. If not, this method should be
- defined as a no-op to silence the warning.
- """
- warnings.warn('subclasses of BasePasswordHasher should provide a harden_runtime() method')
-
class PBKDF2PasswordHasher(BasePasswordHasher):
"""
@@ -280,12 +259,6 @@ class PBKDF2PasswordHasher(BasePasswordHasher):
algorithm, iterations, salt, hash = encoded.split('$', 3)
return int(iterations) != self.iterations
- def harden_runtime(self, password, encoded):
- algorithm, iterations, salt, hash = encoded.split('$', 3)
- extra_iterations = self.iterations - int(iterations)
- if extra_iterations > 0:
- self.encode(password, salt, extra_iterations)
-
class PBKDF2SHA1PasswordHasher(PBKDF2PasswordHasher):
"""
@@ -336,8 +309,23 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
def verify(self, password, encoded):
algorithm, data = encoded.split('$', 1)
assert algorithm == self.algorithm
- encoded_2 = self.encode(password, force_bytes(data))
- return constant_time_compare(encoded, encoded_2)
+ bcrypt = self._load_library()
+
+ # Hash the password prior to using bcrypt to prevent password truncation
+ # See: https://code.djangoproject.com/ticket/20138
+ if self.digest is not None:
+ # We use binascii.hexlify here because Python3 decided that a hex encoded
+ # bytestring is somehow a unicode.
+ password = binascii.hexlify(self.digest(force_bytes(password)).digest())
+ else:
+ password = force_bytes(password)
+
+ # Ensure that our data is a bytestring
+ data = force_bytes(data)
+ # force_bytes() necessary for py-bcrypt compatibility
+ hashpw = force_bytes(bcrypt.hashpw(password, data))
+
+ return constant_time_compare(data, hashpw)
def safe_summary(self, encoded):
algorithm, empty, algostr, work_factor, data = encoded.split('$', 4)
@@ -350,16 +338,6 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
(_('checksum'), mask_hash(checksum)),
])
- def harden_runtime(self, password, encoded):
- _, data = encoded.split('$', 1)
- salt = data[:29] # Length of the salt in bcrypt.
- rounds = data.split('$')[2]
- # work factor is logarithmic, adding one doubles the load.
- diff = 2**(self.rounds - int(rounds)) - 1
- while diff > 0:
- self.encode(password, force_bytes(salt))
- diff -= 1
-
class BCryptPasswordHasher(BCryptSHA256PasswordHasher):
"""
@@ -407,9 +385,6 @@ class SHA1PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(hash)),
])
- def harden_runtime(self, password, encoded):
- pass
-
class MD5PasswordHasher(BasePasswordHasher):
"""
@@ -438,9 +413,6 @@ class MD5PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(hash)),
])
- def harden_runtime(self, password, encoded):
- pass
-
class UnsaltedSHA1PasswordHasher(BasePasswordHasher):
"""
@@ -473,9 +445,6 @@ class UnsaltedSHA1PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(hash)),
])
- def harden_runtime(self, password, encoded):
- pass
-
class UnsaltedMD5PasswordHasher(BasePasswordHasher):
"""
@@ -509,9 +478,6 @@ class UnsaltedMD5PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(encoded, show=3)),
])
- def harden_runtime(self, password, encoded):
- pass
-
class CryptPasswordHasher(BasePasswordHasher):
"""
@@ -546,6 +512,3 @@ class CryptPasswordHasher(BasePasswordHasher):
(_('salt'), salt),
(_('hash'), mask_hash(data, show=3)),
])
-
- def harden_runtime(self, password, encoded):
- pass
diff --git a/django/contrib/auth/tests/test_hashers.py b/django/contrib/auth/tests/test_hashers.py
index 3a06b43..85f1c15 100644
--- a/django/contrib/auth/tests/test_hashers.py
+++ b/django/contrib/auth/tests/test_hashers.py
@@ -9,12 +9,7 @@ from django.contrib.auth.hashers import (is_password_usable, BasePasswordHasher,
get_hasher, identify_hasher, UNUSABLE_PASSWORD_PREFIX, UNUSABLE_PASSWORD_SUFFIX_LENGTH)
from django.test import SimpleTestCase
from django.utils import six
-from django.utils.encoding import force_bytes
-try:
- from unittest import mock
-except ImportError:
- import mock
try:
import crypt
@@ -181,28 +176,6 @@ class TestUtilsHashPass(SimpleTestCase):
self.assertTrue(check_password('', blank_encoded))
self.assertFalse(check_password(' ', blank_encoded))
- @skipUnless(bcrypt, "bcrypt not installed")
- def test_bcrypt_harden_runtime(self):
- hasher = get_hasher('bcrypt')
- self.assertEqual('bcrypt', hasher.algorithm)
-
- with mock.patch.object(hasher, 'rounds', 4):
- encoded = make_password('letmein', hasher='bcrypt')
-
- with mock.patch.object(hasher, 'rounds', 6), \
- mock.patch.object(hasher, 'encode', side_effect=hasher.encode):
- hasher.harden_runtime('wrong_password', encoded)
-
- # Increasing rounds from 4 to 6 means an increase of 4 in workload,
- # therefore hardening should run 3 times to make the timing the
- # same (the original encode() call already ran once).
- self.assertEqual(hasher.encode.call_count, 3)
-
- # Get the original salt (includes the original workload factor)
- algorithm, data = encoded.split('$', 1)
- expected_call = (('wrong_password', force_bytes(data[:29])),)
- self.assertEqual(hasher.encode.call_args_list, [expected_call] * 3)
-
def test_unusable(self):
encoded = make_password(None)
self.assertEqual(len(encoded), len(UNUSABLE_PASSWORD_PREFIX) + UNUSABLE_PASSWORD_SUFFIX_LENGTH)
@@ -310,25 +283,6 @@ class TestUtilsHashPass(SimpleTestCase):
finally:
hasher.iterations = old_iterations
- def test_pbkdf2_harden_runtime(self):
- hasher = get_hasher('default')
- self.assertEqual('pbkdf2_sha256', hasher.algorithm)
-
- with mock.patch.object(hasher, 'iterations', 1):
- encoded = make_password('letmein')
-
- with mock.patch.object(hasher, 'iterations', 6), \
- mock.patch.object(hasher, 'encode', side_effect=hasher.encode):
- hasher.harden_runtime('wrong_password', encoded)
-
- # Encode should get called once ...
- self.assertEqual(hasher.encode.call_count, 1)
-
- # ... with the original salt and 5 iterations.
- algorithm, iterations, salt, hash = encoded.split('$', 3)
- expected_call = (('wrong_password', salt, 5),)
- self.assertEqual(hasher.encode.call_args, expected_call)
-
def test_pbkdf2_upgrade_new_hasher(self):
self.assertEqual('pbkdf2_sha256', get_hasher('default').algorithm)
hasher = get_hasher('default')
@@ -357,20 +311,6 @@ class TestUtilsHashPass(SimpleTestCase):
self.assertTrue(check_password('letmein', encoded, setter))
self.assertTrue(state['upgraded'])
- def test_check_password_calls_harden_runtime(self):
- hasher = get_hasher('default')
- encoded = make_password('letmein')
-
- with mock.patch.object(hasher, 'harden_runtime'), \
- mock.patch.object(hasher, 'must_update', return_value=True):
- # Correct password supplied, no hardening needed
- check_password('letmein', encoded)
- self.assertEqual(hasher.harden_runtime.call_count, 0)
-
- # Wrong password supplied, hardening needed
- check_password('wrong_password', encoded)
- self.assertEqual(hasher.harden_runtime.call_count, 1)
-
def test_load_library_no_algorithm(self):
with self.assertRaises(ValueError) as e:
BasePasswordHasher()._load_library()
diff --git a/django/contrib/gis/geoip/base.py b/django/contrib/gis/geoip/base.py
index 0b05f43..9295030 100644
--- a/django/contrib/gis/geoip/base.py
+++ b/django/contrib/gis/geoip/base.py
@@ -67,8 +67,7 @@ class GeoIP(object):
* path: Base directory to where GeoIP data is located or the full path
to where the city or country data files (*.dat) are located.
Assumes that both the city and country data sets are located in
- this directory. Overrides the GEOIP_PATH settings attribute.
- If neither is set, defaults to '/usr/share/GeoIP'.
+ this directory; overrides the GEOIP_PATH settings attribute.
* cache: The cache settings when opening up the GeoIP datasets,
and may be an integer in (0, 1, 2, 4, 8) corresponding to
@@ -77,13 +76,11 @@ class GeoIP(object):
settings, respectively. Defaults to 0, meaning that the data is read
from the disk.
- * country: The name of the GeoIP country data file. Overrides
- the GEOIP_COUNTRY settings attribute. If neither is set,
- defaults to 'GeoIP.dat'
+ * country: The name of the GeoIP country data file. Defaults to
+ 'GeoIP.dat'; overrides the GEOIP_COUNTRY settings attribute.
- * city: The name of the GeoIP city data file. Overrides the
- GEOIP_CITY settings attribute. If neither is set, defaults
- to 'GeoIPCity.dat'.
+ * city: The name of the GeoIP city data file. Defaults to
+ 'GeoLiteCity.dat'; overrides the GEOIP_CITY settings attribute.
"""
# Checking the given cache option.
if cache in self.cache_options:
@@ -93,7 +90,9 @@ class GeoIP(object):
# Getting the GeoIP data path.
if not path:
- path = GEOIP_SETTINGS.get('GEOIP_PATH', '/usr/share/GeoIP')
+ path = GEOIP_SETTINGS.get('GEOIP_PATH', None)
+ if not path:
+ raise GeoIPException('GeoIP path must be provided via parameter or the GEOIP_PATH setting.')
if not isinstance(path, six.string_types):
raise TypeError('Invalid path type: %s' % type(path).__name__)
@@ -106,7 +105,7 @@ class GeoIP(object):
self._country = GeoIP_open(force_bytes(country_db), cache)
self._country_file = country_db
- city_db = os.path.join(path, city or GEOIP_SETTINGS.get('GEOIP_CITY', 'GeoIPCity.dat'))
+ city_db = os.path.join(path, city or GEOIP_SETTINGS.get('GEOIP_CITY', 'GeoLiteCity.dat'))
if os.path.isfile(city_db):
self._city = GeoIP_open(force_bytes(city_db), cache)
self._city_file = city_db
diff --git a/django/http/cookie.py b/django/http/cookie.py
index 07d8cbf..7084c87 100644
--- a/django/http/cookie.py
+++ b/django/http/cookie.py
@@ -71,21 +71,18 @@ else:
def parse_cookie(cookie):
- """
- Return a dictionary parsed from a `Cookie:` header string.
- """
+ if cookie == '':
+ return {}
+ if not isinstance(cookie, http_cookies.BaseCookie):
+ try:
+ c = SimpleCookie()
+ c.load(cookie)
+ except http_cookies.CookieError:
+ # Invalid cookie
+ return {}
+ else:
+ c = cookie
cookiedict = {}
- if six.PY2:
- cookie = force_str(cookie)
- for chunk in cookie.split(str(';')):
- if str('=') in chunk:
- key, val = chunk.split(str('='), 1)
- else:
- # Assume an empty name per
- # https://bugzilla.mozilla.org/show_bug.cgi?id=169091
- key, val = str(''), chunk
- key, val = key.strip(), val.strip()
- if key or val:
- # unquote using Python's algorithm.
- cookiedict[key] = http_cookies._unquote(val)
+ for key in c.keys():
+ cookiedict[key] = c.get(key).value
return cookiedict
diff --git a/django/utils/http.py b/django/utils/http.py
index 972760e..ef88f65 100644
--- a/django/utils/http.py
+++ b/django/utils/http.py
@@ -274,17 +274,8 @@ def is_safe_url(url, host=None):
url = url.strip()
if not url:
return False
- if six.PY2:
- try:
- url = force_text(url)
- except UnicodeDecodeError:
- return False
- # Chrome treats \ completely as / in paths but it could be part of some
- # basic auth credentials so we need to check both URLs.
- return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'), host)
-
-
-def _is_safe_url(url, host):
+ # Chrome treats \ completely as /
+ url = url.replace('\\', '/')
# Chrome considers any URL with more than two slashes to be absolute, but
# urlparse is not so flexible. Treat any url with three slashes as unsafe.
if url.startswith('///'):
diff --git a/django/views/debug.py b/django/views/debug.py
index 7d8ea05..13992e9 100644
--- a/django/views/debug.py
+++ b/django/views/debug.py
@@ -637,13 +637,13 @@ TECHNICAL_500_TEMPLATE = """
var s = link.getElementsByTagName('span')[0];
var uarr = String.fromCharCode(0x25b6);
var darr = String.fromCharCode(0x25bc);
- s.textContent = s.textContent == uarr ? darr : uarr;
+ s.innerHTML = s.innerHTML == uarr ? darr : uarr;
return false;
}
function switchPastebinFriendly(link) {
s1 = "Switch to copy-and-paste view";
s2 = "Switch back to interactive view";
- link.textContent = link.textContent.trim() == s1 ? s2: s1;
+ link.innerHTML = link.innerHTML == s1 ? s2: s1;
toggle('browserTraceback', 'pastebinTraceback');
return false;
}
diff --git a/docs/conf.py b/docs/conf.py
index 90e4d69..6df8dd8 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -200,10 +200,7 @@ html_additional_pages = {}
#html_split_index = False
# If true, links to the reST sources are added to the pages.
-html_show_sourcelink = False
-
-# Do not ship a copy of the sources
-html_copy_source = False
+#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
diff --git a/docs/man/django-admin.1 b/docs/man/django-admin.1
index bdb6438..c9932ac 100644
--- a/docs/man/django-admin.1
+++ b/docs/man/django-admin.1
@@ -1,8 +1,8 @@
-.TH "django-admin" "1" "March 2008" "Django Project" ""
+.TH "django-admin.py" "1" "March 2008" "Django Project" ""
.SH "NAME"
-django\-admin \- Utility script for the Django Web framework
+django\-admin.py \- Utility script for the Django Web framework
.SH "SYNOPSIS"
-.B django\-admin
+.B django\-admin.py
.I <action>
.B [options]
.sp
diff --git a/docs/topics/auth/passwords.txt b/docs/topics/auth/passwords.txt
index 00964cf..280405f 100644
--- a/docs/topics/auth/passwords.txt
+++ b/docs/topics/auth/passwords.txt
@@ -197,125 +197,12 @@ unmentioned algorithms won't be able to upgrade.
Passwords will be upgraded when changing the PBKDF2 iteration count.
-Be aware that if all the passwords in your database aren't encoded in the
-default hasher's algorithm, you may be vulnerable to a user enumeration timing
-attack due to a difference between the duration of a login request for a user
-with a password encoded in a non-default algorithm and the duration of a login
-request for a nonexistent user (which runs the default hasher). You may be able
-to mitigate this by :ref:`upgrading older password hashes
-<wrapping-password-hashers>`.
-
-.. _wrapping-password-hashers:
-
-Password upgrading without requiring a login
---------------------------------------------
-
-If you have an existing database with an older, weak hash such as MD5 or SHA1,
-you might want to upgrade those hashes yourself instead of waiting for the
-upgrade to happen when a user logs in (which may never happen if a user doesn't
-return to your site). In this case, you can use a "wrapped" password hasher.
-
-For this example, we'll migrate a collection of SHA1 hashes to use
-PBKDF2(SHA1(password)) and add the corresponding password hasher for checking
-if a user entered the correct password on login. We assume we're using the
-built-in ``User`` model and that our project has an ``accounts`` app. You can
-modify the pattern to work with any algorithm or with a custom user model.
-
-First, we'll add the custom hasher:
-
-.. snippet::
- :filename: accounts/hashers.py
-
- from django.contrib.auth.hashers import (
- PBKDF2PasswordHasher, SHA1PasswordHasher,
- )
-
-
- class PBKDF2WrappedSHA1PasswordHasher(PBKDF2PasswordHasher):
- algorithm = 'pbkdf2_wrapped_sha1'
-
- def encode_sha1_hash(self, sha1_hash, salt, iterations=None):
- return super(PBKDF2WrappedSHA1PasswordHasher, self).encode(sha1_hash, salt, iterations)
-
- def encode(self, password, salt, iterations=None):
- _, _, sha1_hash = SHA1PasswordHasher().encode(password, salt).split('$', 2)
- return self.encode_sha1_hash(sha1_hash, salt, iterations)
-
-The data migration might look something like:
-
-.. snippet::
- :filename: accounts/migrations/0002_migrate_sha1_passwords.py
-
- from django.db import migrations
-
- from ..hashers import PBKDF2WrappedSHA1PasswordHasher
-
-
- def forwards_func(apps, schema_editor):
- User = apps.get_model('auth', 'User')
- users = User.objects.filter(password__startswith='sha1$')
- hasher = PBKDF2WrappedSHA1PasswordHasher()
- for user in users:
- algorithm, salt, sha1_hash = user.password.split('$', 2)
- user.password = hasher.encode_sha1_hash(sha1_hash, salt)
- user.save(update_fields=['password'])
-
-
- class Migration(migrations.Migration):
-
- dependencies = [
- ('accounts', '0001_initial'),
- # replace this with the latest migration in contrib.auth
- ('auth', '####_migration_name'),
- ]
-
- operations = [
- migrations.RunPython(forwards_func),
- ]
-
-Be aware that this migration will take on the order of several minutes for
-several thousand users, depending on the speed of your hardware.
-
-Finally, we'll add a :setting:`PASSWORD_HASHERS` setting:
-
-.. snippet::
- :filename: mysite/settings.py
-
- PASSWORD_HASHERS = [
- 'django.contrib.auth.hashers.PBKDF2PasswordHasher',
- 'accounts.hashers.PBKDF2WrappedSHA1PasswordHasher',
- ]
-
-Include any other hashers that your site uses in this list.
-
.. _sha1: http://en.wikipedia.org/wiki/SHA1
.. _pbkdf2: http://en.wikipedia.org/wiki/PBKDF2
.. _nist: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
.. _bcrypt: http://en.wikipedia.org/wiki/Bcrypt
.. _`bcrypt library`: https://pypi.python.org/pypi/bcrypt/
-.. _write-your-own-password-hasher:
-
-Writing your own hasher
------------------------
-
-.. versionadded:: 1.8.10
-
-If you write your own password hasher that contains a work factor such as a
-number of iterations, you should implement a
-``harden_runtime(self, password, encoded)`` method to bridge the runtime gap
-between the work factor supplied in the ``encoded`` password and the default
-work factor of the hasher. This prevents a user enumeration timing attack due
-to difference between a login request for a user with a password encoded in an
-older number of iterations and a nonexistent user (which runs the default
-hasher's default number of iterations).
-
-Taking PBKDF2 as example, if ``encoded`` contains 20,000 iterations and the
-hasher's default ``iterations`` is 30,000, the method should run ``password``
-through another 10,000 iterations of PBKDF2.
-
-If your hasher doesn't have a work factor, implement the method as a no-op
-(``pass``).
Manually managing a user's password
===================================
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index 36187af..15c1384 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -83,8 +83,7 @@ class ChapterXtra1Admin(admin.ModelAdmin):
class ArticleAdmin(admin.ModelAdmin):
list_display = ('content', 'date', callable_year, 'model_year',
- 'modeladmin_year', 'model_year_reversed', 'section')
- list_editable = ('section',)
+ 'modeladmin_year', 'model_year_reversed')
list_filter = ('date', 'section')
view_on_site = False
fieldsets = (
diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py
index 79dd56c..f41b4de 100644
--- a/tests/admin_views/models.py
+++ b/tests/admin_views/models.py
@@ -15,7 +15,6 @@ from django.db import models
from django.utils.encoding import python_2_unicode_compatible
- at python_2_unicode_compatible
class Section(models.Model):
"""
A simple section that links to articles, to test linking to related items
@@ -23,9 +22,6 @@ class Section(models.Model):
"""
name = models.CharField(max_length=100)
- def __str__(self):
- return self.name
-
@property
def name_property(self):
"""
diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py
index 25a9127..7881f2f 100644
--- a/tests/httpwrappers/tests.py
+++ b/tests/httpwrappers/tests.py
@@ -19,7 +19,7 @@ from django.http import (QueryDict, HttpResponse, HttpResponseRedirect,
parse_cookie)
from django.test import TestCase
from django.utils.deprecation import RemovedInDjango18Warning
-from django.utils.encoding import smart_str, force_text, force_str
+from django.utils.encoding import smart_str, force_text
from django.utils.functional import lazy
from django.utils._os import upath
from django.utils import six
@@ -632,8 +632,6 @@ class CookieTests(unittest.TestCase):
c2 = SimpleCookie()
c2.load(c.output())
self.assertEqual(c['test'].value, c2['test'].value)
- c3 = parse_cookie(c.output()[12:])
- self.assertEqual(c['test'].value, c3['test'])
def test_nonstandard_keys(self):
"""
@@ -647,52 +645,6 @@ class CookieTests(unittest.TestCase):
"""
self.assertTrue('good_cookie' in parse_cookie('a:=b; a:=c; good_cookie=yes').keys())
- def test_python_cookies(self):
- """
- Test cases copied from Python's Lib/test/test_http_cookies.py
- """
- self.assertEqual(parse_cookie('chips=ahoy; vienna=finger'), {'chips': 'ahoy', 'vienna': 'finger'})
- # Here parse_cookie() differs from Python's cookie parsing in that it
- # treats all semicolons as delimiters, even within quotes.
- self.assertEqual(
- parse_cookie('keebler="E=mc2; L=\\"Loves\\"; fudge=\\012;"'),
- {'keebler': '"E=mc2', 'L': '\\"Loves\\"', 'fudge': '\\012', '': '"'}
- )
- # Illegal cookies that have an '=' char in an unquoted value.
- self.assertEqual(parse_cookie('keebler=E=mc2'), {'keebler': 'E=mc2'})
- # Cookies with ':' character in their name.
- self.assertEqual(parse_cookie('key:term=value:term'), {'key:term': 'value:term'})
- # Cookies with '[' and ']'.
- self.assertEqual(parse_cookie('a=b; c=[; d=r; f=h'), {'a': 'b', 'c': '[', 'd': 'r', 'f': 'h'})
-
- def test_cookie_edgecases(self):
- # Cookies that RFC6265 allows.
- self.assertEqual(parse_cookie('a=b; Domain=example.com'), {'a': 'b', 'Domain': 'example.com'})
- # parse_cookie() has historically kept only the last cookie with the
- # same name.
- self.assertEqual(parse_cookie('a=b; h=i; a=c'), {'a': 'c', 'h': 'i'})
-
- def test_invalid_cookies(self):
- """
- Cookie strings that go against RFC6265 but browsers will send if set
- via document.cookie.
- """
- # Chunks without an equals sign appear as unnamed values per
- # https://bugzilla.mozilla.org/show_bug.cgi?id=169091
- self.assertIn('django_language', parse_cookie('abc=def; unnamed; django_language=en').keys())
- # Even a double quote may be an unamed value.
- self.assertEqual(parse_cookie('a=b; "; c=d'), {'a': 'b', '': '"', 'c': 'd'})
- # Spaces in names and values, and an equals sign in values.
- self.assertEqual(parse_cookie('a b c=d e = f; gh=i'), {'a b c': 'd e = f', 'gh': 'i'})
- # More characters the spec forbids.
- self.assertEqual(parse_cookie('a b,c<>@:/[]?{}=d " =e,f g'), {'a b,c<>@:/[]?{}': 'd " =e,f g'})
- # Unicode characters. The spec only allows ASCII.
- self.assertEqual(parse_cookie('saint=André Bessette'), {'saint': force_str('André Bessette')})
- # Browsers don't send extra whitespace or semicolons in Cookie headers,
- # but parse_cookie() should parse whitespace the same way
- # document.cookie parses whitespace.
- self.assertEqual(parse_cookie(' = b ; ; = ; c = ; '), {'': 'b', 'c': ''})
-
def test_httponly_after_load(self):
"""
Test that we can use httponly attribute on cookies that we load
diff --git a/tests/requests/tests.py b/tests/requests/tests.py
index 6364ab1..55b37bb 100644
--- a/tests/requests/tests.py
+++ b/tests/requests/tests.py
@@ -11,7 +11,7 @@ from django.db import connection, connections
from django.core import signals
from django.core.exceptions import SuspiciousOperation
from django.core.handlers.wsgi import WSGIRequest, LimitedStream
-from django.http import (HttpRequest, HttpResponse,
+from django.http import (HttpRequest, HttpResponse, parse_cookie,
build_request_repr, UnreadablePostError, RawPostDataException)
from django.test import SimpleTestCase, TransactionTestCase, override_settings
from django.test.client import FakePayload
@@ -128,6 +128,9 @@ class RequestsTests(SimpleTestCase):
request = WSGIRequest({'PATH_INFO': wsgi_str("/سلام/"), 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'')})
self.assertEqual(request.path, "/سلام/")
+ def test_parse_cookie(self):
+ self.assertEqual(parse_cookie('invalid at key=true'), {})
+
def test_httprequest_location(self):
request = HttpRequest()
self.assertEqual(request.build_absolute_uri(location="https://www.example.com/asdf"),
diff --git a/tests/utils_tests/test_http.py b/tests/utils_tests/test_http.py
index 769f163..3b367a4 100644
--- a/tests/utils_tests/test_http.py
+++ b/tests/utils_tests/test_http.py
@@ -1,5 +1,3 @@
-# -*- encoding: utf-8 -*-
-from __future__ import unicode_literals
from datetime import datetime
import sys
import unittest
@@ -112,11 +110,6 @@ class TestUtilsHttp(unittest.TestCase):
'javascript:alert("XSS")',
'\njavascript:alert(x)',
'\x08//example.com',
- r'http://otherserver\@example.com',
- r'http:\\testserver\@example.com',
- r'http://testserver\me:pass@example.com',
- r'http://testserver\@example.com',
- r'http:\\testserver\confirm\me at example.com',
'\n'):
self.assertFalse(http.is_safe_url(bad_url, host='testserver'), "%s should be blocked" % bad_url)
for good_url in ('/view/?param=http://example.com',
@@ -126,27 +119,9 @@ class TestUtilsHttp(unittest.TestCase):
'https://testserver/',
'HTTPS://testserver/',
'//testserver/',
- 'http://testserver/confirm?email=me@example.com',
'/url%20with%20spaces/'):
self.assertTrue(http.is_safe_url(good_url, host='testserver'), "%s should be allowed" % good_url)
- if six.PY2:
- # Check binary URLs, regression tests for #26308
- self.assertTrue(
- http.is_safe_url(b'https://testserver/', host='testserver'),
- "binary URLs should be allowed on Python 2"
- )
- self.assertFalse(http.is_safe_url(b'\x08//example.com', host='testserver'))
- self.assertTrue(http.is_safe_url('àview/'.encode('utf-8'), host='testserver'))
- self.assertFalse(http.is_safe_url('àview'.encode('latin-1'), host='testserver'))
-
- # Valid basic auth credentials are allowed.
- self.assertTrue(http.is_safe_url(r'http://user:pass@testserver/', host='user:pass at testserver'))
- # A path without host is allowed.
- self.assertTrue(http.is_safe_url('/confirm/me at example.com'))
- # Basic auth without host is not allowed.
- self.assertFalse(http.is_safe_url(r'http://testserver\@example.com'))
-
def test_urlsafe_base64_roundtrip(self):
bytestring = b'foo'
encoded = http.urlsafe_base64_encode(bytestring)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-django.git
More information about the Python-modules-commits
mailing list