[Python-modules-commits] [python-django] 01/06: Import python-django_1.8.11.orig.tar.gz
Raphaël Hertzog
hertzog at moszumanska.debian.org
Tue Mar 8 17:27:49 UTC 2016
This is an automated email from the git hooks/post-receive script.
hertzog pushed a commit to branch debian/jessie-backports
in repository python-django.
commit 8fea21d6d20c57d58d53c0df77531bb93883bfee
Author: Raphaël Hertzog <hertzog at debian.org>
Date: Tue Mar 8 17:50:36 2016 +0100
Import python-django_1.8.11.orig.tar.gz
---
Django.egg-info/PKG-INFO | 2 +-
Django.egg-info/SOURCES.txt | 3 +
PKG-INFO | 2 +-
django/__init__.py | 2 +-
django/contrib/admin/actions.py | 2 +-
django/contrib/auth/context_processors.py | 2 +-
django/contrib/auth/hashers.py | 77 ++++++++++----
django/contrib/contenttypes/models.py | 20 ++--
django/contrib/gis/db/backends/postgis/models.py | 2 +-
django/contrib/gis/db/models/query.py | 2 +-
django/contrib/gis/gdal/geomtype.py | 2 +-
django/contrib/gis/sitemaps/kml.py | 2 +-
django/contrib/postgres/fields/array.py | 7 +-
django/contrib/postgres/fields/ranges.py | 8 +-
django/core/validators.py | 9 +-
django/db/backends/postgresql_psycopg2/base.py | 2 +-
django/db/models/expressions.py | 2 +-
django/db/models/fields/related.py | 19 ++--
django/db/models/query_utils.py | 2 +-
django/forms/forms.py | 2 +-
django/template/defaultfilters.py | 2 +-
django/template/defaulttags.py | 2 +-
django/test/signals.py | 2 +-
django/utils/http.py | 13 ++-
django/utils/translation/__init__.py | 7 ++
docs/_theme/djangodocs/static/djangodocs.css | 2 +-
docs/conf.py | 11 +-
docs/howto/custom-model-fields.txt | 3 +-
docs/howto/outputting-pdf.txt | 2 +-
docs/internals/deprecation.txt | 3 +
docs/intro/reusable-apps.txt | 4 +-
docs/ref/contrib/gis/feeds.txt | 4 +-
docs/ref/contrib/gis/testing.txt | 4 +-
docs/ref/contrib/gis/tutorial.txt | 8 +-
docs/ref/contrib/syndication.txt | 2 +-
docs/ref/models/expressions.txt | 6 +-
docs/ref/settings.txt | 27 ++---
docs/ref/validators.txt | 6 +-
docs/releases/1.6.txt | 4 +-
docs/releases/1.8.10.txt | 80 +++++++++++++++
docs/releases/1.8.11.txt | 8 ++
docs/releases/1.8.txt | 7 +-
docs/releases/index.txt | 2 +
docs/releases/security.txt | 38 +++++++
docs/spelling_wordlist | 2 +
docs/topics/auth/customizing.txt | 61 +----------
docs/topics/auth/default.txt | 2 +-
docs/topics/auth/passwords.txt | 113 +++++++++++++++++++++
docs/topics/db/multi-db.txt | 4 +-
docs/topics/email.txt | 2 +
docs/topics/testing/tools.txt | 1 -
setup.cfg | 2 +-
tests/admin_changelist/tests.py | 2 +-
tests/aggregation_regress/tests.py | 4 +-
tests/auth_tests/test_forms.py | 2 +-
tests/auth_tests/test_hashers.py | 58 ++++++++++-
tests/auth_tests/test_views.py | 10 +-
tests/backends/tests.py | 5 +
tests/check_framework/test_security.py | 6 +-
tests/contenttypes_tests/test_models.py | 14 ++-
tests/expressions_case/tests.py | 2 +-
tests/forms_tests/tests/test_fields.py | 3 +
tests/forms_tests/tests/test_forms.py | 16 ++-
tests/forms_tests/tests/tests.py | 2 +-
tests/httpwrappers/tests.py | 2 +-
tests/i18n/commands/__init__.py | 2 +-
tests/i18n/tests.py | 8 ++
tests/invalid_models_tests/test_models.py | 2 +-
tests/invalid_models_tests/test_relative_fields.py | 36 +++++--
tests/m2m_through/tests.py | 8 +-
tests/middleware/tests.py | 4 +-
tests/migrations/test_writer.py | 8 +-
tests/model_fields/models.py | 8 +-
tests/model_options/test_default_related_name.py | 2 +-
tests/modeladmin/tests.py | 2 +-
tests/null_fk_ordering/models.py | 4 +-
tests/postgres_tests/test_array.py | 8 +-
tests/postgres_tests/test_hstore.py | 9 +-
tests/postgres_tests/test_ranges.py | 11 ++
tests/proxy_models/tests.py | 2 +-
tests/queries/models.py | 2 +-
tests/queries/tests.py | 6 +-
tests/queryset_pickle/tests.py | 2 +-
tests/requests/tests.py | 14 +--
tests/serializers_regress/tests.py | 2 +-
tests/signals/tests.py | 2 +-
tests/staticfiles_tests/test_liveserver.py | 2 +-
tests/template_tests/test_response.py | 4 +-
tests/template_tests/test_response_deprecations.py | 42 ++++++++
tests/test_runner/test_discover_runner.py | 6 +-
tests/timezones/tests.py | 2 +-
tests/unmanaged_models/models.py | 2 +-
tests/utils_tests/files/strip_tags2.txt | 2 +-
tests/utils_tests/test_http.py | 28 ++++-
tests/validators/invalid_urls.txt | 4 +-
tests/validators/valid_urls.txt | 4 +
96 files changed, 731 insertions(+), 236 deletions(-)
diff --git a/Django.egg-info/PKG-INFO b/Django.egg-info/PKG-INFO
index 42f9052..c536eb8 100644
--- a/Django.egg-info/PKG-INFO
+++ b/Django.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Django
-Version: 1.8.9
+Version: 1.8.11
Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
Home-page: http://www.djangoproject.com/
Author: Django Software Foundation
diff --git a/Django.egg-info/SOURCES.txt b/Django.egg-info/SOURCES.txt
index 4b68a10..5399da9 100644
--- a/Django.egg-info/SOURCES.txt
+++ b/Django.egg-info/SOURCES.txt
@@ -3402,6 +3402,8 @@ docs/releases/1.7.8.txt
docs/releases/1.7.9.txt
docs/releases/1.7.txt
docs/releases/1.8.1.txt
+docs/releases/1.8.10.txt
+docs/releases/1.8.11.txt
docs/releases/1.8.2.txt
docs/releases/1.8.3.txt
docs/releases/1.8.4.txt
@@ -4794,6 +4796,7 @@ tests/template_tests/test_loaders.py
tests/template_tests/test_nodelist.py
tests/template_tests/test_parser.py
tests/template_tests/test_response.py
+tests/template_tests/test_response_deprecations.py
tests/template_tests/test_smartif.py
tests/template_tests/test_unicode.py
tests/template_tests/tests.py
diff --git a/PKG-INFO b/PKG-INFO
index 42f9052..c536eb8 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: Django
-Version: 1.8.9
+Version: 1.8.11
Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
Home-page: http://www.djangoproject.com/
Author: Django Software Foundation
diff --git a/django/__init__.py b/django/__init__.py
index 80244c4..99e91ca 100644
--- a/django/__init__.py
+++ b/django/__init__.py
@@ -1,6 +1,6 @@
from django.utils.version import get_version
-VERSION = (1, 8, 9, 'final', 0)
+VERSION = (1, 8, 11, 'final', 0)
__version__ = get_version(VERSION)
diff --git a/django/contrib/admin/actions.py b/django/contrib/admin/actions.py
index 4445dd5..c4cccfd 100644
--- a/django/contrib/admin/actions.py
+++ b/django/contrib/admin/actions.py
@@ -16,7 +16,7 @@ def delete_selected(modeladmin, request, queryset):
"""
Default action which deletes the selected objects.
- This action first displays a confirmation page whichs shows all the
+ This action first displays a confirmation page which shows all the
deleteable objects, or, if the user has no permission one of the related
childs (foreignkeys), a "permission denied" message.
diff --git a/django/contrib/auth/context_processors.py b/django/contrib/auth/context_processors.py
index 474002e..ce1e42d 100644
--- a/django/contrib/auth/context_processors.py
+++ b/django/contrib/auth/context_processors.py
@@ -13,7 +13,7 @@ class PermLookupDict(object):
return self.user.has_perm("%s.%s" % (self.app_label, perm_name))
def __iter__(self):
- # To fix 'item in perms.someapp' and __getitem__ iteraction we need to
+ # To fix 'item in perms.someapp' and __getitem__ interaction we need to
# define __iter__. See #18979 for details.
raise TypeError("PermLookupDict is not iterable.")
diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index a8583f7..01f4cec 100644
--- a/django/contrib/auth/hashers.py
+++ b/django/contrib/auth/hashers.py
@@ -4,6 +4,7 @@ import base64
import binascii
import hashlib
import importlib
+import warnings
from collections import OrderedDict
from django.conf import settings
@@ -46,10 +47,17 @@ def check_password(password, encoded, setter=None, preferred='default'):
preferred = get_hasher(preferred)
hasher = identify_hasher(encoded)
- must_update = hasher.algorithm != preferred.algorithm
- if not must_update:
- must_update = preferred.must_update(encoded)
+ hasher_changed = hasher.algorithm != preferred.algorithm
+ must_update = hasher_changed or 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
@@ -216,6 +224,19 @@ 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):
"""
@@ -258,6 +279,12 @@ 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):
"""
@@ -308,23 +335,8 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
def verify(self, password, encoded):
algorithm, data = encoded.split('$', 1)
assert algorithm == self.algorithm
- 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)
+ encoded_2 = self.encode(password, force_bytes(data))
+ return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
algorithm, empty, algostr, work_factor, data = encoded.split('$', 4)
@@ -337,6 +349,16 @@ 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):
"""
@@ -384,6 +406,9 @@ class SHA1PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(hash)),
])
+ def harden_runtime(self, password, encoded):
+ pass
+
class MD5PasswordHasher(BasePasswordHasher):
"""
@@ -412,6 +437,9 @@ class MD5PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(hash)),
])
+ def harden_runtime(self, password, encoded):
+ pass
+
class UnsaltedSHA1PasswordHasher(BasePasswordHasher):
"""
@@ -444,6 +472,9 @@ class UnsaltedSHA1PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(hash)),
])
+ def harden_runtime(self, password, encoded):
+ pass
+
class UnsaltedMD5PasswordHasher(BasePasswordHasher):
"""
@@ -477,6 +508,9 @@ class UnsaltedMD5PasswordHasher(BasePasswordHasher):
(_('hash'), mask_hash(encoded, show=3)),
])
+ def harden_runtime(self, password, encoded):
+ pass
+
class CryptPasswordHasher(BasePasswordHasher):
"""
@@ -511,3 +545,6 @@ class CryptPasswordHasher(BasePasswordHasher):
(_('salt'), salt),
(_('hash'), mask_hash(data, show=3)),
])
+
+ def harden_runtime(self, password, encoded):
+ pass
diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py
index 27a5388..8d459f6 100644
--- a/django/contrib/contenttypes/models.py
+++ b/django/contrib/contenttypes/models.py
@@ -13,13 +13,15 @@ from django.utils.translation import ugettext_lazy as _
class ContentTypeManager(models.Manager):
use_in_migrations = True
- # Cache to avoid re-looking up ContentType objects all over the place.
- # This cache is shared by all the get_for_* methods.
- _cache = {}
+ def __init__(self, *args, **kwargs):
+ super(ContentTypeManager, self).__init__(*args, **kwargs)
+ # Cache shared by all the get_for_* methods to speed up
+ # ContentType retrieval.
+ self._cache = {}
def get_by_natural_key(self, app_label, model):
try:
- ct = self.__class__._cache[self.db][(app_label, model)]
+ ct = self._cache[self.db][(app_label, model)]
except KeyError:
ct = self.get(app_label=app_label, model=model)
self._add_to_cache(self.db, ct)
@@ -34,7 +36,7 @@ class ContentTypeManager(models.Manager):
def _get_from_cache(self, opts):
key = (opts.app_label, opts.model_name)
- return self.__class__._cache[self.db][key]
+ return self._cache[self.db][key]
def create(self, **kwargs):
if 'name' in kwargs:
@@ -129,7 +131,7 @@ class ContentTypeManager(models.Manager):
(though ContentTypes are obviously not created on-the-fly by get_by_id).
"""
try:
- ct = self.__class__._cache[self.db][id]
+ ct = self._cache[self.db][id]
except KeyError:
# This could raise a DoesNotExist; that's correct behavior and will
# make sure that only correct ctypes get stored in the cache dict.
@@ -144,15 +146,15 @@ class ContentTypeManager(models.Manager):
django.contrib.contenttypes.management.update_contenttypes for where
this gets called).
"""
- self.__class__._cache.clear()
+ self._cache.clear()
def _add_to_cache(self, using, ct):
"""Insert a ContentType into the cache."""
# Note it's possible for ContentType objects to be stale; model_class() will return None.
# Hence, there is no reliance on model._meta.app_label here, just using the model fields instead.
key = (ct.app_label, ct.model)
- self.__class__._cache.setdefault(using, {})[key] = ct
- self.__class__._cache.setdefault(using, {})[ct.id] = ct
+ self._cache.setdefault(using, {})[key] = ct
+ self._cache.setdefault(using, {})[ct.id] = ct
@python_2_unicode_compatible
diff --git a/django/contrib/gis/db/backends/postgis/models.py b/django/contrib/gis/db/backends/postgis/models.py
index 83b254c..68d4c18 100644
--- a/django/contrib/gis/db/backends/postgis/models.py
+++ b/django/contrib/gis/db/backends/postgis/models.py
@@ -51,7 +51,7 @@ class PostGISGeometryColumns(models.Model):
class PostGISSpatialRefSys(models.Model, SpatialRefSysMixin):
"""
The 'spatial_ref_sys' table from PostGIS. See the PostGIS
- documentaiton at Ch. 4.2.1.
+ documentation at Ch. 4.2.1.
"""
srid = models.IntegerField(primary_key=True)
auth_name = models.CharField(max_length=256)
diff --git a/django/contrib/gis/db/models/query.py b/django/contrib/gis/db/models/query.py
index 343610c..c60750a 100644
--- a/django/contrib/gis/db/models/query.py
+++ b/django/contrib/gis/db/models/query.py
@@ -500,7 +500,7 @@ class GeoQuerySet(QuerySet):
SQL function to call.
settings:
- Dictonary of internal settings to customize for the spatial procedure.
+ Dictionary of internal settings to customize for the spatial procedure.
Public Keyword Arguments:
diff --git a/django/contrib/gis/gdal/geomtype.py b/django/contrib/gis/gdal/geomtype.py
index abb184e..d0dc1c0 100644
--- a/django/contrib/gis/gdal/geomtype.py
+++ b/django/contrib/gis/gdal/geomtype.py
@@ -3,7 +3,7 @@ from django.utils import six
class OGRGeomType(object):
- "Encapulates OGR Geometry Types."
+ "Encapsulates OGR Geometry Types."
wkb25bit = -2147483648
diff --git a/django/contrib/gis/sitemaps/kml.py b/django/contrib/gis/sitemaps/kml.py
index 4dcaa8f..83e1edc 100644
--- a/django/contrib/gis/sitemaps/kml.py
+++ b/django/contrib/gis/sitemaps/kml.py
@@ -44,7 +44,7 @@ class KMLSitemap(Sitemap):
def get_urls(self, page=1, site=None, protocol=None):
"""
- This method is overrridden so the appropriate `geo_format` attribute
+ This method is overridden so the appropriate `geo_format` attribute
is placed on each URL element.
"""
urls = Sitemap.get_urls(self, page=page, site=site, protocol=protocol)
diff --git a/django/contrib/postgres/fields/array.py b/django/contrib/postgres/fields/array.py
index ceac798..a2953af 100644
--- a/django/contrib/postgres/fields/array.py
+++ b/django/contrib/postgres/fields/array.py
@@ -95,8 +95,11 @@ class ArrayField(Field):
base_field = self.base_field
for val in vals:
- obj = AttributeSetter(base_field.attname, val)
- values.append(base_field.value_to_string(obj))
+ if val is None:
+ values.append(None)
+ else:
+ obj = AttributeSetter(base_field.attname, val)
+ values.append(base_field.value_to_string(obj))
return json.dumps(values)
def get_transform(self, name):
diff --git a/django/contrib/postgres/fields/ranges.py b/django/contrib/postgres/fields/ranges.py
index fe69b08..83319b2 100644
--- a/django/contrib/postgres/fields/ranges.py
+++ b/django/contrib/postgres/fields/ranges.py
@@ -51,8 +51,12 @@ class RangeField(models.Field):
base_field = self.base_field
result = {"bounds": value._bounds}
for end in ('lower', 'upper'):
- obj = AttributeSetter(base_field.attname, getattr(value, end))
- result[end] = base_field.value_to_string(obj)
+ val = getattr(value, end)
+ if val is None:
+ result[end] = None
+ else:
+ obj = AttributeSetter(base_field.attname, val)
+ result[end] = base_field.value_to_string(obj)
return json.dumps(result)
def formfield(self, **kwargs):
diff --git a/django/core/validators.py b/django/core/validators.py
index 89d184f..de25f57 100644
--- a/django/core/validators.py
+++ b/django/core/validators.py
@@ -74,7 +74,14 @@ class URLValidator(RegexValidator):
# Host patterns
hostname_re = r'[a-z' + ul + r'0-9](?:[a-z' + ul + r'0-9-]*[a-z' + ul + r'0-9])?'
domain_re = r'(?:\.(?!-)[a-z' + ul + r'0-9-]+(?<!-))*'
- tld_re = r'\.(?:[a-z' + ul + r']{2,}|xn--[a-z0-9]+)\.?'
+ tld_re = (
+ '\.' # dot
+ '(?!-)' # can't start with a dash
+ '(?:[a-z' + ul + '-]{2,}' # domain label
+ '|xn--[a-z0-9]+)' # or punycode label
+ '(?<!-)' # can't end with a dash
+ '\.?' # may have a trailing dot
+ )
host_re = '(' + hostname_re + domain_re + tld_re + '|localhost)'
regex = re.compile(
diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py
index a76ca3c..e625c28 100644
--- a/django/db/backends/postgresql_psycopg2/base.py
+++ b/django/db/backends/postgresql_psycopg2/base.py
@@ -198,7 +198,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
tz = self.settings_dict['TIME_ZONE']
conn_tz = self.connection.get_parameter_status('TimeZone')
- if conn_tz != tz:
+ if tz and conn_tz != tz:
cursor = self.connection.cursor()
try:
cursor.execute(self.ops.set_time_zone_sql(), [tz])
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index 83121a9..931a9d8 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -302,7 +302,7 @@ class BaseExpression(object):
Does this expression contain a reference to some of the
existing aggregates? If so, returns the aggregate and also
the lookup parts that *weren't* found. So, if
- exsiting_aggregates = {'max_id': Max('id')}
+ existing_aggregates = {'max_id': Max('id')}
self.name = 'max_id'
queryset.filter(max_id__range=[10,100])
then this method will return Max('id') and those parts of the
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index f64ca22..93a0879 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -194,12 +194,6 @@ class RelatedField(Field):
if not isinstance(self.rel.to, ModelBase):
return []
- # If the field doesn't install backward relation on the target model (so
- # `is_hidden` returns True), then there are no clashes to check and we
- # can skip these fields.
- if self.rel.is_hidden():
- return []
-
try:
self.rel
except AttributeError:
@@ -216,12 +210,15 @@ class RelatedField(Field):
# foreign = models.ForeignKey(Target)
# m2m = models.ManyToManyField(Target)
- rel_opts = self.rel.to._meta
# rel_opts.object_name == "Target"
+ rel_opts = self.rel.to._meta
+ # If the field doesn't install a backward relation on the target model
+ # (so `is_hidden` returns True), then there are no clashes to check
+ # and we can skip these fields.
+ rel_is_hidden = self.rel.is_hidden()
rel_name = self.rel.get_accessor_name() # i. e. "model_set"
rel_query_name = self.related_query_name() # i. e. "model"
- field_name = "%s.%s" % (opts.object_name,
- self.name) # i. e. "Model.field"
+ field_name = "%s.%s" % (opts.object_name, self.name) # i. e. "Model.field"
# Check clashes between accessor or reverse query name of `field`
# and any other field name -- i.e. accessor for Model.foreign is
@@ -230,7 +227,7 @@ class RelatedField(Field):
for clash_field in potential_clashes:
clash_name = "%s.%s" % (rel_opts.object_name,
clash_field.name) # i. e. "Target.model_set"
- if clash_field.name == rel_name:
+ if not rel_is_hidden and clash_field.name == rel_name:
errors.append(
checks.Error(
"Reverse accessor for '%s' clashes with field name '%s'." % (field_name, clash_name),
@@ -260,7 +257,7 @@ class RelatedField(Field):
clash_name = "%s.%s" % ( # i. e. "Model.m2m"
clash_field.related_model._meta.object_name,
clash_field.field.name)
- if clash_field.get_accessor_name() == rel_name:
+ if not rel_is_hidden and clash_field.get_accessor_name() == rel_name:
errors.append(
checks.Error(
"Reverse accessor for '%s' clashes with reverse accessor for '%s'." % (field_name, clash_name),
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py
index 4eca2c9..90c294d 100644
--- a/django/db/models/query_utils.py
+++ b/django/db/models/query_utils.py
@@ -42,7 +42,7 @@ class QueryWrapper(object):
class Q(tree.Node):
"""
Encapsulates filters as objects that can then be combined logically (using
- & and |).
+ `&` and `|`).
"""
# Connection types
AND = 'AND'
diff --git a/django/forms/forms.py b/django/forms/forms.py
index 80ba830..3f9d789 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -554,7 +554,7 @@ class BoundField(object):
def __getitem__(self, idx):
# Prevent unnecessary reevaluation when accessing BoundField's attrs
# from templates.
- if not isinstance(idx, six.integer_types):
+ if not isinstance(idx, six.integer_types + (slice,)):
raise TypeError
return list(self.__iter__())[idx]
diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index 9324b7f..cd2457d 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -841,7 +841,7 @@ def default_if_none(value, arg):
@register.filter(is_safe=False)
def divisibleby(value, arg):
- """Returns True if the value is devisible by the argument."""
+ """Returns True if the value is divisible by the argument."""
return int(value) % int(arg) == 0
diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index 09c0e72..4526737 100644
--- a/django/template/defaulttags.py
+++ b/django/template/defaulttags.py
@@ -824,7 +824,7 @@ def do_for(parser, token):
than -- the following::
<ul>
- {% if althete_list %}
+ {% if athlete_list %}
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
diff --git a/django/test/signals.py b/django/test/signals.py
index 0c2bf52..fd3de51 100644
--- a/django/test/signals.py
+++ b/django/test/signals.py
@@ -73,7 +73,7 @@ def update_connections_time_zone(**kwargs):
for conn in connections.all():
conn.settings_dict['TIME_ZONE'] = tz
tz_sql = conn.ops.set_time_zone_sql()
- if tz_sql:
+ if tz_sql and tz:
conn.cursor().execute(tz_sql, [tz])
diff --git a/django/utils/http.py b/django/utils/http.py
index 34c1742..b70720d 100644
--- a/django/utils/http.py
+++ b/django/utils/http.py
@@ -277,8 +277,17 @@ def is_safe_url(url, host=None):
url = url.strip()
if not url:
return False
- # Chrome treats \ completely as /
- url = url.replace('\\', '/')
+ 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 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/utils/translation/__init__.py b/django/utils/translation/__init__.py
index a4c6963..ed45250 100644
--- a/django/utils/translation/__init__.py
+++ b/django/utils/translation/__init__.py
@@ -105,6 +105,8 @@ def lazy_number(func, resultclass, number=None, **kwargs):
kwargs['number'] = number
proxy = lazy(func, resultclass)(**kwargs)
else:
+ original_kwargs = kwargs.copy()
+
class NumberAwareString(resultclass):
def __mod__(self, rhs):
if isinstance(rhs, dict) and number:
@@ -127,9 +129,14 @@ def lazy_number(func, resultclass, number=None, **kwargs):
return translated
proxy = lazy(lambda **kwargs: NumberAwareString(), NumberAwareString)(**kwargs)
+ proxy.__reduce__ = lambda: (_lazy_number_unpickle, (func, resultclass, number, original_kwargs))
return proxy
+def _lazy_number_unpickle(func, resultclass, number, kwargs):
+ return lazy_number(func, resultclass, number=number, **kwargs)
+
+
def ngettext_lazy(singular, plural, number=None):
return lazy_number(ngettext, str, singular=singular, plural=plural, number=number)
diff --git a/docs/_theme/djangodocs/static/djangodocs.css b/docs/_theme/djangodocs/static/djangodocs.css
index 9cf2384..a05f747 100644
--- a/docs/_theme/djangodocs/static/djangodocs.css
+++ b/docs/_theme/djangodocs/static/djangodocs.css
@@ -118,7 +118,7 @@ div.admonition-philosophy { padding-left:65px; background:url(docicons-philosoph
div.admonition-behind-the-scenes { padding-left:65px; background:url(docicons-behindscenes.png) .8em .8em no-repeat;}
.admonition.warning { background:url(docicons-warning.png) .8em .8em no-repeat; border:1px solid #ffc83c;}
-/*** versoinadded/changes ***/
+/*** versionadded/changes ***/
div.versionadded, div.versionchanged { }
div.versionadded span.title, div.versionchanged span.title, span.versionmodified { font-weight: bold; }
div.versionadded, div.versionchanged, div.deprecated { color:#555; }
diff --git a/docs/conf.py b/docs/conf.py
index 55d13f0..1176f8d 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -6,7 +6,7 @@
# This file is execfile()d with the current directory set to its containing dir.
#
# The contents of this file are pickled, so don't put values in the namespace
-# that aren't pickleable (module imports are okay, they're removed automatically).
+# that aren't picklable (module imports are okay, they're removed automatically).
#
# All configuration values have a default; values that are commented out
# serve to show the default.
@@ -16,6 +16,15 @@ from __future__ import unicode_literals
import sys
from os.path import abspath, dirname, join
+# Workaround for sphinx-build recursion limit overflow:
+# pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
+# RuntimeError: maximum recursion depth exceeded while pickling an object
+#
+# Python's default allowed recursion depth is 1000 but this isn't enough for
+# building docs/ref/settings.txt sometimes.
+# https://groups.google.com/d/topic/sphinx-dev/MtRf64eGtv4/discussion
+sys.setrecursionlimit(2000)
+
# Make sure we get the version of this copy of Django
sys.path.insert(1, dirname(dirname(abspath(__file__))))
diff --git a/docs/howto/custom-model-fields.txt b/docs/howto/custom-model-fields.txt
index f41e950..9848f2c 100644
--- a/docs/howto/custom-model-fields.txt
+++ b/docs/howto/custom-model-fields.txt
@@ -470,6 +470,7 @@ instances::
from django.core.exceptions import ValidationError
from django.db import models
+ from django.utils.translation import ugettext_lazy as _
def parse_hand(hand_string):
"""Takes a string of cards and splits into a full hand."""
@@ -477,7 +478,7 @@ instances::
p2 = re.compile('..')
args = [p2.findall(x) for x in p1.findall(hand_string)]
if len(args) != 4:
- raise ValidationError("Invalid input for a Hand instance")
+ raise ValidationError(_("Invalid input for a Hand instance"))
return Hand(*args)
class HandField(models.Field):
diff --git a/docs/howto/outputting-pdf.txt b/docs/howto/outputting-pdf.txt
index 5b070c6..0e82ecc 100644
--- a/docs/howto/outputting-pdf.txt
+++ b/docs/howto/outputting-pdf.txt
@@ -153,7 +153,7 @@ Further resources
using ``system`` or ``popen`` and retrieve the output in Python.
.. _PDFlib: http://www.pdflib.org/
-.. _`Pisa XHTML2PDF`: http://www.xhtml2pdf.com/
+.. _`Pisa XHTML2PDF`: https://github.com/xhtml2pdf/xhtml2pdf
.. _HTMLdoc: https://www.msweet.org/projects.php?Z1
Other formats
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index 2fca895..ed82ad2 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -34,6 +34,9 @@ details on these changes.
* The ability to :func:`~django.core.urlresolvers.reverse` URLs using a dotted
Python path will be removed.
+* The ability to use a dotted Python path for the ``LOGIN_URL`` and
+ ``LOGIN_REDIRECT_URL`` settings will be removed.
+
* Support for :py:mod:`optparse` will be dropped for custom management commands
(replaced by :py:mod:`argparse`).
diff --git a/docs/intro/reusable-apps.txt b/docs/intro/reusable-apps.txt
index 245a88b..ffe1295 100644
--- a/docs/intro/reusable-apps.txt
+++ b/docs/intro/reusable-apps.txt
@@ -193,7 +193,7 @@ this. For a small app like polls, this process isn't too difficult.
:filename: django-polls/setup.py
import os
- from setuptools import setup
+ from setuptools import find_packages, setup
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
README = readme.read()
@@ -204,7 +204,7 @@ this. For a small app like polls, this process isn't too difficult.
setup(
name='django-polls',
version='0.1',
- packages=['polls'],
+ packages=find_packages(),
include_package_data=True,
license='BSD License', # example license
description='A simple Django app to conduct Web-based polls.',
diff --git a/docs/ref/contrib/gis/feeds.txt b/docs/ref/contrib/gis/feeds.txt
index 72c51b5..49c8f97 100644
--- a/docs/ref/contrib/gis/feeds.txt
+++ b/docs/ref/contrib/gis/feeds.txt
@@ -31,9 +31,9 @@ API Reference
base class, GeoDjango's ``Feed`` class provides
the following overrides. Note that these overrides may be done in multiple ways::
- from django.contrib.gis.feeds import Feed
+ from django.contrib.gis.feeds import Feed
- class MyFeed(Feed):
+ class MyFeed(Feed):
# First, as a class attribute.
geometry = ...
diff --git a/docs/ref/contrib/gis/testing.txt b/docs/ref/contrib/gis/testing.txt
index bdd46e9..17eeeac 100644
--- a/docs/ref/contrib/gis/testing.txt
+++ b/docs/ref/contrib/gis/testing.txt
@@ -132,11 +132,11 @@ in :mod:`django.contrib.gis`::
'NAME': 'geodjango',
'USER': 'geodjango',
},
- 'other': {
+ 'other': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'other',
'USER': 'geodjango',
- }
+ },
}
SECRET_KEY = 'django_tests_secret_key'
diff --git a/docs/ref/contrib/gis/tutorial.txt b/docs/ref/contrib/gis/tutorial.txt
index 6ea5dd3..5b0a0f3 100644
--- a/docs/ref/contrib/gis/tutorial.txt
+++ b/docs/ref/contrib/gis/tutorial.txt
@@ -107,7 +107,7 @@ file. Edit the database connection settings to match your setup::
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'geodjango',
'USER': 'geo',
- }
+ },
}
In addition, modify the :setting:`INSTALLED_APPS` setting to include
@@ -122,7 +122,7 @@ and ``world`` (your newly created application)::
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis',
- 'world'
+ 'world',
)
Geographic Data
@@ -470,7 +470,7 @@ with the following code::
import os
from django.contrib.gis.utils import LayerMapping
- from models import WorldBorder
+ from .models import WorldBorder
world_mapping = {
'fips' : 'FIPS',
@@ -738,7 +738,7 @@ Let's dive right in. Create a file called ``admin.py`` inside the
``world`` application with the following code::
from django.contrib.gis import admin
- from models import WorldBorder
+ from .models import WorldBorder
admin.site.register(WorldBorder, admin.GeoModelAdmin)
diff --git a/docs/ref/contrib/syndication.txt b/docs/ref/contrib/syndication.txt
index 002cafe..bf1e3f6 100644
--- a/docs/ref/contrib/syndication.txt
+++ b/docs/ref/contrib/syndication.txt
@@ -823,7 +823,7 @@ This example illustrates all possible attributes and methods for a
def item_updateddate(self):
"""
- Returns the updateddated for every item in the feed.
+ Returns the updateddate for every item in the feed.
"""
item_updateddate = datetime.datetime(2005, 5, 3) # Hard-coded updateddate.
diff --git a/docs/ref/models/expressions.txt b/docs/ref/models/expressions.txt
index 2f780e4..67c2f39 100644
--- a/docs/ref/models/expressions.txt
+++ b/docs/ref/models/expressions.txt
@@ -448,7 +448,7 @@ calling the appropriate methods on the wrapped expression.
Tells Django that this expression contains an aggregate and that a
``GROUP BY`` clause needs to be added to the query.
- .. method:: resolve_expression(query=None, allow_joins=True, reuse=None, summarize=False)
+ .. method:: resolve_expression(query=None, allow_joins=True, reuse=None, summarize=False, for_save=False)
Provides the chance to do any pre-processing or validation of
the expression before it's added to the query. ``resolve_expression()``
@@ -579,11 +579,11 @@ Now we implement the pre-processing and validation. Since we do not have
any of our own validation at this point, we just delegate to the nested
expressions::
- def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False):
+ def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
c = self.copy()
c.is_summary = summarize
for pos, expression in enumerate(self.expressions):
- c.expressions[pos] = expression.resolve_expression(query, allow_joins, reuse, summarize)
+ c.expressions[pos] = expression.resolve_expression(query, allow_joins, reuse, summarize, for_save)
return c
Next, we write the method responsible for generating the SQL::
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
index 426cae5..30a2c7d 100644
--- a/docs/ref/settings.txt
+++ b/docs/ref/settings.txt
@@ -2866,9 +2866,14 @@ The URL where requests are redirected after login when the
This is used by the :func:`~django.contrib.auth.decorators.login_required`
decorator, for example.
-This setting also accepts view function names and :ref:`named URL patterns
-<naming-url-patterns>` which can be used to reduce configuration duplication
-since you don't have to define the URL in two places (``settings`` and URLconf).
+This setting also accepts :ref:`named URL patterns <naming-url-patterns>` which
+can be used to reduce configuration duplication since you don't have to define
+the URL in two places (``settings`` and URLconf).
+
+.. deprecated:: 1.8
+
+ The setting may also be a dotted Python path to a view function. Support
+ for this will be removed in Django 1.10.
.. setting:: LOGIN_URL
@@ -2880,18 +2885,14 @@ Default: ``'/accounts/login/'``
The URL where requests are redirected for login, especially when using the
:func:`~django.contrib.auth.decorators.login_required` decorator.
-This setting also accepts view function names and :ref:`named URL patterns
-<naming-url-patterns>` which can be used to reduce configuration duplication
-since you don't have to define the URL in two places (``settings`` and URLconf).
-
-.. setting:: LOGOUT_URL
+This setting also accepts :ref:`named URL patterns <naming-url-patterns>` which
+can be used to reduce configuration duplication since you don't have to define
+the URL in two places (``settings`` and URLconf).
-LOGOUT_URL
-----------
-
-Default: ``'/accounts/logout/'``
+.. deprecated:: 1.8
-LOGIN_URL counterpart.
+ The setting may also be a dotted Python path to a view function. Support
+ for this will be removed in Django 1.10.
.. setting:: PASSWORD_RESET_TIMEOUT_DAYS
diff --git a/docs/ref/validators.txt b/docs/ref/validators.txt
index 0ae1ba5..5119f53 100644
--- a/docs/ref/validators.txt
+++ b/docs/ref/validators.txt
@@ -16,10 +16,14 @@ different types of fields.
For example, here's a validator that only allows even numbers::
from django.core.exceptions import ValidationError
+ from django.utils.translation import ugettext_lazy as _
def validate_even(value):
if value % 2 != 0:
- raise ValidationError('%s is not an even number' % value)
+ raise ValidationError(
+ _('%(value)s is not an even number'),
+ params={'value': value},
+ )
... 1596 lines suppressed ...
--
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