Browse Source

2to3 --nobackups --write .

pitchum 7 years ago
parent
commit
73580928fc

+ 2 - 2
ffdnispdb/__init__.py

@@ -15,9 +15,9 @@ cache = Cache()
 mail = Mail()
 mail = Mail()
 
 
 def get_locale():
 def get_locale():
-    if request.cookies.get('locale') in current_app.config['LANGUAGES'].keys():
+    if request.cookies.get('locale') in list(current_app.config['LANGUAGES'].keys()):
         return request.cookies.get('locale')
         return request.cookies.get('locale')
-    return request.accept_languages.best_match(current_app.config['LANGUAGES'].keys(), 'en')
+    return request.accept_languages.best_match(list(current_app.config['LANGUAGES'].keys()), 'en')
 
 
 
 
 def create_app(config={}):
 def create_app(config={}):

+ 7 - 7
ffdnispdb/constants.py

@@ -3,13 +3,13 @@
 from flask.ext.babel import lazy_gettext as _
 from flask.ext.babel import lazy_gettext as _
 
 
 STEPS = {
 STEPS = {
-    1: _(u'Project considered'),
-    2: _(u'Primary members found'),
-    3: _(u'Legal structure being created'),
-    4: _(u'Legal structure created'),
-    5: _(u'Base tools created (bank account, first members)'),
-    6: _(u'ISP partially functional (first subscribers, maybe in degraded mode)'),
-    7: _(u'ISP fully working')
+    1: _('Project considered'),
+    2: _('Primary members found'),
+    3: _('Legal structure being created'),
+    4: _('Legal structure created'),
+    5: _('Base tools created (bank account, first members)'),
+    6: _('ISP partially functional (first subscribers, maybe in degraded mode)'),
+    7: _('ISP fully working')
 }
 }
 
 
 STEPS_LABELS = {
 STEPS_LABELS = {

+ 22 - 22
ffdnispdb/crawler.py

@@ -28,7 +28,7 @@ class Crawler(object):
 
 
     MAX_JSON_SIZE = 1 * 1024 * 1024
     MAX_JSON_SIZE = 1 * 1024 * 1024
 
 
-    escape = staticmethod(lambda x: unicode(str(x), 'utf8') if type(x) != unicode else x)
+    escape = staticmethod(lambda x: str(str(x), 'utf8') if type(x) != str else x)
 
 
     def __init__(self):
     def __init__(self):
         self.success = False
         self.success = False
@@ -39,18 +39,18 @@ class Crawler(object):
 
 
     def m(self, msg, evt=None):
     def m(self, msg, evt=None):
         if not evt:
         if not evt:
-            return u'%s\n' % msg
+            return '%s\n' % msg
         else:
         else:
-            return u''
+            return ''
 
 
     def err(self, msg, *args):
     def err(self, msg, *args):
-        return self.m(u'! %s' % msg, *args)
+        return self.m('! %s' % msg, *args)
 
 
     def warn(self, msg):
     def warn(self, msg):
-        return self.m(u'@ %s' % msg)
+        return self.m('@ %s' % msg)
 
 
     def info(self, msg):
     def info(self, msg):
-        return self.m(u'\u2013 %s' % msg)
+        return self.m('\u2013 %s' % msg)
 
 
     def abort(self, msg):
     def abort(self, msg):
         raise NotImplemented
         raise NotImplemented
@@ -70,9 +70,9 @@ class Crawler(object):
     def format_validation_errors(self, errs):
     def format_validation_errors(self, errs):
         r = []
         r = []
         for e in errs:
         for e in errs:
-            r.append(u'    %s: %s' % ('.'.join(list(e.schema_path)[1:]), e.message))
+            r.append('    %s: %s' % ('.'.join(list(e.schema_path)[1:]), e.message))
 
 
-        return u'\n'.join(r) + '\n'
+        return '\n'.join(r) + '\n'
 
 
     def pre_done_cb(self, *args):
     def pre_done_cb(self, *args):
         pass
         pass
@@ -126,7 +126,7 @@ class Crawler(object):
             # so that it's logged.
             # so that it's logged.
             tb = sys.exc_info()[2]
             tb = sys.exc_info()[2]
             yield self.abort('Unexpected request exception')
             yield self.abort('Unexpected request exception')
-            raise e, None, tb
+            raise e.with_traceback(tb)
 
 
         if r is None:
         if r is None:
             yield self.abort('Connection could not be established, aborting')
             yield self.abort('Connection could not be established, aborting')
@@ -154,7 +154,7 @@ class Crawler(object):
                 yield self.warn('Invalid max-age ' + esc(_maxage))
                 yield self.warn('Invalid max-age ' + esc(_maxage))
 
 
             yield self.info('Cache control: ' + self.bold(esc(
             yield self.info('Cache control: ' + self.bold(esc(
-                ', '.join([k + '=' + v if type(v) != bool else k for k, v in cachecontrol.iteritems()]))
+                ', '.join([k + '=' + v if type(v) != bool else k for k, v in cachecontrol.items()]))
             ))
             ))
 
 
         _expires = r.headers.get('expires')
         _expires = r.headers.get('expires')
@@ -318,36 +318,36 @@ class PrettyValidator(Crawler):
         super(PrettyValidator, self).__init__(*args, **kwargs)
         super(PrettyValidator, self).__init__(*args, **kwargs)
         self.session = session
         self.session = session
         self.sesskey = sesskey
         self.sesskey = sesskey
-        self.escape = lambda x: escape(unicode(str(x), 'utf8') if type(x) != unicode else x)
+        self.escape = lambda x: escape(str(str(x), 'utf8') if type(x) != str else x)
 
 
     def m(self, msg, evt=None):
     def m(self, msg, evt=None):
-        return u'%sdata: %s\n\n' % (u'event: %s\n' % evt if evt else '', msg)
+        return '%sdata: %s\n\n' % ('event: %s\n' % evt if evt else '', msg)
 
 
     def err(self, msg, *args):
     def err(self, msg, *args):
-        return self.m(u'<strong style="color: crimson">!</strong> %s' % msg, *args)
+        return self.m('<strong style="color: crimson">!</strong> %s' % msg, *args)
 
 
     def warn(self, msg):
     def warn(self, msg):
-        return self.m(u'<strong style="color: dodgerblue">@</strong> %s' % msg)
+        return self.m('<strong style="color: dodgerblue">@</strong> %s' % msg)
 
 
     def info(self, msg):
     def info(self, msg):
-        return self.m(u'&ndash; %s' % msg)
+        return self.m('&ndash; %s' % msg)
 
 
     def abort(self, msg):
     def abort(self, msg):
-        return (self.m(u'<br />== <span style="color: crimson">%s</span>' % msg) +
+        return (self.m('<br />== <span style="color: crimson">%s</span>' % msg) +
                 self.m(json.dumps({'closed': 1}), 'control'))
                 self.m(json.dumps({'closed': 1}), 'control'))
 
 
     def bold(self, msg):
     def bold(self, msg):
-        return u'<strong>%s</strong>' % msg
+        return '<strong>%s</strong>' % msg
 
 
     def italics(self, msg):
     def italics(self, msg):
-        return u'<em>%s</em>' % msg
+        return '<em>%s</em>' % msg
 
 
     def color(self, color, msg):
     def color(self, color, msg):
-        return u'<span style="color: %s">%s</span>' % (color, msg)
+        return '<span style="color: %s">%s</span>' % (color, msg)
 
 
     def format_validation_errors(self, errs):
     def format_validation_errors(self, errs):
         lns = super(PrettyValidator, self).format_validation_errors(errs)
         lns = super(PrettyValidator, self).format_validation_errors(errs)
-        buf = u''
+        buf = ''
         for l in lns.split('\n'):
         for l in lns.split('\n'):
             buf += self.m(self.escape(l))
             buf += self.m(self.escape(l))
         return buf
         return buf
@@ -380,6 +380,6 @@ class WebValidator(PrettyValidator):
 class TextValidator(Crawler):
 class TextValidator(Crawler):
 
 
     def abort(self, msg):
     def abort(self, msg):
-        res = u'FATAL ERROR: %s\n' % msg
-        pad = u'=' * (len(res) - 1) + '\n'
+        res = 'FATAL ERROR: %s\n' % msg
+        pad = '=' * (len(res) - 1) + '\n'
         return self.m(pad + res + pad)
         return self.m(pad + res + pad)

+ 17 - 17
ffdnispdb/cron_task.py

@@ -65,7 +65,7 @@ def gen_reactivate_key(isp):
 
 
 
 
 def send_warning_email(isp, debug_msg):
 def send_warning_email(isp, debug_msg):
-    msg = Message(u"Problem while updating your ISP's data", sender=app.config['EMAIL_SENDER'])
+    msg = Message("Problem while updating your ISP's data", sender=app.config['EMAIL_SENDER'])
     msg.body = """
     msg.body = """
 Hello,
 Hello,
 
 
@@ -89,7 +89,7 @@ https://db.ffdn.org
     """.strip() % (isp.complete_name, isp.json_url, debug_msg.strip(),
     """.strip() % (isp.complete_name, isp.json_url, debug_msg.strip(),
                  url_for('ispdb.reactivate_isp', projectid=isp.id), gen_reactivate_key(isp))
                  url_for('ispdb.reactivate_isp', projectid=isp.id), gen_reactivate_key(isp))
     msg.add_recipient(isp.tech_email)
     msg.add_recipient(isp.tech_email)
-    print u'    Sending notification email to %s' % (isp.tech_email)
+    print('    Sending notification email to %s' % (isp.tech_email))
     mail.send(msg)
     mail.send(msg)
 
 
 
 
@@ -102,11 +102,11 @@ try:
                                 ISP.update_error_strike < 3)\
                                 ISP.update_error_strike < 3)\
             .order_by(ISP.last_update_success):
             .order_by(ISP.last_update_success):
         try:
         try:
-            print u'%s: Attempting to update %s' % (datetime.now(), isp)
-            print u'    last successful update=%s' % (utils.tosystemtz(isp.last_update_success))
-            print u'    last update attempt=%s' % (utils.tosystemtz(isp.last_update_attempt))
-            print u'    next update was scheduled %s ago' % (utils.utcnow() - isp.next_update)
-            print u'    strike=%d' % (isp.update_error_strike)
+            print('%s: Attempting to update %s' % (datetime.now(), isp))
+            print('    last successful update=%s' % (utils.tosystemtz(isp.last_update_success)))
+            print('    last update attempt=%s' % (utils.tosystemtz(isp.last_update_attempt)))
+            print('    next update was scheduled %s ago' % (utils.utcnow() - isp.next_update))
+            print('    strike=%d' % (isp.update_error_strike))
 
 
             isp.last_update_attempt = utils.utcnow()
             isp.last_update_attempt = utils.utcnow()
             db.session.add(isp)
             db.session.add(isp)
@@ -129,15 +129,15 @@ try:
                 isp.next_update = utils.utcnow() + timedelta(seconds=validator.jdict_max_age)
                 isp.next_update = utils.utcnow() + timedelta(seconds=validator.jdict_max_age)
                 db.session.add(isp)
                 db.session.add(isp)
                 db.session.commit()
                 db.session.commit()
-                print u'%s: Error while updating:' % (datetime.now())
+                print('%s: Error while updating:' % (datetime.now()))
                 if isp.update_error_strike >= 3:
                 if isp.update_error_strike >= 3:
-                    print u'    three strikes, you\'re out'
+                    print('    three strikes, you\'re out')
                     send_warning_email(isp, log)
                     send_warning_email(isp, log)
 
 
-                print log.rstrip().encode('utf-8') + '\n'
+                print(log.rstrip().encode('utf-8') + '\n')
                 if exc:
                 if exc:
-                    print u'Unexpected exception in the validator: %r' % exc
-                    print exc_trace
+                    print('Unexpected exception in the validator: %r' % exc)
+                    print(exc_trace)
 
 
                 continue
                 continue
 
 
@@ -150,10 +150,10 @@ try:
             db.session.add(isp)
             db.session.add(isp)
             db.session.commit()
             db.session.commit()
 
 
-            print u'%s: Update successful !' % (datetime.now())
-            print u'    next update is scheduled for %s\n' % (isp.next_update)
+            print('%s: Update successful !' % (datetime.now()))
+            print('    next update is scheduled for %s\n' % (isp.next_update))
         except Timeout:
         except Timeout:
-            print u'%s: Timeout while updating:' % (datetime.now())
+            print('%s: Timeout while updating:' % (datetime.now()))
             isp = ISP.query.get(isp.id)
             isp = ISP.query.get(isp.id)
             isp.update_error_strike += 1
             isp.update_error_strike += 1
             db.session.add(isp)
             db.session.add(isp)
@@ -161,8 +161,8 @@ try:
             if isp.update_error_strike >= 3:
             if isp.update_error_strike >= 3:
                 send_warning_email(isp, 'Your ISP took more then 18 seconds to process. '
                 send_warning_email(isp, 'Your ISP took more then 18 seconds to process. '
                                         'Having problems with your webserver ?')
                                         'Having problems with your webserver ?')
-                print u'    three strikes, you\'re out'
-            print traceback.format_exc()
+                print('    three strikes, you\'re out')
+            print(traceback.format_exc())
 
 
 except ScriptTimeout:
 except ScriptTimeout:
     pass
     pass

+ 2 - 2
ffdnispdb/default_settings.py

@@ -7,8 +7,8 @@ CRAWLER_DEFAULT_CACHE_TIME = 60 * 60 * 12  # 12 hours
 CRAWLER_CRON_INTERVAL = 60 * 20  # used to return valid cache info in the API
 CRAWLER_CRON_INTERVAL = 60 * 20  # used to return valid cache info in the API
 SYSTEM_TIME_ZONE = 'Europe/Paris'
 SYSTEM_TIME_ZONE = 'Europe/Paris'
 LANGUAGES = {
 LANGUAGES = {
-    'en': u'English',
-    'fr': u'Français',
+    'en': 'English',
+    'fr': 'Français',
 }
 }
 ISP_FORM_GEOJSON_MAX_SIZE = 256 * 1024
 ISP_FORM_GEOJSON_MAX_SIZE = 256 * 1024
 ISP_FORM_GEOJSON_MAX_SIZE_TOTAL = 1024 * 1024
 ISP_FORM_GEOJSON_MAX_SIZE_TOTAL = 1024 * 1024

+ 58 - 58
ffdnispdb/forms.py

@@ -1,6 +1,6 @@
 from functools import partial
 from functools import partial
 import itertools
 import itertools
-import urlparse
+import urllib.parse
 import json
 import json
 import collections
 import collections
 from flask import current_app
 from flask import current_app
@@ -46,7 +46,7 @@ class MyFormField(FormField):
 
 
     @property
     @property
     def flattened_errors(self):
     def flattened_errors(self):
-        return list(itertools.chain.from_iterable(self.errors.values()))
+        return list(itertools.chain.from_iterable(list(self.errors.values())))
 
 
 
 
 class GeoJSONField(TextField):
 class GeoJSONField(TextField):
@@ -56,12 +56,12 @@ class GeoJSONField(TextField):
         if valuelist and valuelist[0]:
         if valuelist and valuelist[0]:
             max_size = current_app.config['ISP_FORM_GEOJSON_MAX_SIZE']
             max_size = current_app.config['ISP_FORM_GEOJSON_MAX_SIZE']
             if len(valuelist[0]) > max_size:
             if len(valuelist[0]) > max_size:
-                raise ValueError(_(u'JSON value too big, must be less than %(max_size)s',
+                raise ValueError(_('JSON value too big, must be less than %(max_size)s',
                                    max_size=filesize_fmt(max_size)))
                                    max_size=filesize_fmt(max_size)))
             try:
             try:
                 self.data = json.loads(valuelist[0], object_pairs_hook=collections.OrderedDict)
                 self.data = json.loads(valuelist[0], object_pairs_hook=collections.OrderedDict)
             except Exception as e:
             except Exception as e:
-                raise ValueError(_(u'Not a valid JSON value'))
+                raise ValueError(_('Not a valid JSON value'))
         elif valuelist and valuelist[0].strip() == '':
         elif valuelist and valuelist[0].strip() == '':
             self.data = None  # if an empty string was passed, set data as None
             self.data = None  # if an empty string was passed, set data as None
 
 
@@ -76,10 +76,10 @@ class GeoJSONField(TextField):
     def pre_validate(self, form):
     def pre_validate(self, form):
         if self.data is not None:
         if self.data is not None:
             if not validate_geojson(self.data):
             if not validate_geojson(self.data):
-                raise StopValidation(_(u'Invalid GeoJSON, please check it'))
+                raise StopValidation(_('Invalid GeoJSON, please check it'))
             if not check_geojson_spatialite(self.data):
             if not check_geojson_spatialite(self.data):
                 current_app.logger.error('Spatialite could not decode the following GeoJSON: %s', self.data)
                 current_app.logger.error('Spatialite could not decode the following GeoJSON: %s', self.data)
-                raise StopValidation(_(u'Unable to store GeoJSON in database'))
+                raise StopValidation(_('Unable to store GeoJSON in database'))
 
 
 
 
 class Unique(object):
 class Unique(object):
@@ -89,7 +89,7 @@ class Unique(object):
         self.model = model
         self.model = model
         self.field = field
         self.field = field
         if not message:
         if not message:
-            message = _(u'this element already exists')
+            message = _('this element already exists')
         self.message = message
         self.message = message
 
 
     def __call__(self, form, field):
     def __call__(self, form, field):
@@ -112,59 +112,59 @@ TECHNOLOGIES_CHOICES = (
 
 
 
 
 class CoveredArea(InsecureForm):
 class CoveredArea(InsecureForm):
-    name = TextField(_(u'name'), widget=partial(TextInput(), class_='input-medium', placeholder=_(u'Area')))
-    technologies = SelectMultipleField(_(u'technologies'), choices=TECHNOLOGIES_CHOICES,
-                                       widget=partial(Select(True), **{'class': 'selectpicker', 'data-title': _(u'Technologies deployed')}))
+    name = TextField(_('name'), widget=partial(TextInput(), class_='input-medium', placeholder=_('Area')))
+    technologies = SelectMultipleField(_('technologies'), choices=TECHNOLOGIES_CHOICES,
+                                       widget=partial(Select(True), **{'class': 'selectpicker', 'data-title': _('Technologies deployed')}))
     area = GeoJSONField(_('area'), widget=partial(TextArea(), class_='geoinput'))
     area = GeoJSONField(_('area'), widget=partial(TextArea(), class_='geoinput'))
 
 
     def validate(self, *args, **kwargs):
     def validate(self, *args, **kwargs):
         r = super(CoveredArea, self).validate(*args, **kwargs)
         r = super(CoveredArea, self).validate(*args, **kwargs)
         if bool(self.name.data) != bool(self.technologies.data):
         if bool(self.name.data) != bool(self.technologies.data):
-            self._fields['name'].errors += [_(u'You must fill both fields')]
+            self._fields['name'].errors += [_('You must fill both fields')]
             r = False
             r = False
         return r
         return r
 
 
 
 
 class OtherWebsites(InsecureForm):
 class OtherWebsites(InsecureForm):
-    name = TextField(_(u'name'), widget=partial(TextInput(), class_='input-small', placeholder=_(u'Name')))
-    url = TextField(_(u'url'), widget=partial(TextInput(), class_='input-medium', placeholder=_(u'URL')),
+    name = TextField(_('name'), widget=partial(TextInput(), class_='input-small', placeholder=_('Name')))
+    url = TextField(_('url'), widget=partial(TextInput(), class_='input-medium', placeholder=_('URL')),
                     validators=[Optional(), URL(require_tld=True)])
                     validators=[Optional(), URL(require_tld=True)])
 
 
 
 
-STEP_CHOICES = [(k, LazyProxy(lambda k, s: u'%u - %s' % (k, s), k, STEPS[k], enable_cache=False)) for k in STEPS]
+STEP_CHOICES = [(k, LazyProxy(lambda k, s: '%u - %s' % (k, s), k, STEPS[k], enable_cache=False)) for k in STEPS]
 
 
 
 
 class ProjectForm(Form):
 class ProjectForm(Form):
-    name = TextField(_(u'full name'), description=[_(u'E.g. French Data Network')],
+    name = TextField(_('full name'), description=[_('E.g. French Data Network')],
                      validators=[DataRequired(), Length(min=2), Unique(ISP, ISP.name)])
                      validators=[DataRequired(), Length(min=2), Unique(ISP, ISP.name)])
-    shortname = TextField(_(u'short name'), description=[_(u'E.g. FDN')],
+    shortname = TextField(_('short name'), description=[_('E.g. FDN')],
                           validators=[Optional(), Length(min=2, max=15), Unique(ISP, ISP.shortname)])
                           validators=[Optional(), Length(min=2, max=15), Unique(ISP, ISP.shortname)])
-    description = TextField(_(u'description'), description=[None, _(u'Short text describing the project')])
-    logo_url = TextField(_(u'logo url'), validators=[Optional(), URL(require_tld=True)])
-    website = TextField(_(u'website'), validators=[Optional(), URL(require_tld=True)])
+    description = TextField(_('description'), description=[None, _('Short text describing the project')])
+    logo_url = TextField(_('logo url'), validators=[Optional(), URL(require_tld=True)])
+    website = TextField(_('website'), validators=[Optional(), URL(require_tld=True)])
     other_websites = FieldList(MyFormField(OtherWebsites, widget=partial(InputListWidget(), class_='formfield')),
     other_websites = FieldList(MyFormField(OtherWebsites, widget=partial(InputListWidget(), class_='formfield')),
                                min_entries=1, widget=InputListWidget(),
                                min_entries=1, widget=InputListWidget(),
-                               description=[None, _(u'Additional websites that you host (e.g. wiki, etherpad...)')])
-    contact_email = TextField(_(u'contact email'), validators=[Optional(), Email()],
-                              description=[None, _(u'General contact email address')])
-    main_ml = TextField(_(u'main mailing list'), validators=[Optional(), Email()],
-                        description=[None, _(u'Address of your main mailing list')])
-    creation_date = DateField(_(u'creation date'), validators=[Optional()], widget=partial(TextInput(), placeholder=_(u'YYYY-mm-dd')),
-                              description=[None, _(u'Date at which the legal structure for your project was created')])
-    chatrooms = FieldList(TextField(_(u'chatrooms')), min_entries=1, widget=InputListWidget(),
-                          description=[None, _(u'In URI form, e.g. <code>irc://irc.isp.net/#isp</code> or ' +
+                               description=[None, _('Additional websites that you host (e.g. wiki, etherpad...)')])
+    contact_email = TextField(_('contact email'), validators=[Optional(), Email()],
+                              description=[None, _('General contact email address')])
+    main_ml = TextField(_('main mailing list'), validators=[Optional(), Email()],
+                        description=[None, _('Address of your main mailing list')])
+    creation_date = DateField(_('creation date'), validators=[Optional()], widget=partial(TextInput(), placeholder=_('YYYY-mm-dd')),
+                              description=[None, _('Date at which the legal structure for your project was created')])
+    chatrooms = FieldList(TextField(_('chatrooms')), min_entries=1, widget=InputListWidget(),
+                          description=[None, _('In URI form, e.g. <code>irc://irc.isp.net/#isp</code> or ' +
                           '<code>xmpp:isp@chat.isp.net?join</code>')])
                           '<code>xmpp:isp@chat.isp.net?join</code>')])
     covered_areas = FieldList(MyFormField(CoveredArea, _('Covered Areas'), widget=partial(InputListWidget(), class_='formfield')),
     covered_areas = FieldList(MyFormField(CoveredArea, _('Covered Areas'), widget=partial(InputListWidget(), class_='formfield')),
                               min_entries=1, widget=InputListWidget(),
                               min_entries=1, widget=InputListWidget(),
-                              description=[None, _(u'Descriptive name of the covered areas and technologies deployed')])
-    latitude = DecimalField(_(u'latitude'), validators=[Optional(), NumberRange(min=-90, max=90)],
-                            description=[None, _(u'Coordinates of your registered office or usual meeting location. '
+                              description=[None, _('Descriptive name of the covered areas and technologies deployed')])
+    latitude = DecimalField(_('latitude'), validators=[Optional(), NumberRange(min=-90, max=90)],
+                            description=[None, _('Coordinates of your registered office or usual meeting location. '
                             '<strong>Required in order to appear on the map.</strong>')])
                             '<strong>Required in order to appear on the map.</strong>')])
-    longitude = DecimalField(_(u'longitude'), validators=[Optional(), NumberRange(min=-180, max=180)])
-    step = SelectField(_(u'progress step'), choices=STEP_CHOICES, coerce=int)
-    member_count = IntegerField(_(u'members'), validators=[Optional(), NumberRange(min=0)],
+    longitude = DecimalField(_('longitude'), validators=[Optional(), NumberRange(min=-180, max=180)])
+    step = SelectField(_('progress step'), choices=STEP_CHOICES, coerce=int)
+    member_count = IntegerField(_('members'), validators=[Optional(), NumberRange(min=0)],
                                 description=[None, _('Number of members')])
                                 description=[None, _('Number of members')])
-    subscriber_count = IntegerField(_(u'subscribers'), validators=[Optional(), NumberRange(min=0)],
+    subscriber_count = IntegerField(_('subscribers'), validators=[Optional(), NumberRange(min=0)],
                                     description=[None, _('Number of subscribers to an internet access')])
                                     description=[None, _('Number of subscribers to an internet access')])
 
 
     tech_email = TextField(_('Email'), validators=[Email(), DataRequired()], description=[None,
     tech_email = TextField(_('Email'), validators=[Email(), DataRequired()], description=[None,
@@ -173,20 +173,20 @@ class ProjectForm(Form):
     def validate(self, *args, **kwargs):
     def validate(self, *args, **kwargs):
         r = super(ProjectForm, self).validate(*args, **kwargs)
         r = super(ProjectForm, self).validate(*args, **kwargs)
         if (self.latitude.data is None) != (self.longitude.data is None):
         if (self.latitude.data is None) != (self.longitude.data is None):
-            self._fields['longitude'].errors += [_(u'You must fill both fields')]
+            self._fields['longitude'].errors += [_('You must fill both fields')]
             r = False
             r = False
         return r
         return r
 
 
     def validate_covered_areas(self, field):
     def validate_covered_areas(self, field):
-        if len(filter(lambda e: e['name'], field.data)) == 0:
+        if len([e for e in field.data if e['name']]) == 0:
             # not printed, whatever..
             # not printed, whatever..
-            raise ValidationError(_(u'You must specify at least one area'))
+            raise ValidationError(_('You must specify at least one area'))
 
 
         geojson_size = sum([len(ca.area.raw_data[0]) for ca in self.covered_areas if ca.area.raw_data])
         geojson_size = sum([len(ca.area.raw_data[0]) for ca in self.covered_areas if ca.area.raw_data])
         max_size = current_app.config['ISP_FORM_GEOJSON_MAX_SIZE_TOTAL']
         max_size = current_app.config['ISP_FORM_GEOJSON_MAX_SIZE_TOTAL']
         if geojson_size > max_size:
         if geojson_size > max_size:
             # TODO: XXX This is not printed !
             # TODO: XXX This is not printed !
-            raise ValidationError(gettext(u'The size of all GeoJSON data combined must not exceed %(max_size)s',
+            raise ValidationError(gettext('The size of all GeoJSON data combined must not exceed %(max_size)s',
                                           max_size=filesize_fmt(max_size)))
                                           max_size=filesize_fmt(max_size)))
 
 
     def to_json(self, json=None):
     def to_json(self, json=None):
@@ -222,7 +222,7 @@ class ProjectForm(Form):
         optstr('progressStatus', self.step.data)
         optstr('progressStatus', self.step.data)
         optstr('memberCount', self.member_count.data)
         optstr('memberCount', self.member_count.data)
         optstr('subscriberCount', self.subscriber_count.data)
         optstr('subscriberCount', self.subscriber_count.data)
-        optlist('chatrooms', filter(bool, self.chatrooms.data))  # remove empty strings
+        optlist('chatrooms', list(filter(bool, self.chatrooms.data)))  # remove empty strings
         optstr('coordinates', {'latitude': self.latitude.data, 'longitude': self.longitude.data}
         optstr('coordinates', {'latitude': self.latitude.data, 'longitude': self.longitude.data}
               if self.latitude.data else {})
               if self.latitude.data else {})
         optlist('coveredAreas', list(transform_covered_areas(self.covered_areas.data)))
         optlist('coveredAreas', list(transform_covered_areas(self.covered_areas.data)))
@@ -256,7 +256,7 @@ class ProjectForm(Form):
             set_attr('latitude', d=json['coordinates'])
             set_attr('latitude', d=json['coordinates'])
             set_attr('longitude', d=json['coordinates'])
             set_attr('longitude', d=json['coordinates'])
         if 'otherWebsites' in json:
         if 'otherWebsites' in json:
-            setattr(obj, 'other_websites', [{'name': n, 'url': w} for n, w in json['otherWebsites'].iteritems()])
+            setattr(obj, 'other_websites', [{'name': n, 'url': w} for n, w in json['otherWebsites'].items()])
         set_attr('covered_areas', 'coveredAreas')
         set_attr('covered_areas', 'coveredAreas')
         obj.tech_email = isp.tech_email
         obj.tech_email = isp.tech_email
         return cls(obj=obj)
         return cls(obj=obj)
@@ -265,53 +265,53 @@ class ProjectForm(Form):
 class URLField(TextField):
 class URLField(TextField):
 
 
     def _value(self):
     def _value(self):
-        if isinstance(self.data, basestring):
+        if isinstance(self.data, str):
             return self.data
             return self.data
         elif self.data is None:
         elif self.data is None:
             return ''
             return ''
         else:
         else:
-            return urlparse.urlunsplit(self.data)
+            return urllib.parse.urlunsplit(self.data)
 
 
     def process_formdata(self, valuelist):
     def process_formdata(self, valuelist):
         if valuelist:
         if valuelist:
             try:
             try:
-                self.data = urlparse.urlsplit(valuelist[0])
+                self.data = urllib.parse.urlsplit(valuelist[0])
             except:
             except:
                 self.data = None
                 self.data = None
-                raise ValidationError(_(u'Invalid URL'))
+                raise ValidationError(_('Invalid URL'))
 
 
 
 
 def is_url_unique(url):
 def is_url_unique(url):
-    if isinstance(url, basestring):
-        url = urlparse.urlsplit(url)
+    if isinstance(url, str):
+        url = urllib.parse.urlsplit(url)
     t = list(url)
     t = list(url)
     t[2] = ''
     t[2] = ''
-    u1 = urlparse.urlunsplit(t)
+    u1 = urllib.parse.urlunsplit(t)
     t[0] = 'http' if t[0] == 'https' else 'https'
     t[0] = 'http' if t[0] == 'https' else 'https'
-    u2 = urlparse.urlunsplit(t)
+    u2 = urllib.parse.urlunsplit(t)
     if ISP.query.filter(ISP.json_url.startswith(u1) | ISP.json_url.startswith(u2)).count() > 0:
     if ISP.query.filter(ISP.json_url.startswith(u1) | ISP.json_url.startswith(u2)).count() > 0:
         return False
         return False
     return True
     return True
 
 
 
 
 class ProjectJSONForm(Form):
 class ProjectJSONForm(Form):
-    json_url = URLField(_(u'base url'), description=[_(u'E.g. https://isp.com/'),
-                            _(u'A ressource implementing our JSON-Schema specification ' +
+    json_url = URLField(_('base url'), description=[_('E.g. https://isp.com/'),
+                            _('A ressource implementing our JSON-Schema specification ' +
                        'must exist at path /isp.json')])
                        'must exist at path /isp.json')])
-    tech_email = TextField(_(u'Email'), validators=[Email()], description=[None,
-                           _(u'Technical contact, in case of problems')])
+    tech_email = TextField(_('Email'), validators=[Email()], description=[None,
+                           _('Technical contact, in case of problems')])
 
 
     def validate_json_url(self, field):
     def validate_json_url(self, field):
         if not field.data.netloc:
         if not field.data.netloc:
-            raise ValidationError(_(u'Invalid URL'))
+            raise ValidationError(_('Invalid URL'))
 
 
         if field.data.scheme not in ('http', 'https'):
         if field.data.scheme not in ('http', 'https'):
-            raise ValidationError(_(u'Invalid URL (must be HTTP(S))'))
+            raise ValidationError(_('Invalid URL (must be HTTP(S))'))
 
 
         if not field.object_data and not is_url_unique(field.data):
         if not field.object_data and not is_url_unique(field.data):
-            raise ValidationError(_(u'This URL is already in our database'))
+            raise ValidationError(_('This URL is already in our database'))
 
 
 
 
 class RequestEditToken(Form):
 class RequestEditToken(Form):
-    tech_email = TextField(_(u'Tech Email'), validators=[Email()], description=[None,
-                           _(u'The Technical contact you provided while registering')])
+    tech_email = TextField(_('Tech Email'), validators=[Email()], description=[None,
+                           _('The Technical contact you provided while registering')])

+ 6 - 6
ffdnispdb/models.py

@@ -133,9 +133,9 @@ class ISP(db.Model):
     @property
     @property
     def complete_name(self):
     def complete_name(self):
         if 'shortname' in self.json:
         if 'shortname' in self.json:
-            return u'%s (%s)' % (self.json['shortname'], self.json['name'])
+            return '%s (%s)' % (self.json['shortname'], self.json['name'])
         else:
         else:
-            return u'%s' % self.json['name']
+            return '%s' % self.json['name']
 
 
     @staticmethod
     @staticmethod
     def str2date(_str):
     def str2date(_str):
@@ -160,7 +160,7 @@ class ISP(db.Model):
         return False
         return False
 
 
     def __repr__(self):
     def __repr__(self):
-        return u'<ISP %r>' % (self.shortname if self.shortname else self.name,)
+        return '<ISP %r>' % (self.shortname if self.shortname else self.name,)
 
 
 
 
 class CoveredArea(db.Model):
 class CoveredArea(db.Model):
@@ -182,7 +182,7 @@ class CoveredArea(db.Model):
         )
         )
 
 
     def __repr__(self):
     def __repr__(self):
-        return u'<CoveredArea %r>' % (self.name,)
+        return '<CoveredArea %r>' % (self.name,)
 
 
 geo.GeometryDDL(CoveredArea.__table__)
 geo.GeometryDDL(CoveredArea.__table__)
 
 
@@ -257,14 +257,14 @@ class ISPWhoosh(object):
             if not len(ranks):
             if not len(ranks):
                 return []
                 return []
 
 
-            _res = ISP.query.filter(ISP.id.in_(ranks.keys()))
+            _res = ISP.query.filter(ISP.id.in_(list(ranks.keys())))
 
 
         return sorted(_res, key=lambda r: ranks[r.id])
         return sorted(_res, key=lambda r: ranks[r.id])
 
 
     @classmethod
     @classmethod
     def update_document(cls, writer, model):
     def update_document(cls, writer, model):
         kw = {
         kw = {
-            'id': unicode(model.id),
+            'id': str(model.id),
             '_stored_id': model.id,
             '_stored_id': model.id,
             'is_ffdn_member': model.is_ffdn_member,
             'is_ffdn_member': model.is_ffdn_member,
             'is_disabled': model.is_disabled,
             'is_disabled': model.is_disabled,

+ 4 - 4
ffdnispdb/sessions.py

@@ -9,7 +9,7 @@ from sqlalchemy import Table, Column, String, LargeBinary, DateTime,\
 from random import SystemRandom, randrange
 from random import SystemRandom, randrange
 import string
 import string
 from datetime import datetime, timedelta
 from datetime import datetime, timedelta
-import cPickle
+import pickle
 
 
 random = SystemRandom()
 random = SystemRandom()
 
 
@@ -32,7 +32,7 @@ class SQLSession(CallbackDict, SessionMixin):
             self.db.execute(self.table.insert({
             self.db.execute(self.table.insert({
                 'session_id': self.sid,
                 'session_id': self.sid,
                 'expire': datetime.utcnow() + timedelta(hours=1),
                 'expire': datetime.utcnow() + timedelta(hours=1),
-                'value': cPickle.dumps(dict(self), -1)
+                'value': pickle.dumps(dict(self), -1)
             }))
             }))
             self.new = False
             self.new = False
         else:
         else:
@@ -40,7 +40,7 @@ class SQLSession(CallbackDict, SessionMixin):
                 self.table.c.session_id == self.sid,
                 self.table.c.session_id == self.sid,
                 {
                 {
                     'expire': datetime.utcnow() + timedelta(hours=1),
                     'expire': datetime.utcnow() + timedelta(hours=1),
-                    'value': cPickle.dumps(dict(self), -1)
+                    'value': pickle.dumps(dict(self), -1)
                 }
                 }
             ))
             ))
 
 
@@ -62,7 +62,7 @@ class MySessionInterface(SessionInterface):
             res = self.db.engine.execute(select([self.table.c.value], (self.table.c.session_id == sid) &
             res = self.db.engine.execute(select([self.table.c.value], (self.table.c.session_id == sid) &
                                                 (self.table.c.expire > datetime.utcnow()))).first()
                                                 (self.table.c.expire > datetime.utcnow()))).first()
             if res:
             if res:
-                return SQLSession(sid, self.db.engine, self.table, False, cPickle.loads(res[0]))
+                return SQLSession(sid, self.db.engine, self.table, False, pickle.loads(res[0]))
 
 
         while True:
         while True:
             sid = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(32))
             sid = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(32))

+ 1 - 1
ffdnispdb/utils.py

@@ -4,7 +4,7 @@ from flask import current_app
 from flask.globals import _request_ctx_stack
 from flask.globals import _request_ctx_stack
 from collections import OrderedDict
 from collections import OrderedDict
 from datetime import datetime
 from datetime import datetime
-from urlparse import urlunsplit
+from urllib.parse import urlunsplit
 import pytz
 import pytz
 import json
 import json
 import sys
 import sys

+ 12 - 12
ffdnispdb/views.py

@@ -58,7 +58,7 @@ def isp_map_data():
     data = []
     data = []
     for isp in isps:
     for isp in isps:
         d = dict(isp.json)
         d = dict(isp.json)
-        for k in d.keys():
+        for k in list(d.keys()):
             if k not in ('name', 'shortname', 'coordinates'):
             if k not in ('name', 'shortname', 'coordinates'):
                 del d[k]
                 del d[k]
 
 
@@ -77,7 +77,7 @@ def isp_map_data_cube():
     data = []
     data = []
     for isp in isps:
     for isp in isps:
         d = dict(isp.json)
         d = dict(isp.json)
-        for k in d.keys():
+        for k in list(d.keys()):
             if k not in ('name', 'shortname', 'coordinates'):
             if k not in ('name', 'shortname', 'coordinates'):
                 del d[k]
                 del d[k]
 
 
@@ -188,7 +188,7 @@ def edit_project(projectid):
 
 
             db.session.add(isp)
             db.session.add(isp)
             db.session.commit()
             db.session.commit()
-            flash(_(u'Project modified'), 'info')
+            flash(_('Project modified'), 'info')
             return redirect(url_for('.project', projectid=isp.id))
             return redirect(url_for('.project', projectid=isp.id))
         return render_template('edit_project_form.html', form=form)
         return render_template('edit_project_form.html', form=form)
     else:
     else:
@@ -200,7 +200,7 @@ def edit_project(projectid):
 
 
             db.session.add(isp)
             db.session.add(isp)
             db.session.commit()
             db.session.commit()
-            flash(_(u'Project modified'), 'info')
+            flash(_('Project modified'), 'info')
             return redirect(url_for('.project', projectid=isp.id))
             return redirect(url_for('.project', projectid=isp.id))
         return render_template('edit_project_json_form.html', form=form)
         return render_template('edit_project_json_form.html', form=form)
 
 
@@ -235,7 +235,7 @@ https://db.ffdn.org
             mail.send(msg)
             mail.send(msg)
 
 
         # if the email provided is not the correct one, we still redirect
         # if the email provided is not the correct one, we still redirect
-        flash(_(u'If you provided the correct email adress, '
+        flash(_('If you provided the correct email adress, '
                 'you must will receive a message shortly (check your spam folder)'), 'info')
                 'you must will receive a message shortly (check your spam folder)'), 'info')
         return redirect(url_for('.project', projectid=isp.id))
         return redirect(url_for('.project', projectid=isp.id))
 
 
@@ -259,7 +259,7 @@ def create_project_form():
 
 
         db.session.add(isp)
         db.session.add(isp)
         db.session.commit()
         db.session.commit()
-        flash(_(u'Project created'), 'info')
+        flash(_('Project created'), 'info')
         return redirect(url_for('.project', projectid=isp.id))
         return redirect(url_for('.project', projectid=isp.id))
     return render_template('add_project_form.html', form=form)
     return render_template('add_project_form.html', form=form)
 
 
@@ -315,7 +315,7 @@ def create_project_json_confirm():
 
 
         db.session.add(isp)
         db.session.add(isp)
         db.session.commit()
         db.session.commit()
-        flash(_(u'Project created'), 'info')
+        flash(_('Project created'), 'info')
         return redirect(url_for('.project', projectid=isp.id))
         return redirect(url_for('.project', projectid=isp.id))
     else:
     else:
         return redirect(url_for('.create_project_json'))
         return redirect(url_for('.create_project_json'))
@@ -382,7 +382,7 @@ def reactivate_isp(projectid):
         db.session.add(p)
         db.session.add(p)
         db.session.commit()
         db.session.commit()
 
 
-        flash(_(u'Automatic updates activated'), 'info')
+        flash(_('Automatic updates activated'), 'info')
         return redirect(url_for('.project', projectid=p.id))
         return redirect(url_for('.project', projectid=p.id))
 
 
 
 
@@ -468,7 +468,7 @@ def locale_selector():
         return resp
         return resp
 
 
     return render_template('locale_selector.html', locales=(
     return render_template('locale_selector.html', locales=(
-        (code, LOCALES_FLAGS[code], name) for code, name in l.iteritems()
+        (code, LOCALES_FLAGS[code], name) for code, name in l.items()
     ))
     ))
 
 
 
 
@@ -478,9 +478,9 @@ def locale_selector():
 @ispdb.app_template_filter('step_to_label')
 @ispdb.app_template_filter('step_to_label')
 def step_to_label(step):
 def step_to_label(step):
     if step:
     if step:
-        return u"<a href='#' data-toggle='tooltip' data-placement='right' title='" + STEPS[step] + "'><span class='badge badge-" + STEPS_LABELS[step] + "'>" + str(step) + "</span></a>"
+        return "<a href='#' data-toggle='tooltip' data-placement='right' title='" + STEPS[step] + "'><span class='badge badge-" + STEPS_LABELS[step] + "'>" + str(step) + "</span></a>"
     else:
     else:
-        return u'-'
+        return '-'
 
 
 
 
 @ispdb.app_template_filter('stepname')
 @ispdb.app_template_filter('stepname')
@@ -490,7 +490,7 @@ def stepname(step):
 
 
 @ispdb.app_template_filter('js_str')
 @ispdb.app_template_filter('js_str')
 def json_filter(v):
 def json_filter(v):
-    return Markup(json.dumps(unicode(v)))
+    return Markup(json.dumps(str(v)))
 
 
 
 
 @ispdb.app_template_filter('locale_flag')
 @ispdb.app_template_filter('locale_flag')

+ 3 - 3
ffdnispdb/views_api.py

@@ -76,10 +76,10 @@ class RESTException(Exception):
         self.error_type = error_type
         self.error_type = error_type
 
 
     def __iter__(self):
     def __iter__(self):
-        return {
+        return iter({
             'error_type': self.error_type,
             'error_type': self.error_type,
             'message': self.message
             'message': self.message
-        }.iteritems()
+        }.items())
 
 
     def __json__(self):
     def __json__(self):
         return {
         return {
@@ -130,7 +130,7 @@ class Resource(MethodView, REST):
         if not range_:
         if not range_:
             return None
             return None
         try:
         try:
-            range_ = map(int, filter(None, range_.split(',', 1)))
+            range_ = list(map(int, [_f for _f in range_.split(',', 1) if _f]))
             return range_
             return range_
         except ValueError:
         except ValueError:
             return None
             return None

+ 3 - 3
manage.py

@@ -23,7 +23,7 @@ class CreateDB(Command):
     def run(self):
     def run(self):
         ffdnispdb.db.create_all()
         ffdnispdb.db.create_all()
 
 
-database_manager = Manager(usage=u'Perform database operations')
+database_manager = Manager(usage='Perform database operations')
 database_manager.add_command("create", CreateDB)
 database_manager.add_command("create", CreateDB)
 
 
 @database_manager.command
 @database_manager.command
@@ -33,7 +33,7 @@ def drop():
         ffdnispdb.db.drop_all()
         ffdnispdb.db.drop_all()
 
 
 
 
-index_manager = Manager(usage=u'Manage the Whoosh index')
+index_manager = Manager(usage='Manage the Whoosh index')
 
 
 @index_manager.command
 @index_manager.command
 def rebuild():
 def rebuild():
@@ -56,7 +56,7 @@ class MyServer(Server):
     def handle(self, app, host, port, use_debugger, use_reloader,
     def handle(self, app, host, port, use_debugger, use_reloader,
                threaded, processes, passthrough_errors):
                threaded, processes, passthrough_errors):
         if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
         if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
-            print >>sys.stderr, ' * Running on http://%s:%d/'%(host, port)
+            print(' * Running on http://%s:%d/'%(host, port), file=sys.stderr)
 
 
         if use_debugger:
         if use_debugger:
             app=DebuggedApplication(app, evalex=True)
             app=DebuggedApplication(app, evalex=True)

+ 1 - 1
test_ffdnispdb.py

@@ -180,7 +180,7 @@ class TestAPI(TestCase):
         db_urls = [u[0] for u in db_urls]
         db_urls = [u[0] for u in db_urls]
         c = self.client.get('/api/v1/isp/export_urls/')
         c = self.client.get('/api/v1/isp/export_urls/')
         self.assertStatus(c, 200)
         self.assertStatus(c, 200)
-        api_urls = map(lambda x: x['json_url'], json.loads(c.data)['isps'])
+        api_urls = [x['json_url'] for x in json.loads(c.data)['isps']]
         self.assertEqual(len(api_urls), len(db_urls))
         self.assertEqual(len(api_urls), len(db_urls))
         for au in api_urls:
         for au in api_urls:
             self.assertIn(au, db_urls)
             self.assertIn(au, db_urls)