diff --git a/combo/apps/assets/templatetags/assets.py b/combo/apps/assets/templatetags/assets.py
index 03938d31..da0e81a3 100644
--- a/combo/apps/assets/templatetags/assets.py
+++ b/combo/apps/assets/templatetags/assets.py
@@ -16,6 +16,7 @@
from django import template
from django.db.models.fields.files import ImageFieldFile
+from django.utils import six
from sorl.thumbnail.shortcuts import get_thumbnail
@@ -36,7 +37,7 @@ def asset_url(*args, **kwargs):
asset = asset_object
break
- if isinstance(asset_object, basestring):
+ if isinstance(asset_object, six.string_types):
try:
asset = Asset.objects.get(key=asset_object).asset
break
diff --git a/combo/apps/calendar/utils.py b/combo/apps/calendar/utils.py
index 846f0d7b..fb7e001e 100644
--- a/combo/apps/calendar/utils.py
+++ b/combo/apps/calendar/utils.py
@@ -16,12 +16,11 @@
import datetime
import math
-import urllib
-
from django.conf import settings
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.utils.dateparse import parse_datetime
+from django.utils.http import urlencode
from django.utils.timezone import localtime, make_aware
from django.utils.translation import ugettext_lazy as _
@@ -39,7 +38,7 @@ def get_wcs_services():
def get_chrono_service():
- for chrono_key, chrono_site in get_services('chrono').iteritems():
+ for chrono_key, chrono_site in get_services('chrono').items():
if not chrono_site.get('secondary', True):
chrono_site['slug'] = chrono_key
return chrono_site
@@ -128,7 +127,7 @@ def get_form_url_with_params(cell, data):
}
wcs_key, wcs_slug = cell.formdef_reference.split(':')
wcs = get_wcs_services().get(wcs_key)
- url = '%s%s/?%s' % (wcs['url'], wcs_slug, urllib.urlencode(session_vars))
+ url = '%s%s/?%s' % (wcs['url'], wcs_slug, urlencode(session_vars))
return url
@@ -189,7 +188,7 @@ class Calendar(object):
"""return the first available slot that has enough
consecutive available slots to be allowed for booking
"""
- required_contiguous_slots = self.min_duration.seconds / self.offset.seconds
+ required_contiguous_slots = self.min_duration.seconds // self.offset.seconds
for day in self.days:
slots = day.slots
for idx in range(len(slots) - required_contiguous_slots):
diff --git a/combo/apps/calendar/views.py b/combo/apps/calendar/views.py
index 136279c6..248590ff 100644
--- a/combo/apps/calendar/views.py
+++ b/combo/apps/calendar/views.py
@@ -16,6 +16,7 @@
from django.contrib import messages
from django.http import HttpResponseRedirect
+from django.utils.encoding import force_text
from django.views.generic import View, DetailView
from django.views.generic.detail import SingleObjectMixin
@@ -36,7 +37,7 @@ class BookingView(SingleObjectMixin, View):
try:
form.is_valid()
except ValueError as exc:
- messages.error(request, exc.message)
+ messages.error(request, force_text(exc))
redirect_url = '%s?%s' % (
cell.page.get_online_url(), request.GET.urlencode())
return HttpResponseRedirect(redirect_url)
diff --git a/combo/apps/family/utils.py b/combo/apps/family/utils.py
index f95f84ae..60b533ac 100644
--- a/combo/apps/family/utils.py
+++ b/combo/apps/family/utils.py
@@ -21,7 +21,7 @@ from combo.utils import requests
def get_passerelle_service():
if hasattr(settings, 'KNOWN_SERVICES') and settings.KNOWN_SERVICES.get('passerelle'):
- return settings.KNOWN_SERVICES['passerelle'].values()[0]
+ return list(settings.KNOWN_SERVICES['passerelle'].values())[0]
def is_family_enabled():
return get_passerelle_service() and hasattr(settings, 'FAMILY_SERVICE')
diff --git a/combo/apps/lingo/management/commands/notify_new_remote_invoices.py b/combo/apps/lingo/management/commands/notify_new_remote_invoices.py
index 9bca307f..b3e17ed7 100644
--- a/combo/apps/lingo/management/commands/notify_new_remote_invoices.py
+++ b/combo/apps/lingo/management/commands/notify_new_remote_invoices.py
@@ -35,5 +35,5 @@ class Command(BaseCommand):
for regie in Regie.objects.exclude(webservice_url=''):
try:
regie.notify_new_remote_invoices()
- except Exception, e:
+ except Exception as e:
logger.exception('error while notifying new remote invoices: %s', e)
diff --git a/combo/apps/lingo/manager_views.py b/combo/apps/lingo/manager_views.py
index c40c0421..cf761ab4 100644
--- a/combo/apps/lingo/manager_views.py
+++ b/combo/apps/lingo/manager_views.py
@@ -20,6 +20,7 @@ from dateutil import parser as date_parser
from django.core.urlresolvers import reverse_lazy
from django.db.models import Q
+from django.utils import six
from django.utils.timezone import make_aware
from django.views.generic import (CreateView, UpdateView, ListView,
DeleteView, TemplateView)
@@ -93,7 +94,10 @@ def download_transactions_csv(request):
str(transaction.amount)]
for item in transaction.items.all():
row.extend([item.subject, str(item.amount)])
- writer.writerow([unicode(x).encode('utf-8') for x in row])
+ if six.PY3:
+ writer.writerow([x for x in row])
+ else:
+ writer.writerow([unicode(x).encode('utf-8') for x in row])
return response
diff --git a/combo/apps/lingo/models.py b/combo/apps/lingo/models.py
index e8478c66..f93bf063 100644
--- a/combo/apps/lingo/models.py
+++ b/combo/apps/lingo/models.py
@@ -19,7 +19,6 @@
import datetime
import json
import logging
-import urlparse
from decimal import Decimal
@@ -36,8 +35,10 @@ from django.utils import timezone, dateparse
from django.core.mail import EmailMultiAlternatives
from django.core.urlresolvers import reverse
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
+from django.utils.encoding import python_2_unicode_compatible
from django.utils.formats import localize
from django.utils.http import urlencode
+from django.utils.six.moves.urllib import parse as urlparse
from django.contrib.auth.models import User
from django.template.loader import render_to_string
@@ -84,6 +85,7 @@ def build_remote_item(data, regie):
no_online_payment_reason=data.get('no_online_payment_reason'))
+@python_2_unicode_compatible
class Regie(models.Model):
label = models.CharField(verbose_name=_('Label'), max_length=64)
slug = models.SlugField(unique=True, verbose_name=_('Identifier'),
@@ -127,7 +129,7 @@ class Regie(models.Model):
def natural_key(self):
return (self.slug,)
- def __unicode__(self):
+ def __str__(self):
return self.label
def get_text_on_success(self):
@@ -271,7 +273,7 @@ class Regie(models.Model):
return
pending_invoices = self.get_remote_pending_invoices()
notification_ids = []
- for uuid, items in pending_invoices.iteritems():
+ for uuid, items in pending_invoices.items():
try:
user = UserSAMLIdentifier.objects.get(name_id=uuid).user
except UserSAMLIdentifier.DoesNotExist:
@@ -534,7 +536,7 @@ class LingoBasketCell(CellBase):
for items in regies.values():
items['total'] = sum([x.amount for x in items['items']])
- context['regies'] = regies.values()
+ context['regies'] = sorted(regies.values(), key=lambda x: x['regie'].label)
return basket_template.render(context)
diff --git a/combo/apps/lingo/views.py b/combo/apps/lingo/views.py
index f469aea7..f06976ff 100644
--- a/combo/apps/lingo/views.py
+++ b/combo/apps/lingo/views.py
@@ -238,7 +238,7 @@ class ValidateTransactionApiView(View):
except eopayment.ResponseError as e:
logger.error(u'failed in validation operation: %s', e)
response = HttpResponse(content_type='application/json')
- response.write(json.dumps({'err': 1, 'e': unicode(e)}))
+ response.write(json.dumps({'err': 1, 'e': force_text(e)}))
return response
logger.info(u'bank validation result: %r', result)
@@ -279,7 +279,7 @@ class CancelTransactionApiView(View):
except eopayment.ResponseError as e:
logger.error(u'failed in cancel operation: %s', e)
response = HttpResponse(content_type='application/json')
- response.write(json.dumps({'err': 1, 'e': unicode(e)}))
+ response.write(json.dumps({'err': 1, 'e': force_text(e)}))
return response
logger.info(u'bank cancellation result: %r', result)
@@ -414,7 +414,7 @@ class PaymentView(View):
'eopayment_order_id': smart_text(payment_response.order_id),
'eopayment_response': repr(payment_response),
}
- for k, v in payment_response.bank_data.iteritems():
+ for k, v in payment_response.bank_data.items():
extra_info['eopayment_bank_data_' + k] = smart_text(v)
if not payment_response.signed and not payment_response.result == eopayment.CANCELLED:
# we accept unsigned cancellation requests as some platforms do
@@ -494,9 +494,9 @@ class CallbackView(PaymentView):
try:
self.handle_response(request, backend_response, **kwargs)
except UnknownPaymentException as e:
- raise Http404(unicode(e))
+ raise Http404(force_text(e))
except PaymentException as e:
- return HttpResponseBadRequest(unicode(e))
+ return HttpResponseBadRequest(force_text(e))
return HttpResponse()
def get(self, request, *args, **kwargs):
diff --git a/combo/apps/maps/models.py b/combo/apps/maps/models.py
index b5af1f15..e700e4e0 100644
--- a/combo/apps/maps/models.py
+++ b/combo/apps/maps/models.py
@@ -18,6 +18,8 @@ import json
from django.core import serializers
from django.db import models
+from django.utils import six
+from django.utils.encoding import python_2_unicode_compatible
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse_lazy
@@ -88,6 +90,7 @@ class MapLayerManager(models.Manager):
return self.get(slug=slug)
+@python_2_unicode_compatible
class MapLayer(models.Model):
objects = MapLayerManager()
@@ -123,7 +126,7 @@ class MapLayer(models.Model):
self.slug = slug
super(MapLayer, self).save(*args, **kwargs)
- def __unicode__(self):
+ def __str__(self):
return self.label
def natural_key(self):
@@ -204,7 +207,7 @@ class MapLayer(models.Model):
def match(feature):
for geo_property in feature['properties'].values():
- if not isinstance(geo_property, basestring):
+ if not isinstance(geo_property, six.string_types):
continue
if query in slugify(geo_property):
return True
diff --git a/combo/apps/momo/management/commands/update_momo_manifest.py b/combo/apps/momo/management/commands/update_momo_manifest.py
index 5395bcd8..68fddfc2 100644
--- a/combo/apps/momo/management/commands/update_momo_manifest.py
+++ b/combo/apps/momo/management/commands/update_momo_manifest.py
@@ -14,13 +14,12 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see