Merge branch 'master' into schema-alteration

This commit is contained in:
Andrew Godwin 2012-08-10 12:40:37 +01:00
commit 184cf9ab79
262 changed files with 2533 additions and 1757 deletions

View File

@ -158,7 +158,7 @@ class UserSettingsHolder(BaseSettings):
return getattr(self.default_settings, name)
def __dir__(self):
return self.__dict__.keys() + dir(self.default_settings)
return list(self.__dict__) + dir(self.default_settings)
# For Python < 2.6:
__members__ = property(lambda self: self.__dir__())

View File

@ -7,7 +7,7 @@ from __future__ import unicode_literals
# see http://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
DATE_FORMAT = 'j. E Y'
TIME_FORMAT = 'G.i.s'
# DATETIME_FORMAT =
DATETIME_FORMAT = r'j. E Y \k\e\l\l\o G.i.s'
YEAR_MONTH_FORMAT = 'F Y'
MONTH_DAY_FORMAT = 'j. F'
SHORT_DATE_FORMAT = 'j.n.Y'

View File

@ -1,17 +1,18 @@
# -*- encoding: utf-8 -*-
# This file is distributed under the same license as the Django package.
#
from __future__ import unicode_literals
# The *_FORMAT strings use the Django date format syntax,
# see http://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
DATE_FORMAT = 'd F Y'
DATE_FORMAT = r'j \d\e F \d\e Y'
TIME_FORMAT = 'H:i:s'
# DATETIME_FORMAT =
YEAR_MONTH_FORMAT = 'F Y'
MONTH_DAY_FORMAT = 'j F'
SHORT_DATE_FORMAT = 'j M, Y'
# SHORT_DATETIME_FORMAT =
# FIRST_DAY_OF_WEEK =
DATETIME_FORMAT = r'j \d\e F \d\e Y \á\s H:i'
YEAR_MONTH_FORMAT = r'F \d\e Y'
MONTH_DAY_FORMAT = r'j \d\e F'
SHORT_DATE_FORMAT = 'd-m-Y'
SHORT_DATETIME_FORMAT = 'd-m-Y, H:i'
FIRST_DAY_OF_WEEK = 1 # Monday
# The *_INPUT_FORMATS strings use the Python strftime format syntax,
# see http://docs.python.org/library/datetime.html#strftime-strptime-behavior

View File

@ -1,5 +1,5 @@
from django.conf import settings
from django.conf.urls import patterns
from django.conf.urls import patterns, url
from django.core.urlresolvers import LocaleRegexURLResolver
def i18n_patterns(prefix, *args):
@ -16,5 +16,5 @@ def i18n_patterns(prefix, *args):
urlpatterns = patterns('',
(r'^setlang/$', 'django.views.i18n.set_language'),
url(r'^setlang/$', 'django.views.i18n.set_language', name='set_language'),
)

View File

@ -7,7 +7,7 @@ from django.contrib.admin import helpers
from django.contrib.admin.util import get_deleted_objects, model_ngettext
from django.db import router
from django.template.response import TemplateResponse
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy, ugettext as _
def delete_selected(modeladmin, request, queryset):
@ -42,7 +42,7 @@ def delete_selected(modeladmin, request, queryset):
n = queryset.count()
if n:
for obj in queryset:
obj_display = force_unicode(obj)
obj_display = force_text(obj)
modeladmin.log_deletion(request, obj, obj_display)
queryset.delete()
modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
@ -52,9 +52,9 @@ def delete_selected(modeladmin, request, queryset):
return None
if len(queryset) == 1:
objects_name = force_unicode(opts.verbose_name)
objects_name = force_text(opts.verbose_name)
else:
objects_name = force_unicode(opts.verbose_name_plural)
objects_name = force_text(opts.verbose_name_plural)
if perms_needed or protected:
title = _("Cannot delete %(name)s") % {"name": objects_name}

View File

@ -9,7 +9,7 @@ import datetime
from django.db import models
from django.core.exceptions import ImproperlyConfigured
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
@ -195,7 +195,7 @@ class RelatedFieldListFilter(FieldListFilter):
}
for pk_val, val in self.lookup_choices:
yield {
'selected': self.lookup_val == smart_unicode(pk_val),
'selected': self.lookup_val == smart_text(pk_val),
'query_string': cl.get_query_string({
self.lookup_kwarg: pk_val,
}, [self.lookup_kwarg_isnull]),
@ -272,7 +272,7 @@ class ChoicesFieldListFilter(FieldListFilter):
}
for lookup, title in self.field.flatchoices:
yield {
'selected': smart_unicode(lookup) == self.lookup_val,
'selected': smart_text(lookup) == self.lookup_val,
'query_string': cl.get_query_string({
self.lookup_kwarg: lookup}),
'display': title,
@ -381,7 +381,7 @@ class AllValuesFieldListFilter(FieldListFilter):
if val is None:
include_none = True
continue
val = smart_unicode(val)
val = smart_text(val)
yield {
'selected': self.lookup_val == val,
'query_string': cl.get_query_string({

View File

@ -9,7 +9,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.db.models.fields.related import ManyToManyRel
from django.forms.util import flatatt
from django.template.defaultfilters import capfirst
from django.utils.encoding import force_unicode, smart_unicode
from django.utils.encoding import force_text, smart_text
from django.utils.html import conditional_escape, format_html
from django.utils.safestring import mark_safe
from django.utils import six
@ -94,7 +94,7 @@ class Fieldset(object):
class Fieldline(object):
def __init__(self, form, field, readonly_fields=None, model_admin=None):
self.form = form # A django.forms.Form instance
if not hasattr(field, "__iter__"):
if not hasattr(field, "__iter__") or isinstance(field, six.text_type):
self.fields = [field]
else:
self.fields = field
@ -122,7 +122,7 @@ class AdminField(object):
def label_tag(self):
classes = []
contents = conditional_escape(force_unicode(self.field.label))
contents = conditional_escape(force_text(self.field.label))
if self.is_checkbox:
classes.append('vCheckboxLabel')
else:
@ -166,7 +166,7 @@ class AdminReadonlyField(object):
label = self.field['label']
return format_html('<label{0}>{1}:</label>',
flatatt(attrs),
capfirst(force_unicode(label)))
capfirst(force_text(label)))
def contents(self):
from django.contrib.admin.templatetags.admin_list import _boolean_icon
@ -182,7 +182,7 @@ class AdminReadonlyField(object):
if boolean:
result_repr = _boolean_icon(value)
else:
result_repr = smart_unicode(value)
result_repr = smart_text(value)
if getattr(attr, "allow_tags", False):
result_repr = mark_safe(result_repr)
else:
@ -325,11 +325,11 @@ class AdminErrorList(forms.util.ErrorList):
"""
def __init__(self, form, inline_formsets):
if form.is_bound:
self.extend(form.errors.values())
self.extend(list(six.itervalues(form.errors)))
for inline_formset in inline_formsets:
self.extend(inline_formset.non_form_errors())
for errors_in_inline_form in inline_formset.errors:
self.extend(errors_in_inline_form.values())
self.extend(list(six.itervalues(errors_in_inline_form)))
def normalize_fieldsets(fieldsets):
"""

View File

@ -5,7 +5,7 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.contrib.admin.util import quote
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
ADDITION = 1
CHANGE = 2
@ -13,7 +13,7 @@ DELETION = 3
class LogEntryManager(models.Manager):
def log_action(self, user_id, content_type_id, object_id, object_repr, action_flag, change_message=''):
e = self.model(None, None, user_id, content_type_id, smart_unicode(object_id), object_repr[:200], action_flag, change_message)
e = self.model(None, None, user_id, content_type_id, smart_text(object_id), object_repr[:200], action_flag, change_message)
e.save()
class LogEntry(models.Model):
@ -34,7 +34,7 @@ class LogEntry(models.Model):
ordering = ('-action_time',)
def __repr__(self):
return smart_unicode(self.action_time)
return smart_text(self.action_time)
def __unicode__(self):
if self.action_flag == ADDITION:

View File

@ -28,7 +28,7 @@ from django.utils import six
from django.utils.text import capfirst, get_text_list
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
HORIZONTAL, VERTICAL = 1, 2
# returns the <ul> class for a given radio_admin field
@ -425,7 +425,7 @@ class ModelAdmin(BaseModelAdmin):
if self.declared_fieldsets:
return self.declared_fieldsets
form = self.get_form(request, obj)
fields = form.base_fields.keys() + list(self.get_readonly_fields(request, obj))
fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
return [(None, {'fields': fields})]
def get_form(self, request, obj=None, **kwargs):
@ -520,7 +520,7 @@ class ModelAdmin(BaseModelAdmin):
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = force_unicode(object),
object_repr = force_text(object),
action_flag = ADDITION
)
@ -535,7 +535,7 @@ class ModelAdmin(BaseModelAdmin):
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = force_unicode(object),
object_repr = force_text(object),
action_flag = CHANGE,
change_message = message
)
@ -560,7 +560,7 @@ class ModelAdmin(BaseModelAdmin):
"""
A list_display column containing a checkbox widget.
"""
return helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME, force_unicode(obj.pk))
return helpers.checkbox.render(helpers.ACTION_CHECKBOX_NAME, force_text(obj.pk))
action_checkbox.short_description = mark_safe('<input type="checkbox" id="action-toggle" />')
action_checkbox.allow_tags = True
@ -608,7 +608,7 @@ class ModelAdmin(BaseModelAdmin):
tuple (name, description).
"""
choices = [] + default_choices
for func, name, description in self.get_actions(request).itervalues():
for func, name, description in six.itervalues(self.get_actions(request)):
choice = (name, description % model_format_dict(self.opts))
choices.append(choice)
return choices
@ -674,17 +674,17 @@ class ModelAdmin(BaseModelAdmin):
for formset in formsets:
for added_object in formset.new_objects:
change_message.append(_('Added %(name)s "%(object)s".')
% {'name': force_unicode(added_object._meta.verbose_name),
'object': force_unicode(added_object)})
% {'name': force_text(added_object._meta.verbose_name),
'object': force_text(added_object)})
for changed_object, changed_fields in formset.changed_objects:
change_message.append(_('Changed %(list)s for %(name)s "%(object)s".')
% {'list': get_text_list(changed_fields, _('and')),
'name': force_unicode(changed_object._meta.verbose_name),
'object': force_unicode(changed_object)})
'name': force_text(changed_object._meta.verbose_name),
'object': force_text(changed_object)})
for deleted_object in formset.deleted_objects:
change_message.append(_('Deleted %(name)s "%(object)s".')
% {'name': force_unicode(deleted_object._meta.verbose_name),
'object': force_unicode(deleted_object)})
% {'name': force_text(deleted_object._meta.verbose_name),
'object': force_text(deleted_object)})
change_message = ' '.join(change_message)
return change_message or _('No fields changed.')
@ -769,7 +769,7 @@ class ModelAdmin(BaseModelAdmin):
opts = obj._meta
pk_value = obj._get_pk_val()
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj)}
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_text(opts.verbose_name), 'obj': force_text(obj)}
# Here, we distinguish between different save types by checking for
# the presence of keys in request.POST.
if "_continue" in request.POST:
@ -782,10 +782,10 @@ class ModelAdmin(BaseModelAdmin):
return HttpResponse(
'<!DOCTYPE html><html><head><title></title></head><body>'
'<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
# escape() calls force_unicode.
# escape() calls force_text.
(escape(pk_value), escapejs(obj)))
elif "_addanother" in request.POST:
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_text(opts.verbose_name)))
return HttpResponseRedirect(request.path)
else:
self.message_user(request, msg)
@ -819,7 +819,7 @@ class ModelAdmin(BaseModelAdmin):
pk_value = obj._get_pk_val()
msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(verbose_name), 'obj': force_unicode(obj)}
msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_text(verbose_name), 'obj': force_text(obj)}
if "_continue" in request.POST:
self.message_user(request, msg + ' ' + _("You may edit it again below."))
if "_popup" in request.REQUEST:
@ -827,14 +827,14 @@ class ModelAdmin(BaseModelAdmin):
else:
return HttpResponseRedirect(request.path)
elif "_saveasnew" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(verbose_name), 'obj': obj}
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_text(verbose_name), 'obj': obj}
self.message_user(request, msg)
return HttpResponseRedirect(reverse('admin:%s_%s_change' %
(opts.app_label, module_name),
args=(pk_value,),
current_app=self.admin_site.name))
elif "_addanother" in request.POST:
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_unicode(verbose_name)))
self.message_user(request, msg + ' ' + (_("You may add another %s below.") % force_text(verbose_name)))
return HttpResponseRedirect(reverse('admin:%s_%s_add' %
(opts.app_label, module_name),
current_app=self.admin_site.name))
@ -995,7 +995,7 @@ class ModelAdmin(BaseModelAdmin):
media = media + inline_admin_formset.media
context = {
'title': _('Add %s') % force_unicode(opts.verbose_name),
'title': _('Add %s') % force_text(opts.verbose_name),
'adminform': adminForm,
'is_popup': "_popup" in request.REQUEST,
'media': media,
@ -1019,7 +1019,7 @@ class ModelAdmin(BaseModelAdmin):
raise PermissionDenied
if obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_unicode(opts.verbose_name), 'key': escape(object_id)})
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_text(opts.verbose_name), 'key': escape(object_id)})
if request.method == 'POST' and "_saveasnew" in request.POST:
return self.add_view(request, form_url=reverse('admin:%s_%s_add' %
@ -1085,7 +1085,7 @@ class ModelAdmin(BaseModelAdmin):
media = media + inline_admin_formset.media
context = {
'title': _('Change %s') % force_unicode(opts.verbose_name),
'title': _('Change %s') % force_text(opts.verbose_name),
'adminform': adminForm,
'object_id': object_id,
'original': obj,
@ -1194,14 +1194,14 @@ class ModelAdmin(BaseModelAdmin):
if changecount:
if changecount == 1:
name = force_unicode(opts.verbose_name)
name = force_text(opts.verbose_name)
else:
name = force_unicode(opts.verbose_name_plural)
name = force_text(opts.verbose_name_plural)
msg = ungettext("%(count)s %(name)s was changed successfully.",
"%(count)s %(name)s were changed successfully.",
changecount) % {'count': changecount,
'name': name,
'obj': force_unicode(obj)}
'obj': force_text(obj)}
self.message_user(request, msg)
return HttpResponseRedirect(request.get_full_path())
@ -1228,7 +1228,7 @@ class ModelAdmin(BaseModelAdmin):
'All %(total_count)s selected', cl.result_count)
context = {
'module_name': force_unicode(opts.verbose_name_plural),
'module_name': force_text(opts.verbose_name_plural),
'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
'selection_note_all': selection_note_all % {'total_count': cl.result_count},
'title': cl.title,
@ -1263,7 +1263,7 @@ class ModelAdmin(BaseModelAdmin):
raise PermissionDenied
if obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_unicode(opts.verbose_name), 'key': escape(object_id)})
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_text(opts.verbose_name), 'key': escape(object_id)})
using = router.db_for_write(self.model)
@ -1275,11 +1275,11 @@ class ModelAdmin(BaseModelAdmin):
if request.POST: # The user has already confirmed the deletion.
if perms_needed:
raise PermissionDenied
obj_display = force_unicode(obj)
obj_display = force_text(obj)
self.log_deletion(request, obj, obj_display)
self.delete_model(request, obj)
self.message_user(request, _('The %(name)s "%(obj)s" was deleted successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj_display)})
self.message_user(request, _('The %(name)s "%(obj)s" was deleted successfully.') % {'name': force_text(opts.verbose_name), 'obj': force_text(obj_display)})
if not self.has_change_permission(request, None):
return HttpResponseRedirect(reverse('admin:index',
@ -1288,7 +1288,7 @@ class ModelAdmin(BaseModelAdmin):
(opts.app_label, opts.module_name),
current_app=self.admin_site.name))
object_name = force_unicode(opts.verbose_name)
object_name = force_text(opts.verbose_name)
if perms_needed or protected:
title = _("Cannot delete %(name)s") % {"name": object_name}
@ -1326,9 +1326,9 @@ class ModelAdmin(BaseModelAdmin):
# If no history was found, see whether this object even exists.
obj = get_object_or_404(model, pk=unquote(object_id))
context = {
'title': _('Change history: %s') % force_unicode(obj),
'title': _('Change history: %s') % force_text(obj),
'action_list': action_list,
'module_name': capfirst(force_unicode(opts.verbose_name_plural)),
'module_name': capfirst(force_text(opts.verbose_name_plural)),
'object': obj,
'app_label': app_label,
'opts': opts,
@ -1415,7 +1415,7 @@ class InlineModelAdmin(BaseModelAdmin):
if self.declared_fieldsets:
return self.declared_fieldsets
form = self.get_formset(request, obj).form
fields = form.base_fields.keys() + list(self.get_readonly_fields(request, obj))
fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
return [(None, {'fields': fields})]
def queryset(self, request):

View File

@ -10,6 +10,7 @@ from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse, NoReverseMatch
from django.template.response import TemplateResponse
from django.utils.safestring import mark_safe
from django.utils import six
from django.utils.text import capfirst
from django.utils.translation import ugettext as _
from django.views.decorators.cache import never_cache
@ -133,7 +134,7 @@ class AdminSite(object):
"""
Get all the enabled actions as an iterable of (name, func).
"""
return self._actions.iteritems()
return six.iteritems(self._actions)
def has_permission(self, request):
"""
@ -239,7 +240,7 @@ class AdminSite(object):
)
# Add in each model's views.
for model, model_admin in self._registry.iteritems():
for model, model_admin in six.iteritems(self._registry):
urlpatterns += patterns('',
url(r'^%s/%s/' % (model._meta.app_label, model._meta.module_name),
include(model_admin.urls))
@ -370,7 +371,7 @@ class AdminSite(object):
}
# Sort the apps alphabetically.
app_list = app_dict.values()
app_list = list(six.itervalues(app_dict))
app_list.sort(key=lambda x: x['name'])
# Sort the models alphabetically within each app.

View File

@ -12,9 +12,10 @@ from django.db import models
from django.utils import formats
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils import six
from django.utils.text import capfirst
from django.utils.translation import ugettext as _
from django.utils.encoding import smart_unicode, force_unicode
from django.utils.encoding import smart_text, force_text
from django.template import Library
from django.template.loader import get_template
from django.template.context import Context
@ -125,7 +126,7 @@ def result_headers(cl):
if i in ordering_field_columns:
sorted = True
order_type = ordering_field_columns.get(i).lower()
sort_priority = ordering_field_columns.keys().index(i) + 1
sort_priority = list(ordering_field_columns).index(i) + 1
th_classes.append('sorted %sending' % order_type)
new_order_type = {'asc': 'desc', 'desc': 'asc'}[order_type]
@ -209,7 +210,7 @@ def items_for_result(cl, result, form):
result_repr = display_for_field(value, f)
if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
row_class = mark_safe(' class="nowrap"')
if force_unicode(result_repr) == '':
if force_text(result_repr) == '':
result_repr = mark_safe('&nbsp;')
# If list_display_links not defined, add the link tag to the first field
if (first and not cl.list_display_links) or field_name in cl.list_display_links:
@ -223,7 +224,7 @@ def items_for_result(cl, result, form):
else:
attr = pk
value = result.serializable_value(attr)
result_id = repr(force_unicode(value))[1:]
result_id = repr(force_text(value))[1:]
yield format_html('<{0}{1}><a href="{2}"{3}>{4}</a></{5}>',
table_tag,
row_class,
@ -240,10 +241,10 @@ def items_for_result(cl, result, form):
field_name == cl.model._meta.pk.name and
form[cl.model._meta.pk.name].is_hidden)):
bf = form[field_name]
result_repr = mark_safe(force_unicode(bf.errors) + force_unicode(bf))
result_repr = mark_safe(force_text(bf.errors) + force_text(bf))
yield format_html('<td{0}>{1}</td>', row_class, result_repr)
if form and not form[cl.model._meta.pk.name].is_hidden:
yield format_html('<td>{0}</td>', force_unicode(form[cl.model._meta.pk.name]))
yield format_html('<td>{0}</td>', force_text(form[cl.model._meta.pk.name]))
class ResultList(list):
# Wrapper class used to return items in a list_editable
@ -266,7 +267,7 @@ def result_hidden_fields(cl):
if cl.formset:
for res, form in zip(cl.result_list, cl.formset.forms):
if form[cl.model._meta.pk.name].is_hidden:
yield mark_safe(force_unicode(form[cl.model._meta.pk.name]))
yield mark_safe(force_text(form[cl.model._meta.pk.name]))
@register.inclusion_tag("admin/change_list_results.html")
def result_list(cl):

View File

@ -12,7 +12,7 @@ from django.utils import formats
from django.utils.html import format_html
from django.utils.text import capfirst
from django.utils import timezone
from django.utils.encoding import force_unicode, smart_unicode, smart_str
from django.utils.encoding import force_text, smart_text, smart_bytes
from django.utils import six
from django.utils.translation import ungettext
from django.core.urlresolvers import reverse
@ -132,7 +132,7 @@ def get_deleted_objects(objs, opts, user, admin_site, using):
# Don't display link to edit, because it either has no
# admin or is edited inline.
return '%s: %s' % (capfirst(opts.verbose_name),
force_unicode(obj))
force_text(obj))
to_delete = collector.nested(format_callback)
@ -207,8 +207,8 @@ def model_format_dict(obj):
else:
opts = obj
return {
'verbose_name': force_unicode(opts.verbose_name),
'verbose_name_plural': force_unicode(opts.verbose_name_plural)
'verbose_name': force_text(opts.verbose_name),
'verbose_name_plural': force_text(opts.verbose_name_plural)
}
@ -274,10 +274,10 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
label = field.verbose_name
except models.FieldDoesNotExist:
if name == "__unicode__":
label = force_unicode(model._meta.verbose_name)
label = force_text(model._meta.verbose_name)
attr = six.text_type
elif name == "__str__":
label = smart_str(model._meta.verbose_name)
label = smart_bytes(model._meta.verbose_name)
attr = bytes
else:
if callable(name):
@ -311,7 +311,7 @@ def help_text_for_field(name, model):
help_text = model._meta.get_field_by_name(name)[0].help_text
except models.FieldDoesNotExist:
help_text = ""
return smart_unicode(help_text)
return smart_text(help_text)
def display_for_field(value, field):
@ -335,7 +335,7 @@ def display_for_field(value, field):
elif isinstance(field, models.FloatField):
return formats.number_format(value)
else:
return smart_unicode(value)
return smart_text(value)
def display_for_value(value, boolean=False):
@ -353,7 +353,7 @@ def display_for_value(value, boolean=False):
elif isinstance(value, six.integer_types + (decimal.Decimal, float)):
return formats.number_format(value)
else:
return smart_unicode(value)
return smart_text(value)
class NotRelationField(Exception):

View File

@ -6,7 +6,7 @@ from django.core.paginator import InvalidPage
from django.db import models
from django.db.models.fields import FieldDoesNotExist
from django.utils.datastructures import SortedDict
from django.utils.encoding import force_unicode, smart_str
from django.utils.encoding import force_text, smart_bytes
from django.utils.translation import ugettext, ugettext_lazy
from django.utils.http import urlencode
@ -75,7 +75,7 @@ class ChangeList(object):
title = ugettext('Select %s')
else:
title = ugettext('Select %s to change')
self.title = title % force_unicode(self.opts.verbose_name)
self.title = title % force_text(self.opts.verbose_name)
self.pk_attname = self.lookup_opts.pk.attname
def get_filters(self, request):
@ -94,7 +94,7 @@ class ChangeList(object):
# 'key' will be used as a keyword argument later, so Python
# requires it to be a string.
del lookup_params[key]
lookup_params[smart_str(key)] = value
lookup_params[smart_bytes(key)] = value
if not self.model_admin.lookup_allowed(key, value):
raise SuspiciousOperation("Filtering by %s not allowed" % key)

View File

@ -14,7 +14,7 @@ from django.utils.html import escape, format_html, format_html_join
from django.utils.text import Truncator
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils import six
@ -96,7 +96,7 @@ class AdminRadioFieldRenderer(RadioFieldRenderer):
return format_html('<ul{0}>\n{1}\n</ul>',
flatatt(self.attrs),
format_html_join('\n', '<li>{0}</li>',
((force_unicode(w),) for w in self)))
((force_text(w),) for w in self)))
class AdminRadioSelect(forms.RadioSelect):
renderer = AdminRadioFieldRenderer
@ -197,7 +197,7 @@ class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
# The related object is registered with the same AdminSite
attrs['class'] = 'vManyToManyRawIdAdminField'
if value:
value = ','.join([force_unicode(v) for v in value])
value = ','.join([force_text(v) for v in value])
else:
value = ''
return super(ManyToManyRawIdWidget, self).render(name, value, attrs)
@ -221,7 +221,7 @@ class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
if len(initial) != len(data):
return True
for pk1, pk2 in zip(initial, data):
if force_unicode(pk1) != force_unicode(pk2):
if force_text(pk1) != force_text(pk2):
return True
return False

View File

@ -6,7 +6,7 @@ from email.errors import HeaderParseError
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
try:
import docutils.core
import docutils.nodes
@ -66,7 +66,7 @@ def parse_rst(text, default_reference_context, thing_being_parsed=None):
"link_base" : reverse('django-admindocs-docroot').rstrip('/')
}
if thing_being_parsed:
thing_being_parsed = smart_str("<%s>" % thing_being_parsed)
thing_being_parsed = smart_bytes("<%s>" % thing_being_parsed)
parts = docutils.core.publish_parts(text, source_path=thing_being_parsed,
destination_path=None, writer_name='html',
settings_overrides=overrides)

View File

@ -14,6 +14,7 @@ from django.core import urlresolvers
from django.contrib.admindocs import utils
from django.contrib.sites.models import Site
from django.utils.importlib import import_module
from django.utils import six
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
@ -48,7 +49,7 @@ def template_tag_index(request):
load_all_installed_template_libraries()
tags = []
app_libs = template.libraries.items()
app_libs = list(six.iteritems(template.libraries))
builtin_libs = [(None, lib) for lib in template.builtins]
for module_name, library in builtin_libs + app_libs:
for tag_name, tag_func in library.tags.items():
@ -83,7 +84,7 @@ def template_filter_index(request):
load_all_installed_template_libraries()
filters = []
app_libs = template.libraries.items()
app_libs = list(six.iteritems(template.libraries))
builtin_libs = [(None, lib) for lib in template.builtins]
for module_name, library in builtin_libs + app_libs:
for filter_name, filter_func in library.filters.items():

View File

@ -12,6 +12,7 @@ from django.template.response import TemplateResponse
from django.utils.html import escape
from django.utils.decorators import method_decorator
from django.utils.safestring import mark_safe
from django.utils import six
from django.utils.translation import ugettext, ugettext_lazy as _
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
@ -128,7 +129,7 @@ class UserAdmin(admin.ModelAdmin):
else:
form = self.change_password_form(user)
fieldsets = [(None, {'fields': form.base_fields.keys()})]
fieldsets = [(None, {'fields': list(form.base_fields)})]
adminForm = admin.helpers.AdminForm(form, fieldsets, {})
context = {

View File

@ -11,8 +11,9 @@ class PermLookupDict(object):
def __getitem__(self, perm_name):
return self.user.has_perm("%s.%s" % (self.module_name, perm_name))
def __nonzero__(self):
def __bool__(self):
return self.user.has_module_perms(self.module_name)
__nonzero__ = __bool__ # Python 2
class PermWrapper(object):

View File

@ -89,9 +89,9 @@ class UserCreationForm(forms.ModelForm):
raise forms.ValidationError(self.error_messages['duplicate_username'])
def clean_password2(self):
password1 = self.cleaned_data.get("password1", "")
password2 = self.cleaned_data["password2"]
if password1 != password2:
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'])
return password2

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals
import base64
import hashlib
from django.dispatch import receiver
@ -7,7 +8,7 @@ from django.conf import settings
from django.test.signals import setting_changed
from django.utils import importlib
from django.utils.datastructures import SortedDict
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.core.exceptions import ImproperlyConfigured
from django.utils.crypto import (
pbkdf2, constant_time_compare, get_random_string)
@ -218,7 +219,7 @@ class PBKDF2PasswordHasher(BasePasswordHasher):
if not iterations:
iterations = self.iterations
hash = pbkdf2(password, salt, iterations, digest=self.digest)
hash = hash.encode('base64').strip()
hash = base64.b64encode(hash).strip()
return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)
def verify(self, password, encoded):
@ -298,7 +299,7 @@ class SHA1PasswordHasher(BasePasswordHasher):
def encode(self, password, salt):
assert password
assert salt and '$' not in salt
hash = hashlib.sha1(smart_str(salt + password)).hexdigest()
hash = hashlib.sha1(smart_bytes(salt + password)).hexdigest()
return "%s$%s$%s" % (self.algorithm, salt, hash)
def verify(self, password, encoded):
@ -326,7 +327,7 @@ class MD5PasswordHasher(BasePasswordHasher):
def encode(self, password, salt):
assert password
assert salt and '$' not in salt
hash = hashlib.md5(smart_str(salt + password)).hexdigest()
hash = hashlib.md5(smart_bytes(salt + password)).hexdigest()
return "%s$%s$%s" % (self.algorithm, salt, hash)
def verify(self, password, encoded):
@ -360,7 +361,7 @@ class UnsaltedMD5PasswordHasher(BasePasswordHasher):
return ''
def encode(self, password, salt):
return hashlib.md5(smart_str(password)).hexdigest()
return hashlib.md5(smart_bytes(password)).hexdigest()
def verify(self, password, encoded):
encoded_2 = self.encode(password, '')

View File

@ -9,6 +9,7 @@ import unicodedata
from django.contrib.auth import models as auth_app
from django.db.models import get_models, signals
from django.contrib.auth.models import User
from django.utils.six.moves import input
def _get_permission_codename(action, opts):
@ -66,10 +67,10 @@ def create_superuser(app, created_models, verbosity, db, **kwargs):
msg = ("\nYou just installed Django's auth system, which means you "
"don't have any superusers defined.\nWould you like to create one "
"now? (yes/no): ")
confirm = raw_input(msg)
confirm = input(msg)
while 1:
if confirm not in ('yes', 'no'):
confirm = raw_input('Please enter either "yes" or "no": ')
confirm = input('Please enter either "yes" or "no": ')
continue
if confirm == 'yes':
call_command("createsuperuser", interactive=True, database=db)

View File

@ -12,6 +12,7 @@ from django.contrib.auth.management import get_default_username
from django.core import exceptions
from django.core.management.base import BaseCommand, CommandError
from django.db import DEFAULT_DB_ALIAS
from django.utils.six.moves import input
from django.utils.translation import ugettext as _
RE_VALID_USERNAME = re.compile('[\w.@+-]+$')
@ -76,7 +77,7 @@ class Command(BaseCommand):
input_msg = 'Username'
if default_username:
input_msg += ' (leave blank to use %r)' % default_username
username = raw_input(input_msg + ': ')
username = input(input_msg + ': ')
if default_username and username == '':
username = default_username
if not RE_VALID_USERNAME.match(username):
@ -94,7 +95,7 @@ class Command(BaseCommand):
# Get an email
while 1:
if not email:
email = raw_input('E-mail address: ')
email = input('E-mail address: ')
try:
is_valid_email(email)
except exceptions.ValidationError:

View File

@ -8,7 +8,8 @@ from django.core import mail
from django.forms.fields import Field, EmailField
from django.test import TestCase
from django.test.utils import override_settings
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils import six
from django.utils import translation
from django.utils.translation import ugettext as _
@ -27,7 +28,7 @@ class UserCreationFormTest(TestCase):
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form["username"].errors,
[force_unicode(form.error_messages['duplicate_username'])])
[force_text(form.error_messages['duplicate_username'])])
def test_invalid_data(self):
data = {
@ -38,7 +39,7 @@ class UserCreationFormTest(TestCase):
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form["username"].errors,
[force_unicode(form.fields['username'].error_messages['invalid'])])
[force_text(form.fields['username'].error_messages['invalid'])])
def test_password_verification(self):
# The verification password is incorrect.
@ -50,13 +51,13 @@ class UserCreationFormTest(TestCase):
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form["password2"].errors,
[force_unicode(form.error_messages['password_mismatch'])])
[force_text(form.error_messages['password_mismatch'])])
def test_both_passwords(self):
# One (or both) passwords weren't given
data = {'username': 'jsmith'}
form = UserCreationForm(data)
required_error = [force_unicode(Field.default_error_messages['required'])]
required_error = [force_text(Field.default_error_messages['required'])]
self.assertFalse(form.is_valid())
self.assertEqual(form['password1'].errors, required_error)
self.assertEqual(form['password2'].errors, required_error)
@ -65,6 +66,7 @@ class UserCreationFormTest(TestCase):
form = UserCreationForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form['password1'].errors, required_error)
self.assertEqual(form['password2'].errors, [])
def test_success(self):
# The success case.
@ -94,7 +96,7 @@ class AuthenticationFormTest(TestCase):
form = AuthenticationForm(None, data)
self.assertFalse(form.is_valid())
self.assertEqual(form.non_field_errors(),
[force_unicode(form.error_messages['invalid_login'])])
[force_text(form.error_messages['invalid_login'])])
def test_inactive_user(self):
# The user is inactive.
@ -105,7 +107,7 @@ class AuthenticationFormTest(TestCase):
form = AuthenticationForm(None, data)
self.assertFalse(form.is_valid())
self.assertEqual(form.non_field_errors(),
[force_unicode(form.error_messages['inactive'])])
[force_text(form.error_messages['inactive'])])
def test_inactive_user_i18n(self):
with self.settings(USE_I18N=True):
@ -118,7 +120,7 @@ class AuthenticationFormTest(TestCase):
form = AuthenticationForm(None, data)
self.assertFalse(form.is_valid())
self.assertEqual(form.non_field_errors(),
[force_unicode(form.error_messages['inactive'])])
[force_text(form.error_messages['inactive'])])
def test_success(self):
# The success case
@ -146,7 +148,7 @@ class SetPasswordFormTest(TestCase):
form = SetPasswordForm(user, data)
self.assertFalse(form.is_valid())
self.assertEqual(form["new_password2"].errors,
[force_unicode(form.error_messages['password_mismatch'])])
[force_text(form.error_messages['password_mismatch'])])
def test_success(self):
user = User.objects.get(username='testclient')
@ -173,7 +175,7 @@ class PasswordChangeFormTest(TestCase):
form = PasswordChangeForm(user, data)
self.assertFalse(form.is_valid())
self.assertEqual(form["old_password"].errors,
[force_unicode(form.error_messages['password_incorrect'])])
[force_text(form.error_messages['password_incorrect'])])
def test_password_verification(self):
# The two new passwords do not match.
@ -186,7 +188,7 @@ class PasswordChangeFormTest(TestCase):
form = PasswordChangeForm(user, data)
self.assertFalse(form.is_valid())
self.assertEqual(form["new_password2"].errors,
[force_unicode(form.error_messages['password_mismatch'])])
[force_text(form.error_messages['password_mismatch'])])
def test_success(self):
# The success case.
@ -202,7 +204,7 @@ class PasswordChangeFormTest(TestCase):
def test_field_order(self):
# Regression test - check the order of fields:
user = User.objects.get(username='testclient')
self.assertEqual(PasswordChangeForm(user, {}).fields.keys(),
self.assertEqual(list(PasswordChangeForm(user, {}).fields),
['old_password', 'new_password1', 'new_password2'])
@ -217,7 +219,7 @@ class UserChangeFormTest(TestCase):
form = UserChangeForm(data, instance=user)
self.assertFalse(form.is_valid())
self.assertEqual(form['username'].errors,
[force_unicode(form.fields['username'].error_messages['invalid'])])
[force_text(form.fields['username'].error_messages['invalid'])])
def test_bug_14242(self):
# A regression test, introduce by adding an optimization for the
@ -272,7 +274,7 @@ class PasswordResetFormTest(TestCase):
form = PasswordResetForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form['email'].errors,
[force_unicode(EmailField.default_error_messages['invalid'])])
[force_text(EmailField.default_error_messages['invalid'])])
def test_nonexistant_email(self):
# Test nonexistant email address
@ -280,7 +282,7 @@ class PasswordResetFormTest(TestCase):
form = PasswordResetForm(data)
self.assertFalse(form.is_valid())
self.assertEqual(form.errors,
{'email': [force_unicode(form.error_messages['unknown'])]})
{'email': [force_text(form.error_messages['unknown'])]})
def test_cleaned_data(self):
# Regression test

View File

@ -7,7 +7,7 @@ from django.contrib.auth.models import User
from django.core import mail
from django.core.urlresolvers import reverse, NoReverseMatch
from django.http import QueryDict
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils.html import escape
from django.utils.http import urlquote
from django.test import TestCase
@ -46,7 +46,7 @@ class AuthViewsTestCase(TestCase):
self.assertTrue(SESSION_KEY in self.client.session)
def assertContainsEscaped(self, response, text, **kwargs):
return self.assertContains(response, escape(force_unicode(text)), **kwargs)
return self.assertContains(response, escape(force_text(text)), **kwargs)
class AuthViewNamedURLTests(AuthViewsTestCase):

View File

@ -5,7 +5,7 @@ from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.contrib.comments.models import Comment
from django.utils.crypto import salted_hmac, constant_time_compare
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils.text import get_text_list
from django.utils import timezone
from django.utils.translation import ungettext, ugettext, ugettext_lazy as _
@ -133,7 +133,7 @@ class CommentDetailsForm(CommentSecurityForm):
"""
return dict(
content_type = ContentType.objects.get_for_model(self.target_object),
object_pk = force_unicode(self.target_object._get_pk_val()),
object_pk = force_text(self.target_object._get_pk_val()),
user_name = self.cleaned_data["name"],
user_email = self.cleaned_data["email"],
user_url = self.cleaned_data["url"],

View File

@ -1,6 +1,6 @@
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
class CommentManager(models.Manager):
@ -18,5 +18,5 @@ class CommentManager(models.Manager):
ct = ContentType.objects.get_for_model(model)
qs = self.get_query_set().filter(content_type=ct)
if isinstance(model, models.Model):
qs = qs.filter(object_pk=force_unicode(model._get_pk_val()))
qs = qs.filter(object_pk=force_text(model._get_pk_val()))
return qs

View File

@ -3,7 +3,7 @@ from django.template.loader import render_to_string
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.contrib import comments
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
register = template.Library()
@ -75,7 +75,7 @@ class BaseCommentNode(template.Node):
qs = self.comment_model.objects.filter(
content_type = ctype,
object_pk = smart_unicode(object_pk),
object_pk = smart_text(object_pk),
site__pk = settings.SITE_ID,
)

View File

@ -17,7 +17,7 @@ from django.forms import ModelForm
from django.forms.models import BaseModelFormSet, modelformset_factory, save_instance
from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
class GenericForeignKey(object):
"""
@ -169,7 +169,7 @@ class GenericRelation(RelatedField, Field):
def value_to_string(self, obj):
qs = getattr(obj, self.name).all()
return smart_unicode([instance._get_pk_val() for instance in qs])
return smart_text([instance._get_pk_val() for instance in qs])
def m2m_db_table(self):
return self.rel.to._meta.db_table

View File

@ -1,6 +1,8 @@
from django.contrib.contenttypes.models import ContentType
from django.db.models import get_apps, get_models, signals
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils import six
from django.utils.six.moves import input
def update_contenttypes(app, created_models, verbosity=2, **kwargs):
"""
@ -24,17 +26,17 @@ def update_contenttypes(app, created_models, verbosity=2, **kwargs):
)
to_remove = [
ct
for (model_name, ct) in content_types.iteritems()
for (model_name, ct) in six.iteritems(content_types)
if model_name not in app_models
]
cts = ContentType.objects.bulk_create([
ContentType(
name=smart_unicode(model._meta.verbose_name_raw),
name=smart_text(model._meta.verbose_name_raw),
app_label=app_label,
model=model_name,
)
for (model_name, model) in app_models.iteritems()
for (model_name, model) in six.iteritems(app_models)
if model_name not in content_types
])
if verbosity >= 2:
@ -48,7 +50,7 @@ def update_contenttypes(app, created_models, verbosity=2, **kwargs):
' %s | %s' % (ct.app_label, ct.model)
for ct in to_remove
])
ok_to_delete = raw_input("""The following content types are stale and need to be deleted:
ok_to_delete = input("""The following content types are stale and need to be deleted:
%s

View File

@ -1,6 +1,6 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode, force_unicode
from django.utils.encoding import smart_text, force_text
class ContentTypeManager(models.Manager):
@ -37,13 +37,13 @@ class ContentTypeManager(models.Manager):
try:
ct = self._get_from_cache(opts)
except KeyError:
# Load or create the ContentType entry. The smart_unicode() is
# Load or create the ContentType entry. The smart_text() is
# needed around opts.verbose_name_raw because name_raw might be a
# django.utils.functional.__proxy__ object.
ct, created = self.get_or_create(
app_label = opts.app_label,
model = opts.object_name.lower(),
defaults = {'name': smart_unicode(opts.verbose_name_raw)},
defaults = {'name': smart_text(opts.verbose_name_raw)},
)
self._add_to_cache(self.db, ct)
@ -86,7 +86,7 @@ class ContentTypeManager(models.Manager):
ct = self.create(
app_label=opts.app_label,
model=opts.object_name.lower(),
name=smart_unicode(opts.verbose_name_raw),
name=smart_text(opts.verbose_name_raw),
)
self._add_to_cache(self.db, ct)
results[ct.model_class()] = ct
@ -147,7 +147,7 @@ class ContentType(models.Model):
if not model or self.name != model._meta.verbose_name_raw:
return self.name
else:
return force_unicode(model._meta.verbose_name)
return force_text(model._meta.verbose_name)
def model_class(self):
"Returns the Python model class for this type of content."

View File

@ -7,7 +7,7 @@ from __future__ import unicode_literals
from django.db import models
from django.utils import formats
from django.utils.text import capfirst
from django.utils.encoding import smart_unicode, smart_str, iri_to_uri
from django.utils.encoding import smart_text, smart_bytes, iri_to_uri
from django.db.models.query import QuerySet
EMPTY_VALUE = '(None)'
@ -17,12 +17,12 @@ class EasyModel(object):
def __init__(self, site, model):
self.site = site
self.model = model
self.model_list = site.registry.keys()
self.model_list = list(site.registry.keys())
self.verbose_name = model._meta.verbose_name
self.verbose_name_plural = model._meta.verbose_name_plural
def __repr__(self):
return '<EasyModel for %s>' % smart_str(self.model._meta.object_name)
return '<EasyModel for %s>' % smart_bytes(self.model._meta.object_name)
def model_databrowse(self):
"Returns the ModelDatabrowse class for this model."
@ -61,7 +61,7 @@ class EasyField(object):
self.model, self.field = easy_model, field
def __repr__(self):
return smart_str('<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
return smart_bytes('<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def choices(self):
for value, label in self.field.choices:
@ -79,7 +79,7 @@ class EasyChoice(object):
self.value, self.label = value, label
def __repr__(self):
return smart_str('<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
return smart_bytes('<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def url(self):
return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, iri_to_uri(self.value))
@ -89,10 +89,10 @@ class EasyInstance(object):
self.model, self.instance = easy_model, instance
def __repr__(self):
return smart_str('<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()))
return smart_bytes('<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()))
def __unicode__(self):
val = smart_unicode(self.instance)
val = smart_text(self.instance)
if len(val) > DISPLAY_SIZE:
return val[:DISPLAY_SIZE] + '...'
return val
@ -136,7 +136,7 @@ class EasyInstanceField(object):
self.raw_value = getattr(instance.instance, field.name)
def __repr__(self):
return smart_str('<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
return smart_bytes('<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def values(self):
"""
@ -176,8 +176,6 @@ class EasyInstanceField(object):
for plugin_name, plugin in self.model.model_databrowse().plugins.items():
urls = plugin.urls(plugin_name, self)
if urls is not None:
#plugin_urls.append(urls)
values = self.values()
return zip(self.values(), urls)
if self.field.rel:
m = EasyModel(self.model.site, self.field.rel.to)
@ -187,7 +185,7 @@ class EasyInstanceField(object):
if value is None:
continue
url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, iri_to_uri(value._get_pk_val()))
lst.append((smart_unicode(value), url))
lst.append((smart_text(value), url))
else:
lst = [(value, None) for value in self.values()]
elif self.field.choices:
@ -196,10 +194,10 @@ class EasyInstanceField(object):
url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, iri_to_uri(self.raw_value))
lst.append((value, url))
elif isinstance(self.field, models.URLField):
val = self.values()[0]
val = list(self.values())[0]
lst = [(val, iri_to_uri(val))]
else:
lst = [(self.values()[0], None)]
lst = [(list(self.values())[0], None)]
return lst
class EasyQuerySet(QuerySet):

View File

@ -7,7 +7,7 @@ from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
from django.utils.html import format_html, format_html_join
from django.utils.text import capfirst
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.views.generic import dates
from django.utils import datetime_safe
@ -66,7 +66,7 @@ class CalendarPlugin(DatabrowsePlugin):
return ''
return format_html('<p class="filter"><strong>View calendar by:</strong> {0}</p>',
format_html_join(', ', '<a href="calendars/{0}/">{1}</a>',
((f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values())))
((f.name, force_text(capfirst(f.verbose_name))) for f in fields.values())))
def urls(self, plugin_name, easy_instance_field):
if isinstance(easy_instance_field.field, models.DateField):
@ -96,7 +96,7 @@ class CalendarPlugin(DatabrowsePlugin):
def homepage_view(self, request):
easy_model = EasyModel(self.site, self.model)
field_list = self.fields.values()
field_list = list(self.fields.values())
field_list.sort(key=lambda k:k.verbose_name)
return render_to_response('databrowse/calendar_homepage.html', {
'root_url': self.site.root_url,

View File

@ -8,7 +8,7 @@ from django.shortcuts import render_to_response
from django.utils.html import format_html, format_html_join
from django.utils.http import urlquote
from django.utils.text import capfirst
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
class FieldChoicePlugin(DatabrowsePlugin):
@ -35,7 +35,7 @@ class FieldChoicePlugin(DatabrowsePlugin):
return ''
return format_html('<p class="filter"><strong>View by:</strong> {0}</p>',
format_html_join(', ', '<a href="fields/{0}/">{1}</a>',
((f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values())))
((f.name, force_text(capfirst(f.verbose_name))) for f in fields.values())))
def urls(self, plugin_name, easy_instance_field):
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
@ -63,7 +63,7 @@ class FieldChoicePlugin(DatabrowsePlugin):
def homepage_view(self, request):
easy_model = EasyModel(self.site, self.model)
field_list = self.fields.values()
field_list = list(self.fields.values())
field_list.sort(key=lambda k: k.verbose_name)
return render_to_response('databrowse/fieldchoice_homepage.html', {'root_url': self.site.root_url, 'model': easy_model, 'field_list': field_list})

View File

@ -317,7 +317,7 @@ class WizardTests(TestCase):
class WizardWithProcessStep(TestWizardClass):
def process_step(self, request, form, step):
that.assertTrue(hasattr(form, 'cleaned_data'))
that.assertTrue(form.is_valid())
reached[0] = True
wizard = WizardWithProcessStep([WizardPageOneForm,

View File

@ -1,7 +1,8 @@
from django.core.files.uploadedfile import UploadedFile
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils.functional import lazy_property
from django.utils import six
from django.contrib.formtools.wizard.storage.exceptions import NoFileStorageConfigured
@ -72,9 +73,9 @@ class BaseStorage(object):
raise NoFileStorageConfigured
files = {}
for field, field_dict in wizard_files.iteritems():
field_dict = dict((smart_str(k), v)
for k, v in field_dict.iteritems())
for field, field_dict in six.iteritems(wizard_files):
field_dict = dict((smart_bytes(k), v)
for k, v in six.iteritems(field_dict))
tmp_name = field_dict.pop('tmp_name')
files[field] = UploadedFile(
file=self.file_storage.open(tmp_name), **field_dict)
@ -87,7 +88,7 @@ class BaseStorage(object):
if step not in self.data[self.step_files_key]:
self.data[self.step_files_key][step] = {}
for field, field_file in (files or {}).iteritems():
for field, field_file in six.iteritems(files or {}):
tmp_filename = self.file_storage.save(field_file.name, field_file)
file_dict = {
'tmp_name': tmp_filename,

View File

@ -44,7 +44,7 @@ class StepsHelper(object):
@property
def all(self):
"Returns the names of all steps/forms."
return self._wizard.get_form_list().keys()
return list(self._wizard.get_form_list())
@property
def count(self):
@ -164,14 +164,14 @@ class WizardView(TemplateView):
init_form_list[six.text_type(i)] = form
# walk through the new created list of forms
for form in init_form_list.itervalues():
for form in six.itervalues(init_form_list):
if issubclass(form, formsets.BaseFormSet):
# if the element is based on BaseFormSet (FormSet/ModelFormSet)
# we need to override the form variable.
form = form.form
# check if any form contains a FileField, if yes, we need a
# file_storage added to the wizardview (by subclassing).
for field in form.base_fields.itervalues():
for field in six.itervalues(form.base_fields):
if (isinstance(field, forms.FileField) and
not hasattr(cls, 'file_storage')):
raise NoFileStorageConfigured
@ -196,7 +196,7 @@ class WizardView(TemplateView):
could use data from other (maybe previous forms).
"""
form_list = SortedDict()
for form_key, form_class in self.form_list.iteritems():
for form_key, form_class in six.iteritems(self.form_list):
# try to fetch the value from condition list, by default, the form
# gets passed to the new list.
condition = self.condition_dict.get(form_key, True)

View File

@ -3,6 +3,8 @@ from django.db.backends.mysql.base import DatabaseOperations
from django.contrib.gis.db.backends.adapter import WKTAdapter
from django.contrib.gis.db.backends.base import BaseSpatialOperations
from django.utils import six
class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
compiler_module = 'django.contrib.gis.db.backends.mysql.compiler'
@ -30,7 +32,7 @@ class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
'within' : 'MBRWithin',
}
gis_terms = dict([(term, None) for term in geometry_functions.keys() + ['isnull']])
gis_terms = dict([(term, None) for term in list(geometry_functions) + ['isnull']])
def geo_db_type(self, f):
return f.geom_type

View File

@ -128,7 +128,7 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
geometry_functions.update(distance_functions)
gis_terms = ['isnull']
gis_terms += geometry_functions.keys()
gis_terms += list(geometry_functions)
gis_terms = dict([(term, None) for term in gis_terms])
truncate_params = {'relate' : None}

View File

@ -163,7 +163,9 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
'contains' : PostGISFunction(prefix, 'Contains'),
'intersects' : PostGISFunction(prefix, 'Intersects'),
'relate' : (PostGISRelate, six.string_types),
}
'coveredby' : PostGISFunction(prefix, 'CoveredBy'),
'covers' : PostGISFunction(prefix, 'Covers'),
}
# Valid distance types and substitutions
dtypes = (Decimal, Distance, float) + six.integer_types
@ -178,33 +180,12 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
'distance_gte' : (get_dist_ops('>='), dtypes),
'distance_lt' : (get_dist_ops('<'), dtypes),
'distance_lte' : (get_dist_ops('<='), dtypes),
}
# Versions 1.2.2+ have KML serialization support.
if version < (1, 2, 2):
ASKML = False
else:
ASKML = 'ST_AsKML'
self.geometry_functions.update(
{'coveredby' : PostGISFunction(prefix, 'CoveredBy'),
'covers' : PostGISFunction(prefix, 'Covers'),
})
self.distance_functions['dwithin'] = (PostGISFunctionParam(prefix, 'DWithin'), dtypes)
'dwithin' : (PostGISFunctionParam(prefix, 'DWithin'), dtypes)
}
# Adding the distance functions to the geometries lookup.
self.geometry_functions.update(self.distance_functions)
# The union aggregate and topology operation use the same signature
# in versions 1.3+.
if version < (1, 3, 0):
UNIONAGG = 'GeomUnion'
UNION = 'Union'
MAKELINE = False
else:
UNIONAGG = 'ST_Union'
UNION = 'ST_Union'
MAKELINE = 'ST_MakeLine'
# Only PostGIS versions 1.3.4+ have GeoJSON serialization support.
if version < (1, 3, 4):
GEOJSON = False
@ -236,8 +217,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
# Creating a dictionary lookup of all GIS terms for PostGIS.
gis_terms = ['isnull']
gis_terms += self.geometry_operators.keys()
gis_terms += self.geometry_functions.keys()
gis_terms += list(self.geometry_operators)
gis_terms += list(self.geometry_functions)
self.gis_terms = dict([(term, None) for term in gis_terms])
self.area = prefix + 'Area'
@ -256,11 +237,11 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
self.geojson = GEOJSON
self.gml = prefix + 'AsGML'
self.intersection = prefix + 'Intersection'
self.kml = ASKML
self.kml = prefix + 'AsKML'
self.length = prefix + 'Length'
self.length3d = prefix + 'Length3D'
self.length_spheroid = prefix + 'length_spheroid'
self.makeline = MAKELINE
self.makeline = prefix + 'MakeLine'
self.mem_size = prefix + 'mem_size'
self.num_geom = prefix + 'NumGeometries'
self.num_points =prefix + 'npoints'
@ -275,8 +256,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
self.sym_difference = prefix + 'SymDifference'
self.transform = prefix + 'Transform'
self.translate = prefix + 'Translate'
self.union = UNION
self.unionagg = UNIONAGG
self.union = prefix + 'Union'
self.unionagg = prefix + 'Union'
def check_aggregate_support(self, aggregate):
"""

View File

@ -99,14 +99,14 @@ class SpatiaLiteCreation(DatabaseCreation):
"""
This routine loads up the SpatiaLite SQL file.
"""
if self.connection.ops.spatial_version[:2] >= (3, 0):
# Spatialite >= 3.0.x -- No need to load any SQL file, calling
if self.connection.ops.spatial_version[:2] >= (2, 4):
# Spatialite >= 2.4 -- No need to load any SQL file, calling
# InitSpatialMetaData() transparently creates the spatial metadata
# tables
cur = self.connection._cursor()
cur.execute("SELECT InitSpatialMetaData()")
else:
# Spatialite < 3.0.x -- Load the initial SQL
# Spatialite < 2.4 -- Load the initial SQL
# Getting the location of the SpatiaLite SQL file, and confirming
# it exists.

View File

@ -131,7 +131,7 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
# Creating the GIS terms dictionary.
gis_terms = ['isnull']
gis_terms += self.geometry_functions.keys()
gis_terms += list(self.geometry_functions)
self.gis_terms = dict([(term, None) for term in gis_terms])
if version >= (2, 4, 0):

View File

@ -1,5 +1,6 @@
from django.db import connections
from django.db.models.query import QuerySet, ValuesQuerySet, ValuesListQuerySet
from django.utils import six
from django.contrib.gis.db.models import aggregates
from django.contrib.gis.db.models.fields import get_srid_info, PointField, LineStringField
@ -25,7 +26,7 @@ class GeoQuerySet(QuerySet):
flat = kwargs.pop('flat', False)
if kwargs:
raise TypeError('Unexpected keyword arguments to values_list: %s'
% (kwargs.keys(),))
% (list(kwargs),))
if flat and len(fields) > 1:
raise TypeError("'flat' is not valid when values_list is called with more than one field.")
return self._clone(klass=GeoValuesListQuerySet, setup=True, flat=flat,
@ -531,7 +532,7 @@ class GeoQuerySet(QuerySet):
if settings.get('setup', True):
default_args, geo_field = self._spatial_setup(att, desc=settings['desc'], field_name=field_name,
geo_field_type=settings.get('geo_field_type', None))
for k, v in default_args.iteritems(): settings['procedure_args'].setdefault(k, v)
for k, v in six.iteritems(default_args): settings['procedure_args'].setdefault(k, v)
else:
geo_field = settings['geo_field']

View File

@ -3,6 +3,7 @@ from django.utils.six.moves import zip
from django.db.backends.util import truncate_name, typecast_timestamp
from django.db.models.sql import compiler
from django.db.models.sql.constants import MULTI
from django.utils import six
SQLCompiler = compiler.SQLCompiler
@ -24,7 +25,7 @@ class GeoSQLCompiler(compiler.SQLCompiler):
qn = self.quote_name_unless_alias
qn2 = self.connection.ops.quote_name
result = ['(%s) AS %s' % (self.get_extra_select_format(alias) % col[0], qn2(alias))
for alias, col in self.query.extra_select.iteritems()]
for alias, col in six.iteritems(self.query.extra_select)]
aliases = set(self.query.extra_select.keys())
if with_aliases:
col_aliases = aliases.copy()
@ -170,7 +171,7 @@ class GeoSQLCompiler(compiler.SQLCompiler):
objects.
"""
values = []
aliases = self.query.extra_select.keys()
aliases = list(self.query.extra_select)
# Have to set a starting row number offset that is used for
# determining the correct starting row index -- needed for

View File

@ -40,7 +40,7 @@
"""
# Python library requisites.
import sys
from binascii import a2b_hex
from binascii import a2b_hex, b2a_hex
from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p
# Getting GDAL prerequisites
@ -322,8 +322,7 @@ class OGRGeometry(GDALBase):
@property
def hex(self):
"Returns the hexadecimal representation of the WKB (a string)."
return str(self.wkb).encode('hex').upper()
#return b2a_hex(self.wkb).upper()
return b2a_hex(self.wkb).upper()
@property
def json(self):

View File

@ -7,6 +7,7 @@ import json
import os
from django.contrib import gis
from django.utils import six
# This global used to store reference geometry data.
@ -25,7 +26,7 @@ def tuplize(seq):
def strconvert(d):
"Converts all keys in dictionary to str type."
return dict([(str(k), v) for k, v in d.iteritems()])
return dict([(str(k), v) for k, v in six.iteritems(d)])
def get_ds_file(name, ext):

View File

@ -143,7 +143,7 @@ class MeasureBase(object):
def __rmul__(self, other):
return self * other
def __div__(self, other):
def __truediv__(self, other):
if isinstance(other, self.__class__):
return self.standard / other.standard
if isinstance(other, NUMERIC_TYPES):
@ -151,16 +151,19 @@ class MeasureBase(object):
**{self.STANDARD_UNIT: (self.standard / other)})
else:
raise TypeError('%(class)s must be divided with number or %(class)s' % {"class":pretty_name(self)})
__div__ = __truediv__ # Python 2 compatibility
def __idiv__(self, other):
def __itruediv__(self, other):
if isinstance(other, NUMERIC_TYPES):
self.standard /= float(other)
return self
else:
raise TypeError('%(class)s must be divided with number' % {"class":pretty_name(self)})
__idiv__ = __itruediv__ # Python 2 compatibility
def __nonzero__(self):
def __bool__(self):
return bool(self.standard)
__nonzero__ = __bool__ # Python 2 compatibility
def default_units(self, kwargs):
"""
@ -169,7 +172,7 @@ class MeasureBase(object):
"""
val = 0.0
default_unit = self.STANDARD_UNIT
for unit, value in kwargs.iteritems():
for unit, value in six.iteritems(kwargs):
if not isinstance(value, float): value = float(value)
if unit in self.UNITS:
val += self.UNITS[unit] * value
@ -305,12 +308,13 @@ class Area(MeasureBase):
ALIAS = dict([(k, '%s%s' % (AREA_PREFIX, v)) for k, v in Distance.ALIAS.items()])
LALIAS = dict([(k.lower(), v) for k, v in ALIAS.items()])
def __div__(self, other):
def __truediv__(self, other):
if isinstance(other, NUMERIC_TYPES):
return self.__class__(default_unit=self._default_unit,
**{self.STANDARD_UNIT: (self.standard / other)})
else:
raise TypeError('%(class)s must be divided by a number' % {"class":pretty_name(self)})
__div__ = __truediv__ # Python 2 compatibility
# Shortcuts

View File

@ -8,7 +8,8 @@ from django.core.paginator import EmptyPage, PageNotAnInteger
from django.contrib.gis.db.models.fields import GeometryField
from django.db import connections, DEFAULT_DB_ALIAS
from django.db.models import get_model
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils import six
from django.utils.translation import ugettext as _
from django.contrib.gis.shortcuts import render_to_kml, render_to_kmz
@ -46,7 +47,7 @@ def sitemap(request, sitemaps, section=None):
raise Http404(_("No sitemap available for section: %r") % section)
maps.append(sitemaps[section])
else:
maps = sitemaps.values()
maps = list(six.itervalues(sitemaps))
page = request.GET.get("p", 1)
current_site = get_current_site(request)
@ -60,7 +61,7 @@ def sitemap(request, sitemaps, section=None):
raise Http404(_("Page %s empty") % page)
except PageNotAnInteger:
raise Http404(_("No page '%s'") % page)
xml = smart_str(loader.render_to_string('gis/sitemaps/geo_sitemap.xml', {'urlset': urls}))
xml = smart_bytes(loader.render_to_string('gis/sitemaps/geo_sitemap.xml', {'urlset': urls}))
return HttpResponse(xml, content_type='application/xml')
def kml(request, label, model, field_name=None, compress=False, using=DEFAULT_DB_ALIAS):

View File

@ -12,7 +12,7 @@ from .models import City, PennsylvaniaCity, State, Truth
class GeoRegressionTests(TestCase):
def test01_update(self):
def test_update(self):
"Testing GeoQuerySet.update(). See #10411."
pnt = City.objects.get(name='Pueblo').point
bak = pnt.clone()
@ -24,7 +24,7 @@ class GeoRegressionTests(TestCase):
City.objects.filter(name='Pueblo').update(point=bak)
self.assertEqual(bak, City.objects.get(name='Pueblo').point)
def test02_kmz(self):
def test_kmz(self):
"Testing `render_to_kmz` with non-ASCII data. See #11624."
name = '\xc3\x85land Islands'.decode('iso-8859-1')
places = [{'name' : name,
@ -35,7 +35,7 @@ class GeoRegressionTests(TestCase):
@no_spatialite
@no_mysql
def test03_extent(self):
def test_extent(self):
"Testing `extent` on a table with a single point. See #11827."
pnt = City.objects.get(name='Pueblo').point
ref_ext = (pnt.x, pnt.y, pnt.x, pnt.y)
@ -43,14 +43,14 @@ class GeoRegressionTests(TestCase):
for ref_val, val in zip(ref_ext, extent):
self.assertAlmostEqual(ref_val, val, 4)
def test04_unicode_date(self):
def test_unicode_date(self):
"Testing dates are converted properly, even on SpatiaLite. See #16408."
founded = datetime(1857, 5, 23)
mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)',
founded=founded)
self.assertEqual(founded, PennsylvaniaCity.objects.dates('founded', 'day')[0])
def test05_empty_count(self):
def test_empty_count(self):
"Testing that PostGISAdapter.__eq__ does check empty strings. See #13670."
# contrived example, but need a geo lookup paired with an id__in lookup
pueblo = City.objects.get(name='Pueblo')
@ -60,12 +60,12 @@ class GeoRegressionTests(TestCase):
# .count() should not throw TypeError in __eq__
self.assertEqual(cities_within_state.count(), 1)
def test06_defer_or_only_with_annotate(self):
def test_defer_or_only_with_annotate(self):
"Regression for #16409. Make sure defer() and only() work with annotate()"
self.assertIsInstance(list(City.objects.annotate(Count('point')).defer('name')), list)
self.assertIsInstance(list(City.objects.annotate(Count('point')).only('name')), list)
def test07_boolean_conversion(self):
def test_boolean_conversion(self):
"Testing Boolean value conversion with the spatial backend, see #15169."
t1 = Truth.objects.create(val=True)
t2 = Truth.objects.create(val=False)

View File

@ -15,19 +15,24 @@ from django.utils import six
from .models import Country, City, PennsylvaniaCity, State, Track
from .test_feeds import GeoFeedTest
from .test_regress import GeoRegressionTests
from .test_sitemaps import GeoSitemapTest
if not spatialite:
from .models import Feature, MinusOneSRID
class GeoModelTest(TestCase):
def test01_fixtures(self):
def test_fixtures(self):
"Testing geographic model initialization from fixtures."
# Ensuring that data was loaded from initial data fixtures.
self.assertEqual(2, Country.objects.count())
self.assertEqual(8, City.objects.count())
self.assertEqual(2, State.objects.count())
def test02_proxy(self):
def test_proxy(self):
"Testing Lazy-Geometry support (using the GeometryProxy)."
## Testing on a Point
pnt = Point(0, 0)
@ -95,165 +100,97 @@ class GeoModelTest(TestCase):
self.assertEqual(ply, State.objects.get(name='NullState').poly)
ns.delete()
def test03a_kml(self):
"Testing KML output from the database using GeoQuerySet.kml()."
# Only PostGIS and Spatialite (>=2.4.0-RC4) support KML serialization
if not (postgis or (spatialite and connection.ops.kml)):
self.assertRaises(NotImplementedError, State.objects.all().kml, field_name='poly')
return
# Should throw a TypeError when trying to obtain KML from a
# non-geometry field.
qs = City.objects.all()
self.assertRaises(TypeError, qs.kml, 'name')
# The reference KML depends on the version of PostGIS used
# (the output stopped including altitude in 1.3.3).
if connection.ops.spatial_version >= (1, 3, 3):
ref_kml = '<Point><coordinates>-104.609252,38.255001</coordinates></Point>'
else:
ref_kml = '<Point><coordinates>-104.609252,38.255001,0</coordinates></Point>'
# Ensuring the KML is as expected.
ptown1 = City.objects.kml(field_name='point', precision=9).get(name='Pueblo')
ptown2 = City.objects.kml(precision=9).get(name='Pueblo')
for ptown in [ptown1, ptown2]:
self.assertEqual(ref_kml, ptown.kml)
def test03b_gml(self):
"Testing GML output from the database using GeoQuerySet.gml()."
if mysql or (spatialite and not connection.ops.gml) :
self.assertRaises(NotImplementedError, Country.objects.all().gml, field_name='mpoly')
return
# Should throw a TypeError when tyring to obtain GML from a
# non-geometry field.
qs = City.objects.all()
self.assertRaises(TypeError, qs.gml, field_name='name')
ptown1 = City.objects.gml(field_name='point', precision=9).get(name='Pueblo')
ptown2 = City.objects.gml(precision=9).get(name='Pueblo')
@no_mysql
def test_lookup_insert_transform(self):
"Testing automatic transform for lookups and inserts."
# San Antonio in 'WGS84' (SRID 4326)
sa_4326 = 'POINT (-98.493183 29.424170)'
wgs_pnt = fromstr(sa_4326, srid=4326) # Our reference point in WGS84
# Oracle doesn't have SRID 3084, using 41157.
if oracle:
# No precision parameter for Oracle :-/
gml_regex = re.compile(r'^<gml:Point srsName="SDO:4326" xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="\." cs="," ts=" ">-104.60925\d+,38.25500\d+ </gml:coordinates></gml:Point>')
elif spatialite:
# Spatialite has extra colon in SrsName
gml_regex = re.compile(r'^<gml:Point SrsName="EPSG::4326"><gml:coordinates decimal="\." cs="," ts=" ">-104.609251\d+,38.255001</gml:coordinates></gml:Point>')
# San Antonio in 'Texas 4205, Southern Zone (1983, meters)' (SRID 41157)
# Used the following Oracle SQL to get this value:
# SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_CS.TRANSFORM(SDO_GEOMETRY('POINT (-98.493183 29.424170)', 4326), 41157)) FROM DUAL;
nad_wkt = 'POINT (300662.034646583 5416427.45974934)'
nad_srid = 41157
else:
gml_regex = re.compile(r'^<gml:Point srsName="EPSG:4326"><gml:coordinates>-104\.60925\d+,38\.255001</gml:coordinates></gml:Point>')
# San Antonio in 'NAD83(HARN) / Texas Centric Lambert Conformal' (SRID 3084)
nad_wkt = 'POINT (1645978.362408288754523 6276356.025927528738976)' # Used ogr.py in gdal 1.4.1 for this transform
nad_srid = 3084
for ptown in [ptown1, ptown2]:
self.assertTrue(gml_regex.match(ptown.gml))
def test03c_geojson(self):
"Testing GeoJSON output from the database using GeoQuerySet.geojson()."
# Only PostGIS 1.3.4+ supports GeoJSON.
if not connection.ops.geojson:
self.assertRaises(NotImplementedError, Country.objects.all().geojson, field_name='mpoly')
return
if connection.ops.spatial_version >= (1, 4, 0):
pueblo_json = '{"type":"Point","coordinates":[-104.609252,38.255001]}'
houston_json = '{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"coordinates":[-95.363151,29.763374]}'
victoria_json = '{"type":"Point","bbox":[-123.30519600,48.46261100,-123.30519600,48.46261100],"coordinates":[-123.305196,48.462611]}'
chicago_json = '{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"bbox":[-87.65018,41.85039,-87.65018,41.85039],"coordinates":[-87.65018,41.85039]}'
# Constructing & querying with a point from a different SRID. Oracle
# `SDO_OVERLAPBDYINTERSECT` operates differently from
# `ST_Intersects`, so contains is used instead.
nad_pnt = fromstr(nad_wkt, srid=nad_srid)
if oracle:
tx = Country.objects.get(mpoly__contains=nad_pnt)
else:
pueblo_json = '{"type":"Point","coordinates":[-104.60925200,38.25500100]}'
houston_json = '{"type":"Point","crs":{"type":"EPSG","properties":{"EPSG":4326}},"coordinates":[-95.36315100,29.76337400]}'
victoria_json = '{"type":"Point","bbox":[-123.30519600,48.46261100,-123.30519600,48.46261100],"coordinates":[-123.30519600,48.46261100]}'
chicago_json = '{"type":"Point","crs":{"type":"EPSG","properties":{"EPSG":4326}},"bbox":[-87.65018,41.85039,-87.65018,41.85039],"coordinates":[-87.65018,41.85039]}'
tx = Country.objects.get(mpoly__intersects=nad_pnt)
self.assertEqual('Texas', tx.name)
# Precision argument should only be an integer
self.assertRaises(TypeError, City.objects.geojson, precision='foo')
# Creating San Antonio. Remember the Alamo.
sa = City.objects.create(name='San Antonio', point=nad_pnt)
# Reference queries and values.
# SELECT ST_AsGeoJson("geoapp_city"."point", 8, 0) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Pueblo';
self.assertEqual(pueblo_json, City.objects.geojson().get(name='Pueblo').geojson)
# Now verifying that San Antonio was transformed correctly
sa = City.objects.get(name='San Antonio')
self.assertAlmostEqual(wgs_pnt.x, sa.point.x, 6)
self.assertAlmostEqual(wgs_pnt.y, sa.point.y, 6)
# 1.3.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
# 1.4.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
# This time we want to include the CRS by using the `crs` keyword.
self.assertEqual(houston_json, City.objects.geojson(crs=True, model_att='json').get(name='Houston').json)
# If the GeometryField SRID is -1, then we shouldn't perform any
# transformation if the SRID of the input geometry is different.
# SpatiaLite does not support missing SRID values.
if not spatialite:
m1 = MinusOneSRID(geom=Point(17, 23, srid=4326))
m1.save()
self.assertEqual(-1, m1.geom.srid)
# 1.3.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Victoria';
# 1.4.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
# This time we include the bounding box by using the `bbox` keyword.
self.assertEqual(victoria_json, City.objects.geojson(bbox=True).get(name='Victoria').geojson)
def test_createnull(self):
"Testing creating a model instance and the geometry being None"
c = City()
self.assertEqual(c.point, None)
# 1.(3|4).x: SELECT ST_AsGeoJson("geoapp_city"."point", 5, 3) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Chicago';
# Finally, we set every available keyword.
self.assertEqual(chicago_json, City.objects.geojson(bbox=True, crs=True, precision=5).get(name='Chicago').geojson)
@no_spatialite # SpatiaLite does not support abstract geometry columns
def test_geometryfield(self):
"Testing the general GeometryField."
Feature(name='Point', geom=Point(1, 1)).save()
Feature(name='LineString', geom=LineString((0, 0), (1, 1), (5, 5))).save()
Feature(name='Polygon', geom=Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0)))).save()
Feature(name='GeometryCollection',
geom=GeometryCollection(Point(2, 2), LineString((0, 0), (2, 2)),
Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0))))).save()
def test03d_svg(self):
"Testing SVG output using GeoQuerySet.svg()."
if mysql or oracle:
self.assertRaises(NotImplementedError, City.objects.svg)
return
f_1 = Feature.objects.get(name='Point')
self.assertEqual(True, isinstance(f_1.geom, Point))
self.assertEqual((1.0, 1.0), f_1.geom.tuple)
f_2 = Feature.objects.get(name='LineString')
self.assertEqual(True, isinstance(f_2.geom, LineString))
self.assertEqual(((0.0, 0.0), (1.0, 1.0), (5.0, 5.0)), f_2.geom.tuple)
self.assertRaises(TypeError, City.objects.svg, precision='foo')
# SELECT AsSVG(geoapp_city.point, 0, 8) FROM geoapp_city WHERE name = 'Pueblo';
svg1 = 'cx="-104.609252" cy="-38.255001"'
# Even though relative, only one point so it's practically the same except for
# the 'c' letter prefix on the x,y values.
svg2 = svg1.replace('c', '')
self.assertEqual(svg1, City.objects.svg().get(name='Pueblo').svg)
self.assertEqual(svg2, City.objects.svg(relative=5).get(name='Pueblo').svg)
f_3 = Feature.objects.get(name='Polygon')
self.assertEqual(True, isinstance(f_3.geom, Polygon))
f_4 = Feature.objects.get(name='GeometryCollection')
self.assertEqual(True, isinstance(f_4.geom, GeometryCollection))
self.assertEqual(f_3.geom, f_4.geom[2])
@no_mysql
def test04_transform(self):
"Testing the transform() GeoManager method."
# Pre-transformed points for Houston and Pueblo.
htown = fromstr('POINT(1947516.83115183 6322297.06040572)', srid=3084)
ptown = fromstr('POINT(992363.390841912 481455.395105533)', srid=2774)
prec = 3 # Precision is low due to version variations in PROJ and GDAL.
def test_inherited_geofields(self):
"Test GeoQuerySet methods on inherited Geometry fields."
# Creating a Pennsylvanian city.
mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)')
# Asserting the result of the transform operation with the values in
# the pre-transformed points. Oracle does not have the 3084 SRID.
if not oracle:
h = City.objects.transform(htown.srid).get(name='Houston')
self.assertEqual(3084, h.point.srid)
self.assertAlmostEqual(htown.x, h.point.x, prec)
self.assertAlmostEqual(htown.y, h.point.y, prec)
# All transformation SQL will need to be performed on the
# _parent_ table.
qs = PennsylvaniaCity.objects.transform(32128)
p1 = City.objects.transform(ptown.srid, field_name='point').get(name='Pueblo')
p2 = City.objects.transform(srid=ptown.srid).get(name='Pueblo')
for p in [p1, p2]:
self.assertEqual(2774, p.point.srid)
self.assertAlmostEqual(ptown.x, p.point.x, prec)
self.assertAlmostEqual(ptown.y, p.point.y, prec)
self.assertEqual(1, qs.count())
for pc in qs: self.assertEqual(32128, pc.point.srid)
class GeoLookupTest(TestCase):
@no_mysql
@no_spatialite # SpatiaLite does not have an Extent function
def test05_extent(self):
"Testing the `extent` GeoQuerySet method."
# Reference query:
# `SELECT ST_extent(point) FROM geoapp_city WHERE (name='Houston' or name='Dallas');`
# => BOX(-96.8016128540039 29.7633724212646,-95.3631439208984 32.7820587158203)
expected = (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820)
qs = City.objects.filter(name__in=('Houston', 'Dallas'))
extent = qs.extent()
for val, exp in zip(extent, expected):
self.assertAlmostEqual(exp, val, 4)
# Only PostGIS has support for the MakeLine aggregate.
@no_mysql
@no_oracle
@no_spatialite
def test06_make_line(self):
"Testing the `make_line` GeoQuerySet method."
# Ensuring that a `TypeError` is raised on models without PointFields.
self.assertRaises(TypeError, State.objects.make_line)
self.assertRaises(TypeError, Country.objects.make_line)
# Reference query:
# SELECT AsText(ST_MakeLine(geoapp_city.point)) FROM geoapp_city;
ref_line = GEOSGeometry('LINESTRING(-95.363151 29.763374,-96.801611 32.782057,-97.521157 34.464642,174.783117 -41.315268,-104.609252 38.255001,-95.23506 38.971823,-87.650175 41.850385,-123.305196 48.462611)', srid=4326)
self.assertEqual(ref_line, City.objects.make_line())
@no_mysql
def test09_disjoint(self):
def test_disjoint_lookup(self):
"Testing the `disjoint` lookup type."
ptown = City.objects.get(name='Pueblo')
qs1 = City.objects.filter(point__disjoint=ptown.point)
@ -263,7 +200,7 @@ class GeoModelTest(TestCase):
self.assertEqual(1, qs2.count())
self.assertEqual('Kansas', qs2[0].name)
def test10_contains_contained(self):
def test_contains_contained_lookups(self):
"Testing the 'contained', 'contains', and 'bbcontains' lookup types."
# Getting Texas, yes we were a country -- once ;)
texas = Country.objects.get(name='Texas')
@ -308,86 +245,11 @@ class GeoModelTest(TestCase):
self.assertEqual(1, len(qs))
self.assertEqual('Texas', qs[0].name)
@no_mysql
def test11_lookup_insert_transform(self):
"Testing automatic transform for lookups and inserts."
# San Antonio in 'WGS84' (SRID 4326)
sa_4326 = 'POINT (-98.493183 29.424170)'
wgs_pnt = fromstr(sa_4326, srid=4326) # Our reference point in WGS84
# Oracle doesn't have SRID 3084, using 41157.
if oracle:
# San Antonio in 'Texas 4205, Southern Zone (1983, meters)' (SRID 41157)
# Used the following Oracle SQL to get this value:
# SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_CS.TRANSFORM(SDO_GEOMETRY('POINT (-98.493183 29.424170)', 4326), 41157)) FROM DUAL;
nad_wkt = 'POINT (300662.034646583 5416427.45974934)'
nad_srid = 41157
else:
# San Antonio in 'NAD83(HARN) / Texas Centric Lambert Conformal' (SRID 3084)
nad_wkt = 'POINT (1645978.362408288754523 6276356.025927528738976)' # Used ogr.py in gdal 1.4.1 for this transform
nad_srid = 3084
# Constructing & querying with a point from a different SRID. Oracle
# `SDO_OVERLAPBDYINTERSECT` operates differently from
# `ST_Intersects`, so contains is used instead.
nad_pnt = fromstr(nad_wkt, srid=nad_srid)
if oracle:
tx = Country.objects.get(mpoly__contains=nad_pnt)
else:
tx = Country.objects.get(mpoly__intersects=nad_pnt)
self.assertEqual('Texas', tx.name)
# Creating San Antonio. Remember the Alamo.
sa = City.objects.create(name='San Antonio', point=nad_pnt)
# Now verifying that San Antonio was transformed correctly
sa = City.objects.get(name='San Antonio')
self.assertAlmostEqual(wgs_pnt.x, sa.point.x, 6)
self.assertAlmostEqual(wgs_pnt.y, sa.point.y, 6)
# If the GeometryField SRID is -1, then we shouldn't perform any
# transformation if the SRID of the input geometry is different.
# SpatiaLite does not support missing SRID values.
if not spatialite:
m1 = MinusOneSRID(geom=Point(17, 23, srid=4326))
m1.save()
self.assertEqual(-1, m1.geom.srid)
@no_mysql
def test12_null_geometries(self):
"Testing NULL geometry support, and the `isnull` lookup type."
# Creating a state with a NULL boundary.
State.objects.create(name='Puerto Rico')
# Querying for both NULL and Non-NULL values.
nullqs = State.objects.filter(poly__isnull=True)
validqs = State.objects.filter(poly__isnull=False)
# Puerto Rico should be NULL (it's a commonwealth unincorporated territory)
self.assertEqual(1, len(nullqs))
self.assertEqual('Puerto Rico', nullqs[0].name)
# The valid states should be Colorado & Kansas
self.assertEqual(2, len(validqs))
state_names = [s.name for s in validqs]
self.assertEqual(True, 'Colorado' in state_names)
self.assertEqual(True, 'Kansas' in state_names)
# Saving another commonwealth w/a NULL geometry.
nmi = State.objects.create(name='Northern Mariana Islands', poly=None)
self.assertEqual(nmi.poly, None)
# Assigning a geomery and saving -- then UPDATE back to NULL.
nmi.poly = 'POLYGON((0 0,1 0,1 1,1 0,0 0))'
nmi.save()
State.objects.filter(name='Northern Mariana Islands').update(poly=None)
self.assertEqual(None, State.objects.get(name='Northern Mariana Islands').poly)
# Only PostGIS has `left` and `right` lookup types.
@no_mysql
@no_oracle
@no_spatialite
def test13_left_right(self):
def test_left_right_lookups(self):
"Testing the 'left' and 'right' lookup types."
# Left: A << B => true if xmax(A) < xmin(B)
# Right: A >> B => true if xmin(A) > xmax(B)
@ -423,7 +285,7 @@ class GeoModelTest(TestCase):
self.assertEqual(2, len(qs))
for c in qs: self.assertEqual(True, c.name in cities)
def test14_equals(self):
def test_equals_lookups(self):
"Testing the 'same_as' and 'equals' lookup types."
pnt = fromstr('POINT (-95.363151 29.763374)', srid=4326)
c1 = City.objects.get(point=pnt)
@ -432,7 +294,37 @@ class GeoModelTest(TestCase):
for c in [c1, c2, c3]: self.assertEqual('Houston', c.name)
@no_mysql
def test15_relate(self):
def test_null_geometries(self):
"Testing NULL geometry support, and the `isnull` lookup type."
# Creating a state with a NULL boundary.
State.objects.create(name='Puerto Rico')
# Querying for both NULL and Non-NULL values.
nullqs = State.objects.filter(poly__isnull=True)
validqs = State.objects.filter(poly__isnull=False)
# Puerto Rico should be NULL (it's a commonwealth unincorporated territory)
self.assertEqual(1, len(nullqs))
self.assertEqual('Puerto Rico', nullqs[0].name)
# The valid states should be Colorado & Kansas
self.assertEqual(2, len(validqs))
state_names = [s.name for s in validqs]
self.assertEqual(True, 'Colorado' in state_names)
self.assertEqual(True, 'Kansas' in state_names)
# Saving another commonwealth w/a NULL geometry.
nmi = State.objects.create(name='Northern Mariana Islands', poly=None)
self.assertEqual(nmi.poly, None)
# Assigning a geomery and saving -- then UPDATE back to NULL.
nmi.poly = 'POLYGON((0 0,1 0,1 1,1 0,0 0))'
nmi.save()
State.objects.filter(name='Northern Mariana Islands').update(poly=None)
self.assertEqual(None, State.objects.get(name='Northern Mariana Islands').poly)
@no_mysql
def test_relate_lookup(self):
"Testing the 'relate' lookup type."
# To make things more interesting, we will have our Texas reference point in
# different SRIDs.
@ -474,60 +366,12 @@ class GeoModelTest(TestCase):
self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt2, intersects_mask)).name)
self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, intersects_mask)).name)
def test16_createnull(self):
"Testing creating a model instance and the geometry being None"
c = City()
self.assertEqual(c.point, None)
class GeoQuerySetTest(TestCase):
# Please keep the tests in GeoQuerySet method's alphabetic order
@no_mysql
def test17_unionagg(self):
"Testing the `unionagg` (aggregate union) GeoManager method."
tx = Country.objects.get(name='Texas').mpoly
# Houston, Dallas -- Oracle has different order.
union1 = fromstr('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
union2 = fromstr('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
qs = City.objects.filter(point__within=tx)
self.assertRaises(TypeError, qs.unionagg, 'name')
# Using `field_name` keyword argument in one query and specifying an
# order in the other (which should not be used because this is
# an aggregate method on a spatial column)
u1 = qs.unionagg(field_name='point')
u2 = qs.order_by('name').unionagg()
tol = 0.00001
if oracle:
union = union2
else:
union = union1
self.assertEqual(True, union.equals_exact(u1, tol))
self.assertEqual(True, union.equals_exact(u2, tol))
qs = City.objects.filter(name='NotACity')
self.assertEqual(None, qs.unionagg(field_name='point'))
@no_spatialite # SpatiaLite does not support abstract geometry columns
def test18_geometryfield(self):
"Testing the general GeometryField."
Feature(name='Point', geom=Point(1, 1)).save()
Feature(name='LineString', geom=LineString((0, 0), (1, 1), (5, 5))).save()
Feature(name='Polygon', geom=Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0)))).save()
Feature(name='GeometryCollection',
geom=GeometryCollection(Point(2, 2), LineString((0, 0), (2, 2)),
Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0))))).save()
f_1 = Feature.objects.get(name='Point')
self.assertEqual(True, isinstance(f_1.geom, Point))
self.assertEqual((1.0, 1.0), f_1.geom.tuple)
f_2 = Feature.objects.get(name='LineString')
self.assertEqual(True, isinstance(f_2.geom, LineString))
self.assertEqual(((0.0, 0.0), (1.0, 1.0), (5.0, 5.0)), f_2.geom.tuple)
f_3 = Feature.objects.get(name='Polygon')
self.assertEqual(True, isinstance(f_3.geom, Polygon))
f_4 = Feature.objects.get(name='GeometryCollection')
self.assertEqual(True, isinstance(f_4.geom, GeometryCollection))
self.assertEqual(f_3.geom, f_4.geom[2])
@no_mysql
def test19_centroid(self):
def test_centroid(self):
"Testing the `centroid` GeoQuerySet method."
qs = State.objects.exclude(poly__isnull=True).centroid()
if oracle:
@ -540,84 +384,7 @@ class GeoModelTest(TestCase):
self.assertEqual(True, s.poly.centroid.equals_exact(s.centroid, tol))
@no_mysql
def test20_pointonsurface(self):
"Testing the `point_on_surface` GeoQuerySet method."
# Reference values.
if oracle:
# SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_GEOM.SDO_POINTONSURFACE(GEOAPP_COUNTRY.MPOLY, 0.05)) FROM GEOAPP_COUNTRY;
ref = {'New Zealand' : fromstr('POINT (174.616364 -36.100861)', srid=4326),
'Texas' : fromstr('POINT (-103.002434 36.500397)', srid=4326),
}
elif postgis or spatialite:
# Using GEOSGeometry to compute the reference point on surface values
# -- since PostGIS also uses GEOS these should be the same.
ref = {'New Zealand' : Country.objects.get(name='New Zealand').mpoly.point_on_surface,
'Texas' : Country.objects.get(name='Texas').mpoly.point_on_surface
}
for c in Country.objects.point_on_surface():
if spatialite:
# XXX This seems to be a WKT-translation-related precision issue?
tol = 0.00001
else:
tol = 0.000000001
self.assertEqual(True, ref[c.name].equals_exact(c.point_on_surface, tol))
@no_mysql
@no_oracle
def test21_scale(self):
"Testing the `scale` GeoQuerySet method."
xfac, yfac = 2, 3
tol = 5 # XXX The low precision tolerance is for SpatiaLite
qs = Country.objects.scale(xfac, yfac, model_att='scaled')
for c in qs:
for p1, p2 in zip(c.mpoly, c.scaled):
for r1, r2 in zip(p1, p2):
for c1, c2 in zip(r1.coords, r2.coords):
self.assertAlmostEqual(c1[0] * xfac, c2[0], tol)
self.assertAlmostEqual(c1[1] * yfac, c2[1], tol)
@no_mysql
@no_oracle
def test22_translate(self):
"Testing the `translate` GeoQuerySet method."
xfac, yfac = 5, -23
qs = Country.objects.translate(xfac, yfac, model_att='translated')
for c in qs:
for p1, p2 in zip(c.mpoly, c.translated):
for r1, r2 in zip(p1, p2):
for c1, c2 in zip(r1.coords, r2.coords):
# XXX The low precision is for SpatiaLite
self.assertAlmostEqual(c1[0] + xfac, c2[0], 5)
self.assertAlmostEqual(c1[1] + yfac, c2[1], 5)
@no_mysql
def test23_numgeom(self):
"Testing the `num_geom` GeoQuerySet method."
# Both 'countries' only have two geometries.
for c in Country.objects.num_geom(): self.assertEqual(2, c.num_geom)
for c in City.objects.filter(point__isnull=False).num_geom():
# Oracle will return 1 for the number of geometries on non-collections,
# whereas PostGIS will return None.
if postgis:
self.assertEqual(None, c.num_geom)
else:
self.assertEqual(1, c.num_geom)
@no_mysql
@no_spatialite # SpatiaLite can only count vertices in LineStrings
def test24_numpoints(self):
"Testing the `num_points` GeoQuerySet method."
for c in Country.objects.num_points():
self.assertEqual(c.mpoly.num_points, c.num_points)
if not oracle:
# Oracle cannot count vertices in Point geometries.
for c in City.objects.num_points(): self.assertEqual(1, c.num_points)
@no_mysql
def test25_geoset(self):
def test_diff_intersection_union(self):
"Testing the `difference`, `intersection`, `sym_difference`, and `union` GeoQuerySet methods."
geom = Point(5, 23)
tol = 1
@ -644,22 +411,232 @@ class GeoModelTest(TestCase):
self.assertEqual(c.mpoly.union(geom), c.union)
@no_mysql
def test26_inherited_geofields(self):
"Test GeoQuerySet methods on inherited Geometry fields."
# Creating a Pennsylvanian city.
mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)')
@no_spatialite # SpatiaLite does not have an Extent function
def test_extent(self):
"Testing the `extent` GeoQuerySet method."
# Reference query:
# `SELECT ST_extent(point) FROM geoapp_city WHERE (name='Houston' or name='Dallas');`
# => BOX(-96.8016128540039 29.7633724212646,-95.3631439208984 32.7820587158203)
expected = (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820)
# All transformation SQL will need to be performed on the
# _parent_ table.
qs = PennsylvaniaCity.objects.transform(32128)
qs = City.objects.filter(name__in=('Houston', 'Dallas'))
extent = qs.extent()
self.assertEqual(1, qs.count())
for pc in qs: self.assertEqual(32128, pc.point.srid)
for val, exp in zip(extent, expected):
self.assertAlmostEqual(exp, val, 4)
@no_mysql
@no_oracle
@no_spatialite
def test27_snap_to_grid(self):
def test_force_rhr(self):
"Testing GeoQuerySet.force_rhr()."
rings = ( ( (0, 0), (5, 0), (0, 5), (0, 0) ),
( (1, 1), (1, 3), (3, 1), (1, 1) ),
)
rhr_rings = ( ( (0, 0), (0, 5), (5, 0), (0, 0) ),
( (1, 1), (3, 1), (1, 3), (1, 1) ),
)
State.objects.create(name='Foo', poly=Polygon(*rings))
s = State.objects.force_rhr().get(name='Foo')
self.assertEqual(rhr_rings, s.force_rhr.coords)
@no_mysql
@no_oracle
@no_spatialite
def test_geohash(self):
"Testing GeoQuerySet.geohash()."
if not connection.ops.geohash: return
# Reference query:
# SELECT ST_GeoHash(point) FROM geoapp_city WHERE name='Houston';
# SELECT ST_GeoHash(point, 5) FROM geoapp_city WHERE name='Houston';
ref_hash = '9vk1mfq8jx0c8e0386z6'
h1 = City.objects.geohash().get(name='Houston')
h2 = City.objects.geohash(precision=5).get(name='Houston')
self.assertEqual(ref_hash, h1.geohash)
self.assertEqual(ref_hash[:5], h2.geohash)
def test_geojson(self):
"Testing GeoJSON output from the database using GeoQuerySet.geojson()."
# Only PostGIS 1.3.4+ supports GeoJSON.
if not connection.ops.geojson:
self.assertRaises(NotImplementedError, Country.objects.all().geojson, field_name='mpoly')
return
if connection.ops.spatial_version >= (1, 4, 0):
pueblo_json = '{"type":"Point","coordinates":[-104.609252,38.255001]}'
houston_json = '{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"coordinates":[-95.363151,29.763374]}'
victoria_json = '{"type":"Point","bbox":[-123.30519600,48.46261100,-123.30519600,48.46261100],"coordinates":[-123.305196,48.462611]}'
chicago_json = '{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"bbox":[-87.65018,41.85039,-87.65018,41.85039],"coordinates":[-87.65018,41.85039]}'
else:
pueblo_json = '{"type":"Point","coordinates":[-104.60925200,38.25500100]}'
houston_json = '{"type":"Point","crs":{"type":"EPSG","properties":{"EPSG":4326}},"coordinates":[-95.36315100,29.76337400]}'
victoria_json = '{"type":"Point","bbox":[-123.30519600,48.46261100,-123.30519600,48.46261100],"coordinates":[-123.30519600,48.46261100]}'
chicago_json = '{"type":"Point","crs":{"type":"EPSG","properties":{"EPSG":4326}},"bbox":[-87.65018,41.85039,-87.65018,41.85039],"coordinates":[-87.65018,41.85039]}'
# Precision argument should only be an integer
self.assertRaises(TypeError, City.objects.geojson, precision='foo')
# Reference queries and values.
# SELECT ST_AsGeoJson("geoapp_city"."point", 8, 0) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Pueblo';
self.assertEqual(pueblo_json, City.objects.geojson().get(name='Pueblo').geojson)
# 1.3.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
# 1.4.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
# This time we want to include the CRS by using the `crs` keyword.
self.assertEqual(houston_json, City.objects.geojson(crs=True, model_att='json').get(name='Houston').json)
# 1.3.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 2) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Victoria';
# 1.4.x: SELECT ST_AsGeoJson("geoapp_city"."point", 8, 1) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Houston';
# This time we include the bounding box by using the `bbox` keyword.
self.assertEqual(victoria_json, City.objects.geojson(bbox=True).get(name='Victoria').geojson)
# 1.(3|4).x: SELECT ST_AsGeoJson("geoapp_city"."point", 5, 3) FROM "geoapp_city" WHERE "geoapp_city"."name" = 'Chicago';
# Finally, we set every available keyword.
self.assertEqual(chicago_json, City.objects.geojson(bbox=True, crs=True, precision=5).get(name='Chicago').geojson)
def test_gml(self):
"Testing GML output from the database using GeoQuerySet.gml()."
if mysql or (spatialite and not connection.ops.gml) :
self.assertRaises(NotImplementedError, Country.objects.all().gml, field_name='mpoly')
return
# Should throw a TypeError when tyring to obtain GML from a
# non-geometry field.
qs = City.objects.all()
self.assertRaises(TypeError, qs.gml, field_name='name')
ptown1 = City.objects.gml(field_name='point', precision=9).get(name='Pueblo')
ptown2 = City.objects.gml(precision=9).get(name='Pueblo')
if oracle:
# No precision parameter for Oracle :-/
gml_regex = re.compile(r'^<gml:Point srsName="SDO:4326" xmlns:gml="http://www.opengis.net/gml"><gml:coordinates decimal="\." cs="," ts=" ">-104.60925\d+,38.25500\d+ </gml:coordinates></gml:Point>')
elif spatialite:
# Spatialite has extra colon in SrsName
gml_regex = re.compile(r'^<gml:Point SrsName="EPSG::4326"><gml:coordinates decimal="\." cs="," ts=" ">-104.609251\d+,38.255001</gml:coordinates></gml:Point>')
else:
gml_regex = re.compile(r'^<gml:Point srsName="EPSG:4326"><gml:coordinates>-104\.60925\d+,38\.255001</gml:coordinates></gml:Point>')
for ptown in [ptown1, ptown2]:
self.assertTrue(gml_regex.match(ptown.gml))
def test_kml(self):
"Testing KML output from the database using GeoQuerySet.kml()."
# Only PostGIS and Spatialite (>=2.4.0-RC4) support KML serialization
if not (postgis or (spatialite and connection.ops.kml)):
self.assertRaises(NotImplementedError, State.objects.all().kml, field_name='poly')
return
# Should throw a TypeError when trying to obtain KML from a
# non-geometry field.
qs = City.objects.all()
self.assertRaises(TypeError, qs.kml, 'name')
# The reference KML depends on the version of PostGIS used
# (the output stopped including altitude in 1.3.3).
if connection.ops.spatial_version >= (1, 3, 3):
ref_kml = '<Point><coordinates>-104.609252,38.255001</coordinates></Point>'
else:
ref_kml = '<Point><coordinates>-104.609252,38.255001,0</coordinates></Point>'
# Ensuring the KML is as expected.
ptown1 = City.objects.kml(field_name='point', precision=9).get(name='Pueblo')
ptown2 = City.objects.kml(precision=9).get(name='Pueblo')
for ptown in [ptown1, ptown2]:
self.assertEqual(ref_kml, ptown.kml)
# Only PostGIS has support for the MakeLine aggregate.
@no_mysql
@no_oracle
@no_spatialite
def test_make_line(self):
"Testing the `make_line` GeoQuerySet method."
# Ensuring that a `TypeError` is raised on models without PointFields.
self.assertRaises(TypeError, State.objects.make_line)
self.assertRaises(TypeError, Country.objects.make_line)
# Reference query:
# SELECT AsText(ST_MakeLine(geoapp_city.point)) FROM geoapp_city;
ref_line = GEOSGeometry('LINESTRING(-95.363151 29.763374,-96.801611 32.782057,-97.521157 34.464642,174.783117 -41.315268,-104.609252 38.255001,-95.23506 38.971823,-87.650175 41.850385,-123.305196 48.462611)', srid=4326)
self.assertEqual(ref_line, City.objects.make_line())
@no_mysql
def test_num_geom(self):
"Testing the `num_geom` GeoQuerySet method."
# Both 'countries' only have two geometries.
for c in Country.objects.num_geom(): self.assertEqual(2, c.num_geom)
for c in City.objects.filter(point__isnull=False).num_geom():
# Oracle will return 1 for the number of geometries on non-collections,
# whereas PostGIS will return None.
if postgis:
self.assertEqual(None, c.num_geom)
else:
self.assertEqual(1, c.num_geom)
@no_mysql
@no_spatialite # SpatiaLite can only count vertices in LineStrings
def test_num_points(self):
"Testing the `num_points` GeoQuerySet method."
for c in Country.objects.num_points():
self.assertEqual(c.mpoly.num_points, c.num_points)
if not oracle:
# Oracle cannot count vertices in Point geometries.
for c in City.objects.num_points(): self.assertEqual(1, c.num_points)
@no_mysql
def test_point_on_surface(self):
"Testing the `point_on_surface` GeoQuerySet method."
# Reference values.
if oracle:
# SELECT SDO_UTIL.TO_WKTGEOMETRY(SDO_GEOM.SDO_POINTONSURFACE(GEOAPP_COUNTRY.MPOLY, 0.05)) FROM GEOAPP_COUNTRY;
ref = {'New Zealand' : fromstr('POINT (174.616364 -36.100861)', srid=4326),
'Texas' : fromstr('POINT (-103.002434 36.500397)', srid=4326),
}
elif postgis or spatialite:
# Using GEOSGeometry to compute the reference point on surface values
# -- since PostGIS also uses GEOS these should be the same.
ref = {'New Zealand' : Country.objects.get(name='New Zealand').mpoly.point_on_surface,
'Texas' : Country.objects.get(name='Texas').mpoly.point_on_surface
}
for c in Country.objects.point_on_surface():
if spatialite:
# XXX This seems to be a WKT-translation-related precision issue?
tol = 0.00001
else:
tol = 0.000000001
self.assertEqual(True, ref[c.name].equals_exact(c.point_on_surface, tol))
@no_mysql
@no_spatialite
def test_reverse_geom(self):
"Testing GeoQuerySet.reverse_geom()."
coords = [ (-95.363151, 29.763374), (-95.448601, 29.713803) ]
Track.objects.create(name='Foo', line=LineString(coords))
t = Track.objects.reverse_geom().get(name='Foo')
coords.reverse()
self.assertEqual(tuple(coords), t.reverse_geom.coords)
if oracle:
self.assertRaises(TypeError, State.objects.reverse_geom)
@no_mysql
@no_oracle
def test_scale(self):
"Testing the `scale` GeoQuerySet method."
xfac, yfac = 2, 3
tol = 5 # XXX The low precision tolerance is for SpatiaLite
qs = Country.objects.scale(xfac, yfac, model_att='scaled')
for c in qs:
for p1, p2 in zip(c.mpoly, c.scaled):
for r1, r2 in zip(p1, p2):
for c1, c2 in zip(r1.coords, r2.coords):
self.assertAlmostEqual(c1[0] * xfac, c2[0], tol)
self.assertAlmostEqual(c1[1] * yfac, c2[1], tol)
@no_mysql
@no_oracle
@no_spatialite
def test_snap_to_grid(self):
"Testing GeoQuerySet.snap_to_grid()."
# Let's try and break snap_to_grid() with bad combinations of arguments.
for bad_args in ((), range(3), range(5)):
@ -695,48 +672,78 @@ class GeoModelTest(TestCase):
ref = fromstr('MULTIPOLYGON(((12.4 43.87,12.45 43.87,12.45 44.1,12.5 44.1,12.5 43.87,12.45 43.87,12.4 43.87)))')
self.assertTrue(ref.equals_exact(Country.objects.snap_to_grid(0.05, 0.23, 0.5, 0.17).get(name='San Marino').snap_to_grid, tol))
def test_svg(self):
"Testing SVG output using GeoQuerySet.svg()."
if mysql or oracle:
self.assertRaises(NotImplementedError, City.objects.svg)
return
self.assertRaises(TypeError, City.objects.svg, precision='foo')
# SELECT AsSVG(geoapp_city.point, 0, 8) FROM geoapp_city WHERE name = 'Pueblo';
svg1 = 'cx="-104.609252" cy="-38.255001"'
# Even though relative, only one point so it's practically the same except for
# the 'c' letter prefix on the x,y values.
svg2 = svg1.replace('c', '')
self.assertEqual(svg1, City.objects.svg().get(name='Pueblo').svg)
self.assertEqual(svg2, City.objects.svg(relative=5).get(name='Pueblo').svg)
@no_mysql
@no_spatialite
def test28_reverse(self):
"Testing GeoQuerySet.reverse_geom()."
coords = [ (-95.363151, 29.763374), (-95.448601, 29.713803) ]
Track.objects.create(name='Foo', line=LineString(coords))
t = Track.objects.reverse_geom().get(name='Foo')
coords.reverse()
self.assertEqual(tuple(coords), t.reverse_geom.coords)
def test_transform(self):
"Testing the transform() GeoQuerySet method."
# Pre-transformed points for Houston and Pueblo.
htown = fromstr('POINT(1947516.83115183 6322297.06040572)', srid=3084)
ptown = fromstr('POINT(992363.390841912 481455.395105533)', srid=2774)
prec = 3 # Precision is low due to version variations in PROJ and GDAL.
# Asserting the result of the transform operation with the values in
# the pre-transformed points. Oracle does not have the 3084 SRID.
if not oracle:
h = City.objects.transform(htown.srid).get(name='Houston')
self.assertEqual(3084, h.point.srid)
self.assertAlmostEqual(htown.x, h.point.x, prec)
self.assertAlmostEqual(htown.y, h.point.y, prec)
p1 = City.objects.transform(ptown.srid, field_name='point').get(name='Pueblo')
p2 = City.objects.transform(srid=ptown.srid).get(name='Pueblo')
for p in [p1, p2]:
self.assertEqual(2774, p.point.srid)
self.assertAlmostEqual(ptown.x, p.point.x, prec)
self.assertAlmostEqual(ptown.y, p.point.y, prec)
@no_mysql
@no_oracle
def test_translate(self):
"Testing the `translate` GeoQuerySet method."
xfac, yfac = 5, -23
qs = Country.objects.translate(xfac, yfac, model_att='translated')
for c in qs:
for p1, p2 in zip(c.mpoly, c.translated):
for r1, r2 in zip(p1, p2):
for c1, c2 in zip(r1.coords, r2.coords):
# XXX The low precision is for SpatiaLite
self.assertAlmostEqual(c1[0] + xfac, c2[0], 5)
self.assertAlmostEqual(c1[1] + yfac, c2[1], 5)
@no_mysql
def test_unionagg(self):
"Testing the `unionagg` (aggregate union) GeoQuerySet method."
tx = Country.objects.get(name='Texas').mpoly
# Houston, Dallas -- Oracle has different order.
union1 = fromstr('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
union2 = fromstr('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)')
qs = City.objects.filter(point__within=tx)
self.assertRaises(TypeError, qs.unionagg, 'name')
# Using `field_name` keyword argument in one query and specifying an
# order in the other (which should not be used because this is
# an aggregate method on a spatial column)
u1 = qs.unionagg(field_name='point')
u2 = qs.order_by('name').unionagg()
tol = 0.00001
if oracle:
self.assertRaises(TypeError, State.objects.reverse_geom)
@no_mysql
@no_oracle
@no_spatialite
def test29_force_rhr(self):
"Testing GeoQuerySet.force_rhr()."
rings = ( ( (0, 0), (5, 0), (0, 5), (0, 0) ),
( (1, 1), (1, 3), (3, 1), (1, 1) ),
)
rhr_rings = ( ( (0, 0), (0, 5), (5, 0), (0, 0) ),
( (1, 1), (3, 1), (1, 3), (1, 1) ),
)
State.objects.create(name='Foo', poly=Polygon(*rings))
s = State.objects.force_rhr().get(name='Foo')
self.assertEqual(rhr_rings, s.force_rhr.coords)
@no_mysql
@no_oracle
@no_spatialite
def test30_geohash(self):
"Testing GeoQuerySet.geohash()."
if not connection.ops.geohash: return
# Reference query:
# SELECT ST_GeoHash(point) FROM geoapp_city WHERE name='Houston';
# SELECT ST_GeoHash(point, 5) FROM geoapp_city WHERE name='Houston';
ref_hash = '9vk1mfq8jx0c8e0386z6'
h1 = City.objects.geohash().get(name='Houston')
h2 = City.objects.geohash(precision=5).get(name='Houston')
self.assertEqual(ref_hash, h1.geohash)
self.assertEqual(ref_hash[:5], h2.geohash)
from .test_feeds import GeoFeedTest
from .test_regress import GeoRegressionTests
from .test_sitemaps import GeoSitemapTest
union = union2
else:
union = union1
self.assertEqual(True, union.equals_exact(u1, tol))
self.assertEqual(True, union.equals_exact(u2, tol))
qs = City.objects.filter(name='NotACity')
self.assertEqual(None, qs.unionagg(field_name='point'))

View File

@ -5,7 +5,7 @@ from datetime import date, datetime
from django import template
from django.conf import settings
from django.template import defaultfilters
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils.formats import number_format
from django.utils.translation import pgettext, ungettext, ugettext as _
from django.utils.timezone import is_aware, utc
@ -41,7 +41,7 @@ def intcomma(value, use_l10n=True):
return intcomma(value, False)
else:
return number_format(value, force_grouping=True)
orig = force_unicode(value)
orig = force_text(value)
new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', orig)
if orig == new:
return new

View File

@ -10,7 +10,7 @@ from django.contrib.localflavor.au.au_states import STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -44,7 +44,7 @@ class AUPhoneNumberField(Field):
super(AUPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+|-)', '', smart_unicode(value))
value = re.sub('(\(|\)|\s+|-)', '', smart_text(value))
phone_match = PHONE_DIGITS_RE.search(value)
if phone_match:
return '%s' % phone_match.group(1)

View File

@ -11,7 +11,7 @@ from django.contrib.localflavor.br.br_states import STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, CharField, Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -35,7 +35,7 @@ class BRPhoneNumberField(Field):
super(BRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
value = re.sub('(\(|\)|\s+)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
@ -68,10 +68,10 @@ class BRStateChoiceField(Field):
value = super(BRStateChoiceField, self).clean(value)
if value in EMPTY_VALUES:
value = ''
value = smart_unicode(value)
value = smart_text(value)
if value == '':
return value
valid_values = set([smart_unicode(k) for k, v in self.widget.choices])
valid_values = set([smart_text(k) for k, v in self.widget.choices])
if value not in valid_values:
raise ValidationError(self.error_messages['invalid'])
return value
@ -154,10 +154,10 @@ class BRCNPJField(Field):
raise ValidationError(self.error_messages['max_digits'])
orig_dv = value[-2:]
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))])
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(list(range(5, 1, -1)) + list(range(9, 1, -1)))])
new_1dv = DV_maker(new_1dv % 11)
value = value[:-2] + str(new_1dv) + value[-1]
new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(6, 1, -1) + range(9, 1, -1))])
new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(list(range(6, 1, -1)) + list(range(9, 1, -1)))])
new_2dv = DV_maker(new_2dv % 11)
value = value[:-1] + str(new_2dv)
if value[-2:] != orig_dv:

View File

@ -9,7 +9,7 @@ import re
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, CharField, Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -53,7 +53,7 @@ class CAPhoneNumberField(Field):
super(CAPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
value = re.sub('(\(|\)|\s+)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s-%s-%s' % (m.group(1), m.group(2), m.group(3))

View File

@ -10,7 +10,7 @@ from django.contrib.localflavor.ch.ch_states import STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -41,7 +41,7 @@ class CHPhoneNumberField(Field):
super(CHPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\.|\s|/|-)', '', smart_unicode(value))
value = re.sub('(\.|\s|/|-)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10])

View File

@ -8,7 +8,7 @@ from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import RegexField, Select
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from .cl_regions import REGION_CHOICES
@ -75,7 +75,7 @@ class CLRutField(RegexField):
Turns the RUT into one normalized format. Returns a (rut, verifier)
tuple.
"""
rut = smart_unicode(rut).replace(' ', '').replace('.', '').replace('-', '')
rut = smart_text(rut).replace(' ', '').replace('.', '').replace('-', '')
return rut[:-1], rut[-1].upper()
def _format(self, code, verifier=None):

View File

@ -9,7 +9,7 @@ from django.contrib.localflavor.fr.fr_department import DEPARTMENT_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import CharField, RegexField, Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -43,7 +43,7 @@ class FRPhoneNumberField(CharField):
super(FRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\.|\s)', '', smart_unicode(value))
value = re.sub('(\.|\s)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s %s %s %s %s' % (value[0:2], value[2:4], value[4:6], value[6:8], value[8:10])

View File

@ -8,7 +8,7 @@ import re
from django.core.validators import EMPTY_VALUES
from django.forms import CharField
from django.forms import ValidationError
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -53,7 +53,7 @@ class HKPhoneNumberField(CharField):
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+|\+)', '', smart_unicode(value))
value = re.sub('(\(|\)|\s+|\+)', '', smart_text(value))
m = hk_phone_digits_re.search(value)
if not m:
raise ValidationError(self.error_messages['invalid'])

View File

@ -12,7 +12,7 @@ from django.contrib.localflavor.hr.hr_choices import (
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, Select, RegexField
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -159,7 +159,7 @@ class HRLicensePlateField(Field):
if value in EMPTY_VALUES:
return ''
value = re.sub(r'[\s\-]+', '', smart_unicode(value.strip())).upper()
value = re.sub(r'[\s\-]+', '', smart_text(value.strip())).upper()
matches = plate_re.search(value)
if matches is None:
@ -225,7 +225,7 @@ class HRPhoneNumberField(Field):
if value in EMPTY_VALUES:
return ''
value = re.sub(r'[\-\s\(\)]', '', smart_unicode(value))
value = re.sub(r'[\-\s\(\)]', '', smart_text(value))
matches = phone_re.search(value)
if matches is None:

View File

@ -11,7 +11,7 @@ from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, Select
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
postcode_re = re.compile(r'^[1-9]\d{4}$')
@ -77,10 +77,10 @@ class IDPhoneNumberField(Field):
if value in EMPTY_VALUES:
return ''
phone_number = re.sub(r'[\-\s\(\)]', '', smart_unicode(value))
phone_number = re.sub(r'[\-\s\(\)]', '', smart_text(value))
if phone_re.search(phone_number):
return smart_unicode(value)
return smart_text(value)
raise ValidationError(self.error_messages['invalid'])
@ -120,7 +120,7 @@ class IDLicensePlateField(Field):
return ''
plate_number = re.sub(r'\s+', ' ',
smart_unicode(value.strip())).upper()
smart_text(value.strip())).upper()
matches = plate_re.search(plate_number)
if matches is None:
@ -181,7 +181,7 @@ class IDNationalIdentityNumberField(Field):
if value in EMPTY_VALUES:
return ''
value = re.sub(r'[\s.]', '', smart_unicode(value))
value = re.sub(r'[\s.]', '', smart_text(value))
if not nik_re.search(value):
raise ValidationError(self.error_messages['invalid'])

View File

@ -10,7 +10,7 @@ from django.contrib.localflavor.in_.in_states import STATES_NORMALIZED, STATE_CH
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, CharField, Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -74,7 +74,7 @@ class INStateField(Field):
pass
else:
try:
return smart_unicode(STATES_NORMALIZED[value.strip().lower()])
return smart_text(STATES_NORMALIZED[value.strip().lower()])
except KeyError:
pass
raise ValidationError(self.error_messages['invalid'])
@ -107,7 +107,7 @@ class INPhoneNumberField(CharField):
super(INPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = smart_unicode(value)
value = smart_text(value)
m = phone_digits_re.match(value)
if m:
return '%s' % (value)

View File

@ -9,7 +9,7 @@ from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import RegexField
from django.forms.widgets import Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -58,7 +58,7 @@ class ISIdNumberField(RegexField):
Takes in the value in canonical form and returns it in the common
display format.
"""
return smart_unicode(value[:6]+'-'+value[6:])
return smart_text(value[:6]+'-'+value[6:])
class ISPhoneNumberField(RegexField):
"""

View File

@ -13,7 +13,7 @@ from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
class ITZipCodeField(RegexField):
@ -85,4 +85,4 @@ class ITVatNumberField(Field):
check_digit = vat_number_check_digit(vat_number[0:10])
if not vat_number[10] == check_digit:
raise ValidationError(self.error_messages['invalid'])
return smart_unicode(vat_number)
return smart_text(vat_number)

View File

@ -1,4 +1,4 @@
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
def ssn_check_digit(value):
"Calculate Italian social security number check digit."
@ -34,11 +34,11 @@ def ssn_check_digit(value):
def vat_number_check_digit(vat_number):
"Calculate Italian VAT number check digit."
normalized_vat_number = smart_unicode(vat_number).zfill(10)
normalized_vat_number = smart_text(vat_number).zfill(10)
total = 0
for i in range(0, 10, 2):
total += int(normalized_vat_number[i])
for i in range(1, 11, 2):
quotient , remainder = divmod(int(normalized_vat_number[i]) * 2, 10)
total += quotient + remainder
return smart_unicode((10 - total % 10) % 10)
return smart_text((10 - total % 10) % 10)

View File

@ -10,7 +10,7 @@ from django.contrib.localflavor.nl.nl_provinces import PROVINCE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, Select
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -61,7 +61,7 @@ class NLPhoneNumberField(Field):
if value in EMPTY_VALUES:
return ''
phone_nr = re.sub('[\-\s\(\)]', '', smart_unicode(value))
phone_nr = re.sub('[\-\s\(\)]', '', smart_text(value))
if len(phone_nr) == 10 and numeric_re.search(phone_nr):
return value

View File

@ -8,7 +8,7 @@ import re
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
phone_digits_re = re.compile(r'^(\d{9}|(00|\+)\d*)$')
@ -43,7 +43,7 @@ class PTPhoneNumberField(Field):
super(PTPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\.|\s)', '', smart_unicode(value))
value = re.sub('(\.|\s)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s' % value

View File

@ -41,7 +41,7 @@ class SIEMSOField(CharField):
# Validate EMSO
s = 0
int_values = [int(i) for i in value]
for a, b in zip(int_values, range(7, 1, -1) * 2):
for a, b in zip(int_values, list(range(7, 1, -1)) * 2):
s += a * b
chk = s % 11
if chk == 0:

View File

@ -10,7 +10,7 @@ from django.contrib.localflavor.tr.tr_provinces import PROVINCE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select, CharField
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -46,7 +46,7 @@ class TRPhoneNumberField(CharField):
super(TRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
value = re.sub('(\(|\)|\s+)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s%s' % (m.group(2), m.group(4))

View File

@ -9,7 +9,7 @@ import re
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select, CharField
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
@ -34,7 +34,7 @@ class USPhoneNumberField(CharField):
super(USPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
value = re.sub('(\(|\)|\s+)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s-%s-%s' % (m.group(1), m.group(2), m.group(3))

View File

@ -13,7 +13,7 @@ markup syntaxes to HTML; currently there is support for:
from django import template
from django.conf import settings
from django.utils.encoding import smart_str, force_unicode
from django.utils.encoding import smart_bytes, force_text
from django.utils.safestring import mark_safe
register = template.Library()
@ -25,9 +25,9 @@ def textile(value):
except ImportError:
if settings.DEBUG:
raise template.TemplateSyntaxError("Error in 'textile' filter: The Python textile library isn't installed.")
return force_unicode(value)
return force_text(value)
else:
return mark_safe(force_unicode(textile.textile(smart_str(value), encoding='utf-8', output='utf-8')))
return mark_safe(force_text(textile.textile(smart_bytes(value), encoding='utf-8', output='utf-8')))
@register.filter(is_safe=True)
def markdown(value, arg=''):
@ -52,23 +52,23 @@ def markdown(value, arg=''):
except ImportError:
if settings.DEBUG:
raise template.TemplateSyntaxError("Error in 'markdown' filter: The Python markdown library isn't installed.")
return force_unicode(value)
return force_text(value)
else:
markdown_vers = getattr(markdown, "version_info", 0)
if markdown_vers < (2, 1):
if settings.DEBUG:
raise template.TemplateSyntaxError(
"Error in 'markdown' filter: Django does not support versions of the Python markdown library < 2.1.")
return force_unicode(value)
return force_text(value)
else:
extensions = [e for e in arg.split(",") if e]
if extensions and extensions[0] == "safe":
extensions = extensions[1:]
return mark_safe(markdown.markdown(
force_unicode(value), extensions, safe_mode=True, enable_attributes=False))
force_text(value), extensions, safe_mode=True, enable_attributes=False))
else:
return mark_safe(markdown.markdown(
force_unicode(value), extensions, safe_mode=False))
force_text(value), extensions, safe_mode=False))
@register.filter(is_safe=True)
def restructuredtext(value):
@ -77,8 +77,8 @@ def restructuredtext(value):
except ImportError:
if settings.DEBUG:
raise template.TemplateSyntaxError("Error in 'restructuredtext' filter: The Python docutils library isn't installed.")
return force_unicode(value)
return force_text(value)
else:
docutils_settings = getattr(settings, "RESTRUCTUREDTEXT_FILTER_SETTINGS", {})
parts = publish_parts(source=smart_str(value), writer_name="html4css1", settings_overrides=docutils_settings)
return mark_safe(force_unicode(parts["fragment"]))
parts = publish_parts(source=smart_bytes(value), writer_name="html4css1", settings_overrides=docutils_settings)
return mark_safe(force_text(parts["fragment"]))

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals
from django.conf import settings
from django.utils.encoding import force_unicode, StrAndUnicode
from django.utils.encoding import force_text, StrAndUnicode
from django.contrib.messages import constants, utils
@ -26,22 +26,22 @@ class Message(StrAndUnicode):
and ``extra_tags`` to unicode in case they are lazy translations.
Known "safe" types (None, int, etc.) are not converted (see Django's
``force_unicode`` implementation for details).
``force_text`` implementation for details).
"""
self.message = force_unicode(self.message, strings_only=True)
self.extra_tags = force_unicode(self.extra_tags, strings_only=True)
self.message = force_text(self.message, strings_only=True)
self.extra_tags = force_text(self.extra_tags, strings_only=True)
def __eq__(self, other):
return isinstance(other, Message) and self.level == other.level and \
self.message == other.message
def __unicode__(self):
return force_unicode(self.message)
return force_text(self.message)
def _get_tags(self):
label_tag = force_unicode(LEVEL_TAGS.get(self.level, ''),
label_tag = force_text(LEVEL_TAGS.get(self.level, ''),
strings_only=True)
extra_tags = force_unicode(self.extra_tags, strings_only=True)
extra_tags = force_text(self.extra_tags, strings_only=True)
if extra_tags and label_tag:
return ' '.join([extra_tags, label_tag])
elif extra_tags:

View File

@ -4,6 +4,7 @@ from django.conf import settings
from django.contrib.messages.storage.base import BaseStorage, Message
from django.http import SimpleCookie
from django.utils.crypto import salted_hmac, constant_time_compare
from django.utils import six
class MessageEncoder(json.JSONEncoder):
@ -33,7 +34,7 @@ class MessageDecoder(json.JSONDecoder):
return [self.process_messages(item) for item in obj]
if isinstance(obj, dict):
return dict([(key, self.process_messages(value))
for key, value in obj.iteritems()])
for key, value in six.iteritems(obj)])
return obj
def decode(self, s, **kwargs):

View File

@ -1,7 +1,7 @@
from django.contrib.sessions.backends.base import SessionBase, CreateError
from django.core.exceptions import SuspiciousOperation
from django.db import IntegrityError, transaction, router
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils import timezone
@ -18,7 +18,7 @@ class SessionStore(SessionBase):
session_key = self.session_key,
expire_date__gt=timezone.now()
)
return self.decode(force_unicode(s.session_data))
return self.decode(force_text(s.session_data))
except (Session.DoesNotExist, SuspiciousOperation):
self.create()
return {}

View File

@ -16,6 +16,7 @@ from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.http import HttpResponse
from django.test import TestCase, RequestFactory
from django.test.utils import override_settings
from django.utils import six
from django.utils import timezone
from django.utils import unittest
@ -86,16 +87,16 @@ class SessionTestsMixin(object):
self.assertFalse(self.session.modified)
def test_values(self):
self.assertEqual(self.session.values(), [])
self.assertEqual(list(self.session.values()), [])
self.assertTrue(self.session.accessed)
self.session['some key'] = 1
self.assertEqual(self.session.values(), [1])
self.assertEqual(list(self.session.values()), [1])
def test_iterkeys(self):
self.session['x'] = 1
self.session.modified = False
self.session.accessed = False
i = self.session.iterkeys()
i = six.iterkeys(self.session)
self.assertTrue(hasattr(i, '__iter__'))
self.assertTrue(self.session.accessed)
self.assertFalse(self.session.modified)
@ -105,7 +106,7 @@ class SessionTestsMixin(object):
self.session['x'] = 1
self.session.modified = False
self.session.accessed = False
i = self.session.itervalues()
i = six.itervalues(self.session)
self.assertTrue(hasattr(i, '__iter__'))
self.assertTrue(self.session.accessed)
self.assertFalse(self.session.modified)
@ -115,7 +116,7 @@ class SessionTestsMixin(object):
self.session['x'] = 1
self.session.modified = False
self.session.accessed = False
i = self.session.iteritems()
i = six.iteritems(self.session)
self.assertTrue(hasattr(i, '__iter__'))
self.assertTrue(self.session.accessed)
self.assertFalse(self.session.modified)
@ -125,9 +126,9 @@ class SessionTestsMixin(object):
self.session['x'] = 1
self.session.modified = False
self.session.accessed = False
self.assertEqual(self.session.items(), [('x', 1)])
self.assertEqual(list(self.session.items()), [('x', 1)])
self.session.clear()
self.assertEqual(self.session.items(), [])
self.assertEqual(list(self.session.items()), [])
self.assertTrue(self.session.accessed)
self.assertTrue(self.session.modified)
@ -154,10 +155,10 @@ class SessionTestsMixin(object):
self.session['a'], self.session['b'] = 'c', 'd'
self.session.save()
prev_key = self.session.session_key
prev_data = self.session.items()
prev_data = list(self.session.items())
self.session.cycle_key()
self.assertNotEqual(self.session.session_key, prev_key)
self.assertEqual(self.session.items(), prev_data)
self.assertEqual(list(self.session.items()), prev_data)
def test_invalid_key(self):
# Submitting an invalid session key (either by guessing, or if the db has

View File

@ -3,6 +3,7 @@ from django.core import urlresolvers
from django.core.paginator import EmptyPage, PageNotAnInteger
from django.http import Http404
from django.template.response import TemplateResponse
from django.utils import six
def index(request, sitemaps,
template_name='sitemap_index.xml', mimetype='application/xml',
@ -35,7 +36,7 @@ def sitemap(request, sitemaps, section=None,
raise Http404("No sitemap available for section: %r" % section)
maps = [sitemaps[section]]
else:
maps = sitemaps.values()
maps = list(six.itervalues(sitemaps))
page = request.GET.get("p", 1)
urls = []

View File

@ -6,6 +6,7 @@ from django.utils.datastructures import SortedDict
from django.utils.functional import empty, memoize, LazyObject
from django.utils.importlib import import_module
from django.utils._os import safe_join
from django.utils import six
from django.contrib.staticfiles import utils
from django.contrib.staticfiles.storage import AppStaticStorage
@ -132,7 +133,7 @@ class AppDirectoriesFinder(BaseFinder):
"""
List all files in all app storages.
"""
for storage in self.storages.itervalues():
for storage in six.itervalues(self.storages):
if storage.exists(''): # check if storage location exists
for path in utils.get_files(storage, ignore_patterns):
yield path, storage

View File

@ -6,8 +6,9 @@ from optparse import make_option
from django.core.files.storage import FileSystemStorage
from django.core.management.base import CommandError, NoArgsCommand
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils.datastructures import SortedDict
from django.utils.six.moves import input
from django.contrib.staticfiles import finders, storage
@ -148,7 +149,7 @@ class Command(NoArgsCommand):
clear_display = 'This will overwrite existing files!'
if self.interactive:
confirm = raw_input("""
confirm = input("""
You have requested to collect static files at the destination
location as specified in your settings%s
@ -198,9 +199,9 @@ Type 'yes' to continue, or 'no' to cancel: """
fpath = os.path.join(path, f)
if self.dry_run:
self.log("Pretending to delete '%s'" %
smart_unicode(fpath), level=1)
smart_text(fpath), level=1)
else:
self.log("Deleting '%s'" % smart_unicode(fpath), level=1)
self.log("Deleting '%s'" % smart_text(fpath), level=1)
self.storage.delete(fpath)
for d in dirs:
self.clear_dir(os.path.join(path, d))

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
import os
from optparse import make_option
from django.core.management.base import LabelCommand
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.contrib.staticfiles import finders
@ -19,12 +19,12 @@ class Command(LabelCommand):
def handle_label(self, path, **options):
verbosity = int(options.get('verbosity', 1))
result = finders.find(path, all=options['all'])
path = smart_unicode(path)
path = smart_text(path)
if result:
if not isinstance(result, (list, tuple)):
result = [result]
output = '\n '.join(
(smart_unicode(os.path.realpath(path)) for path in result))
(smart_text(os.path.realpath(path)) for path in result))
self.stdout.write("Found '%s' here:\n %s" % (path, output))
else:
if verbosity >= 1:

View File

@ -16,7 +16,7 @@ from django.core.exceptions import ImproperlyConfigured
from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage, get_storage_class
from django.utils.datastructures import SortedDict
from django.utils.encoding import force_unicode, smart_str
from django.utils.encoding import force_text, smart_bytes
from django.utils.functional import LazyObject
from django.utils.importlib import import_module
@ -112,7 +112,7 @@ class CachedFilesMixin(object):
return urlunsplit(unparsed_name)
def cache_key(self, name):
return 'staticfiles:%s' % hashlib.md5(smart_str(name)).hexdigest()
return 'staticfiles:%s' % hashlib.md5(smart_bytes(name)).hexdigest()
def url(self, name, force=False):
"""
@ -248,9 +248,9 @@ class CachedFilesMixin(object):
if hashed_file_exists:
self.delete(hashed_name)
# then save the processed result
content_file = ContentFile(smart_str(content))
content_file = ContentFile(smart_bytes(content))
saved_name = self._save(hashed_name, content_file)
hashed_name = force_unicode(saved_name.replace('\\', '/'))
hashed_name = force_text(saved_name.replace('\\', '/'))
processed = True
else:
# or handle the case in which neither processing nor
@ -258,7 +258,7 @@ class CachedFilesMixin(object):
if not hashed_file_exists:
processed = True
saved_name = self._save(hashed_name, original_file)
hashed_name = force_unicode(saved_name.replace('\\', '/'))
hashed_name = force_text(saved_name.replace('\\', '/'))
# and then set the cache accordingly
hashed_paths[self.cache_key(name)] = hashed_name

View File

@ -6,7 +6,7 @@ from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.http import HttpResponse, Http404
from django.template import loader, TemplateDoesNotExist, RequestContext
from django.utils import feedgenerator, tzinfo
from django.utils.encoding import force_unicode, iri_to_uri, smart_unicode
from django.utils.encoding import force_text, iri_to_uri, smart_text
from django.utils.html import escape
from django.utils.timezone import is_naive
@ -43,10 +43,10 @@ class Feed(object):
def item_title(self, item):
# Titles should be double escaped by default (see #6533)
return escape(force_unicode(item))
return escape(force_text(item))
def item_description(self, item):
return force_unicode(item)
return force_text(item)
def item_link(self, item):
try:
@ -154,9 +154,9 @@ class Feed(object):
enc_url = self.__get_dynamic_attr('item_enclosure_url', item)
if enc_url:
enc = feedgenerator.Enclosure(
url = smart_unicode(enc_url),
length = smart_unicode(self.__get_dynamic_attr('item_enclosure_length', item)),
mime_type = smart_unicode(self.__get_dynamic_attr('item_enclosure_mime_type', item))
url = smart_text(enc_url),
length = smart_text(self.__get_dynamic_attr('item_enclosure_length', item)),
mime_type = smart_text(self.__get_dynamic_attr('item_enclosure_mime_type', item))
)
author_name = self.__get_dynamic_attr('item_author_name', item)
if author_name is not None:

View File

@ -3,7 +3,7 @@
import warnings
from django.core.exceptions import ImproperlyConfigured, DjangoRuntimeWarning
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils.importlib import import_module
class InvalidCacheBackendError(ImproperlyConfigured):
@ -23,7 +23,7 @@ def default_key_func(key, key_prefix, version):
the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
function with custom key making behavior.
"""
return ':'.join([key_prefix, str(version), smart_str(key)])
return ':'.join([key_prefix, str(version), smart_bytes(key)])
def get_key_func(key_func):
"""
@ -62,7 +62,7 @@ class BaseCache(object):
except (ValueError, TypeError):
self._cull_frequency = 3
self.key_prefix = smart_str(params.get('KEY_PREFIX', ''))
self.key_prefix = smart_bytes(params.get('KEY_PREFIX', ''))
self.version = params.get('VERSION', 1)
self.key_func = get_key_func(params.get('KEY_FUNCTION', None))

View File

@ -9,7 +9,7 @@ RequestContext.
from django.conf import settings
from django.middleware.csrf import get_token
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils.functional import lazy
def csrf(request):
@ -25,7 +25,7 @@ def csrf(request):
# instead of returning an empty dict.
return b'NOTPROVIDED'
else:
return smart_str(token)
return smart_bytes(token)
_get_val = lazy(_get_val, str)
return {'csrf_token': _get_val() }

View File

@ -43,7 +43,7 @@ class ValidationError(Exception):
"""An error while validating data."""
def __init__(self, message, code=None, params=None):
import operator
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
"""
ValidationError can be passed any object that can be printed (usually
a string), a list of objects or a dictionary.
@ -54,11 +54,11 @@ class ValidationError(Exception):
message = reduce(operator.add, message.values())
if isinstance(message, list):
self.messages = [force_unicode(msg) for msg in message]
self.messages = [force_text(msg) for msg in message]
else:
self.code = code
self.params = params
message = force_unicode(message)
message = force_text(message)
self.messages = [message]
def __str__(self):

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
import os
from io import BytesIO
from django.utils.encoding import smart_str, smart_unicode
from django.utils.encoding import smart_bytes, smart_text
from django.core.files.utils import FileProxyMixin
class File(FileProxyMixin):
@ -18,16 +18,17 @@ class File(FileProxyMixin):
self.mode = file.mode
def __str__(self):
return smart_str(self.name or '')
return smart_bytes(self.name or '')
def __unicode__(self):
return smart_unicode(self.name or '')
return smart_text(self.name or '')
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, self or "None")
def __nonzero__(self):
def __bool__(self):
return bool(self.name)
__nonzero__ = __bool__ # Python 2
def __len__(self):
return self.size
@ -135,8 +136,9 @@ class ContentFile(File):
def __str__(self):
return 'Raw content'
def __nonzero__(self):
def __bool__(self):
return True
__nonzero__ = __bool__ # Python 2
def open(self, mode=None):
self.seek(0)

View File

@ -47,13 +47,18 @@ def get_image_dimensions(file_or_path, close=False):
file = open(file_or_path, 'rb')
close = True
try:
# Most of the time PIL only needs a small chunk to parse the image and
# get the dimensions, but with some TIFF files PIL needs to parse the
# whole file.
chunk_size = 1024
while 1:
data = file.read(1024)
data = file.read(chunk_size)
if not data:
break
p.feed(data)
if p.image:
return p.image.size
chunk_size = chunk_size*2
return None
finally:
if close:

View File

@ -11,7 +11,7 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.core.files import locks, File
from django.core.files.move import file_move_safe
from django.utils.encoding import force_unicode, filepath_to_uri
from django.utils.encoding import force_text, filepath_to_uri
from django.utils.functional import LazyObject
from django.utils.importlib import import_module
from django.utils.text import get_valid_filename
@ -48,7 +48,7 @@ class Storage(object):
name = self._save(name, content)
# Store filenames with forward slashes, even on Windows
return force_unicode(name.replace('\\', '/'))
return force_text(name.replace('\\', '/'))
# These methods are part of the public API, with default implementations.

View File

@ -8,7 +8,7 @@ from io import BytesIO
from django.conf import settings
from django.core.files.base import File
from django.core.files import temp as tempfile
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
__all__ = ('UploadedFile', 'TemporaryUploadedFile', 'InMemoryUploadedFile',
'SimpleUploadedFile')
@ -30,7 +30,7 @@ class UploadedFile(File):
self.charset = charset
def __repr__(self):
return smart_str("<%s: %s (%s)>" % (
return smart_bytes("<%s: %s (%s)>" % (
self.__class__.__name__, self.name, self.content_type))
def _get_name(self):

View File

@ -4,7 +4,7 @@ import sys
from django import http
from django.core import signals
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from django.utils.importlib import import_module
from django.utils.log import getLogger
from django.utils import six
@ -250,7 +250,7 @@ def get_script_name(environ):
"""
from django.conf import settings
if settings.FORCE_SCRIPT_NAME is not None:
return force_unicode(settings.FORCE_SCRIPT_NAME)
return force_text(settings.FORCE_SCRIPT_NAME)
# If Apache's mod_rewrite had a whack at the URL, Apache set either
# SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any
@ -261,5 +261,5 @@ def get_script_name(environ):
if not script_url:
script_url = environ.get('REDIRECT_URL', '')
if script_url:
return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))])
return force_unicode(environ.get('SCRIPT_NAME', ''))
return force_text(script_url[:-len(environ.get('PATH_INFO', ''))])
return force_text(environ.get('SCRIPT_NAME', ''))

View File

@ -9,7 +9,7 @@ from django.core import signals
from django.core.handlers import base
from django.core.urlresolvers import set_script_prefix
from django.utils import datastructures
from django.utils.encoding import force_unicode, smart_str, iri_to_uri
from django.utils.encoding import force_text, smart_bytes, iri_to_uri
from django.utils.log import getLogger
logger = getLogger('django.request')
@ -127,7 +127,7 @@ class LimitedStream(object):
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
script_name = base.get_script_name(environ)
path_info = force_unicode(environ.get('PATH_INFO', '/'))
path_info = force_text(environ.get('PATH_INFO', '/'))
if not path_info or path_info == script_name:
# Sometimes PATH_INFO exists, but is empty (e.g. accessing
# the SCRIPT_NAME URL without a trailing slash). We really need to
@ -245,6 +245,6 @@ class WSGIHandler(base.BaseHandler):
status = '%s %s' % (response.status_code, status_text)
response_headers = [(str(k), str(v)) for k, v in response.items()]
for c in response.cookies.values():
response_headers.append((b'Set-Cookie', str(c.output(header=''))))
start_response(smart_str(status), response_headers)
response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
start_response(smart_bytes(status), response_headers)
return response

View File

@ -11,11 +11,10 @@ from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.header import Header
from email.utils import formatdate, getaddresses, formataddr, parseaddr
from io import BytesIO
from django.conf import settings
from django.core.mail.utils import DNS_NAME
from django.utils.encoding import smart_str, force_unicode
from django.utils.encoding import force_text
from django.utils import six
@ -79,38 +78,38 @@ ADDRESS_HEADERS = set([
def forbid_multi_line_headers(name, val, encoding):
"""Forbids multi-line headers, to prevent header injection."""
encoding = encoding or settings.DEFAULT_CHARSET
val = force_unicode(val)
val = force_text(val)
if '\n' in val or '\r' in val:
raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name))
try:
val = val.encode('ascii')
val.encode('ascii')
except UnicodeEncodeError:
if name.lower() in ADDRESS_HEADERS:
val = ', '.join(sanitize_address(addr, encoding)
for addr in getaddresses((val,)))
else:
val = str(Header(val, encoding))
val = Header(val, encoding).encode()
else:
if name.lower() == 'subject':
val = Header(val)
return smart_str(name), val
val = Header(val).encode()
return str(name), val
def sanitize_address(addr, encoding):
if isinstance(addr, six.string_types):
addr = parseaddr(force_unicode(addr))
addr = parseaddr(force_text(addr))
nm, addr = addr
nm = str(Header(nm, encoding))
nm = Header(nm, encoding).encode()
try:
addr = addr.encode('ascii')
addr.encode('ascii')
except UnicodeEncodeError: # IDN
if '@' in addr:
localpart, domain = addr.split('@', 1)
localpart = str(Header(localpart, encoding))
domain = domain.encode('idna')
domain = domain.encode('idna').decode('ascii')
addr = '@'.join([localpart, domain])
else:
addr = str(Header(addr, encoding))
addr = Header(addr, encoding).encode()
return formataddr((nm, addr))
@ -132,7 +131,7 @@ class SafeMIMEText(MIMEText):
This overrides the default as_string() implementation to not mangle
lines that begin with 'From '. See bug #13433 for details.
"""
fp = BytesIO()
fp = six.StringIO()
g = Generator(fp, mangle_from_ = False)
g.flatten(self, unixfrom=unixfrom)
return fp.getvalue()
@ -156,7 +155,7 @@ class SafeMIMEMultipart(MIMEMultipart):
This overrides the default as_string() implementation to not mangle
lines that begin with 'From '. See bug #13433 for details.
"""
fp = BytesIO()
fp = six.StringIO()
g = Generator(fp, mangle_from_ = False)
g.flatten(self, unixfrom=unixfrom)
return fp.getvalue()
@ -210,8 +209,7 @@ class EmailMessage(object):
def message(self):
encoding = self.encoding or settings.DEFAULT_CHARSET
msg = SafeMIMEText(smart_str(self.body, encoding),
self.content_subtype, encoding)
msg = SafeMIMEText(self.body, self.content_subtype, encoding)
msg = self._create_message(msg)
msg['Subject'] = self.subject
msg['From'] = self.extra_headers.get('From', self.from_email)
@ -293,7 +291,7 @@ class EmailMessage(object):
basetype, subtype = mimetype.split('/', 1)
if basetype == 'text':
encoding = self.encoding or settings.DEFAULT_CHARSET
attachment = SafeMIMEText(smart_str(content, encoding), subtype, encoding)
attachment = SafeMIMEText(content, subtype, encoding)
else:
# Encode non-text attachments with base64.
attachment = MIMEBase(basetype, subtype)
@ -313,9 +311,11 @@ class EmailMessage(object):
attachment = self._create_mime_attachment(content, mimetype)
if filename:
try:
filename = filename.encode('ascii')
filename.encode('ascii')
except UnicodeEncodeError:
filename = ('utf-8', '', filename.encode('utf-8'))
if not six.PY3:
filename = filename.encode('utf-8')
filename = ('utf-8', '', filename)
attachment.add_header('Content-Disposition', 'attachment',
filename=filename)
return attachment

View File

@ -8,6 +8,7 @@ import warnings
from django.core.management.base import BaseCommand, CommandError, handle_default_options
from django.core.management.color import color_style
from django.utils.importlib import import_module
from django.utils import six
# For backwards compatibility: get_version() used to be in this module.
from django import get_version
@ -228,7 +229,7 @@ class ManagementUtility(object):
"Available subcommands:",
]
commands_dict = collections.defaultdict(lambda: [])
for name, app in get_commands().iteritems():
for name, app in six.iteritems(get_commands()):
if app == 'django.core':
app = 'django'
else:
@ -294,7 +295,7 @@ class ManagementUtility(object):
except IndexError:
curr = ''
subcommands = get_commands().keys() + ['help']
subcommands = list(get_commands()) + ['help']
options = [('--help', None)]
# subcommand

View File

@ -6,7 +6,6 @@ be executed through ``django-admin.py`` or ``manage.py``).
import os
import sys
from io import BytesIO
from optparse import make_option, OptionParser
import traceback
@ -14,6 +13,7 @@ import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style
from django.utils.encoding import smart_str
from django.utils.six import StringIO
class CommandError(Exception):
@ -273,7 +273,7 @@ class BaseCommand(object):
"""
from django.core.management.validation import get_validation_errors
s = BytesIO()
s = StringIO()
num_errors = get_validation_errors(s, app)
if num_errors:
s.seek(0)

View File

@ -1,3 +1,5 @@
from __future__ import unicode_literals
import codecs
import os
import sys
@ -7,7 +9,7 @@ from django.core.management.base import BaseCommand, CommandError
def has_bom(fn):
with open(fn, 'rb') as f:
sample = f.read(4)
return sample[:3] == '\xef\xbb\xbf' or \
return sample[:3] == b'\xef\xbb\xbf' or \
sample.startswith(codecs.BOM_UTF16_LE) or \
sample.startswith(codecs.BOM_UTF16_BE)

View File

@ -4,7 +4,7 @@ from django.core.cache.backends.db import BaseDatabaseCache
from django.core.management.base import LabelCommand, CommandError
from django.db import connections, router, transaction, models, DEFAULT_DB_ALIAS
from django.db.utils import DatabaseError
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
class Command(LabelCommand):
@ -60,7 +60,7 @@ class Command(LabelCommand):
transaction.rollback_unless_managed(using=db)
raise CommandError(
"Cache table '%s' could not be created.\nThe error was: %s." %
(tablename, force_unicode(e)))
(tablename, force_text(e)))
for statement in index_output:
curs.execute(statement)
transaction.commit_unless_managed(using=db)

View File

@ -22,9 +22,7 @@ class Command(NoArgsCommand):
default_settings = module_to_dict(global_settings)
output = []
keys = user_settings.keys()
keys.sort()
for key in keys:
for key in sorted(user_settings.keys()):
if key not in default_settings:
output.append("%s = %s ###" % (key, user_settings[key]))
elif user_settings[key] != default_settings[key]:

View File

@ -7,6 +7,7 @@ from django.core.management.base import NoArgsCommand, CommandError
from django.core.management.color import no_style
from django.core.management.sql import sql_flush, emit_post_sync_signal
from django.utils.importlib import import_module
from django.utils.six.moves import input
class Command(NoArgsCommand):
@ -45,7 +46,7 @@ class Command(NoArgsCommand):
sql_list = sql_flush(self.style, connection, only_django=True, reset_sequences=reset_sequences)
if interactive:
confirm = raw_input("""You have requested a flush of the database.
confirm = input("""You have requested a flush of the database.
This will IRREVERSIBLY DESTROY all data currently in the %r database,
and return each table to the state it was in after syncdb.
Are you sure you want to do this?

View File

@ -14,7 +14,7 @@ from django.core.management.color import no_style
from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
IntegrityError, DatabaseError)
from django.db.models import get_apps
from django.utils.encoding import force_unicode
from django.utils.encoding import force_text
from itertools import product
try:
@ -189,7 +189,7 @@ class Command(BaseCommand):
'app_label': obj.object._meta.app_label,
'object_name': obj.object._meta.object_name,
'pk': obj.object.pk,
'error_msg': force_unicode(e)
'error_msg': force_text(e)
},)
raise

View File

@ -18,6 +18,7 @@ To add your own serializers, use the SERIALIZATION_MODULES setting::
from django.conf import settings
from django.utils import importlib
from django.utils import six
from django.core.serializers.base import SerializerDoesNotExist
# Built-in serializers
@ -75,12 +76,12 @@ def get_serializer(format):
def get_serializer_formats():
if not _serializers:
_load_serializers()
return _serializers.keys()
return list(_serializers)
def get_public_serializer_formats():
if not _serializers:
_load_serializers()
return [k for k, v in _serializers.iteritems() if not v.Serializer.internal_use_only]
return [k for k, v in six.iteritems(_serializers) if not v.Serializer.internal_use_only]
def get_deserializer(format):
if not _serializers:

View File

@ -5,7 +5,7 @@ Module for abstract serializer/unserializer base classes.
from io import BytesIO
from django.db import models
from django.utils.encoding import smart_unicode
from django.utils.encoding import smart_text
from django.utils import six
class SerializerDoesNotExist(KeyError):
@ -136,10 +136,12 @@ class Deserializer(object):
def __iter__(self):
return self
def next(self):
def __next__(self):
"""Iteration iterface -- return the next item in the stream"""
raise NotImplementedError
next = __next__ # Python 2 compatibility
class DeserializedObject(object):
"""
A deserialized model.

View File

@ -12,7 +12,7 @@ import json
from django.core.serializers.base import DeserializationError
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.python import Deserializer as PythonDeserializer
from django.utils.encoding import smart_str
from django.utils.encoding import smart_bytes
from django.utils import six
from django.utils.timezone import is_aware

View File

@ -8,7 +8,8 @@ from __future__ import unicode_literals
from django.conf import settings
from django.core.serializers import base
from django.db import models, DEFAULT_DB_ALIAS
from django.utils.encoding import smart_unicode, is_protected_type
from django.utils.encoding import smart_text, is_protected_type
from django.utils import six
class Serializer(base.Serializer):
"""
@ -33,8 +34,8 @@ class Serializer(base.Serializer):
def get_dump_object(self, obj):
return {
"pk": smart_unicode(obj._get_pk_val(), strings_only=True),
"model": smart_unicode(obj._meta),
"pk": smart_text(obj._get_pk_val(), strings_only=True),
"model": smart_text(obj._meta),
"fields": self._current
}
@ -64,7 +65,7 @@ class Serializer(base.Serializer):
if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'):
m2m_value = lambda value: value.natural_key()
else:
m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True)
m2m_value = lambda value: smart_text(value._get_pk_val(), strings_only=True)
self._current[field.name] = [m2m_value(related)
for related in getattr(obj, field.name).iterator()]
@ -87,9 +88,9 @@ def Deserializer(object_list, **options):
m2m_data = {}
# Handle each field
for (field_name, field_value) in d["fields"].iteritems():
for (field_name, field_value) in six.iteritems(d["fields"]):
if isinstance(field_value, str):
field_value = smart_unicode(field_value, options.get("encoding", settings.DEFAULT_CHARSET), strings_only=True)
field_value = smart_text(field_value, options.get("encoding", settings.DEFAULT_CHARSET), strings_only=True)
field = Model._meta.get_field(field_name)
@ -97,19 +98,19 @@ def Deserializer(object_list, **options):
if field.rel and isinstance(field.rel, models.ManyToManyRel):
if hasattr(field.rel.to._default_manager, 'get_by_natural_key'):
def m2m_convert(value):
if hasattr(value, '__iter__'):
if hasattr(value, '__iter__') and not isinstance(value, six.text_type):
return field.rel.to._default_manager.db_manager(db).get_by_natural_key(*value).pk
else:
return smart_unicode(field.rel.to._meta.pk.to_python(value))
return smart_text(field.rel.to._meta.pk.to_python(value))
else:
m2m_convert = lambda v: smart_unicode(field.rel.to._meta.pk.to_python(v))
m2m_convert = lambda v: smart_text(field.rel.to._meta.pk.to_python(v))
m2m_data[field.name] = [m2m_convert(pk) for pk in field_value]
# Handle FK fields
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
if field_value is not None:
if hasattr(field.rel.to._default_manager, 'get_by_natural_key'):
if hasattr(field_value, '__iter__'):
if hasattr(field_value, '__iter__') and not isinstance(field_value, six.text_type):
obj = field.rel.to._default_manager.db_manager(db).get_by_natural_key(*field_value)
value = getattr(obj, field.rel.field_name)
# If this is a natural foreign key to an object that

Some files were not shown because too many files have changed in this diff Show More