Merge branch 'master' of github.com:django/django into schema-alteration
Conflicts: django/db/backends/postgresql_psycopg2/base.py
This commit is contained in:
commit
4a2e80fff4
2
AUTHORS
2
AUTHORS
|
@ -30,6 +30,7 @@ The PRIMARY AUTHORS are (and/or have been):
|
|||
* Aymeric Augustin
|
||||
* Claude Paroz
|
||||
* Anssi Kääriäinen
|
||||
* Florian Apolloner
|
||||
|
||||
More information on the main contributors to Django can be found in
|
||||
docs/internals/committers.txt.
|
||||
|
@ -61,7 +62,6 @@ answer newbie questions, and generally made Django that much better:
|
|||
andy@jadedplanet.net
|
||||
Fabrice Aneche <akh@nobugware.com>
|
||||
ant9000@netwise.it
|
||||
Florian Apolloner <florian@apolloner.eu>
|
||||
arien <regexbot@gmail.com>
|
||||
David Ascher <http://ascher.ca/>
|
||||
atlithorn <atlithorn@gmail.com>
|
||||
|
|
|
@ -15,6 +15,7 @@ from django.conf import global_settings
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.functional import LazyObject, empty
|
||||
from django.utils import importlib
|
||||
from django.utils import six
|
||||
|
||||
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
||||
|
||||
|
@ -73,7 +74,7 @@ class BaseSettings(object):
|
|||
elif name == "ADMIN_MEDIA_PREFIX":
|
||||
warnings.warn("The ADMIN_MEDIA_PREFIX setting has been removed; "
|
||||
"use STATIC_URL instead.", DeprecationWarning)
|
||||
elif name == "ALLOWED_INCLUDE_ROOTS" and isinstance(value, basestring):
|
||||
elif name == "ALLOWED_INCLUDE_ROOTS" and isinstance(value, six.string_types):
|
||||
raise ValueError("The ALLOWED_INCLUDE_ROOTS setting must be set "
|
||||
"to a tuple, not a string.")
|
||||
object.__setattr__(self, name, value)
|
||||
|
@ -102,7 +103,10 @@ class Settings(BaseSettings):
|
|||
if setting == setting.upper():
|
||||
setting_value = getattr(mod, setting)
|
||||
if setting in tuple_settings and \
|
||||
isinstance(setting_value, basestring):
|
||||
isinstance(setting_value, six.string_types):
|
||||
warnings.warn("The %s setting must be a tuple. Please fix your "
|
||||
"settings, as auto-correction is now deprecated." % setting,
|
||||
PendingDeprecationWarning)
|
||||
setting_value = (setting_value,) # In case the user forgot the comma.
|
||||
setattr(self, setting, setting_value)
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.core.urlresolvers import (RegexURLPattern,
|
|||
RegexURLResolver, LocaleRegexURLResolver)
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.importlib import import_module
|
||||
from django.utils import six
|
||||
|
||||
|
||||
__all__ = ['handler403', 'handler404', 'handler500', 'include', 'patterns', 'url']
|
||||
|
@ -20,7 +21,7 @@ def include(arg, namespace=None, app_name=None):
|
|||
# No namespace hint - use manually provided namespace
|
||||
urlconf_module = arg
|
||||
|
||||
if isinstance(urlconf_module, basestring):
|
||||
if isinstance(urlconf_module, six.string_types):
|
||||
urlconf_module = import_module(urlconf_module)
|
||||
patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
|
||||
|
||||
|
@ -52,7 +53,7 @@ def url(regex, view, kwargs=None, name=None, prefix=''):
|
|||
urlconf_module, app_name, namespace = view
|
||||
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
|
||||
else:
|
||||
if isinstance(view, basestring):
|
||||
if isinstance(view, six.string_types):
|
||||
if not view:
|
||||
raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % regex)
|
||||
if prefix:
|
||||
|
|
|
@ -10,8 +10,9 @@ 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.html import escape, conditional_escape
|
||||
from django.utils.html import conditional_escape, format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils import six
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
|
||||
|
@ -49,7 +50,7 @@ class AdminForm(object):
|
|||
try:
|
||||
fieldset_name, fieldset_options = self.fieldsets[0]
|
||||
field_name = fieldset_options['fields'][0]
|
||||
if not isinstance(field_name, basestring):
|
||||
if not isinstance(field_name, six.string_types):
|
||||
field_name = field_name[0]
|
||||
return self.form[field_name]
|
||||
except (KeyError, IndexError):
|
||||
|
@ -163,11 +164,9 @@ class AdminReadonlyField(object):
|
|||
if not self.is_first:
|
||||
attrs["class"] = "inline"
|
||||
label = self.field['label']
|
||||
contents = capfirst(force_unicode(escape(label))) + ":"
|
||||
return mark_safe('<label%(attrs)s>%(contents)s</label>' % {
|
||||
"attrs": flatatt(attrs),
|
||||
"contents": contents,
|
||||
})
|
||||
return format_html('<label{0}>{1}:</label>',
|
||||
flatatt(attrs),
|
||||
capfirst(force_unicode(label)))
|
||||
|
||||
def contents(self):
|
||||
from django.contrib.admin.templatetags.admin_list import _boolean_icon
|
||||
|
@ -190,7 +189,7 @@ class AdminReadonlyField(object):
|
|||
if value is None:
|
||||
result_repr = EMPTY_CHANGELIST_VALUE
|
||||
elif isinstance(f.rel, ManyToManyRel):
|
||||
result_repr = ", ".join(map(unicode, value.all()))
|
||||
result_repr = ", ".join(map(six.text_type, value.all()))
|
||||
else:
|
||||
result_repr = display_for_field(value, f)
|
||||
return conditional_escape(result_repr)
|
||||
|
|
|
@ -6,7 +6,6 @@ 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.safestring import mark_safe
|
||||
|
||||
ADDITION = 1
|
||||
CHANGE = 2
|
||||
|
@ -66,5 +65,5 @@ class LogEntry(models.Model):
|
|||
This is relative to the Django admin index page.
|
||||
"""
|
||||
if self.content_type and self.object_id:
|
||||
return mark_safe("%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, quote(self.object_id)))
|
||||
return "%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, quote(self.object_id))
|
||||
return None
|
||||
|
|
|
@ -24,6 +24,7 @@ from django.utils.decorators import method_decorator
|
|||
from django.utils.datastructures import SortedDict
|
||||
from django.utils.html import escape, escapejs
|
||||
from django.utils.safestring import mark_safe
|
||||
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
|
||||
|
@ -57,9 +58,8 @@ FORMFIELD_FOR_DBFIELD_DEFAULTS = {
|
|||
|
||||
csrf_protect_m = method_decorator(csrf_protect)
|
||||
|
||||
class BaseModelAdmin(object):
|
||||
class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
|
||||
"""Functionality common to both ModelAdmin and InlineAdmin."""
|
||||
__metaclass__ = forms.MediaDefiningClass
|
||||
|
||||
raw_id_fields = ()
|
||||
fields = None
|
||||
|
@ -745,7 +745,7 @@ class ModelAdmin(BaseModelAdmin):
|
|||
'has_file_field': True, # FIXME - this should check if form or formsets have a FileField,
|
||||
'has_absolute_url': hasattr(self.model, 'get_absolute_url'),
|
||||
'ordered_objects': ordered_objects,
|
||||
'form_url': mark_safe(form_url),
|
||||
'form_url': form_url,
|
||||
'opts': opts,
|
||||
'content_type_id': ContentType.objects.get_for_model(self.model).id,
|
||||
'save_as': self.save_as,
|
||||
|
@ -998,7 +998,6 @@ class ModelAdmin(BaseModelAdmin):
|
|||
'title': _('Add %s') % force_unicode(opts.verbose_name),
|
||||
'adminform': adminForm,
|
||||
'is_popup': "_popup" in request.REQUEST,
|
||||
'show_delete': False,
|
||||
'media': media,
|
||||
'inline_admin_formsets': inline_admin_formsets,
|
||||
'errors': helpers.AdminErrorList(form, formsets),
|
||||
|
@ -1321,7 +1320,7 @@ class ModelAdmin(BaseModelAdmin):
|
|||
opts = model._meta
|
||||
app_label = opts.app_label
|
||||
action_list = LogEntry.objects.filter(
|
||||
object_id = object_id,
|
||||
object_id = unquote(object_id),
|
||||
content_type__id__exact = ContentType.objects.get_for_model(model).id
|
||||
).select_related().order_by('action_time')
|
||||
# If no history was found, see whether this object even exists.
|
||||
|
|
|
@ -231,7 +231,8 @@ class AdminSite(object):
|
|||
wrap(self.i18n_javascript, cacheable=True),
|
||||
name='jsi18n'),
|
||||
url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$',
|
||||
wrap(contenttype_views.shortcut)),
|
||||
wrap(contenttype_views.shortcut),
|
||||
name='view_on_site'),
|
||||
url(r'^(?P<app_label>\w+)/$',
|
||||
wrap(self.app_index),
|
||||
name='app_list')
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
text-align: left;
|
||||
}
|
||||
|
||||
.selector .selector-filter label {
|
||||
.selector .selector-filter label,
|
||||
.inline-group .aligned .selector .selector-filter label {
|
||||
width: 16px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
{% load admin_urls %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
{% url 'admin:jsi18n' as jsi18nurl %}
|
||||
<script type="text/javascript" src="{{ jsi18nurl|default:"../../../../jsi18n/" }}"></script>
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{% endblock %}
|
||||
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
|
||||
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
{% load admin_urls %}
|
||||
|
||||
{% block extrahead %}{{ block.super }}
|
||||
{% url 'admin:jsi18n' as jsi18nurl %}
|
||||
<script type="text/javascript" src="{{ jsi18nurl|default:"../../../jsi18n/" }}"></script>
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{{ media }}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -31,7 +30,7 @@
|
|||
<ul class="object-tools">
|
||||
{% block object-tools-items %}
|
||||
<li><a href="history/" class="historylink">{% trans "History" %}</a></li>
|
||||
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ original.pk }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
|
||||
{% if has_absolute_url %}<li><a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
{% endif %}{% endif %}
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
|
||||
{% endif %}
|
||||
{% if cl.formset or action_form %}
|
||||
{% url 'admin:jsi18n' as jsi18nurl %}
|
||||
<script type="text/javascript" src="{{ jsi18nurl|default:'../../jsi18n/' }}"></script>
|
||||
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
|
||||
{% endif %}
|
||||
{{ media.css }}
|
||||
{% if not actions_on_top and not actions_on_bottom %}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ app_label|capfirst }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst|escape }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}{{ object.pk }}">{{ object|truncatewords:"18" }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
|
||||
› {% trans 'Delete' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
{% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if forloop.last %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
|
||||
<h3><b>{{ inline_admin_formset.opts.verbose_name|title }}:</b> <span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %}#{{ forloop.counter }}{% endif %}</span>
|
||||
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.pk }}/">{% trans "View on site" %}</a>{% endif %}
|
||||
{% if inline_admin_form.show_url %}<a href="{% url 'admin:view_on_site' inline_admin_form.original_content_type_id inline_admin_form.original.pk %}">{% trans "View on site" %}</a>{% endif %}
|
||||
{% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
|
||||
</h3>
|
||||
{% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<td class="original">
|
||||
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
|
||||
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
|
||||
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.pk }}/">{% trans "View on site" %}</a>{% endif %}
|
||||
{% if inline_admin_form.show_url %}<a href="{% url 'admin:view_on_site' inline_admin_form.original_content_type_id inline_admin_form.original.pk %}">{% trans "View on site" %}</a>{% endif %}
|
||||
</p>{% endif %}
|
||||
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
||||
{{ inline_admin_form.fk_field.field }}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
|
||||
› <a href="{% url 'admin:app_list' app_label=app_label %}">{{ app_label|capfirst|escape }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ module_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk %}">{{ object|truncatewords:"18" }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
|
||||
› {% trans 'History' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -10,7 +10,7 @@ from django.contrib.admin.templatetags.admin_static import static
|
|||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db import models
|
||||
from django.utils import formats
|
||||
from django.utils.html import escape, conditional_escape
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext as _
|
||||
|
@ -31,9 +31,12 @@ def paginator_number(cl,i):
|
|||
if i == DOT:
|
||||
return '... '
|
||||
elif i == cl.page_num:
|
||||
return mark_safe('<span class="this-page">%d</span> ' % (i+1))
|
||||
return format_html('<span class="this-page">{0}</span> ', i+1)
|
||||
else:
|
||||
return mark_safe('<a href="%s"%s>%d</a> ' % (escape(cl.get_query_string({PAGE_VAR: i})), (i == cl.paginator.num_pages-1 and ' class="end"' or ''), i+1))
|
||||
return format_html('<a href="{0}"{1}>{2}</a> ',
|
||||
cl.get_query_string({PAGE_VAR: i}),
|
||||
mark_safe(' class="end"' if i == cl.paginator.num_pages-1 else ''),
|
||||
i+1)
|
||||
|
||||
@register.inclusion_tag('admin/pagination.html')
|
||||
def pagination(cl):
|
||||
|
@ -159,13 +162,14 @@ def result_headers(cl):
|
|||
"url_primary": cl.get_query_string({ORDER_VAR: '.'.join(o_list_primary)}),
|
||||
"url_remove": cl.get_query_string({ORDER_VAR: '.'.join(o_list_remove)}),
|
||||
"url_toggle": cl.get_query_string({ORDER_VAR: '.'.join(o_list_toggle)}),
|
||||
"class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')
|
||||
"class_attrib": format_html(' class="{0}"', ' '.join(th_classes))
|
||||
if th_classes else '',
|
||||
}
|
||||
|
||||
def _boolean_icon(field_val):
|
||||
icon_url = static('admin/img/icon-%s.gif' %
|
||||
{True: 'yes', False: 'no', None: 'unknown'}[field_val])
|
||||
return mark_safe('<img src="%s" alt="%s" />' % (icon_url, field_val))
|
||||
return format_html('<img src="{0}" alt="{1}" />', icon_url, field_val)
|
||||
|
||||
def items_for_result(cl, result, form):
|
||||
"""
|
||||
|
@ -182,7 +186,7 @@ def items_for_result(cl, result, form):
|
|||
else:
|
||||
if f is None:
|
||||
if field_name == 'action_checkbox':
|
||||
row_class = ' class="action-checkbox"'
|
||||
row_class = mark_safe(' class="action-checkbox"')
|
||||
allow_tags = getattr(attr, 'allow_tags', False)
|
||||
boolean = getattr(attr, 'boolean', False)
|
||||
if boolean:
|
||||
|
@ -190,23 +194,21 @@ def items_for_result(cl, result, form):
|
|||
result_repr = display_for_value(value, boolean)
|
||||
# Strip HTML tags in the resulting text, except if the
|
||||
# function has an "allow_tags" attribute set to True.
|
||||
if not allow_tags:
|
||||
result_repr = escape(result_repr)
|
||||
else:
|
||||
if allow_tags:
|
||||
result_repr = mark_safe(result_repr)
|
||||
if isinstance(value, (datetime.date, datetime.time)):
|
||||
row_class = ' class="nowrap"'
|
||||
row_class = mark_safe(' class="nowrap"')
|
||||
else:
|
||||
if isinstance(f.rel, models.ManyToOneRel):
|
||||
field_val = getattr(result, f.name)
|
||||
if field_val is None:
|
||||
result_repr = EMPTY_CHANGELIST_VALUE
|
||||
else:
|
||||
result_repr = escape(field_val)
|
||||
result_repr = field_val
|
||||
else:
|
||||
result_repr = display_for_field(value, f)
|
||||
if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
|
||||
row_class = ' class="nowrap"'
|
||||
row_class = mark_safe(' class="nowrap"')
|
||||
if force_unicode(result_repr) == '':
|
||||
result_repr = mark_safe(' ')
|
||||
# If list_display_links not defined, add the link tag to the first field
|
||||
|
@ -222,8 +224,14 @@ def items_for_result(cl, result, form):
|
|||
attr = pk
|
||||
value = result.serializable_value(attr)
|
||||
result_id = repr(force_unicode(value))[1:]
|
||||
yield mark_safe('<%s%s><a href="%s"%s>%s</a></%s>' % \
|
||||
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), conditional_escape(result_repr), table_tag))
|
||||
yield format_html('<{0}{1}><a href="{2}"{3}>{4}</a></{5}>',
|
||||
table_tag,
|
||||
row_class,
|
||||
url,
|
||||
format_html(' onclick="opener.dismissRelatedLookupPopup(window, {0}); return false;"', result_id)
|
||||
if cl.is_popup else '',
|
||||
result_repr,
|
||||
table_tag)
|
||||
else:
|
||||
# By default the fields come from ModelAdmin.list_editable, but if we pull
|
||||
# the fields out of the form instead of list_editable custom admins
|
||||
|
@ -233,11 +241,9 @@ def items_for_result(cl, result, form):
|
|||
form[cl.model._meta.pk.name].is_hidden)):
|
||||
bf = form[field_name]
|
||||
result_repr = mark_safe(force_unicode(bf.errors) + force_unicode(bf))
|
||||
else:
|
||||
result_repr = conditional_escape(result_repr)
|
||||
yield mark_safe('<td%s>%s</td>' % (row_class, result_repr))
|
||||
yield format_html('<td{0}>{1}</td>', row_class, result_repr)
|
||||
if form and not form[cl.model._meta.pk.name].is_hidden:
|
||||
yield mark_safe('<td>%s</td>' % force_unicode(form[cl.model._meta.pk.name]))
|
||||
yield format_html('<td>{0}</td>', force_unicode(form[cl.model._meta.pk.name]))
|
||||
|
||||
class ResultList(list):
|
||||
# Wrapper class used to return items in a list_editable
|
||||
|
|
|
@ -32,7 +32,7 @@ def submit_row(context):
|
|||
'onclick_attrib': (opts.get_ordered_objects() and change
|
||||
and 'onclick="submitOrderForm();"' or ''),
|
||||
'show_delete_link': (not is_popup and context['has_delete_permission']
|
||||
and (change or context['show_delete'])),
|
||||
and change and context.get('show_delete', True)),
|
||||
'show_save_as_new': not is_popup and change and save_as,
|
||||
'show_save_and_add_another': context['has_add_permission'] and
|
||||
not is_popup and (not save_as or context['add']),
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
from django.core.urlresolvers import reverse, NoReverseMatch
|
||||
from django.core.urlresolvers import reverse
|
||||
from django import template
|
||||
from django.contrib.admin.util import quote
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def admin_urlname(value, arg):
|
||||
return 'admin:%s_%s_%s' % (value.app_label, value.module_name, arg)
|
||||
|
||||
|
||||
@register.filter
|
||||
def admin_urlquote(value):
|
||||
return quote(value)
|
||||
|
|
|
@ -9,11 +9,11 @@ from django.db.models.deletion import Collector
|
|||
from django.db.models.related import RelatedObject
|
||||
from django.forms.forms import pretty_name
|
||||
from django.utils import formats
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
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 import six
|
||||
from django.utils.translation import ungettext
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
|
@ -52,7 +52,7 @@ def quote(s):
|
|||
quoting is slightly different so that it doesn't get automatically
|
||||
unquoted by the Web browser.
|
||||
"""
|
||||
if not isinstance(s, basestring):
|
||||
if not isinstance(s, six.string_types):
|
||||
return s
|
||||
res = list(s)
|
||||
for i in range(len(res)):
|
||||
|
@ -124,10 +124,10 @@ def get_deleted_objects(objs, opts, user, admin_site, using):
|
|||
if not user.has_perm(p):
|
||||
perms_needed.add(opts.verbose_name)
|
||||
# Display a link to the admin page.
|
||||
return mark_safe('%s: <a href="%s">%s</a>' %
|
||||
(escape(capfirst(opts.verbose_name)),
|
||||
return format_html('{0}: <a href="{1}">{2}</a>',
|
||||
capfirst(opts.verbose_name),
|
||||
admin_url,
|
||||
escape(obj)))
|
||||
obj)
|
||||
else:
|
||||
# Don't display link to edit, because it either has no
|
||||
# admin or is edited inline.
|
||||
|
@ -275,10 +275,10 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
|
|||
except models.FieldDoesNotExist:
|
||||
if name == "__unicode__":
|
||||
label = force_unicode(model._meta.verbose_name)
|
||||
attr = unicode
|
||||
attr = six.text_type
|
||||
elif name == "__str__":
|
||||
label = smart_str(model._meta.verbose_name)
|
||||
attr = str
|
||||
attr = bytes
|
||||
else:
|
||||
if callable(name):
|
||||
attr = name
|
||||
|
@ -350,7 +350,7 @@ def display_for_value(value, boolean=False):
|
|||
return formats.localize(timezone.template_localtime(value))
|
||||
elif isinstance(value, (datetime.date, datetime.time)):
|
||||
return formats.localize(value)
|
||||
elif isinstance(value, (decimal.Decimal, float, int, long)):
|
||||
elif isinstance(value, six.integer_types + (decimal.Decimal, float)):
|
||||
return formats.number_format(value)
|
||||
else:
|
||||
return smart_unicode(value)
|
||||
|
|
|
@ -10,11 +10,12 @@ from django.contrib.admin.templatetags.admin_static import static
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.forms.widgets import RadioFieldRenderer
|
||||
from django.forms.util import flatatt
|
||||
from django.utils.html import escape
|
||||
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 import six
|
||||
|
||||
|
||||
class FilteredSelectMultiple(forms.SelectMultiple):
|
||||
|
@ -85,16 +86,17 @@ class AdminSplitDateTime(forms.SplitDateTimeWidget):
|
|||
forms.MultiWidget.__init__(self, widgets, attrs)
|
||||
|
||||
def format_output(self, rendered_widgets):
|
||||
return mark_safe('<p class="datetime">%s %s<br />%s %s</p>' % \
|
||||
(_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
|
||||
return format_html('<p class="datetime">{0} {1}<br />{2} {3}</p>',
|
||||
_('Date:'), rendered_widgets[0],
|
||||
_('Time:'), rendered_widgets[1])
|
||||
|
||||
class AdminRadioFieldRenderer(RadioFieldRenderer):
|
||||
def render(self):
|
||||
"""Outputs a <ul> for this set of radio fields."""
|
||||
return mark_safe('<ul%s>\n%s\n</ul>' % (
|
||||
return format_html('<ul{0}>\n{1}\n</ul>',
|
||||
flatatt(self.attrs),
|
||||
'\n'.join(['<li>%s</li>' % force_unicode(w) for w in self]))
|
||||
)
|
||||
format_html_join('\n', '<li>{0}</li>',
|
||||
((force_unicode(w),) for w in self)))
|
||||
|
||||
class AdminRadioSelect(forms.RadioSelect):
|
||||
renderer = AdminRadioFieldRenderer
|
||||
|
@ -120,7 +122,7 @@ def url_params_from_lookup_dict(lookups):
|
|||
# See django.db.fields.BooleanField.get_prep_lookup
|
||||
v = ('0', '1')[v]
|
||||
else:
|
||||
v = unicode(v)
|
||||
v = six.text_type(v)
|
||||
items.append((k, v))
|
||||
params.update(dict(items))
|
||||
return params
|
||||
|
|
|
@ -22,7 +22,7 @@ your computer is "internal").</p>
|
|||
{% endblocktrans %}
|
||||
|
||||
<div id="content-main">
|
||||
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('HEAD',location.href,false);x.send(null);try{view=x.getResponseHeader('x-view');}catch(e){alert('No view found for this page');return;}if(view=='undefined'){alert('No view found for this page');}document.location='{{ admin_url }}doc/views/'+view+'/';})()">{% trans "Documentation for this page" %}</a></h3>
|
||||
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('HEAD',location.href,false);x.send(null);try{view=x.getResponseHeader('x-view');}catch(e){alert('No view found for this page');return;}if(view=='undefined'){alert('No view found for this page');}document.location='{{ admin_url|escapejs }}doc/views/'+view+'/';})()">{% trans "Documentation for this page" %}</a></h3>
|
||||
<p>{% trans "Jumps you from any page to the documentation for the view that generates that page." %}</p>
|
||||
|
||||
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{type=x.getResponseHeader('x-object-type');id=x.getResponseHeader('x-object-id');}catch(e){type='(none)';id='(none)';}d=document;b=d.body;e=d.createElement('div');e.id='xxxhhh';s=e.style;s.position='absolute';s.left='10px';s.top='10px';s.font='10px monospace';s.border='1px black solid';s.padding='4px';s.backgroundColor='#eee';e.appendChild(d.createTextNode('Type: '+type));e.appendChild(d.createElement('br'));e.appendChild(d.createTextNode('ID: '+id));e.appendChild(d.createElement('br'));l=d.createElement('a');l.href='#';l.onclick=function(){b.removeChild(e);};l.appendChild(d.createTextNode('[close]'));l.style.textDecoration='none';e.appendChild(l);b.appendChild(e);})();">{% trans "Show object ID" %}</a></h3>
|
||||
|
|
|
@ -37,7 +37,7 @@ def bookmarklets(request):
|
|||
admin_root = urlresolvers.reverse('admin:index')
|
||||
return render_to_response('admin_doc/bookmarklets.html', {
|
||||
'root_path': admin_root,
|
||||
'admin_url': mark_safe("%s://%s%s" % (request.is_secure() and 'https' or 'http', request.get_host(), admin_root)),
|
||||
'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', request.get_host(), admin_root),
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
@staff_member_required
|
||||
|
|
|
@ -134,7 +134,7 @@ class UserAdmin(admin.ModelAdmin):
|
|||
context = {
|
||||
'title': _('Change password: %s') % escape(user.username),
|
||||
'adminForm': adminForm,
|
||||
'form_url': mark_safe(form_url),
|
||||
'form_url': form_url,
|
||||
'form': form,
|
||||
'is_popup': '_popup' in request.REQUEST,
|
||||
'add': True,
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import urlparse
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
except ImportError: # Python 2
|
||||
from urlparse import urlparse
|
||||
from functools import wraps
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
|
@ -21,9 +24,8 @@ def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIE
|
|||
path = request.build_absolute_uri()
|
||||
# If the login url is the same scheme and net location then just
|
||||
# use the path as the "next" url.
|
||||
login_scheme, login_netloc = urlparse.urlparse(login_url or
|
||||
settings.LOGIN_URL)[:2]
|
||||
current_scheme, current_netloc = urlparse.urlparse(path)[:2]
|
||||
login_scheme, login_netloc = urlparse(login_url or settings.LOGIN_URL)[:2]
|
||||
current_scheme, current_netloc = urlparse(path)[:2]
|
||||
if ((not login_scheme or login_scheme == current_scheme) and
|
||||
(not login_netloc or login_netloc == current_netloc)):
|
||||
path = request.get_full_path()
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django import forms
|
||||
from django.forms.util import flatatt
|
||||
from django.template import loader
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.utils.html import format_html, format_html_join
|
||||
from django.utils.http import int_to_base36
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
@ -11,6 +15,7 @@ from django.contrib.auth.hashers import UNUSABLE_PASSWORD, is_password_usable, i
|
|||
from django.contrib.auth.tokens import default_token_generator
|
||||
from django.contrib.sites.models import get_current_site
|
||||
|
||||
|
||||
UNMASKED_DIGITS_TO_SHOW = 6
|
||||
|
||||
mask_password = lambda p: "%s%s" % (p[:UNMASKED_DIGITS_TO_SHOW], "*" * max(len(p) - UNMASKED_DIGITS_TO_SHOW, 0))
|
||||
|
@ -28,13 +33,15 @@ class ReadOnlyPasswordHashWidget(forms.Widget):
|
|||
try:
|
||||
hasher = identify_hasher(encoded)
|
||||
except ValueError:
|
||||
summary = "<strong>Invalid password format or unknown hashing algorithm.</strong>"
|
||||
summary = mark_safe("<strong>Invalid password format or unknown hashing algorithm.</strong>")
|
||||
else:
|
||||
summary = ""
|
||||
for key, value in hasher.safe_summary(encoded).iteritems():
|
||||
summary += "<strong>%(key)s</strong>: %(value)s " % {"key": ugettext(key), "value": value}
|
||||
summary = format_html_join('',
|
||||
"<strong>{0}</strong>: {1} ",
|
||||
((ugettext(key), value)
|
||||
for key, value in hasher.safe_summary(encoded).items())
|
||||
)
|
||||
|
||||
return mark_safe("<div%(attrs)s>%(summary)s</div>" % {"attrs": flatatt(final_attrs), "summary": summary})
|
||||
return format_html("<div{0}>{1}</div>", flatatt(final_attrs), summary)
|
||||
|
||||
|
||||
class ReadOnlyPasswordHashField(forms.Field):
|
||||
|
@ -288,8 +295,11 @@ class PasswordChangeForm(SetPasswordForm):
|
|||
raise forms.ValidationError(
|
||||
self.error_messages['password_incorrect'])
|
||||
return old_password
|
||||
PasswordChangeForm.base_fields.keyOrder = ['old_password', 'new_password1',
|
||||
'new_password2']
|
||||
|
||||
PasswordChangeForm.base_fields = SortedDict([
|
||||
(k, PasswordChangeForm.base_fields[k])
|
||||
for k in ['old_password', 'new_password1', 'new_password2']
|
||||
])
|
||||
|
||||
|
||||
class AdminPasswordChangeForm(forms.Form):
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import urllib
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.mail import send_mail
|
||||
from django.db import models
|
||||
from django.db.models.manager import EmptyManager
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.http import urlquote
|
||||
from django.utils import six
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils import timezone
|
||||
|
||||
|
@ -79,9 +78,9 @@ class Permission(models.Model):
|
|||
|
||||
def __unicode__(self):
|
||||
return "%s | %s | %s" % (
|
||||
unicode(self.content_type.app_label),
|
||||
unicode(self.content_type),
|
||||
unicode(self.name))
|
||||
six.text_type(self.content_type.app_label),
|
||||
six.text_type(self.content_type),
|
||||
six.text_type(self.name))
|
||||
|
||||
def natural_key(self):
|
||||
return (self.codename,) + self.content_type.natural_key()
|
||||
|
@ -267,7 +266,7 @@ class User(models.Model):
|
|||
return (self.username,)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return "/users/%s/" % urllib.quote(smart_str(self.username))
|
||||
return "/users/%s/" % urlquote(self.username)
|
||||
|
||||
def is_anonymous(self):
|
||||
"""
|
||||
|
@ -300,7 +299,7 @@ class User(models.Model):
|
|||
"""
|
||||
def setter(raw_password):
|
||||
self.set_password(raw_password)
|
||||
self.save()
|
||||
self.save(update_fields=["password"])
|
||||
return check_password(raw_password, self.password, setter)
|
||||
|
||||
def set_unusable_password(self):
|
||||
|
@ -421,7 +420,7 @@ class AnonymousUser(object):
|
|||
return 'AnonymousUser'
|
||||
|
||||
def __str__(self):
|
||||
return unicode(self).encode('utf-8')
|
||||
return six.text_type(self).encode('utf-8')
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from django.test import TestCase
|
||||
from django.utils.unittest import skipUnless
|
||||
from django.contrib.auth.models import User, AnonymousUser
|
||||
from django.core.management import call_command
|
||||
from StringIO import StringIO
|
||||
from django.test import TestCase
|
||||
from django.utils.six import StringIO
|
||||
from django.utils.unittest import skipUnless
|
||||
|
||||
try:
|
||||
import crypt as crypt_module
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from StringIO import StringIO
|
||||
|
||||
from django.contrib.auth import models, management
|
||||
from django.contrib.auth.management.commands import changepassword
|
||||
from django.core.management.base import CommandError
|
||||
from django.test import TestCase
|
||||
from django.utils.six import StringIO
|
||||
|
||||
|
||||
class GetDefaultUsernameTestCase(TestCase):
|
||||
|
|
|
@ -5,39 +5,29 @@ from django.contrib.auth.models import (Group, User,
|
|||
SiteProfileNotAvailable, UserManager)
|
||||
|
||||
|
||||
@override_settings(USE_TZ=False)
|
||||
@override_settings(USE_TZ=False, AUTH_PROFILE_MODULE='')
|
||||
class ProfileTestCase(TestCase):
|
||||
fixtures = ['authtestdata.json']
|
||||
|
||||
def setUp(self):
|
||||
"""Backs up the AUTH_PROFILE_MODULE"""
|
||||
self.old_AUTH_PROFILE_MODULE = getattr(settings,
|
||||
'AUTH_PROFILE_MODULE', None)
|
||||
|
||||
def tearDown(self):
|
||||
"""Restores the AUTH_PROFILE_MODULE -- if it was not set it is deleted,
|
||||
otherwise the old value is restored"""
|
||||
if self.old_AUTH_PROFILE_MODULE is None and \
|
||||
hasattr(settings, 'AUTH_PROFILE_MODULE'):
|
||||
del settings.AUTH_PROFILE_MODULE
|
||||
|
||||
if self.old_AUTH_PROFILE_MODULE is not None:
|
||||
settings.AUTH_PROFILE_MODULE = self.old_AUTH_PROFILE_MODULE
|
||||
|
||||
def test_site_profile_not_available(self):
|
||||
user = User.objects.create(username='testclient')
|
||||
|
||||
# calling get_profile without AUTH_PROFILE_MODULE set
|
||||
if hasattr(settings, 'AUTH_PROFILE_MODULE'):
|
||||
del settings.AUTH_PROFILE_MODULE
|
||||
user = User.objects.get(username='testclient')
|
||||
self.assertRaises(SiteProfileNotAvailable, user.get_profile)
|
||||
with self.assertRaisesRegexp(SiteProfileNotAvailable,
|
||||
"You need to set AUTH_PROFILE_MODULE in your project"):
|
||||
user.get_profile()
|
||||
|
||||
# Bad syntax in AUTH_PROFILE_MODULE:
|
||||
settings.AUTH_PROFILE_MODULE = 'foobar'
|
||||
self.assertRaises(SiteProfileNotAvailable, user.get_profile)
|
||||
with self.assertRaisesRegexp(SiteProfileNotAvailable,
|
||||
"app_label and model_name should be separated by a dot"):
|
||||
user.get_profile()
|
||||
|
||||
# module that doesn't exist
|
||||
settings.AUTH_PROFILE_MODULE = 'foo.bar'
|
||||
self.assertRaises(SiteProfileNotAvailable, user.get_profile)
|
||||
with self.assertRaisesRegexp(SiteProfileNotAvailable,
|
||||
"Unable to load the profile model"):
|
||||
user.get_profile()
|
||||
|
||||
|
||||
@override_settings(USE_TZ=False)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
import re
|
||||
import urllib
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site, RequestSite
|
||||
|
@ -10,6 +9,7 @@ from django.core.urlresolvers import reverse, NoReverseMatch
|
|||
from django.http import QueryDict
|
||||
from django.utils.encoding import force_unicode
|
||||
from django.utils.html import escape
|
||||
from django.utils.http import urlquote
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
|
||||
|
@ -256,7 +256,7 @@ class LoginTest(AuthViewsTestCase):
|
|||
nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
|
||||
'url': login_url,
|
||||
'next': REDIRECT_FIELD_NAME,
|
||||
'bad_url': urllib.quote(bad_url),
|
||||
'bad_url': urlquote(bad_url),
|
||||
}
|
||||
response = self.client.post(nasty_url, {
|
||||
'username': 'testclient',
|
||||
|
@ -277,7 +277,7 @@ class LoginTest(AuthViewsTestCase):
|
|||
safe_url = '%(url)s?%(next)s=%(good_url)s' % {
|
||||
'url': login_url,
|
||||
'next': REDIRECT_FIELD_NAME,
|
||||
'good_url': urllib.quote(good_url),
|
||||
'good_url': urlquote(good_url),
|
||||
}
|
||||
response = self.client.post(safe_url, {
|
||||
'username': 'testclient',
|
||||
|
@ -412,7 +412,7 @@ class LogoutTest(AuthViewsTestCase):
|
|||
nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
|
||||
'url': logout_url,
|
||||
'next': REDIRECT_FIELD_NAME,
|
||||
'bad_url': urllib.quote(bad_url),
|
||||
'bad_url': urlquote(bad_url),
|
||||
}
|
||||
self.login()
|
||||
response = self.client.get(nasty_url)
|
||||
|
@ -432,7 +432,7 @@ class LogoutTest(AuthViewsTestCase):
|
|||
safe_url = '%(url)s?%(next)s=%(good_url)s' % {
|
||||
'url': logout_url,
|
||||
'next': REDIRECT_FIELD_NAME,
|
||||
'good_url': urllib.quote(good_url),
|
||||
'good_url': urlquote(good_url),
|
||||
}
|
||||
self.login()
|
||||
response = self.client.get(safe_url)
|
||||
|
|
|
@ -2,6 +2,7 @@ from datetime import date
|
|||
from django.conf import settings
|
||||
from django.utils.http import int_to_base36, base36_to_int
|
||||
from django.utils.crypto import constant_time_compare, salted_hmac
|
||||
from django.utils import six
|
||||
|
||||
class PasswordResetTokenGenerator(object):
|
||||
"""
|
||||
|
@ -56,8 +57,8 @@ class PasswordResetTokenGenerator(object):
|
|||
# Ensure results are consistent across DB backends
|
||||
login_timestamp = user.last_login.replace(microsecond=0, tzinfo=None)
|
||||
|
||||
value = (unicode(user.id) + user.password +
|
||||
unicode(login_timestamp) + unicode(timestamp))
|
||||
value = (six.text_type(user.id) + user.password +
|
||||
six.text_type(login_timestamp) + six.text_type(timestamp))
|
||||
hash = salted_hmac(key_salt, value).hexdigest()[::2]
|
||||
return "%s-%s" % (ts_b36, hash)
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import urlparse
|
||||
try:
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
except ImportError: # Python 2
|
||||
from urlparse import urlparse, urlunparse
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
|
@ -34,7 +37,7 @@ def login(request, template_name='registration/login.html',
|
|||
if request.method == "POST":
|
||||
form = authentication_form(data=request.POST)
|
||||
if form.is_valid():
|
||||
netloc = urlparse.urlparse(redirect_to)[1]
|
||||
netloc = urlparse(redirect_to)[1]
|
||||
|
||||
# Use default setting if redirect_to is empty
|
||||
if not redirect_to:
|
||||
|
@ -80,7 +83,7 @@ def logout(request, next_page=None,
|
|||
auth_logout(request)
|
||||
redirect_to = request.REQUEST.get(redirect_field_name, '')
|
||||
if redirect_to:
|
||||
netloc = urlparse.urlparse(redirect_to)[1]
|
||||
netloc = urlparse(redirect_to)[1]
|
||||
# Security check -- don't allow redirection to a different host.
|
||||
if not (netloc and netloc != request.get_host()):
|
||||
return HttpResponseRedirect(redirect_to)
|
||||
|
@ -116,13 +119,13 @@ def redirect_to_login(next, login_url=None,
|
|||
if not login_url:
|
||||
login_url = settings.LOGIN_URL
|
||||
|
||||
login_url_parts = list(urlparse.urlparse(login_url))
|
||||
login_url_parts = list(urlparse(login_url))
|
||||
if redirect_field_name:
|
||||
querystring = QueryDict(login_url_parts[4], mutable=True)
|
||||
querystring[redirect_field_name] = next
|
||||
login_url_parts[4] = querystring.urlencode(safe='/')
|
||||
|
||||
return HttpResponseRedirect(urlparse.urlunparse(login_url_parts))
|
||||
return HttpResponseRedirect(urlunparse(login_url_parts))
|
||||
|
||||
# 4 views for password reset:
|
||||
# - password_reset sends the mail
|
||||
|
|
|
@ -17,7 +17,7 @@ def flag(request, comment_id, next=None):
|
|||
"""
|
||||
Flags a comment. Confirmation on GET, action on POST.
|
||||
|
||||
Templates: `comments/flag.html`,
|
||||
Templates: :template:`comments/flag.html`,
|
||||
Context:
|
||||
comment
|
||||
the flagged `comments.comment` object
|
||||
|
@ -43,7 +43,7 @@ def delete(request, comment_id, next=None):
|
|||
Deletes a comment. Confirmation on GET, action on POST. Requires the "can
|
||||
moderate comments" permission.
|
||||
|
||||
Templates: `comments/delete.html`,
|
||||
Templates: :template:`comments/delete.html`,
|
||||
Context:
|
||||
comment
|
||||
the flagged `comments.comment` object
|
||||
|
@ -70,7 +70,7 @@ def approve(request, comment_id, next=None):
|
|||
Approve a comment (that is, mark it as public and non-removed). Confirmation
|
||||
on GET, action on POST. Requires the "can moderate comments" permission.
|
||||
|
||||
Templates: `comments/approve.html`,
|
||||
Templates: :template:`comments/approve.html`,
|
||||
Context:
|
||||
comment
|
||||
the `comments.comment` object for approval
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
A few bits of helper functions for comment views.
|
||||
"""
|
||||
|
||||
import urllib
|
||||
import textwrap
|
||||
try:
|
||||
from urllib.parse import urlencode
|
||||
except ImportError: # Python 2
|
||||
from urllib import urlencode
|
||||
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.core import urlresolvers
|
||||
from django.shortcuts import render_to_response
|
||||
|
@ -33,7 +37,7 @@ def next_redirect(data, default, default_view, **get_kwargs):
|
|||
anchor = ''
|
||||
|
||||
joiner = ('?' in next) and '&' or '?'
|
||||
next += joiner + urllib.urlencode(get_kwargs) + anchor
|
||||
next += joiner + urlencode(get_kwargs) + anchor
|
||||
return HttpResponseRedirect(next)
|
||||
|
||||
def confirmation_view(template, doc="Display a confirmation view."):
|
||||
|
@ -56,7 +60,7 @@ def confirmation_view(template, doc="Display a confirmation view."):
|
|||
confirmed.__doc__ = textwrap.dedent("""\
|
||||
%s
|
||||
|
||||
Templates: `%s``
|
||||
Templates: :template:`%s``
|
||||
Context:
|
||||
comment
|
||||
The posted comment
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import urllib
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.contenttypes.views import shortcut
|
||||
from django.contrib.sites.models import Site
|
||||
from django.http import HttpRequest, Http404
|
||||
from django.test import TestCase
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.http import urlquote
|
||||
from django.utils import six
|
||||
|
||||
|
||||
class ConcreteModel(models.Model):
|
||||
|
@ -35,7 +34,7 @@ class FooWithUrl(FooWithoutUrl):
|
|||
"""
|
||||
|
||||
def get_absolute_url(self):
|
||||
return "/users/%s/" % urllib.quote(smart_str(self.name))
|
||||
return "/users/%s/" % urlquote(self.name)
|
||||
|
||||
class FooWithBrokenAbsoluteUrl(FooWithoutUrl):
|
||||
"""
|
||||
|
@ -271,4 +270,4 @@ class ContentTypesTests(TestCase):
|
|||
app_label = 'contenttypes',
|
||||
model = 'OldModel',
|
||||
)
|
||||
self.assertEqual(unicode(ct), 'Old model')
|
||||
self.assertEqual(six.text_type(ct), 'Old model')
|
||||
|
|
|
@ -8,7 +8,6 @@ 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.safestring import mark_safe
|
||||
from django.db.models.query import QuerySet
|
||||
|
||||
EMPTY_VALUE = '(None)'
|
||||
|
@ -30,7 +29,7 @@ class EasyModel(object):
|
|||
return self.site.registry[self.model]
|
||||
|
||||
def url(self):
|
||||
return mark_safe('%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name))
|
||||
return '%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name)
|
||||
|
||||
def objects(self, **kwargs):
|
||||
return self.get_query_set().filter(**kwargs)
|
||||
|
@ -70,9 +69,9 @@ class EasyField(object):
|
|||
|
||||
def url(self):
|
||||
if self.field.choices:
|
||||
return mark_safe('%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name))
|
||||
return '%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name)
|
||||
elif self.field.rel:
|
||||
return mark_safe('%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name))
|
||||
return '%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name)
|
||||
|
||||
class EasyChoice(object):
|
||||
def __init__(self, easy_model, field, value, label):
|
||||
|
@ -83,7 +82,7 @@ class EasyChoice(object):
|
|||
return smart_str('<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
|
||||
|
||||
def url(self):
|
||||
return mark_safe('%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)))
|
||||
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))
|
||||
|
||||
class EasyInstance(object):
|
||||
def __init__(self, easy_model, instance):
|
||||
|
@ -105,7 +104,7 @@ class EasyInstance(object):
|
|||
return self.instance._get_pk_val()
|
||||
|
||||
def url(self):
|
||||
return mark_safe('%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk())))
|
||||
return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk()))
|
||||
|
||||
def fields(self):
|
||||
"""
|
||||
|
@ -187,14 +186,14 @@ class EasyInstanceField(object):
|
|||
for value in self.values():
|
||||
if value is None:
|
||||
continue
|
||||
url = mark_safe('%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())))
|
||||
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))
|
||||
else:
|
||||
lst = [(value, None) for value in self.values()]
|
||||
elif self.field.choices:
|
||||
lst = []
|
||||
for value in self.values():
|
||||
url = mark_safe('%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)))
|
||||
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]
|
||||
|
|
|
@ -5,9 +5,9 @@ from django.db import models
|
|||
from django.contrib.databrowse.datastructures import EasyModel
|
||||
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.safestring import mark_safe
|
||||
from django.views.generic import dates
|
||||
from django.utils import datetime_safe
|
||||
|
||||
|
@ -64,18 +64,19 @@ class CalendarPlugin(DatabrowsePlugin):
|
|||
fields = self.field_dict(model)
|
||||
if not fields:
|
||||
return ''
|
||||
return mark_safe('<p class="filter"><strong>View calendar by:</strong> %s</p>' % \
|
||||
', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()]))
|
||||
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())))
|
||||
|
||||
def urls(self, plugin_name, easy_instance_field):
|
||||
if isinstance(easy_instance_field.field, models.DateField):
|
||||
d = easy_instance_field.raw_value
|
||||
return [mark_safe('%s%s/%s/%s/%s/%s/' % (
|
||||
return ['%s%s/%s/%s/%s/%s/' % (
|
||||
easy_instance_field.model.url(),
|
||||
plugin_name, easy_instance_field.field.name,
|
||||
str(d.year),
|
||||
datetime_safe.new_date(d).strftime('%b').lower(),
|
||||
d.day))]
|
||||
d.day)]
|
||||
|
||||
def model_view(self, request, model_databrowse, url):
|
||||
self.model, self.site = model_databrowse.model, model_databrowse.site
|
||||
|
|
|
@ -5,10 +5,11 @@ from django.db import models
|
|||
from django.contrib.databrowse.datastructures import EasyModel
|
||||
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.http import urlquote
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.encoding import smart_str, force_unicode
|
||||
from django.utils.safestring import mark_safe
|
||||
import urllib
|
||||
from django.utils.encoding import force_unicode
|
||||
|
||||
|
||||
class FieldChoicePlugin(DatabrowsePlugin):
|
||||
def __init__(self, field_filter=None):
|
||||
|
@ -32,16 +33,16 @@ class FieldChoicePlugin(DatabrowsePlugin):
|
|||
fields = self.field_dict(model)
|
||||
if not fields:
|
||||
return ''
|
||||
return mark_safe('<p class="filter"><strong>View by:</strong> %s</p>' % \
|
||||
', '.join(['<a href="fields/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()]))
|
||||
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())))
|
||||
|
||||
def urls(self, plugin_name, easy_instance_field):
|
||||
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
|
||||
field_value = smart_str(easy_instance_field.raw_value)
|
||||
return [mark_safe('%s%s/%s/%s/' % (
|
||||
return ['%s%s/%s/%s/' % (
|
||||
easy_instance_field.model.url(),
|
||||
plugin_name, easy_instance_field.field.name,
|
||||
urllib.quote(field_value, safe='')))]
|
||||
urlquote(easy_instance_field.raw_value, safe=''))]
|
||||
|
||||
def model_view(self, request, model_databrowse, url):
|
||||
self.model, self.site = model_databrowse.model, model_databrowse.site
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
try:
|
||||
from urllib.parse import urljoin
|
||||
except ImportError: # Python 2
|
||||
from urlparse import urljoin
|
||||
|
||||
from django import http
|
||||
from django.contrib.databrowse.datastructures import EasyModel
|
||||
from django.contrib.databrowse.sites import DatabrowsePlugin
|
||||
from django.shortcuts import render_to_response
|
||||
import urlparse
|
||||
|
||||
class ObjectDetailPlugin(DatabrowsePlugin):
|
||||
def model_view(self, request, model_databrowse, url):
|
||||
# If the object ID wasn't provided, redirect to the model page, which is one level up.
|
||||
if url is None:
|
||||
return http.HttpResponseRedirect(urlparse.urljoin(request.path, '../'))
|
||||
return http.HttpResponseRedirect(urljoin(request.path, '../'))
|
||||
easy_model = EasyModel(model_databrowse.site, model_databrowse.model)
|
||||
obj = easy_model.object_by_pk(url)
|
||||
return render_to_response('databrowse/object_detail.html', {'object': obj, 'root_url': model_databrowse.site.root_url})
|
||||
|
|
|
@ -23,7 +23,7 @@ def flatpage(request, url):
|
|||
|
||||
Models: `flatpages.flatpages`
|
||||
Templates: Uses the template defined by the ``template_name`` field,
|
||||
or `flatpages/default.html` if template_name is not defined.
|
||||
or :template:`flatpages/default.html` if template_name is not defined.
|
||||
Context:
|
||||
flatpage
|
||||
`flatpages.flatpages` object
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import pickle
|
||||
|
||||
from django.utils.crypto import salted_hmac
|
||||
from django.utils import six
|
||||
|
||||
|
||||
def form_hmac(form):
|
||||
|
@ -16,7 +17,7 @@ def form_hmac(form):
|
|||
value = bf.data or ''
|
||||
else:
|
||||
value = bf.field.clean(bf.data) or ''
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, six.string_types):
|
||||
value = value.strip()
|
||||
data.append((bf.name, value))
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ from django.forms import formsets, ValidationError
|
|||
from django.views.generic import TemplateView
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.utils.decorators import classonlymethod
|
||||
from django.utils import six
|
||||
|
||||
from django.contrib.formtools.wizard.storage import get_storage
|
||||
from django.contrib.formtools.wizard.storage.exceptions import NoFileStorageConfigured
|
||||
|
@ -133,8 +134,9 @@ class WizardView(TemplateView):
|
|||
The key should be equal to the `step_name` in the `form_list` (or
|
||||
the str of the zero based counter - if no step_names added in the
|
||||
`form_list`)
|
||||
* `instance_dict` - contains a dictionary of instance objects. This
|
||||
is only used when `ModelForm`s are used. The key should be equal to
|
||||
* `instance_dict` - contains a dictionary whose values are model
|
||||
instances if the step is based on a ``ModelForm`` and querysets if
|
||||
the step is based on a ``ModelFormSet``. The key should be equal to
|
||||
the `step_name` in the `form_list`. Same rules as for `initial_dict`
|
||||
apply.
|
||||
* `condition_dict` - contains a dictionary of boolean values or
|
||||
|
@ -156,10 +158,10 @@ class WizardView(TemplateView):
|
|||
if isinstance(form, (list, tuple)):
|
||||
# if the element is a tuple, add the tuple to the new created
|
||||
# sorted dictionary.
|
||||
init_form_list[unicode(form[0])] = form[1]
|
||||
init_form_list[six.text_type(form[0])] = form[1]
|
||||
else:
|
||||
# if not, add the form with a zero based counter as unicode
|
||||
init_form_list[unicode(i)] = form
|
||||
init_form_list[six.text_type(i)] = form
|
||||
|
||||
# walk through the new created list of forms
|
||||
for form in init_form_list.itervalues():
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.forms.widgets import Textarea
|
||||
from django.template import loader, Context
|
||||
from django.templatetags.static import static
|
||||
from django.utils import six
|
||||
from django.utils import translation
|
||||
|
||||
from django.contrib.gis.gdal import OGRException
|
||||
|
@ -25,7 +26,7 @@ class OpenLayersWidget(Textarea):
|
|||
|
||||
# If a string reaches here (via a validation error on another
|
||||
# field) then just reconstruct the Geometry.
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, six.string_types):
|
||||
try:
|
||||
value = GEOSGeometry(value)
|
||||
except (GEOSException, ValueError):
|
||||
|
@ -109,7 +110,7 @@ class OpenLayersWidget(Textarea):
|
|||
""" Compare geographic value of data with its initial value. """
|
||||
|
||||
# Ensure we are dealing with a geographic object
|
||||
if isinstance(initial, basestring):
|
||||
if isinstance(initial, six.string_types):
|
||||
try:
|
||||
initial = GEOSGeometry(initial)
|
||||
except (GEOSException, ValueError):
|
||||
|
|
|
@ -4,6 +4,7 @@ Base/mixin classes for the spatial backend database operations and the
|
|||
"""
|
||||
import re
|
||||
from django.contrib.gis import gdal
|
||||
from django.utils import six
|
||||
|
||||
class BaseSpatialOperations(object):
|
||||
"""
|
||||
|
@ -88,7 +89,7 @@ class BaseSpatialOperations(object):
|
|||
|
||||
# For quoting column values, rather than columns.
|
||||
def geo_quote_name(self, name):
|
||||
if isinstance(name, unicode):
|
||||
if isinstance(name, six.text_type):
|
||||
name = name.encode('ascii')
|
||||
return "'%s'" % name
|
||||
|
||||
|
@ -330,6 +331,6 @@ class SpatialRefSysMixin(object):
|
|||
it will be 'pretty' OGC WKT.
|
||||
"""
|
||||
try:
|
||||
return unicode(self.srs)
|
||||
return six.text_type(self.srs)
|
||||
except:
|
||||
return unicode(self.wkt)
|
||||
return six.text_type(self.wkt)
|
||||
|
|
|
@ -16,6 +16,7 @@ from django.contrib.gis.db.backends.oracle.adapter import OracleSpatialAdapter
|
|||
from django.contrib.gis.db.backends.util import SpatialFunction
|
||||
from django.contrib.gis.geometry.backend import Geometry
|
||||
from django.contrib.gis.measure import Distance
|
||||
from django.utils import six
|
||||
|
||||
class SDOOperation(SpatialFunction):
|
||||
"Base class for SDO* Oracle operations."
|
||||
|
@ -65,7 +66,7 @@ class SDORelate(SpatialFunction):
|
|||
super(SDORelate, self).__init__(self.relate_func, mask=mask)
|
||||
|
||||
# Valid distance types and substitutions
|
||||
dtypes = (Decimal, Distance, float, int, long)
|
||||
dtypes = (Decimal, Distance, float) + six.integer_types
|
||||
|
||||
class OracleOperations(DatabaseOperations, BaseSpatialOperations):
|
||||
compiler_module = "django.contrib.gis.db.backends.oracle.compiler"
|
||||
|
@ -120,7 +121,7 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
'exact' : SDOOperation('SDO_EQUAL'),
|
||||
'overlaps' : SDOOperation('SDO_OVERLAPS'),
|
||||
'same_as' : SDOOperation('SDO_EQUAL'),
|
||||
'relate' : (SDORelate, basestring), # Oracle uses a different syntax, e.g., 'mask=inside+touch'
|
||||
'relate' : (SDORelate, six.string_types), # Oracle uses a different syntax, e.g., 'mask=inside+touch'
|
||||
'touches' : SDOOperation('SDO_TOUCH'),
|
||||
'within' : SDOOperation('SDO_INSIDE'),
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.contrib.gis.measure import Distance
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.backends.postgresql_psycopg2.base import DatabaseOperations
|
||||
from django.db.utils import DatabaseError
|
||||
from django.utils import six
|
||||
|
||||
#### Classes used in constructing PostGIS spatial SQL ####
|
||||
class PostGISOperator(SpatialOperation):
|
||||
|
@ -161,11 +162,11 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
'overlaps' : PostGISFunction(prefix, 'Overlaps'),
|
||||
'contains' : PostGISFunction(prefix, 'Contains'),
|
||||
'intersects' : PostGISFunction(prefix, 'Intersects'),
|
||||
'relate' : (PostGISRelate, basestring),
|
||||
'relate' : (PostGISRelate, six.string_types),
|
||||
}
|
||||
|
||||
# Valid distance types and substitutions
|
||||
dtypes = (Decimal, Distance, float, int, long)
|
||||
dtypes = (Decimal, Distance, float) + six.integer_types
|
||||
def get_dist_ops(operator):
|
||||
"Returns operations for both regular and spherical distances."
|
||||
return {'cartesian' : PostGISDistance(prefix, operator),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.contrib.gis.gdal import OGRGeomType
|
||||
from django.db.backends.sqlite3.introspection import DatabaseIntrospection, FlexibleFieldLookupDict
|
||||
from django.utils import six
|
||||
|
||||
class GeoFlexibleFieldLookupDict(FlexibleFieldLookupDict):
|
||||
"""
|
||||
|
@ -43,7 +44,7 @@ class SpatiaLiteIntrospection(DatabaseIntrospection):
|
|||
field_params = {}
|
||||
if srid != 4326:
|
||||
field_params['srid'] = srid
|
||||
if isinstance(dim, basestring) and 'Z' in dim:
|
||||
if isinstance(dim, six.string_types) and 'Z' in dim:
|
||||
field_params['dim'] = 3
|
||||
finally:
|
||||
cursor.close()
|
||||
|
|
|
@ -9,6 +9,7 @@ from django.contrib.gis.measure import Distance
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.backends.sqlite3.base import DatabaseOperations
|
||||
from django.db.utils import DatabaseError
|
||||
from django.utils import six
|
||||
|
||||
class SpatiaLiteOperator(SpatialOperation):
|
||||
"For SpatiaLite operators (e.g. `&&`, `~`)."
|
||||
|
@ -42,7 +43,7 @@ class SpatiaLiteRelate(SpatiaLiteFunctionParam):
|
|||
super(SpatiaLiteRelate, self).__init__('Relate')
|
||||
|
||||
# Valid distance types and substitutions
|
||||
dtypes = (Decimal, Distance, float, int, long)
|
||||
dtypes = (Decimal, Distance, float) + six.integer_types
|
||||
def get_dist_ops(operator):
|
||||
"Returns operations for regular distances; spherical distances are not currently supported."
|
||||
return (SpatiaLiteDistance(operator),)
|
||||
|
@ -89,7 +90,7 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
'overlaps' : SpatiaLiteFunction('Overlaps'),
|
||||
'contains' : SpatiaLiteFunction('Contains'),
|
||||
'intersects' : SpatiaLiteFunction('Intersects'),
|
||||
'relate' : (SpatiaLiteRelate, basestring),
|
||||
'relate' : (SpatiaLiteRelate, six.string_types),
|
||||
# Returns true if B's bounding box completely contains A's bounding box.
|
||||
'contained' : SpatiaLiteFunction('MbrWithin'),
|
||||
# Returns true if A's bounding box completely contains B's bounding box.
|
||||
|
|
|
@ -3,14 +3,16 @@ A collection of utility routines and classes used by the spatial
|
|||
backends.
|
||||
"""
|
||||
|
||||
from django.utils import six
|
||||
|
||||
def gqn(val):
|
||||
"""
|
||||
The geographic quote name function; used for quoting tables and
|
||||
geometries (they use single rather than the double quotes of the
|
||||
backend quotename function).
|
||||
"""
|
||||
if isinstance(val, basestring):
|
||||
if isinstance(val, unicode): val = val.encode('ascii')
|
||||
if isinstance(val, six.string_types):
|
||||
if isinstance(val, six.text_type): val = val.encode('ascii')
|
||||
return "'%s'" % val
|
||||
else:
|
||||
return str(val)
|
||||
|
|
|
@ -4,6 +4,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from django.contrib.gis import forms
|
||||
from django.contrib.gis.db.models.proxy import GeometryProxy
|
||||
from django.contrib.gis.geometry.backend import Geometry, GeometryException
|
||||
from django.utils import six
|
||||
|
||||
# Local cache of the spatial_ref_sys table, which holds SRID data for each
|
||||
# spatial database alias. This cache exists so that the database isn't queried
|
||||
|
@ -159,7 +160,7 @@ class GeometryField(Field):
|
|||
# from the given string input.
|
||||
if isinstance(geom, Geometry):
|
||||
pass
|
||||
elif isinstance(geom, basestring) or hasattr(geom, '__geo_interface__'):
|
||||
elif isinstance(geom, six.string_types) or hasattr(geom, '__geo_interface__'):
|
||||
try:
|
||||
geom = Geometry(geom)
|
||||
except GeometryException:
|
||||
|
|
|
@ -5,6 +5,7 @@ corresponding to geographic model fields.
|
|||
|
||||
Thanks to Robert Coup for providing this functionality (see #4322).
|
||||
"""
|
||||
from django.utils import six
|
||||
|
||||
class GeometryProxy(object):
|
||||
def __init__(self, klass, field):
|
||||
|
@ -53,7 +54,7 @@ class GeometryProxy(object):
|
|||
if isinstance(value, self._klass) and (str(value.geom_type).upper() == gtype or gtype == 'GEOMETRY'):
|
||||
# Assigning the SRID to the geometry.
|
||||
if value.srid is None: value.srid = self._field.srid
|
||||
elif value is None or isinstance(value, (basestring, buffer)):
|
||||
elif value is None or isinstance(value, six.string_types + (buffer,)):
|
||||
# Set with None, WKT, HEX, or WKB
|
||||
pass
|
||||
else:
|
||||
|
|
|
@ -6,6 +6,9 @@ from django.contrib.gis.db.models.fields import get_srid_info, PointField, LineS
|
|||
from django.contrib.gis.db.models.sql import AreaField, DistanceField, GeomField, GeoQuery
|
||||
from django.contrib.gis.geometry.backend import Geometry
|
||||
from django.contrib.gis.measure import Area, Distance
|
||||
from django.utils import six
|
||||
|
||||
from django.utils import six
|
||||
|
||||
class GeoQuerySet(QuerySet):
|
||||
"The Geographic QuerySet."
|
||||
|
@ -144,7 +147,7 @@ class GeoQuerySet(QuerySet):
|
|||
if not backend.geojson:
|
||||
raise NotImplementedError('Only PostGIS 1.3.4+ supports GeoJSON serialization.')
|
||||
|
||||
if not isinstance(precision, (int, long)):
|
||||
if not isinstance(precision, six.integer_types):
|
||||
raise TypeError('Precision keyword must be set with an integer.')
|
||||
|
||||
# Setting the options flag -- which depends on which version of
|
||||
|
@ -309,7 +312,7 @@ class GeoQuerySet(QuerySet):
|
|||
- 2 arguments: X and Y sizes to snap the grid to.
|
||||
- 4 arguments: X, Y sizes and the X, Y origins.
|
||||
"""
|
||||
if False in [isinstance(arg, (float, int, long)) for arg in args]:
|
||||
if False in [isinstance(arg, (float,) + six.integer_types) for arg in args]:
|
||||
raise TypeError('Size argument(s) for the grid must be a float or integer values.')
|
||||
|
||||
nargs = len(args)
|
||||
|
@ -349,7 +352,7 @@ class GeoQuerySet(QuerySet):
|
|||
digits used in output (defaults to 8).
|
||||
"""
|
||||
relative = int(bool(relative))
|
||||
if not isinstance(precision, (int, long)):
|
||||
if not isinstance(precision, six.integer_types):
|
||||
raise TypeError('SVG precision keyword argument must be an integer.')
|
||||
s = {'desc' : 'SVG',
|
||||
'procedure_fmt' : '%(geo_col)s,%(rel)s,%(precision)s',
|
||||
|
@ -390,7 +393,7 @@ class GeoQuerySet(QuerySet):
|
|||
Transforms the given geometry field to the given SRID. If no SRID is
|
||||
provided, the transformation will default to using 4326 (WGS84).
|
||||
"""
|
||||
if not isinstance(srid, (int, long)):
|
||||
if not isinstance(srid, six.integer_types):
|
||||
raise TypeError('An integer SRID must be provided.')
|
||||
field_name = kwargs.get('field_name', None)
|
||||
tmp, geo_field = self._spatial_setup('transform', field_name=field_name)
|
||||
|
@ -533,7 +536,7 @@ class GeoQuerySet(QuerySet):
|
|||
geo_field = settings['geo_field']
|
||||
|
||||
# The attribute to attach to the model.
|
||||
if not isinstance(model_att, basestring): model_att = att
|
||||
if not isinstance(model_att, six.string_types): model_att = att
|
||||
|
||||
# Special handling for any argument that is a geometry.
|
||||
for name in settings['geom_args']:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from future_builtins import zip
|
||||
from django.utils.six.moves import zip
|
||||
|
||||
from django.db.backends.util import truncate_name, typecast_timestamp
|
||||
from django.db.models.sql import compiler
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
# While this couples the geographic forms to the GEOS library,
|
||||
# it decouples from database (by not importing SpatialBackend).
|
||||
from django.contrib.gis.geos import GEOSGeometry
|
||||
from django.contrib.gis.geos import GEOSException, GEOSGeometry
|
||||
|
||||
class GeometryField(forms.Field):
|
||||
"""
|
||||
|
@ -31,6 +31,15 @@ class GeometryField(forms.Field):
|
|||
self.null = kwargs.pop('null', True)
|
||||
super(GeometryField, self).__init__(**kwargs)
|
||||
|
||||
def to_python(self, value):
|
||||
"""
|
||||
Transforms the value to a Geometry object.
|
||||
"""
|
||||
try:
|
||||
return GEOSGeometry(value)
|
||||
except (GEOSException, ValueError, TypeError):
|
||||
raise forms.ValidationError(self.error_messages['invalid_geom'])
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates that the input value can be converted to a Geometry
|
||||
|
@ -44,11 +53,8 @@ class GeometryField(forms.Field):
|
|||
else:
|
||||
raise forms.ValidationError(self.error_messages['no_geom'])
|
||||
|
||||
# Trying to create a Geometry object from the form value.
|
||||
try:
|
||||
geom = GEOSGeometry(value)
|
||||
except:
|
||||
raise forms.ValidationError(self.error_messages['invalid_geom'])
|
||||
# Transform the value to a python object first
|
||||
geom = self.to_python(value)
|
||||
|
||||
# Ensuring that the geometry is of the correct type (indicated
|
||||
# using the OGC string label).
|
||||
|
|
|
@ -37,12 +37,12 @@
|
|||
try:
|
||||
from django.contrib.gis.gdal.driver import Driver
|
||||
from django.contrib.gis.gdal.datasource import DataSource
|
||||
from django.contrib.gis.gdal.libgdal import gdal_version, gdal_full_version, gdal_release_date, GEOJSON, GDAL_VERSION
|
||||
from django.contrib.gis.gdal.libgdal import gdal_version, gdal_full_version, gdal_release_date, GDAL_VERSION
|
||||
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
|
||||
from django.contrib.gis.gdal.geometries import OGRGeometry
|
||||
HAS_GDAL = True
|
||||
except:
|
||||
HAS_GDAL, GEOJSON = False, False
|
||||
HAS_GDAL = False
|
||||
|
||||
try:
|
||||
from django.contrib.gis.gdal.envelope import Envelope
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from ctypes import c_void_p
|
||||
|
||||
from django.contrib.gis.gdal.error import GDALException
|
||||
from django.utils import six
|
||||
|
||||
class GDALBase(object):
|
||||
"""
|
||||
|
@ -24,7 +25,7 @@ class GDALBase(object):
|
|||
def _set_ptr(self, ptr):
|
||||
# Only allow the pointer to be set with pointers of the
|
||||
# compatible type or None (NULL).
|
||||
if isinstance(ptr, (int, long)):
|
||||
if isinstance(ptr, six.integer_types):
|
||||
self._ptr = self.ptr_type(ptr)
|
||||
elif ptr is None or isinstance(ptr, self.ptr_type):
|
||||
self._ptr = ptr
|
||||
|
|
|
@ -45,6 +45,9 @@ from django.contrib.gis.gdal.layer import Layer
|
|||
# Getting the ctypes prototypes for the DataSource.
|
||||
from django.contrib.gis.gdal.prototypes import ds as capi
|
||||
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
# For more information, see the OGR C API source code:
|
||||
# http://www.gdal.org/ogr/ogr__api_8h.html
|
||||
#
|
||||
|
@ -65,7 +68,7 @@ class DataSource(GDALBase):
|
|||
if not capi.get_driver_count():
|
||||
capi.register_all()
|
||||
|
||||
if isinstance(ds_input, basestring):
|
||||
if isinstance(ds_input, six.string_types):
|
||||
# The data source driver is a void pointer.
|
||||
ds_driver = Driver.ptr_type()
|
||||
try:
|
||||
|
@ -98,7 +101,7 @@ class DataSource(GDALBase):
|
|||
|
||||
def __getitem__(self, index):
|
||||
"Allows use of the index [] operator to get a layer at the index."
|
||||
if isinstance(index, basestring):
|
||||
if isinstance(index, six.string_types):
|
||||
l = capi.get_layer_by_name(self.ptr, index)
|
||||
if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index)
|
||||
elif isinstance(index, int):
|
||||
|
|
|
@ -4,6 +4,8 @@ from django.contrib.gis.gdal.base import GDALBase
|
|||
from django.contrib.gis.gdal.error import OGRException
|
||||
from django.contrib.gis.gdal.prototypes import ds as capi
|
||||
|
||||
from django.utils import six
|
||||
|
||||
# For more information, see the OGR C API source code:
|
||||
# http://www.gdal.org/ogr/ogr__api_8h.html
|
||||
#
|
||||
|
@ -22,7 +24,7 @@ class Driver(GDALBase):
|
|||
def __init__(self, dr_input):
|
||||
"Initializes an OGR driver on either a string or integer input."
|
||||
|
||||
if isinstance(dr_input, basestring):
|
||||
if isinstance(dr_input, six.string_types):
|
||||
# If a string name of the driver was passed in
|
||||
self._register()
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType
|
|||
# ctypes function prototypes
|
||||
from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api
|
||||
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
# For more information, see the OGR C API source code:
|
||||
# http://www.gdal.org/ogr/ogr__api_8h.html
|
||||
#
|
||||
|
@ -33,7 +36,7 @@ class Feature(GDALBase):
|
|||
is not the field's _value_ -- use the `get` method instead to
|
||||
retrieve the value (e.g. an integer) instead of a Field instance.
|
||||
"""
|
||||
if isinstance(index, basestring):
|
||||
if isinstance(index, six.string_types):
|
||||
i = self.index(index)
|
||||
else:
|
||||
if index < 0 or index > self.num_fields:
|
||||
|
|
|
@ -48,7 +48,7 @@ from django.contrib.gis.gdal.base import GDALBase
|
|||
from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
|
||||
from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException
|
||||
from django.contrib.gis.gdal.geomtype import OGRGeomType
|
||||
from django.contrib.gis.gdal.libgdal import GEOJSON, GDAL_VERSION
|
||||
from django.contrib.gis.gdal.libgdal import GDAL_VERSION
|
||||
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
|
||||
|
||||
# Getting the ctypes prototype functions that interface w/the GDAL C library.
|
||||
|
@ -57,6 +57,9 @@ from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
|
|||
# For recognizing geometry input.
|
||||
from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex
|
||||
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
# For more information, see the OGR C API source code:
|
||||
# http://www.gdal.org/ogr/ogr__api_8h.html
|
||||
#
|
||||
|
@ -69,7 +72,7 @@ class OGRGeometry(GDALBase):
|
|||
def __init__(self, geom_input, srs=None):
|
||||
"Initializes Geometry on either WKT or an OGR pointer as input."
|
||||
|
||||
str_instance = isinstance(geom_input, basestring)
|
||||
str_instance = isinstance(geom_input, six.string_types)
|
||||
|
||||
# If HEX, unpack input to to a binary buffer.
|
||||
if str_instance and hex_regex.match(geom_input):
|
||||
|
@ -79,7 +82,7 @@ class OGRGeometry(GDALBase):
|
|||
# Constructing the geometry,
|
||||
if str_instance:
|
||||
# Checking if unicode
|
||||
if isinstance(geom_input, unicode):
|
||||
if isinstance(geom_input, six.text_type):
|
||||
# Encoding to ASCII, WKT or HEX doesn't need any more.
|
||||
geom_input = geom_input.encode('ascii')
|
||||
|
||||
|
@ -97,10 +100,7 @@ class OGRGeometry(GDALBase):
|
|||
else:
|
||||
g = capi.from_wkt(byref(c_char_p(wkt_m.group('wkt'))), None, byref(c_void_p()))
|
||||
elif json_m:
|
||||
if GEOJSON:
|
||||
g = capi.from_json(geom_input)
|
||||
else:
|
||||
raise NotImplementedError('GeoJSON input only supported on GDAL 1.5+.')
|
||||
else:
|
||||
# Seeing if the input is a valid short-hand string
|
||||
# (e.g., 'Point', 'POLYGON').
|
||||
|
@ -284,7 +284,7 @@ class OGRGeometry(GDALBase):
|
|||
# (decremented) when this geometry's destructor is called.
|
||||
if isinstance(srs, SpatialReference):
|
||||
srs_ptr = srs.ptr
|
||||
elif isinstance(srs, (int, long, basestring)):
|
||||
elif isinstance(srs, six.integer_types + six.string_types):
|
||||
sr = SpatialReference(srs)
|
||||
srs_ptr = sr.ptr
|
||||
else:
|
||||
|
@ -300,7 +300,7 @@ class OGRGeometry(GDALBase):
|
|||
return None
|
||||
|
||||
def _set_srid(self, srid):
|
||||
if isinstance(srid, (int, long)):
|
||||
if isinstance(srid, six.integer_types):
|
||||
self.srs = srid
|
||||
else:
|
||||
raise TypeError('SRID must be set with an integer.')
|
||||
|
@ -328,22 +328,15 @@ class OGRGeometry(GDALBase):
|
|||
@property
|
||||
def json(self):
|
||||
"""
|
||||
Returns the GeoJSON representation of this Geometry (requires
|
||||
GDAL 1.5+).
|
||||
Returns the GeoJSON representation of this Geometry.
|
||||
"""
|
||||
if GEOJSON:
|
||||
return capi.to_json(self.ptr)
|
||||
else:
|
||||
raise NotImplementedError('GeoJSON output only supported on GDAL 1.5+.')
|
||||
geojson = json
|
||||
|
||||
@property
|
||||
def kml(self):
|
||||
"Returns the KML representation of the Geometry."
|
||||
if GEOJSON:
|
||||
return capi.to_kml(self.ptr, None)
|
||||
else:
|
||||
raise NotImplementedError('KML output only supported on GDAL 1.5+.')
|
||||
|
||||
@property
|
||||
def wkb_size(self):
|
||||
|
@ -420,7 +413,7 @@ class OGRGeometry(GDALBase):
|
|||
capi.geom_transform(self.ptr, coord_trans.ptr)
|
||||
elif isinstance(coord_trans, SpatialReference):
|
||||
capi.geom_transform_to(self.ptr, coord_trans.ptr)
|
||||
elif isinstance(coord_trans, (int, long, basestring)):
|
||||
elif isinstance(coord_trans, six.integer_types + six.string_types):
|
||||
sr = SpatialReference(coord_trans)
|
||||
capi.geom_transform_to(self.ptr, sr.ptr)
|
||||
else:
|
||||
|
@ -695,7 +688,7 @@ class GeometryCollection(OGRGeometry):
|
|||
for g in geom: capi.add_geom(self.ptr, g.ptr)
|
||||
else:
|
||||
capi.add_geom(self.ptr, geom.ptr)
|
||||
elif isinstance(geom, basestring):
|
||||
elif isinstance(geom, six.string_types):
|
||||
tmp = OGRGeometry(geom)
|
||||
capi.add_geom(self.ptr, tmp.ptr)
|
||||
else:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django.contrib.gis.gdal.error import OGRException
|
||||
|
||||
from django.utils import six
|
||||
|
||||
#### OGRGeomType ####
|
||||
class OGRGeomType(object):
|
||||
"Encapulates OGR Geometry Types."
|
||||
|
@ -32,7 +34,7 @@ class OGRGeomType(object):
|
|||
"Figures out the correct OGR Type based upon the input."
|
||||
if isinstance(type_input, OGRGeomType):
|
||||
num = type_input.num
|
||||
elif isinstance(type_input, basestring):
|
||||
elif isinstance(type_input, six.string_types):
|
||||
type_input = type_input.lower()
|
||||
if type_input == 'geometry': type_input='unknown'
|
||||
num = self._str_types.get(type_input, None)
|
||||
|
@ -59,7 +61,7 @@ class OGRGeomType(object):
|
|||
"""
|
||||
if isinstance(other, OGRGeomType):
|
||||
return self.num == other.num
|
||||
elif isinstance(other, basestring):
|
||||
elif isinstance(other, six.string_types):
|
||||
return self.name.lower() == other.lower()
|
||||
elif isinstance(other, int):
|
||||
return self.num == other
|
||||
|
|
|
@ -14,6 +14,9 @@ from django.contrib.gis.gdal.srs import SpatialReference
|
|||
# GDAL ctypes function prototypes.
|
||||
from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api, srs as srs_api
|
||||
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
# For more information, see the OGR C API source code:
|
||||
# http://www.gdal.org/ogr/ogr__api_8h.html
|
||||
#
|
||||
|
@ -39,7 +42,7 @@ class Layer(GDALBase):
|
|||
|
||||
def __getitem__(self, index):
|
||||
"Gets the Feature at the specified index."
|
||||
if isinstance(index, (int, long)):
|
||||
if isinstance(index, six.integer_types):
|
||||
# An integer index was given -- we cannot do a check based on the
|
||||
# number of features because the beginning and ending feature IDs
|
||||
# are not guaranteed to be 0 and len(layer)-1, respectively.
|
||||
|
|
|
@ -15,10 +15,11 @@ if lib_path:
|
|||
lib_names = None
|
||||
elif os.name == 'nt':
|
||||
# Windows NT shared libraries
|
||||
lib_names = ['gdal18', 'gdal17', 'gdal16', 'gdal15']
|
||||
lib_names = ['gdal19', 'gdal18', 'gdal17', 'gdal16', 'gdal15']
|
||||
elif os.name == 'posix':
|
||||
# *NIX library names.
|
||||
lib_names = ['gdal', 'GDAL', 'gdal1.8.0', 'gdal1.7.0', 'gdal1.6.0', 'gdal1.5.0', 'gdal1.4.0']
|
||||
lib_names = ['gdal', 'GDAL', 'gdal1.9.0', 'gdal1.8.0', 'gdal1.7.0',
|
||||
'gdal1.6.0', 'gdal1.5.0']
|
||||
else:
|
||||
raise OGRException('Unsupported OS "%s"' % os.name)
|
||||
|
||||
|
@ -96,10 +97,3 @@ GDAL_MINOR_VERSION = int(_verinfo['minor'])
|
|||
GDAL_SUBMINOR_VERSION = _verinfo['subminor'] and int(_verinfo['subminor'])
|
||||
GDAL_VERSION = (GDAL_MAJOR_VERSION, GDAL_MINOR_VERSION, GDAL_SUBMINOR_VERSION)
|
||||
del _verinfo
|
||||
|
||||
# GeoJSON support is available only in GDAL 1.5+.
|
||||
if GDAL_VERSION >= (1, 5):
|
||||
GEOJSON = True
|
||||
else:
|
||||
GEOJSON = False
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
from ctypes import c_void_p, string_at
|
||||
from django.contrib.gis.gdal.error import check_err, OGRException, SRSException
|
||||
from django.contrib.gis.gdal.libgdal import lgdal
|
||||
from django.utils import six
|
||||
|
||||
# Helper routines for retrieving pointers and/or values from
|
||||
# arguments passed in by reference.
|
||||
|
@ -71,7 +72,7 @@ def check_geom(result, func, cargs):
|
|||
"Checks a function that returns a geometry."
|
||||
# OGR_G_Clone may return an integer, even though the
|
||||
# restype is set to c_void_p
|
||||
if isinstance(result, (int, long)):
|
||||
if isinstance(result, six.integer_types):
|
||||
result = c_void_p(result)
|
||||
if not result:
|
||||
raise OGRException('Invalid geometry pointer returned from "%s".' % func.__name__)
|
||||
|
@ -85,7 +86,7 @@ def check_geom_offset(result, func, cargs, offset=-1):
|
|||
|
||||
### Spatial Reference error-checking routines ###
|
||||
def check_srs(result, func, cargs):
|
||||
if isinstance(result, (int, long)):
|
||||
if isinstance(result, six.integer_types):
|
||||
result = c_void_p(result)
|
||||
if not result:
|
||||
raise SRSException('Invalid spatial reference pointer returned from "%s".' % func.__name__)
|
||||
|
@ -109,7 +110,7 @@ def check_errcode(result, func, cargs):
|
|||
|
||||
def check_pointer(result, func, cargs):
|
||||
"Makes sure the result pointer is valid."
|
||||
if isinstance(result, (int, long)):
|
||||
if isinstance(result, six.integer_types):
|
||||
result = c_void_p(result)
|
||||
if bool(result):
|
||||
return result
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from ctypes import c_char_p, c_double, c_int, c_void_p, POINTER
|
||||
from django.contrib.gis.gdal.envelope import OGREnvelope
|
||||
from django.contrib.gis.gdal.libgdal import lgdal, GEOJSON
|
||||
from django.contrib.gis.gdal.libgdal import lgdal
|
||||
from django.contrib.gis.gdal.prototypes.errcheck import check_bool, check_envelope
|
||||
from django.contrib.gis.gdal.prototypes.generation import (const_string_output,
|
||||
double_output, geom_output, int_output, srs_output, string_output, void_output)
|
||||
|
@ -25,15 +25,10 @@ def topology_func(f):
|
|||
|
||||
### OGR_G ctypes function prototypes ###
|
||||
|
||||
# GeoJSON routines, if supported.
|
||||
if GEOJSON:
|
||||
# GeoJSON routines.
|
||||
from_json = geom_output(lgdal.OGR_G_CreateGeometryFromJson, [c_char_p])
|
||||
to_json = string_output(lgdal.OGR_G_ExportToJson, [c_void_p], str_result=True)
|
||||
to_kml = string_output(lgdal.OGR_G_ExportToKML, [c_void_p, c_char_p], str_result=True)
|
||||
else:
|
||||
from_json = False
|
||||
to_json = False
|
||||
to_kml = False
|
||||
|
||||
# GetX, GetY, GetZ all return doubles.
|
||||
getx = pnt_func(lgdal.OGR_G_GetX)
|
||||
|
|
|
@ -33,6 +33,8 @@ from django.contrib.gis.gdal.base import GDALBase
|
|||
from django.contrib.gis.gdal.error import SRSException
|
||||
from django.contrib.gis.gdal.prototypes import srs as capi
|
||||
|
||||
from django.utils import six
|
||||
|
||||
#### Spatial Reference class. ####
|
||||
class SpatialReference(GDALBase):
|
||||
"""
|
||||
|
@ -52,9 +54,9 @@ class SpatialReference(GDALBase):
|
|||
buf = c_char_p('')
|
||||
srs_type = 'user'
|
||||
|
||||
if isinstance(srs_input, basestring):
|
||||
if isinstance(srs_input, six.string_types):
|
||||
# Encoding to ASCII if unicode passed in.
|
||||
if isinstance(srs_input, unicode):
|
||||
if isinstance(srs_input, six.text_type):
|
||||
srs_input = srs_input.encode('ascii')
|
||||
try:
|
||||
# If SRID is a string, e.g., '4326', then make acceptable
|
||||
|
@ -63,7 +65,7 @@ class SpatialReference(GDALBase):
|
|||
srs_input = 'EPSG:%d' % srid
|
||||
except ValueError:
|
||||
pass
|
||||
elif isinstance(srs_input, (int, long)):
|
||||
elif isinstance(srs_input, six.integer_types):
|
||||
# EPSG integer code was input.
|
||||
srs_type = 'epsg'
|
||||
elif isinstance(srs_input, self.ptr_type):
|
||||
|
@ -133,7 +135,7 @@ class SpatialReference(GDALBase):
|
|||
The attribute value for the given target node (e.g. 'PROJCS'). The index
|
||||
keyword specifies an index of the child node to return.
|
||||
"""
|
||||
if not isinstance(target, basestring) or not isinstance(index, int):
|
||||
if not isinstance(target, six.string_types) or not isinstance(index, int):
|
||||
raise TypeError
|
||||
return capi.get_attr_value(self.ptr, target, index)
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
from binascii import b2a_hex
|
||||
try:
|
||||
import cPickle as pickle
|
||||
from django.utils.six.moves import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
|
||||
from django.contrib.gis.gdal import (OGRGeometry, OGRGeomType, OGRException,
|
||||
OGRIndexError, SpatialReference, CoordTransform, GDAL_VERSION)
|
||||
from django.contrib.gis.gdal.prototypes.geom import GEOJSON
|
||||
from django.contrib.gis.geometry.test_data import TestDataMixin
|
||||
from django.utils.six.moves import xrange
|
||||
from django.utils import unittest
|
||||
|
||||
class OGRGeomTest(unittest.TestCase, TestDataMixin):
|
||||
|
@ -108,7 +108,6 @@ class OGRGeomTest(unittest.TestCase, TestDataMixin):
|
|||
|
||||
def test01e_json(self):
|
||||
"Testing GeoJSON input/output."
|
||||
if not GEOJSON: return
|
||||
for g in self.geometries.json_geoms:
|
||||
geom = OGRGeometry(g.wkt)
|
||||
if not hasattr(g, 'not_equal'):
|
||||
|
@ -244,9 +243,6 @@ class OGRGeomTest(unittest.TestCase, TestDataMixin):
|
|||
self.fail('Should have raised an OGRException!')
|
||||
print("\nEND - expecting IllegalArgumentException; safe to ignore.\n")
|
||||
|
||||
# Closing the rings -- doesn't work on GDAL versions 1.4.1 and below:
|
||||
# http://trac.osgeo.org/gdal/ticket/1673
|
||||
if GDAL_VERSION <= (1, 4, 1): return
|
||||
poly.close_rings()
|
||||
self.assertEqual(10, poly.point_count) # Two closing points should've been added
|
||||
self.assertEqual(OGRGeometry('POINT(2.5 2.5)'), poly.centroid)
|
||||
|
|
|
@ -10,6 +10,8 @@ from django.contrib.gis.geoip.prototypes import (
|
|||
GeoIP_country_code_by_addr, GeoIP_country_code_by_name,
|
||||
GeoIP_country_name_by_addr, GeoIP_country_name_by_name)
|
||||
|
||||
from django.utils import six
|
||||
|
||||
# Regular expressions for recognizing the GeoIP free database editions.
|
||||
free_regex = re.compile(r'^GEO-\d{3}FREE')
|
||||
lite_regex = re.compile(r'^GEO-\d{3}LITE')
|
||||
|
@ -86,7 +88,7 @@ class GeoIP(object):
|
|||
if not path:
|
||||
path = GEOIP_SETTINGS.get('GEOIP_PATH', None)
|
||||
if not path: raise GeoIPException('GeoIP path must be provided via parameter or the GEOIP_PATH setting.')
|
||||
if not isinstance(path, basestring):
|
||||
if not isinstance(path, six.string_types):
|
||||
raise TypeError('Invalid path type: %s' % type(path).__name__)
|
||||
|
||||
if os.path.isdir(path):
|
||||
|
@ -129,7 +131,7 @@ class GeoIP(object):
|
|||
def _check_query(self, query, country=False, city=False, city_or_country=False):
|
||||
"Helper routine for checking the query and database availability."
|
||||
# Making sure a string was passed in for the query.
|
||||
if not isinstance(query, basestring):
|
||||
if not isinstance(query, six.string_types):
|
||||
raise TypeError('GeoIP query must be a string, not type %s' % type(query).__name__)
|
||||
|
||||
# GeoIP only takes ASCII-encoded strings.
|
||||
|
|
|
@ -6,6 +6,8 @@ from django.contrib.gis.geos import GEOSGeometry
|
|||
from django.contrib.gis.geoip import GeoIP, GeoIPException
|
||||
from django.utils import unittest
|
||||
|
||||
from django.utils import six
|
||||
|
||||
# Note: Requires use of both the GeoIP country and city datasets.
|
||||
# The GEOIP_DATA path should be the only setting set (the directory
|
||||
# should contain links or the actual database files 'GeoIP.dat' and
|
||||
|
@ -35,7 +37,7 @@ class GeoIPTest(unittest.TestCase):
|
|||
bad_params = (23, 'foo', 15.23)
|
||||
for bad in bad_params:
|
||||
self.assertRaises(GeoIPException, GeoIP, cache=bad)
|
||||
if isinstance(bad, basestring):
|
||||
if isinstance(bad, six.string_types):
|
||||
e = GeoIPException
|
||||
else:
|
||||
e = TypeError
|
||||
|
|
|
@ -10,7 +10,6 @@ except ImportError:
|
|||
# A 'dummy' gdal module.
|
||||
class GDALInfo(object):
|
||||
HAS_GDAL = False
|
||||
GEOJSON = False
|
||||
gdal = GDALInfo()
|
||||
|
||||
# NumPy supported?
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.contrib.gis.geos.linestring import LineString, LinearRing
|
|||
from django.contrib.gis.geos.point import Point
|
||||
from django.contrib.gis.geos.polygon import Polygon
|
||||
from django.contrib.gis.geos import prototypes as capi
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
class GeometryCollection(GEOSGeometry):
|
||||
_typeid = 7
|
||||
|
|
|
@ -8,6 +8,7 @@ from django.contrib.gis.geos.base import GEOSBase, numpy
|
|||
from django.contrib.gis.geos.error import GEOSException, GEOSIndexError
|
||||
from django.contrib.gis.geos.libgeos import CS_PTR
|
||||
from django.contrib.gis.geos import prototypes as capi
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
class GEOSCoordSeq(GEOSBase):
|
||||
"The internal representation of a list of coordinates inside a Geometry."
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
from django.contrib.gis.geos.geometry import GEOSGeometry, wkt_regex, hex_regex
|
||||
|
||||
from django.utils import six
|
||||
|
||||
def fromfile(file_h):
|
||||
"""
|
||||
Given a string file name, returns a GEOSGeometry. The file may contain WKB,
|
||||
WKT, or HEX.
|
||||
"""
|
||||
# If given a file name, get a real handle.
|
||||
if isinstance(file_h, basestring):
|
||||
if isinstance(file_h, six.string_types):
|
||||
with open(file_h, 'rb') as file_h:
|
||||
buf = file_h.read()
|
||||
else:
|
||||
|
|
|
@ -27,6 +27,8 @@ from django.contrib.gis.geos.prototypes.io import wkt_r, wkt_w, wkb_r, wkb_w, ew
|
|||
# For recognizing geometry input.
|
||||
from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex
|
||||
|
||||
from django.utils import six
|
||||
|
||||
class GEOSGeometry(GEOSBase, ListMixin):
|
||||
"A class that, generally, encapsulates a GEOS geometry."
|
||||
|
||||
|
@ -52,8 +54,8 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
The `srid` keyword is used to specify the Source Reference Identifier
|
||||
(SRID) number for this Geometry. If not set, the SRID will be None.
|
||||
"""
|
||||
if isinstance(geo_input, basestring):
|
||||
if isinstance(geo_input, unicode):
|
||||
if isinstance(geo_input, six.string_types):
|
||||
if isinstance(geo_input, six.text_type):
|
||||
# Encoding to ASCII, WKT or HEXEWKB doesn't need any more.
|
||||
geo_input = geo_input.encode('ascii')
|
||||
|
||||
|
@ -65,7 +67,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
elif hex_regex.match(geo_input):
|
||||
# Handling HEXEWKB input.
|
||||
g = wkb_r().read(geo_input)
|
||||
elif gdal.GEOJSON and json_regex.match(geo_input):
|
||||
elif gdal.HAS_GDAL and json_regex.match(geo_input):
|
||||
# Handling GeoJSON input.
|
||||
g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb)
|
||||
else:
|
||||
|
@ -153,7 +155,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
Equivalence testing, a Geometry may be compared with another Geometry
|
||||
or a WKT representation.
|
||||
"""
|
||||
if isinstance(other, basestring):
|
||||
if isinstance(other, six.string_types):
|
||||
return self.wkt == other
|
||||
elif isinstance(other, GEOSGeometry):
|
||||
return self.equals_exact(other)
|
||||
|
@ -333,7 +335,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
Returns true if the elements in the DE-9IM intersection matrix for the
|
||||
two Geometries match the elements in pattern.
|
||||
"""
|
||||
if not isinstance(pattern, basestring) or len(pattern) > 9:
|
||||
if not isinstance(pattern, six.string_types) or len(pattern) > 9:
|
||||
raise GEOSException('invalid intersection matrix pattern')
|
||||
return capi.geos_relatepattern(self.ptr, other.ptr, pattern)
|
||||
|
||||
|
@ -409,13 +411,12 @@ class GEOSGeometry(GEOSBase, ListMixin):
|
|||
@property
|
||||
def json(self):
|
||||
"""
|
||||
Returns GeoJSON representation of this Geometry if GDAL 1.5+
|
||||
is installed.
|
||||
Returns GeoJSON representation of this Geometry if GDAL is installed.
|
||||
"""
|
||||
if gdal.GEOJSON:
|
||||
if gdal.HAS_GDAL:
|
||||
return self.ogr.json
|
||||
else:
|
||||
raise GEOSException('GeoJSON output only supported on GDAL 1.5+.')
|
||||
raise GEOSException('GeoJSON output only supported when GDAL is installed.')
|
||||
geojson = json
|
||||
|
||||
@property
|
||||
|
|
|
@ -4,6 +4,7 @@ from django.contrib.gis.geos.error import GEOSException
|
|||
from django.contrib.gis.geos.geometry import GEOSGeometry
|
||||
from django.contrib.gis.geos.point import Point
|
||||
from django.contrib.gis.geos import prototypes as capi
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
class LineString(GEOSGeometry):
|
||||
_init_func = capi.create_linestring
|
||||
|
|
|
@ -9,6 +9,8 @@ See also http://www.aryehleib.com/MutableLists.html
|
|||
Author: Aryeh Leib Taurog.
|
||||
"""
|
||||
from django.utils.functional import total_ordering
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
@total_ordering
|
||||
class ListMixin(object):
|
||||
|
@ -82,12 +84,12 @@ class ListMixin(object):
|
|||
|
||||
def __delitem__(self, index):
|
||||
"Delete the item(s) at the specified index/slice."
|
||||
if not isinstance(index, (int, long, slice)):
|
||||
if not isinstance(index, six.integer_types + (slice,)):
|
||||
raise TypeError("%s is not a legal index" % index)
|
||||
|
||||
# calculate new length and dimensions
|
||||
origLen = len(self)
|
||||
if isinstance(index, (int, long)):
|
||||
if isinstance(index, six.integer_types):
|
||||
index = self._checkindex(index)
|
||||
indexRange = [index]
|
||||
else:
|
||||
|
@ -195,7 +197,7 @@ class ListMixin(object):
|
|||
|
||||
def insert(self, index, val):
|
||||
"Standard list insert method"
|
||||
if not isinstance(index, (int, long)):
|
||||
if not isinstance(index, six.integer_types):
|
||||
raise TypeError("%s is not a legal index" % index)
|
||||
self[index:index] = [val]
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ from ctypes import c_uint
|
|||
from django.contrib.gis.geos.error import GEOSException
|
||||
from django.contrib.gis.geos.geometry import GEOSGeometry
|
||||
from django.contrib.gis.geos import prototypes as capi
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
class Point(GEOSGeometry):
|
||||
_minlength = 2
|
||||
|
@ -20,9 +22,9 @@ class Point(GEOSGeometry):
|
|||
# Here a tuple or list was passed in under the `x` parameter.
|
||||
ndim = len(x)
|
||||
coords = x
|
||||
elif isinstance(x, (int, float, long)) and isinstance(y, (int, float, long)):
|
||||
elif isinstance(x, six.integer_types + (float,)) and isinstance(y, six.integer_types + (float,)):
|
||||
# Here X, Y, and (optionally) Z were passed in individually, as parameters.
|
||||
if isinstance(z, (int, float, long)):
|
||||
if isinstance(z, six.integer_types + (float,)):
|
||||
ndim = 3
|
||||
coords = [x, y, z]
|
||||
else:
|
||||
|
|
|
@ -3,6 +3,8 @@ from django.contrib.gis.geos.geometry import GEOSGeometry
|
|||
from django.contrib.gis.geos.libgeos import get_pointer_arr, GEOM_PTR
|
||||
from django.contrib.gis.geos.linestring import LinearRing
|
||||
from django.contrib.gis.geos import prototypes as capi
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
class Polygon(GEOSGeometry):
|
||||
_minlength = 1
|
||||
|
@ -56,7 +58,7 @@ class Polygon(GEOSGeometry):
|
|||
"Constructs a Polygon from a bounding box (4-tuple)."
|
||||
x0, y0, x1, y1 = bbox
|
||||
for z in bbox:
|
||||
if not isinstance(z, (int, long, float)):
|
||||
if not isinstance(z, six.integer_types + (float,)):
|
||||
return GEOSGeometry('POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' %
|
||||
(x0, y0, x0, y1, x1, y1, x1, y0, x0, y0))
|
||||
return Polygon(((x0, y0), (x0, y1), (x1, y1), (x1, y0), (x0, y0)))
|
||||
|
|
|
@ -6,6 +6,8 @@ from django.contrib.gis.geos.prototypes.errcheck import check_geom, check_string
|
|||
from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p
|
||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
||||
|
||||
from django.utils import six
|
||||
|
||||
### The WKB/WKT Reader/Writer structures and pointers ###
|
||||
class WKTReader_st(Structure): pass
|
||||
class WKTWriter_st(Structure): pass
|
||||
|
@ -118,7 +120,7 @@ class _WKTReader(IOBase):
|
|||
ptr_type = WKT_READ_PTR
|
||||
|
||||
def read(self, wkt):
|
||||
if not isinstance(wkt, basestring): raise TypeError
|
||||
if not isinstance(wkt, six.string_types): raise TypeError
|
||||
return wkt_reader_read(self.ptr, wkt)
|
||||
|
||||
class _WKBReader(IOBase):
|
||||
|
@ -131,7 +133,7 @@ class _WKBReader(IOBase):
|
|||
if isinstance(wkb, buffer):
|
||||
wkb_s = str(wkb)
|
||||
return wkb_reader_read(self.ptr, wkb_s, len(wkb_s))
|
||||
elif isinstance(wkb, basestring):
|
||||
elif isinstance(wkb, six.string_types):
|
||||
return wkb_reader_read_hex(self.ptr, wkb, len(wkb))
|
||||
else:
|
||||
raise TypeError
|
||||
|
|
|
@ -7,6 +7,7 @@ from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOS_PREPARE
|
|||
from django.contrib.gis.geos.prototypes.errcheck import check_dbl, check_string
|
||||
from django.contrib.gis.geos.prototypes.geom import geos_char_p
|
||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
__all__ = ['geos_area', 'geos_distance', 'geos_length']
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ from django.contrib.gis.geos.base import gdal, numpy, GEOSBase
|
|||
from django.contrib.gis.geos.libgeos import GEOS_PREPARE
|
||||
from django.contrib.gis.geometry.test_data import TestDataMixin
|
||||
|
||||
from django.utils import six
|
||||
from django.utils.six.moves import xrange
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
|
@ -196,7 +198,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
|
|||
self.assertEqual(srid, poly.shell.srid)
|
||||
self.assertEqual(srid, fromstr(poly.ewkt).srid) # Checking export
|
||||
|
||||
@unittest.skipUnless(gdal.HAS_GDAL and gdal.GEOJSON, "gdal >= 1.5 is required")
|
||||
@unittest.skipUnless(gdal.HAS_GDAL, "gdal is required")
|
||||
def test_json(self):
|
||||
"Testing GeoJSON input/output (via GDAL)."
|
||||
for g in self.geometries.json_geoms:
|
||||
|
@ -951,7 +953,8 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
|
|||
def test_pickle(self):
|
||||
"Testing pickling and unpickling support."
|
||||
# Using both pickle and cPickle -- just 'cause.
|
||||
import pickle, cPickle
|
||||
from django.utils.six.moves import cPickle
|
||||
import pickle
|
||||
|
||||
# Creating a list of test geometries for pickling,
|
||||
# and setting the SRID on some of them.
|
||||
|
@ -1004,7 +1007,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
|
|||
|
||||
g = GEOSGeometry("POINT(0 0)")
|
||||
self.assertTrue(g.valid)
|
||||
self.assertTrue(isinstance(g.valid_reason, basestring))
|
||||
self.assertTrue(isinstance(g.valid_reason, six.string_types))
|
||||
self.assertEqual(g.valid_reason, "Valid Geometry")
|
||||
|
||||
print("\nBEGIN - expecting GEOS_NOTICE; safe to ignore.\n")
|
||||
|
@ -1012,7 +1015,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
|
|||
g = GEOSGeometry("LINESTRING(0 0, 0 0)")
|
||||
|
||||
self.assertTrue(not g.valid)
|
||||
self.assertTrue(isinstance(g.valid_reason, basestring))
|
||||
self.assertTrue(isinstance(g.valid_reason, six.string_types))
|
||||
self.assertTrue(g.valid_reason.startswith("Too few points in geometry component"))
|
||||
|
||||
print("\nEND - expecting GEOS_NOTICE; safe to ignore.\n")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import binascii
|
||||
import unittest
|
||||
from django.contrib.gis.geos import GEOSGeometry, WKTReader, WKTWriter, WKBReader, WKBWriter, geos_version_info
|
||||
from django.utils import six
|
||||
|
||||
class GEOSIOTest(unittest.TestCase):
|
||||
|
||||
|
@ -12,12 +13,12 @@ class GEOSIOTest(unittest.TestCase):
|
|||
# read() should return a GEOSGeometry
|
||||
ref = GEOSGeometry(wkt)
|
||||
g1 = wkt_r.read(wkt)
|
||||
g2 = wkt_r.read(unicode(wkt))
|
||||
g2 = wkt_r.read(six.text_type(wkt))
|
||||
|
||||
for geom in (g1, g2):
|
||||
self.assertEqual(ref, geom)
|
||||
|
||||
# Should only accept basestring objects.
|
||||
# Should only accept six.string_types objects.
|
||||
self.assertRaises(TypeError, wkt_r.read, 1)
|
||||
self.assertRaises(TypeError, wkt_r.read, buffer('foo'))
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
# Modified from original contribution by Aryeh Leib Taurog, which was
|
||||
# released under the New BSD license.
|
||||
from django.contrib.gis.geos.mutable_list import ListMixin
|
||||
from django.utils import six
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
|
@ -267,7 +268,7 @@ class ListMixinTest(unittest.TestCase):
|
|||
def test07_allowed_types(self):
|
||||
'Type-restricted list'
|
||||
pl, ul = self.lists_of_len()
|
||||
ul._allowed = (int, long)
|
||||
ul._allowed = six.integer_types
|
||||
ul[1] = 50
|
||||
ul[:2] = [60, 70, 80]
|
||||
def setfcn(x, i, v): x[i] = v
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from django.conf import settings
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.six.moves import xrange
|
||||
|
||||
from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker
|
||||
|
||||
|
@ -10,7 +12,7 @@ class GoogleMapException(Exception):
|
|||
|
||||
# The default Google Maps URL (for the API javascript)
|
||||
# TODO: Internationalize for Japan, UK, etc.
|
||||
GOOGLE_MAPS_URL='http://maps.google.com/maps?file=api&v=%s&key='
|
||||
GOOGLE_MAPS_URL='http://maps.google.com/maps?file=api&v=%s&key='
|
||||
|
||||
|
||||
class GoogleMap(object):
|
||||
|
@ -48,7 +50,7 @@ class GoogleMap(object):
|
|||
|
||||
# Can specify the API URL in the `api_url` keyword.
|
||||
if not api_url:
|
||||
self.api_url = mark_safe(getattr(settings, 'GOOGLE_MAPS_URL', GOOGLE_MAPS_URL) % self.version)
|
||||
self.api_url = getattr(settings, 'GOOGLE_MAPS_URL', GOOGLE_MAPS_URL) % self.version
|
||||
else:
|
||||
self.api_url = api_url
|
||||
|
||||
|
@ -111,17 +113,18 @@ class GoogleMap(object):
|
|||
@property
|
||||
def body(self):
|
||||
"Returns HTML body tag for loading and unloading Google Maps javascript."
|
||||
return mark_safe('<body %s %s>' % (self.onload, self.onunload))
|
||||
return format_html('<body {0} {1}>', self.onload, self.onunload)
|
||||
|
||||
@property
|
||||
def onload(self):
|
||||
"Returns the `onload` HTML <body> attribute."
|
||||
return mark_safe('onload="%s.%s_load()"' % (self.js_module, self.dom_id))
|
||||
return format_html('onload="{0}.{1}_load()"', self.js_module, self.dom_id)
|
||||
|
||||
@property
|
||||
def api_script(self):
|
||||
"Returns the <script> tag for the Google Maps API javascript."
|
||||
return mark_safe('<script src="%s%s" type="text/javascript"></script>' % (self.api_url, self.key))
|
||||
return format_html('<script src="{0}{1}" type="text/javascript"></script>',
|
||||
self.api_url, self.key)
|
||||
|
||||
@property
|
||||
def js(self):
|
||||
|
@ -131,17 +134,17 @@ class GoogleMap(object):
|
|||
@property
|
||||
def scripts(self):
|
||||
"Returns all <script></script> tags required with Google Maps JavaScript."
|
||||
return mark_safe('%s\n <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n </script>' % (self.api_script, self.js))
|
||||
return format_html('%s\n <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n </script>', self.api_script, mark_safe(self.js))
|
||||
|
||||
@property
|
||||
def style(self):
|
||||
"Returns additional CSS styling needed for Google Maps on IE."
|
||||
return mark_safe('<style type="text/css">%s</style>' % self.vml_css)
|
||||
return format_html('<style type="text/css">{0}</style>', self.vml_css)
|
||||
|
||||
@property
|
||||
def xhtml(self):
|
||||
"Returns XHTML information needed for IE VML overlays."
|
||||
return mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" %s>' % self.xmlns)
|
||||
return format_html('<html xmlns="http://www.w3.org/1999/xhtml" {0}>', self.xmlns)
|
||||
|
||||
@property
|
||||
def icons(self):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.contrib.gis.geos import fromstr, Point, LineString, LinearRing, Polygon
|
||||
from django.utils.functional import total_ordering
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils import six
|
||||
|
||||
|
||||
class GEvent(object):
|
||||
|
@ -98,7 +99,7 @@ class GPolygon(GOverlayBase):
|
|||
fill_opacity:
|
||||
The opacity of the polygon fill. Defaults to 0.4.
|
||||
"""
|
||||
if isinstance(poly, basestring): poly = fromstr(poly)
|
||||
if isinstance(poly, six.string_types): poly = fromstr(poly)
|
||||
if isinstance(poly, (tuple, list)): poly = Polygon(poly)
|
||||
if not isinstance(poly, Polygon):
|
||||
raise TypeError('GPolygon may only initialize on GEOS Polygons.')
|
||||
|
@ -148,7 +149,7 @@ class GPolyline(GOverlayBase):
|
|||
The opacity of the polyline, between 0 and 1. Defaults to 1.
|
||||
"""
|
||||
# If a GEOS geometry isn't passed in, try to contsruct one.
|
||||
if isinstance(geom, basestring): geom = fromstr(geom)
|
||||
if isinstance(geom, six.string_types): geom = fromstr(geom)
|
||||
if isinstance(geom, (tuple, list)): geom = Polygon(geom)
|
||||
# Generating the lat/lng coordinate pairs.
|
||||
if isinstance(geom, (LineString, LinearRing)):
|
||||
|
@ -278,7 +279,7 @@ class GMarker(GOverlayBase):
|
|||
Draggable option for GMarker, disabled by default.
|
||||
"""
|
||||
# If a GEOS geometry isn't passed in, try to construct one.
|
||||
if isinstance(geom, basestring): geom = fromstr(geom)
|
||||
if isinstance(geom, six.string_types): geom = fromstr(geom)
|
||||
if isinstance(geom, (tuple, list)): geom = Point(geom)
|
||||
if isinstance(geom, Point):
|
||||
self.latlng = self.latlng_from_coords(geom.coords)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.contrib.gis.geos import GEOSGeometry, LinearRing, Polygon, Point
|
||||
from django.contrib.gis.maps.google.gmap import GoogleMapException
|
||||
from django.utils.six.moves import xrange
|
||||
from math import pi, sin, log, exp, atan
|
||||
|
||||
# Constants used for degree to radian conversion, and vice-versa.
|
||||
|
|
|
@ -39,8 +39,9 @@ __all__ = ['A', 'Area', 'D', 'Distance']
|
|||
from decimal import Decimal
|
||||
|
||||
from django.utils.functional import total_ordering
|
||||
from django.utils import six
|
||||
|
||||
NUMERIC_TYPES = (int, float, long, Decimal)
|
||||
NUMERIC_TYPES = six.integer_types + (float, Decimal)
|
||||
AREA_PREFIX = "sq_"
|
||||
|
||||
def pretty_name(obj):
|
||||
|
@ -57,7 +58,7 @@ class MeasureBase(object):
|
|||
def __init__(self, default_unit=None, **kwargs):
|
||||
value, self._default_unit = self.default_units(kwargs)
|
||||
setattr(self, self.STANDARD_UNIT, value)
|
||||
if default_unit and isinstance(default_unit, basestring):
|
||||
if default_unit and isinstance(default_unit, six.string_types):
|
||||
self._default_unit = default_unit
|
||||
|
||||
def _get_standard(self):
|
||||
|
|
|
@ -11,6 +11,7 @@ from django.contrib.gis.tests.utils import (
|
|||
no_mysql, no_oracle, no_spatialite,
|
||||
mysql, oracle, postgis, spatialite)
|
||||
from django.test import TestCase
|
||||
from django.utils import six
|
||||
|
||||
from .models import Country, City, PennsylvaniaCity, State, Track
|
||||
|
||||
|
@ -663,7 +664,7 @@ class GeoModelTest(TestCase):
|
|||
# Let's try and break snap_to_grid() with bad combinations of arguments.
|
||||
for bad_args in ((), range(3), range(5)):
|
||||
self.assertRaises(ValueError, Country.objects.snap_to_grid, *bad_args)
|
||||
for bad_args in (('1.0',), (1.0, None), tuple(map(unicode, range(4)))):
|
||||
for bad_args in (('1.0',), (1.0, None), tuple(map(six.text_type, range(4)))):
|
||||
self.assertRaises(TypeError, Country.objects.snap_to_grid, *bad_args)
|
||||
|
||||
# Boundary for San Marino, courtesy of Bjorn Sandvik of thematicmapping.org
|
||||
|
|
|
@ -56,8 +56,25 @@ class GeometryFieldTest(unittest.TestCase):
|
|||
|
||||
pnt_fld = forms.GeometryField(geom_type='POINT')
|
||||
self.assertEqual(GEOSGeometry('POINT(5 23)'), pnt_fld.clean('POINT(5 23)'))
|
||||
# a WKT for any other geom_type will be properly transformed by `to_python`
|
||||
self.assertEqual(GEOSGeometry('LINESTRING(0 0, 1 1)'), pnt_fld.to_python('LINESTRING(0 0, 1 1)'))
|
||||
# but rejected by `clean`
|
||||
self.assertRaises(forms.ValidationError, pnt_fld.clean, 'LINESTRING(0 0, 1 1)')
|
||||
|
||||
def test04_to_python(self):
|
||||
"""
|
||||
Testing to_python returns a correct GEOSGeometry object or
|
||||
a ValidationError
|
||||
"""
|
||||
fld = forms.GeometryField()
|
||||
# to_python returns the same GEOSGeometry for a WKT
|
||||
for wkt in ('POINT(5 23)', 'MULTIPOLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'LINESTRING(0 0, 1 1)'):
|
||||
self.assertEqual(GEOSGeometry(wkt), fld.to_python(wkt))
|
||||
# but raises a ValidationError for any other string
|
||||
for wkt in ('POINT(5)', 'MULTI POLYGON(((0 0, 0 1, 1 1, 1 0, 0 0)))', 'BLAH(0 0, 1 1)'):
|
||||
self.assertRaises(forms.ValidationError, fld.to_python, wkt)
|
||||
|
||||
|
||||
def suite():
|
||||
s = unittest.TestSuite()
|
||||
s.addTest(unittest.makeSuite(GeometryFieldTest))
|
||||
|
|
|
@ -17,6 +17,7 @@ from django.contrib.gis.gdal.field import (
|
|||
OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime)
|
||||
from django.db import models, transaction
|
||||
from django.contrib.localflavor.us.models import USStateField
|
||||
from django.utils import six
|
||||
|
||||
# LayerMapping exceptions.
|
||||
class LayerMapError(Exception): pass
|
||||
|
@ -74,7 +75,7 @@ class LayerMapping(object):
|
|||
argument usage.
|
||||
"""
|
||||
# Getting the DataSource and the associated Layer.
|
||||
if isinstance(data, basestring):
|
||||
if isinstance(data, six.string_types):
|
||||
self.ds = DataSource(data)
|
||||
else:
|
||||
self.ds = data
|
||||
|
@ -249,7 +250,7 @@ class LayerMapping(object):
|
|||
sr = source_srs
|
||||
elif isinstance(source_srs, self.spatial_backend.spatial_ref_sys()):
|
||||
sr = source_srs.srs
|
||||
elif isinstance(source_srs, (int, basestring)):
|
||||
elif isinstance(source_srs, (int, six.string_types)):
|
||||
sr = SpatialReference(source_srs)
|
||||
else:
|
||||
# Otherwise just pulling the SpatialReference from the layer
|
||||
|
@ -266,7 +267,7 @@ class LayerMapping(object):
|
|||
# List of fields to determine uniqueness with
|
||||
for attr in unique:
|
||||
if not attr in self.mapping: raise ValueError
|
||||
elif isinstance(unique, basestring):
|
||||
elif isinstance(unique, six.string_types):
|
||||
# Only a single field passed in.
|
||||
if unique not in self.mapping: raise ValueError
|
||||
else:
|
||||
|
@ -312,7 +313,7 @@ class LayerMapping(object):
|
|||
will construct and return the uniqueness keyword arguments -- a subset
|
||||
of the feature kwargs.
|
||||
"""
|
||||
if isinstance(self.unique, basestring):
|
||||
if isinstance(self.unique, six.string_types):
|
||||
return {self.unique : kwargs[self.unique]}
|
||||
else:
|
||||
return dict((fld, kwargs[fld]) for fld in self.unique)
|
||||
|
@ -329,7 +330,7 @@ class LayerMapping(object):
|
|||
if self.encoding:
|
||||
# The encoding for OGR data sources may be specified here
|
||||
# (e.g., 'cp437' for Census Bureau boundary files).
|
||||
val = unicode(ogr_field.value, self.encoding)
|
||||
val = six.text_type(ogr_field.value, self.encoding)
|
||||
else:
|
||||
val = ogr_field.value
|
||||
if model_field.max_length and len(val) > model_field.max_length:
|
||||
|
|
|
@ -5,10 +5,11 @@ models for GeoDjango and/or mapping dictionaries for use with the
|
|||
|
||||
Author: Travis Pinney, Dane Springmeyer, & Justin Bronn
|
||||
"""
|
||||
from future_builtins import zip
|
||||
from django.utils.six.moves import zip
|
||||
# Requires GDAL to use.
|
||||
from django.contrib.gis.gdal import DataSource
|
||||
from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime
|
||||
from django.utils import six
|
||||
|
||||
def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False):
|
||||
"""
|
||||
|
@ -24,7 +25,7 @@ def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False):
|
|||
|
||||
`multi_geom` => Boolean (default: False) - specify as multigeometry.
|
||||
"""
|
||||
if isinstance(data_source, basestring):
|
||||
if isinstance(data_source, six.string_types):
|
||||
# Instantiating the DataSource from the string.
|
||||
data_source = DataSource(data_source)
|
||||
elif isinstance(data_source, DataSource):
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
Utilities for manipulating Geometry WKT.
|
||||
"""
|
||||
|
||||
from django.utils import six
|
||||
|
||||
def precision_wkt(geom, prec):
|
||||
"""
|
||||
Returns WKT text of the geometry according to the given precision (an
|
||||
|
@ -19,7 +21,7 @@ def precision_wkt(geom, prec):
|
|||
"""
|
||||
if isinstance(prec, int):
|
||||
num_fmt = '%%.%df' % prec
|
||||
elif isinstance(prec, basestring):
|
||||
elif isinstance(prec, six.string_types):
|
||||
num_fmt = prec
|
||||
else:
|
||||
raise TypeError
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import unicode_literals
|
||||
import re
|
||||
from datetime import date, datetime, timedelta
|
||||
from datetime import date, datetime
|
||||
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
|
@ -143,7 +143,9 @@ def apnumber(value):
|
|||
return value
|
||||
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
|
||||
|
||||
@register.filter
|
||||
# Perform the comparison in the default time zone when USE_TZ = True
|
||||
# (unless a specific time zone has been applied with the |timezone filter).
|
||||
@register.filter(expects_localtime=True)
|
||||
def naturalday(value, arg=None):
|
||||
"""
|
||||
For date values that are tomorrow, today or yesterday compared to
|
||||
|
@ -169,6 +171,8 @@ def naturalday(value, arg=None):
|
|||
return _('yesterday')
|
||||
return defaultfilters.date(value, arg)
|
||||
|
||||
# This filter doesn't require expects_localtime=True because it deals properly
|
||||
# with both naive and aware datetimes. Therefore avoid the cost of conversion.
|
||||
@register.filter
|
||||
def naturaltime(value):
|
||||
"""
|
||||
|
@ -184,7 +188,7 @@ def naturaltime(value):
|
|||
if delta.days != 0:
|
||||
return pgettext(
|
||||
'naturaltime', '%(delta)s ago'
|
||||
) % {'delta': defaultfilters.timesince(value)}
|
||||
) % {'delta': defaultfilters.timesince(value, now)}
|
||||
elif delta.seconds == 0:
|
||||
return _('now')
|
||||
elif delta.seconds < 60:
|
||||
|
@ -206,7 +210,7 @@ def naturaltime(value):
|
|||
if delta.days != 0:
|
||||
return pgettext(
|
||||
'naturaltime', '%(delta)s from now'
|
||||
) % {'delta': defaultfilters.timeuntil(value)}
|
||||
) % {'delta': defaultfilters.timeuntil(value, now)}
|
||||
elif delta.seconds == 0:
|
||||
return _('now')
|
||||
elif delta.seconds < 60:
|
||||
|
|
|
@ -1,13 +1,31 @@
|
|||
from __future__ import unicode_literals
|
||||
import datetime
|
||||
import new
|
||||
|
||||
from django.contrib.humanize.templatetags import humanize
|
||||
from django.template import Template, Context, defaultfilters
|
||||
from django.test import TestCase
|
||||
from django.utils import translation, tzinfo
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.test.utils import override_settings
|
||||
from django.utils.html import escape
|
||||
from django.utils.timezone import utc
|
||||
from django.utils import translation
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils import tzinfo
|
||||
|
||||
|
||||
# Mock out datetime in some tests so they don't fail occasionally when they
|
||||
# run too slow. Use a fixed datetime for datetime.now(). DST change in
|
||||
# America/Chicago (the default time zone) happened on March 11th in 2012.
|
||||
|
||||
now = datetime.datetime(2012, 3, 9, 22, 30)
|
||||
|
||||
class MockDateTime(datetime.datetime):
|
||||
@classmethod
|
||||
def now(self, tz=None):
|
||||
if tz is None or tz.utcoffset(now) is None:
|
||||
return now
|
||||
else:
|
||||
# equals now.replace(tzinfo=utc)
|
||||
return now.replace(tzinfo=tz) + tz.utcoffset(now)
|
||||
|
||||
|
||||
class HumanizeTests(TestCase):
|
||||
|
@ -109,28 +127,36 @@ class HumanizeTests(TestCase):
|
|||
self.humanize_tester(test_list, result_list, 'naturalday')
|
||||
|
||||
def test_naturalday_tz(self):
|
||||
from django.contrib.humanize.templatetags.humanize import naturalday
|
||||
|
||||
today = datetime.date.today()
|
||||
tz_one = tzinfo.FixedOffset(datetime.timedelta(hours=-12))
|
||||
tz_two = tzinfo.FixedOffset(datetime.timedelta(hours=12))
|
||||
|
||||
# Can be today or yesterday
|
||||
date_one = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_one)
|
||||
naturalday_one = naturalday(date_one)
|
||||
naturalday_one = humanize.naturalday(date_one)
|
||||
# Can be today or tomorrow
|
||||
date_two = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_two)
|
||||
naturalday_two = naturalday(date_two)
|
||||
naturalday_two = humanize.naturalday(date_two)
|
||||
|
||||
# As 24h of difference they will never be the same
|
||||
self.assertNotEqual(naturalday_one, naturalday_two)
|
||||
|
||||
def test_naturalday_uses_localtime(self):
|
||||
# Regression for #18504
|
||||
# This is 2012-03-08HT19:30:00-06:00 in Ameria/Chicago
|
||||
dt = datetime.datetime(2012, 3, 9, 1, 30, tzinfo=utc)
|
||||
|
||||
orig_humanize_datetime, humanize.datetime = humanize.datetime, MockDateTime
|
||||
try:
|
||||
with override_settings(USE_TZ=True):
|
||||
self.humanize_tester([dt], ['yesterday'], 'naturalday')
|
||||
finally:
|
||||
humanize.datetime = orig_humanize_datetime
|
||||
|
||||
def test_naturaltime(self):
|
||||
class naive(datetime.tzinfo):
|
||||
def utcoffset(self, dt):
|
||||
return None
|
||||
# we're going to mock datetime.datetime, so use a fixed datetime
|
||||
now = datetime.datetime(2011, 8, 15)
|
||||
test_list = [
|
||||
now,
|
||||
now - datetime.timedelta(seconds=1),
|
||||
|
@ -148,6 +174,7 @@ class HumanizeTests(TestCase):
|
|||
now + datetime.timedelta(hours=1, minutes=30, seconds=30),
|
||||
now + datetime.timedelta(hours=23, minutes=50, seconds=50),
|
||||
now + datetime.timedelta(days=1),
|
||||
now + datetime.timedelta(days=2, hours=6),
|
||||
now + datetime.timedelta(days=500),
|
||||
now.replace(tzinfo=naive()),
|
||||
now.replace(tzinfo=utc),
|
||||
|
@ -169,33 +196,22 @@ class HumanizeTests(TestCase):
|
|||
'an hour from now',
|
||||
'23 hours from now',
|
||||
'1 day from now',
|
||||
'2 days, 6 hours from now',
|
||||
'1 year, 4 months from now',
|
||||
'now',
|
||||
'now',
|
||||
]
|
||||
# Because of the DST change, 2 days and 6 hours after the chosen
|
||||
# date in naive arithmetic is only 2 days and 5 hours after in
|
||||
# aware arithmetic.
|
||||
result_list_with_tz_support = result_list[:]
|
||||
assert result_list_with_tz_support[-4] == '2 days, 6 hours from now'
|
||||
result_list_with_tz_support[-4] == '2 days, 5 hours from now'
|
||||
|
||||
# mock out datetime so these tests don't fail occasionally when the
|
||||
# test runs too slow
|
||||
class MockDateTime(datetime.datetime):
|
||||
@classmethod
|
||||
def now(self, tz=None):
|
||||
if tz is None or tz.utcoffset(now) is None:
|
||||
return now
|
||||
else:
|
||||
# equals now.replace(tzinfo=utc)
|
||||
return now.replace(tzinfo=tz) + tz.utcoffset(now)
|
||||
|
||||
# naturaltime also calls timesince/timeuntil
|
||||
from django.contrib.humanize.templatetags import humanize
|
||||
from django.utils import timesince
|
||||
orig_humanize_datetime = humanize.datetime
|
||||
orig_timesince_datetime = timesince.datetime
|
||||
humanize.datetime = MockDateTime
|
||||
timesince.datetime = new.module(b"mock_datetime")
|
||||
timesince.datetime.datetime = MockDateTime
|
||||
|
||||
orig_humanize_datetime, humanize.datetime = humanize.datetime, MockDateTime
|
||||
try:
|
||||
self.humanize_tester(test_list, result_list, 'naturaltime')
|
||||
with override_settings(USE_TZ=True):
|
||||
self.humanize_tester(test_list, result_list_with_tz_support, 'naturaltime')
|
||||
finally:
|
||||
humanize.datetime = orig_humanize_datetime
|
||||
timesince.datetime = orig_timesince_datetime
|
||||
|
|
|
@ -81,6 +81,7 @@ class ARCUITField(RegexField):
|
|||
default_error_messages = {
|
||||
'invalid': _('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'),
|
||||
'checksum': _("Invalid CUIT."),
|
||||
'legal_type': _('Invalid legal type. Type must be 27, 20, 23 or 30.'),
|
||||
}
|
||||
|
||||
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
|
||||
|
@ -96,6 +97,8 @@ class ARCUITField(RegexField):
|
|||
if value in EMPTY_VALUES:
|
||||
return ''
|
||||
value, cd = self._canon(value)
|
||||
if not value[:2] in ['27', '20', '23', '30']:
|
||||
raise ValidationError(self.error_messages['legal_type'])
|
||||
if self._calc_cd(value) != cd:
|
||||
raise ValidationError(self.error_messages['checksum'])
|
||||
return self._format(value, cd)
|
||||
|
@ -105,9 +108,16 @@ class ARCUITField(RegexField):
|
|||
return cuit[:-1], cuit[-1]
|
||||
|
||||
def _calc_cd(self, cuit):
|
||||
# Calculation code based on:
|
||||
# http://es.wikipedia.org/wiki/C%C3%B3digo_%C3%9Anico_de_Identificaci%C3%B3n_Tributaria
|
||||
mults = (5, 4, 3, 2, 7, 6, 5, 4, 3, 2)
|
||||
tmp = sum([m * int(cuit[idx]) for idx, m in enumerate(mults)])
|
||||
return str(11 - tmp % 11)
|
||||
result = 11 - (tmp % 11)
|
||||
if result == 11:
|
||||
result = 0
|
||||
elif result == 10:
|
||||
result = 9
|
||||
return str(result)
|
||||
|
||||
def _format(self, cuit, check_digit=None):
|
||||
if check_digit == None:
|
||||
|
|
|
@ -8,7 +8,7 @@ import re
|
|||
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 Field, RegexField, Select
|
||||
from django.forms.fields import CharField, RegexField, Select
|
||||
from django.utils.encoding import smart_unicode
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
@ -20,11 +20,11 @@ class FRZipCodeField(RegexField):
|
|||
'invalid': _('Enter a zip code in the format XXXXX.'),
|
||||
}
|
||||
|
||||
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
|
||||
def __init__(self, max_length=5, min_length=5, *args, **kwargs):
|
||||
super(FRZipCodeField, self).__init__(r'^\d{5}$',
|
||||
max_length, min_length, *args, **kwargs)
|
||||
|
||||
class FRPhoneNumberField(Field):
|
||||
class FRPhoneNumberField(CharField):
|
||||
"""
|
||||
Validate local French phone number (not international ones)
|
||||
The correct format is '0X XX XX XX XX'.
|
||||
|
@ -35,6 +35,10 @@ class FRPhoneNumberField(Field):
|
|||
'invalid': _('Phone numbers must be in 0X XX XX XX XX format.'),
|
||||
}
|
||||
|
||||
def __init__(self, max_length=14, min_length=10, *args, **kwargs):
|
||||
super(FRPhoneNumberField, self).__init__(
|
||||
max_length, min_length, *args, **kwargs)
|
||||
|
||||
def clean(self, value):
|
||||
super(FRPhoneNumberField, self).clean(value)
|
||||
if value in EMPTY_VALUES:
|
||||
|
@ -51,4 +55,3 @@ class FRDepartmentSelect(Select):
|
|||
"""
|
||||
def __init__(self, attrs=None):
|
||||
super(FRDepartmentSelect, self).__init__(attrs, choices=DEPARTMENT_CHOICES)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import re
|
|||
|
||||
from django.forms import ValidationError
|
||||
from django.forms.fields import Select, RegexField
|
||||
from django.utils import six
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.validators import EMPTY_VALUES
|
||||
from django.contrib.localflavor.mx.mx_states import STATE_CHOICES
|
||||
|
@ -147,7 +148,7 @@ class MXRFCField(RegexField):
|
|||
if len(rfc) == 11:
|
||||
rfc = '-' + rfc
|
||||
|
||||
sum_ = sum(i * chars.index(c) for i, c in zip(reversed(xrange(14)), rfc))
|
||||
sum_ = sum(i * chars.index(c) for i, c in zip(reversed(range(14)), rfc))
|
||||
checksum = 11 - sum_ % 11
|
||||
|
||||
if checksum == 10:
|
||||
|
@ -155,7 +156,7 @@ class MXRFCField(RegexField):
|
|||
elif checksum == 11:
|
||||
return '0'
|
||||
|
||||
return unicode(checksum)
|
||||
return six.text_type(checksum)
|
||||
|
||||
def _has_inconvenient_word(self, rfc):
|
||||
first_four = rfc[:4]
|
||||
|
@ -214,12 +215,12 @@ class MXCURPField(RegexField):
|
|||
def _checksum(self, value):
|
||||
chars = '0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ'
|
||||
|
||||
s = sum(i * chars.index(c) for i, c in zip(reversed(xrange(19)), value))
|
||||
s = sum(i * chars.index(c) for i, c in zip(reversed(range(19)), value))
|
||||
checksum = 10 - s % 10
|
||||
|
||||
if checksum == 10:
|
||||
return '0'
|
||||
return unicode(checksum)
|
||||
return six.text_type(checksum)
|
||||
|
||||
def _has_inconvenient_word(self, curp):
|
||||
first_four = curp[:4]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import datetime
|
||||
from django.utils import six
|
||||
|
||||
def id_number_checksum(gd):
|
||||
"""
|
||||
|
@ -65,7 +66,7 @@ def validate_id_birthday(gd, fix_coordination_number_day=True):
|
|||
|
||||
def format_personal_id_number(birth_day, gd):
|
||||
# birth_day.strftime cannot be used, since it does not support dates < 1900
|
||||
return unicode(str(birth_day.year) + gd['month'] + gd['day'] + gd['serial'] + gd['checksum'])
|
||||
return six.text_type(str(birth_day.year) + gd['month'] + gd['day'] + gd['serial'] + gd['checksum'])
|
||||
|
||||
def format_organisation_number(gd):
|
||||
if gd['century'] is None:
|
||||
|
@ -73,7 +74,7 @@ def format_organisation_number(gd):
|
|||
else:
|
||||
century = gd['century']
|
||||
|
||||
return unicode(century + gd['year'] + gd['month'] + gd['day'] + gd['serial'] + gd['checksum'])
|
||||
return six.text_type(century + gd['year'] + gd['month'] + gd['day'] + gd['serial'] + gd['checksum'])
|
||||
|
||||
def valid_organisation(gd):
|
||||
return gd['century'] in (None, 16) and \
|
||||
|
|
|
@ -80,10 +80,10 @@ class TRIdentificationNumberField(Field):
|
|||
raise ValidationError(self.error_messages['invalid'])
|
||||
if int(value[0]) == 0:
|
||||
raise ValidationError(self.error_messages['invalid'])
|
||||
chksum = (sum([int(value[i]) for i in xrange(0,9,2)])*7-
|
||||
sum([int(value[i]) for i in xrange(1,9,2)])) % 10
|
||||
chksum = (sum([int(value[i]) for i in range(0, 9, 2)]) * 7 -
|
||||
sum([int(value[i]) for i in range(1, 9, 2)])) % 10
|
||||
if chksum != int(value[9]) or \
|
||||
(sum([int(value[i]) for i in xrange(10)]) % 10) != int(value[10]):
|
||||
(sum([int(value[i]) for i in range(10)]) % 10) != int(value[10]):
|
||||
raise ValidationError(self.error_messages['invalid'])
|
||||
return value
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ class BaseTest(TestCase):
|
|||
cycle.
|
||||
"""
|
||||
data = {
|
||||
'messages': ['Test message %d' % x for x in xrange(10)],
|
||||
'messages': ['Test message %d' % x for x in range(10)],
|
||||
}
|
||||
show_url = reverse('django.contrib.messages.tests.urls.show')
|
||||
for level in ('debug', 'info', 'success', 'warning', 'error'):
|
||||
|
@ -170,7 +170,7 @@ class BaseTest(TestCase):
|
|||
@override_settings(MESSAGE_LEVEL=constants.DEBUG)
|
||||
def test_with_template_response(self):
|
||||
data = {
|
||||
'messages': ['Test message %d' % x for x in xrange(10)],
|
||||
'messages': ['Test message %d' % x for x in range(10)],
|
||||
}
|
||||
show_url = reverse('django.contrib.messages.tests.urls.show_template_response')
|
||||
for level in self.levels.keys():
|
||||
|
@ -194,7 +194,7 @@ class BaseTest(TestCase):
|
|||
before a GET.
|
||||
"""
|
||||
data = {
|
||||
'messages': ['Test message %d' % x for x in xrange(10)],
|
||||
'messages': ['Test message %d' % x for x in range(10)],
|
||||
}
|
||||
show_url = reverse('django.contrib.messages.tests.urls.show')
|
||||
messages = []
|
||||
|
@ -226,7 +226,7 @@ class BaseTest(TestCase):
|
|||
when one attempts to store a message.
|
||||
"""
|
||||
data = {
|
||||
'messages': ['Test message %d' % x for x in xrange(10)],
|
||||
'messages': ['Test message %d' % x for x in range(10)],
|
||||
}
|
||||
show_url = reverse('django.contrib.messages.tests.urls.show')
|
||||
for level in ('debug', 'info', 'success', 'warning', 'error'):
|
||||
|
@ -251,7 +251,7 @@ class BaseTest(TestCase):
|
|||
raised if 'fail_silently' = True
|
||||
"""
|
||||
data = {
|
||||
'messages': ['Test message %d' % x for x in xrange(10)],
|
||||
'messages': ['Test message %d' % x for x in range(10)],
|
||||
'fail_silently': True,
|
||||
}
|
||||
show_url = reverse('django.contrib.messages.tests.urls.show')
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue