diff --git a/ietf/__init__.py b/ietf/__init__.py index aafb77260..2830859d2 100644 --- a/ietf/__init__.py +++ b/ietf/__init__.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2007-2019, All Rights Reserved # -*- coding: utf-8 -*- -import checks # pyflakes:ignore +from . import checks # pyflakes:ignore # Don't add patch number here: __version__ = "6.98.2.dev0" diff --git a/ietf/api/__init__.py b/ietf/api/__init__.py index ba8ad4c91..352b62888 100644 --- a/ietf/api/__init__.py +++ b/ietf/api/__init__.py @@ -1,7 +1,8 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved import re import six import datetime -from urllib import urlencode +from urllib.parse import urlencode from django.conf import settings from django.core.exceptions import ObjectDoesNotExist @@ -129,9 +130,9 @@ class ToOneField(tastypie.fields.ToOneField): if not foreign_obj: if not self.null: if callable(self.attribute): - raise ApiFieldError(u"The related resource for resource %s could not be found." % (previous_obj)) + raise ApiFieldError("The related resource for resource %s could not be found." % (previous_obj)) else: - raise ApiFieldError(u"The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr)) + raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr)) return None fk_resource = self.get_related_resource(foreign_obj) diff --git a/ietf/api/management/commands/makeresources.py b/ietf/api/management/commands/makeresources.py index c564f36a2..03c66d64e 100644 --- a/ietf/api/management/commands/makeresources.py +++ b/ietf/api/management/commands/makeresources.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2014-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import print_function + import os import datetime @@ -66,7 +66,7 @@ class Command(AppCommand): app_resources = {} if os.path.exists(resource_file_path): resources = import_module("%s.resources" % app.name) - for n,v in resources.__dict__.items(): + for n,v in list(resources.__dict__.items()): if issubclass(type(v), type(ModelResource)): app_resources[n] = v @@ -164,7 +164,7 @@ class Command(AppCommand): fields=model._meta.fields, m2m_fields=model._meta.many_to_many, name=model_name, - imports=[ v for k,v in imports.items() ], + imports=[ v for k,v in list(imports.items()) ], foreign_keys=foreign_keys, m2m_keys=m2m_keys, resource_name=resource_name, @@ -184,7 +184,7 @@ class Command(AppCommand): while len(new_models) > 0: list_len = len(new_models) #debug.show('len(new_models)') - keys = new_models.keys() + keys = list(new_models.keys()) for model_name in keys: internal_fk_count = 0 for fk in new_models[model_name]["foreign_keys"]+new_models[model_name]["m2m_keys"]: @@ -207,7 +207,7 @@ class Command(AppCommand): internal_fk_count_limit += 1 else: print("Failed also with partial ordering, writing resource classes without ordering") - new_model_list = [ v for k,v in new_models.items() ] + new_model_list = [ v for k,v in list(new_models.items()) ] break if rfile.tell() == 0: diff --git a/ietf/api/serializer.py b/ietf/api/serializer.py index 11a61f1d3..e57c73bf1 100644 --- a/ietf/api/serializer.py +++ b/ietf/api/serializer.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved import hashlib import json @@ -16,7 +17,7 @@ import debug # pyflakes:ignore def filter_from_queryargs(request): #@debug.trace def fix_ranges(d): - for k,v in d.items(): + for k,v in list(d.items()): if v.startswith("[") and v.endswith("]"): d[k] = [ s for s in v[1:-1].split(",") if s ] elif "," in v: @@ -27,9 +28,9 @@ def filter_from_queryargs(request): def is_ascii(s): return all(ord(c) < 128 for c in s) # limit parameter keys to ascii. - params = dict( (k,v) for (k,v) in request.GET.items() if is_ascii(k) ) - filter = fix_ranges(dict([(k,params[k]) for k in params.keys() if not k.startswith("not__")])) - exclude = fix_ranges(dict([(k[5:],params[k]) for k in params.keys() if k.startswith("not__")])) + params = dict( (k,v) for (k,v) in list(request.GET.items()) if is_ascii(k) ) + filter = fix_ranges(dict([(k,params[k]) for k in list(params.keys()) if not k.startswith("not__")])) + exclude = fix_ranges(dict([(k[5:],params[k]) for k in list(params.keys()) if k.startswith("not__")])) return filter, exclude def unique_obj_name(obj): @@ -147,7 +148,7 @@ class AdminJsonSerializer(Serializer): if hasattr(field_value, "_meta"): self._current[name] = self.expand_related(field_value, name) else: - self._current[name] = unicode(field_value) + self._current[name] = str(field_value) except ObjectDoesNotExist: pass except AttributeError: @@ -224,7 +225,7 @@ class JsonExportMixin(object): def json_view(self, request, filter={}, expand=[]): qfilter, exclude = filter_from_queryargs(request) - for k in qfilter.keys(): + for k in list(qfilter.keys()): if k.startswith("_"): del qfilter[k] qfilter.update(filter) @@ -244,7 +245,7 @@ class JsonExportMixin(object): try: qs = self.get_queryset().filter(**filter).exclude(**exclude) except (FieldError, ValueError) as e: - return HttpResponse(json.dumps({u"error": str(e)}, sort_keys=True, indent=3), content_type=content_type) + return HttpResponse(json.dumps({"error": str(e)}, sort_keys=True, indent=3), content_type=content_type) try: if expand: qs = qs.select_related() @@ -252,7 +253,7 @@ class JsonExportMixin(object): items = [(getattr(o, key), serializer.serialize([o], expand=expand, query_info=query_info) ) for o in qs ] qd = dict( ( k, json.loads(v)[0] ) for k,v in items ) except (FieldError, ValueError) as e: - return HttpResponse(json.dumps({u"error": str(e)}, sort_keys=True, indent=3), content_type=content_type) + return HttpResponse(json.dumps({"error": str(e)}, sort_keys=True, indent=3), content_type=content_type) text = json.dumps({smart_text(self.model._meta): qd}, sort_keys=True, indent=3) return HttpResponse(text, content_type=content_type) diff --git a/ietf/api/tests.py b/ietf/api/tests.py index 64f7b0625..f9cf30ed4 100644 --- a/ietf/api/tests.py +++ b/ietf/api/tests.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2015-2018, All Rights Reserved +# Copyright The IETF Trust 2015-2019, All Rights Reserved import json import os @@ -218,8 +218,8 @@ class TastypieApiTestCase(ResourceTestCaseMixin, TestCase): # model_list = apps.get_app_config(name).get_models() for model in model_list: - if not model._meta.model_name in app_resources.keys(): + if not model._meta.model_name in list(app_resources.keys()): #print("There doesn't seem to be any resource for model %s.models.%s"%(app.__name__,model.__name__,)) - self.assertIn(model._meta.model_name, app_resources.keys(), + self.assertIn(model._meta.model_name, list(app_resources.keys()), "There doesn't seem to be any API resource for model %s.models.%s"%(app.__name__,model.__name__,)) diff --git a/ietf/api/views.py b/ietf/api/views.py index 027a6a8c1..8ac5db805 100644 --- a/ietf/api/views.py +++ b/ietf/api/views.py @@ -1,7 +1,7 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from jwcrypto.jwk import JWK diff --git a/ietf/community/admin.py b/ietf/community/admin.py index e366f48df..e36ac256e 100644 --- a/ietf/community/admin.py +++ b/ietf/community/admin.py @@ -1,24 +1,24 @@ # Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.contrib import admin from ietf.community.models import CommunityList, SearchRule, EmailSubscription class CommunityListAdmin(admin.ModelAdmin): - list_display = [u'id', 'user', 'group'] + list_display = ['id', 'user', 'group'] raw_id_fields = ['user', 'group', 'added_docs'] admin.site.register(CommunityList, CommunityListAdmin) class SearchRuleAdmin(admin.ModelAdmin): - list_display = [u'id', 'community_list', 'rule_type', 'state', 'group', 'person', 'text'] + list_display = ['id', 'community_list', 'rule_type', 'state', 'group', 'person', 'text'] raw_id_fields = ['community_list', 'state', 'group', 'person', 'name_contains_index'] search_fields = ['person__name', 'group__acronym', 'text', ] admin.site.register(SearchRule, SearchRuleAdmin) class EmailSubscriptionAdmin(admin.ModelAdmin): - list_display = [u'id', 'community_list', 'email', 'notify_on'] + list_display = ['id', 'community_list', 'email', 'notify_on'] raw_id_fields = ['community_list', 'email'] admin.site.register(EmailSubscription, EmailSubscriptionAdmin) diff --git a/ietf/community/forms.py b/ietf/community/forms.py index d764d2307..5ad6cddaa 100644 --- a/ietf/community/forms.py +++ b/ietf/community/forms.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved from django import forms from django.db.models import Q @@ -82,9 +83,9 @@ class SearchRuleForm(forms.ModelForm): if 'group' in self.fields: self.fields['group'].queryset = self.fields['group'].queryset.filter(state="active").order_by("acronym") - self.fields['group'].choices = [(g.pk, u"%s - %s" % (g.acronym, g.name)) for g in self.fields['group'].queryset] + self.fields['group'].choices = [(g.pk, "%s - %s" % (g.acronym, g.name)) for g in self.fields['group'].queryset] - for name, f in self.fields.iteritems(): + for name, f in self.fields.items(): f.required = True def clean_text(self): diff --git a/ietf/community/migrations/0001_initial.py b/ietf/community/migrations/0001_initial.py index 44ddb6200..18270ac3d 100644 --- a/ietf/community/migrations/0001_initial.py +++ b/ietf/community/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/community/migrations/0002_auto_20180220_1052.py b/ietf/community/migrations/0002_auto_20180220_1052.py index 2e3f85b17..eda75147f 100644 --- a/ietf/community/migrations/0002_auto_20180220_1052.py +++ b/ietf/community/migrations/0002_auto_20180220_1052.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.conf import settings from django.db import migrations, models diff --git a/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py b/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py index 6ab7a26c7..4bd72b17c 100644 --- a/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py +++ b/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 14:23 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/community/migrations/0004_set_document_m2m_keys.py b/ietf/community/migrations/0004_set_document_m2m_keys.py index 2c2db4d13..f28a44a6b 100644 --- a/ietf/community/migrations/0004_set_document_m2m_keys.py +++ b/ietf/community/migrations/0004_set_document_m2m_keys.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 14:27 -from __future__ import unicode_literals + import sys @@ -21,7 +21,7 @@ def forward(apps, schema_editor): # Document id fixup ------------------------------------------------------------ objs = Document.objects.in_bulk() - nameid = { o.name: o.id for id, o in objs.iteritems() } + nameid = { o.name: o.id for id, o in objs.items() } sys.stderr.write('\n') diff --git a/ietf/community/migrations/0005_1_del_docs_m2m_table.py b/ietf/community/migrations/0005_1_del_docs_m2m_table.py index 68afc2e9f..2aaaa1de9 100644 --- a/ietf/community/migrations/0005_1_del_docs_m2m_table.py +++ b/ietf/community/migrations/0005_1_del_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-22 08:15 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/community/migrations/0005_2_add_docs_m2m_table.py b/ietf/community/migrations/0005_2_add_docs_m2m_table.py index 9e0438702..7e7d4e794 100644 --- a/ietf/community/migrations/0005_2_add_docs_m2m_table.py +++ b/ietf/community/migrations/0005_2_add_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-22 08:15 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/community/migrations/0006_copy_docs_m2m_table.py b/ietf/community/migrations/0006_copy_docs_m2m_table.py index 7d0f76803..0390ab03d 100644 --- a/ietf/community/migrations/0006_copy_docs_m2m_table.py +++ b/ietf/community/migrations/0006_copy_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-27 05:56 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/community/migrations/0007_remove_docs2_m2m.py b/ietf/community/migrations/0007_remove_docs2_m2m.py index 9687aa3ad..2fec92659 100644 --- a/ietf/community/migrations/0007_remove_docs2_m2m.py +++ b/ietf/community/migrations/0007_remove_docs2_m2m.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-30 03:06 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/community/models.py b/ietf/community/models.py index ec8e10f6e..e719f2315 100644 --- a/ietf/community/models.py +++ b/ietf/community/models.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved from django.contrib.auth.models import User from django.db import models from django.db.models import signals @@ -89,7 +90,7 @@ class EmailSubscription(models.Model): notify_on = models.CharField(max_length=30, choices=NOTIFICATION_CHOICES, default="all") def __unicode__(self): - return u"%s to %s (%s changes)" % (self.email, self.community_list, self.notify_on) + return "%s to %s (%s changes)" % (self.email, self.community_list, self.notify_on) def notify_events(sender, instance, **kwargs): diff --git a/ietf/community/views.py b/ietf/community/views.py index 1ee16bd8e..b74b3e718 100644 --- a/ietf/community/views.py +++ b/ietf/community/views.py @@ -196,7 +196,7 @@ def export_to_csv(request, username=None, acronym=None, group_type=None): row.append(e.time.strftime("%Y-%m-%d") if e else "") row.append(strip_tags(doc.friendly_state())) row.append(doc.group.acronym if doc.group else "") - row.append(unicode(doc.ad) if doc.ad else "") + row.append(str(doc.ad) if doc.ad else "") e = doc.latest_event() row.append(e.time.strftime("%Y-%m-%d") if e else "") writer.writerow([v.encode("utf-8") for v in row]) @@ -222,7 +222,7 @@ def feed(request, username=None, acronym=None, group_type=None): host = request.get_host() feed_url = 'https://%s%s' % (host, request.get_full_path()) feed_id = uuid.uuid5(uuid.NAMESPACE_URL, feed_url.encode('utf-8')) - title = u'%s RSS Feed' % clist.long_name() + title = '%s RSS Feed' % clist.long_name() if significant: subtitle = 'Significant document changes' else: diff --git a/ietf/cookies/__init__.py b/ietf/cookies/__init__.py index 306c9879b..65eb4a033 100644 --- a/ietf/cookies/__init__.py +++ b/ietf/cookies/__init__.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2010, All Rights Reserved +# Copyright The IETF Trust 2010-2019, All Rights Reserved # coding: latin-1 from types import ModuleType @@ -9,7 +9,7 @@ DEBUG_EMAILS = [ ('Tero Kivinen', 'kivinen@iki.fi'), ] -for k in locals().keys(): +for k in list(locals().keys()): m = locals()[k] if isinstance(m, ModuleType): if hasattr(m, "DEBUG_EMAILS"): diff --git a/ietf/cookies/tests.py b/ietf/cookies/tests.py index dd02080c0..42ea437b2 100644 --- a/ietf/cookies/tests.py +++ b/ietf/cookies/tests.py @@ -1,5 +1,6 @@ +# Copyright The IETF Trust 2015-2019, All Rights Reserved from pyquery import PyQuery -from Cookie import SimpleCookie +from http.cookies import SimpleCookie from django.urls import reverse as urlreverse @@ -12,7 +13,7 @@ class CookieTests(TestCase): def test_settings_defaults(self): r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -24,7 +25,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'off', 'new_enough' : '7', 'expires_soon' : 7, 'left_menu': 'on', }) r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/7"]').contents(), ['7 days']) @@ -60,7 +61,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'on', 'new_enough' : '90', 'expires_soon' : 7, 'left_menu': 'off', }) r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/90"]').contents(), ['90 days']) @@ -74,7 +75,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'off', 'new_enough' : '60', 'expires_soon' : 14, 'left_menu': 'on', }) r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/60"]').contents(), ['60 days']) @@ -88,7 +89,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'on', 'new_enough' : '30', 'expires_soon' : 21, 'left_menu': 'off'}) r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/30"]').contents(), ['30 days']) @@ -102,7 +103,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'off', 'new_enough' : '21', 'expires_soon' : 30, 'left_menu': 'on', }) r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/21"]').contents(), ['21 days']) @@ -116,7 +117,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'on', 'new_enough' : '14', 'expires_soon' : 60, 'left_menu': 'off', }) r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -130,7 +131,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'off', 'new_enough' : '7', 'expires_soon' : 90, 'left_menu': 'on', }) r = self.client.get(urlreverse("ietf.cookies.views.preferences")) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/7"]').contents(), ['7 days']) @@ -145,7 +146,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.full_draft")) # no value: reset self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['full_draft'].value, '') - self.assertListEqual(['full_draft'], r.cookies.keys()) + self.assertListEqual(['full_draft'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -159,7 +160,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.full_draft", kwargs=dict(enabled="on"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['full_draft'].value, 'on') - self.assertListEqual(['full_draft'], r.cookies.keys()) + self.assertListEqual(['full_draft'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) # self.assertRegexpMatches(r.content, r'ietf-highlight-y.*full_draft.*on') @@ -169,7 +170,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.full_draft", kwargs=dict(enabled="off"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['full_draft'].value, 'off') - self.assertListEqual(['full_draft'], r.cookies.keys()) + self.assertListEqual(['full_draft'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) # self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -180,7 +181,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'off', 'new_enough' : '14', 'expires_soon' : 14}) r = self.client.get(urlreverse("ietf.cookies.views.full_draft", kwargs=dict(enabled="foo"))) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) # self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -192,7 +193,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.left_menu")) # no value: reset self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['left_menu'].value, '') - self.assertListEqual(['left_menu'], r.cookies.keys()) + self.assertListEqual(['left_menu'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/left_menu/off"]').contents(), ['Off']) @@ -204,7 +205,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.left_menu", kwargs=dict(enabled="on"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['left_menu'].value, 'on') - self.assertListEqual(['left_menu'], r.cookies.keys()) + self.assertListEqual(['left_menu'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/left_menu/on"]').contents(), ['On']) @@ -213,7 +214,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.left_menu", kwargs=dict(enabled="off"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['left_menu'].value, 'off') - self.assertListEqual(['left_menu'], r.cookies.keys()) + self.assertListEqual(['left_menu'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/left_menu/off"]').contents(), ['Off']) @@ -221,7 +222,7 @@ class CookieTests(TestCase): self.client.cookies = SimpleCookie({'full_draft': 'off', 'new_enough' : '14', 'expires_soon' : 14, 'left_menu': 'off', }) r = self.client.get(urlreverse("ietf.cookies.views.left_menu", kwargs=dict(enabled="foo"))) self.assertEqual(r.status_code, 200) - self.assertListEqual([], r.cookies.keys()) + self.assertListEqual([], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/left_menu/off"]').contents(), ['Off']) @@ -230,7 +231,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.new_enough")) # no value: reset self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['new_enough'].value, '') - self.assertListEqual(['new_enough'], r.cookies.keys()) + self.assertListEqual(['new_enough'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -244,7 +245,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.new_enough", kwargs=dict(days="7"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['new_enough'].value, '7') - self.assertListEqual(['new_enough'], r.cookies.keys()) + self.assertListEqual(['new_enough'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/7"]').contents(), ['7 days']) @@ -258,7 +259,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.new_enough", kwargs=dict(days="14"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['new_enough'].value, '14') - self.assertListEqual(['new_enough'], r.cookies.keys()) + self.assertListEqual(['new_enough'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -272,7 +273,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.new_enough", kwargs=dict(days="21"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['new_enough'].value, '21') - self.assertListEqual(['new_enough'], r.cookies.keys()) + self.assertListEqual(['new_enough'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/21"]').contents(), ['21 days']) @@ -286,7 +287,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.new_enough", kwargs=dict(days="30"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['new_enough'].value, '30') - self.assertListEqual(['new_enough'], r.cookies.keys()) + self.assertListEqual(['new_enough'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/30"]').contents(), ['30 days']) @@ -300,7 +301,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.new_enough", kwargs=dict(days="60"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['new_enough'].value, '60') - self.assertListEqual(['new_enough'], r.cookies.keys()) + self.assertListEqual(['new_enough'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/60"]').contents(), ['60 days']) @@ -314,7 +315,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.new_enough", kwargs=dict(days="90"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['new_enough'].value, '90') - self.assertListEqual(['new_enough'], r.cookies.keys()) + self.assertListEqual(['new_enough'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/90"]').contents(), ['90 days']) @@ -328,7 +329,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.expires_soon")) # no value: reset self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['expires_soon'].value, '') - self.assertListEqual(['expires_soon'], r.cookies.keys()) + self.assertListEqual(['expires_soon'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -342,7 +343,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.expires_soon", kwargs=dict(days="7"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['expires_soon'].value, '7') - self.assertListEqual(['expires_soon'], r.cookies.keys()) + self.assertListEqual(['expires_soon'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/21"]').contents(), ['21 days']) @@ -356,7 +357,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.expires_soon", kwargs=dict(days="14"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['expires_soon'].value, '14') - self.assertListEqual(['expires_soon'], r.cookies.keys()) + self.assertListEqual(['expires_soon'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href^="/accounts/settings/new_enough/"]').contents(), []) @@ -370,7 +371,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.expires_soon", kwargs=dict(days="21"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['expires_soon'].value, '21') - self.assertListEqual(['expires_soon'], r.cookies.keys()) + self.assertListEqual(['expires_soon'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/on"]').contents(), ['On']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/90"]').contents(), ['90 days']) @@ -384,7 +385,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.expires_soon", kwargs=dict(days="30"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['expires_soon'].value, '30') - self.assertListEqual(['expires_soon'], r.cookies.keys()) + self.assertListEqual(['expires_soon'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/7"]').contents(), ['7 days']) @@ -398,7 +399,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.expires_soon", kwargs=dict(days="60"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['expires_soon'].value, '60') - self.assertListEqual(['expires_soon'], r.cookies.keys()) + self.assertListEqual(['expires_soon'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/14"]').contents(), ['14 days']) @@ -412,7 +413,7 @@ class CookieTests(TestCase): r = self.client.get(urlreverse("ietf.cookies.views.expires_soon", kwargs=dict(days="90"))) self.assertEqual(r.status_code, 200) self.assertEqual(r.cookies['expires_soon'].value, '90') - self.assertListEqual(['expires_soon'], r.cookies.keys()) + self.assertListEqual(['expires_soon'], list(r.cookies.keys())) q = PyQuery(r.content) self.assertEqual(q('div a.active[href="/accounts/settings/full_draft/off"]').contents(), ['Off']) self.assertEqual(q('div a.active[href="/accounts/settings/new_enough/60"]').contents(), ['60 days']) diff --git a/ietf/cookies/views.py b/ietf/cookies/views.py index 6bc5774d9..700222b48 100644 --- a/ietf/cookies/views.py +++ b/ietf/cookies/views.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2010, All Rights Reserved +# Copyright The IETF Trust 2010-2019, All Rights Reserved from django.shortcuts import render from django.conf import settings @@ -10,7 +10,7 @@ def preferences(request, **kwargs): new_cookies = {} del_cookies = [] preferences['defaults'] = settings.USER_PREFERENCE_DEFAULTS - for key in settings.USER_PREFERENCE_DEFAULTS.keys(): + for key in list(settings.USER_PREFERENCE_DEFAULTS.keys()): if key in kwargs: if kwargs[key] == None: del_cookies += [key] diff --git a/ietf/dbtemplate/forms.py b/ietf/dbtemplate/forms.py index e26fbae65..f502249b0 100644 --- a/ietf/dbtemplate/forms.py +++ b/ietf/dbtemplate/forms.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved from django import forms from django.core.exceptions import ValidationError from django.template import Context @@ -20,7 +21,7 @@ class DBTemplateForm(forms.ModelForm): PlainTemplate(content).render(Context({})) else: raise ValidationError("Unexpected DBTemplate.type.slug: %s" % self.type.slug) - except Exception, e: + except Exception as e: raise ValidationError(e) return content diff --git a/ietf/dbtemplate/migrations/0001_initial.py b/ietf/dbtemplate/migrations/0001_initial.py index cc8a64a0f..32fbae322 100644 --- a/ietf/dbtemplate/migrations/0001_initial.py +++ b/ietf/dbtemplate/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/dbtemplate/migrations/0002_auto_20180220_1052.py b/ietf/dbtemplate/migrations/0002_auto_20180220_1052.py index e6926053c..7545334d0 100644 --- a/ietf/dbtemplate/migrations/0002_auto_20180220_1052.py +++ b/ietf/dbtemplate/migrations/0002_auto_20180220_1052.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/dbtemplate/migrations/0003_adjust_review_templates.py b/ietf/dbtemplate/migrations/0003_adjust_review_templates.py index 5a5ffc48b..cd8e9d8c0 100644 --- a/ietf/dbtemplate/migrations/0003_adjust_review_templates.py +++ b/ietf/dbtemplate/migrations/0003_adjust_review_templates.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-03-05 11:39 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/dbtemplate/migrations/0004_adjust_assignment_email_summary_templates.py b/ietf/dbtemplate/migrations/0004_adjust_assignment_email_summary_templates.py index 0c4463a74..ccee5eb17 100644 --- a/ietf/dbtemplate/migrations/0004_adjust_assignment_email_summary_templates.py +++ b/ietf/dbtemplate/migrations/0004_adjust_assignment_email_summary_templates.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-03-13 13:41 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/dbtemplate/models.py b/ietf/dbtemplate/models.py index 29efd07d5..e21633ac2 100644 --- a/ietf/dbtemplate/models.py +++ b/ietf/dbtemplate/models.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright The IETF Trust 2012-2019, All Rights Reserved -from __future__ import unicode_literals, print_function + from django.db import models @@ -41,6 +41,6 @@ class DBTemplate(models.Model): PlainTemplate(self.content).render(Context({})) else: raise ValidationError("Unexpected DBTemplate.type.slug: %s" % self.type.slug) - except Exception, e: + except Exception as e: raise ValidationError(e) diff --git a/ietf/dbtemplate/template.py b/ietf/dbtemplate/template.py index 32882ca2c..624aab3c9 100644 --- a/ietf/dbtemplate/template.py +++ b/ietf/dbtemplate/template.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import os import string from docutils.core import publish_string @@ -54,7 +55,7 @@ class RSTTemplate(PlainTemplate): 'template': RST_TEMPLATE, 'halt_level': 2, }) - except SystemMessage, e: + except SystemMessage as e: e.message = e.message.replace(':', 'line ') args = list(e.args) args[0] = args[0].replace(':', 'line ') diff --git a/ietf/doc/admin.py b/ietf/doc/admin.py index 44b0a8224..08719a6a2 100644 --- a/ietf/doc/admin.py +++ b/ietf/doc/admin.py @@ -4,7 +4,7 @@ from django.contrib import admin from django import forms -from models import (StateType, State, RelatedDocument, DocumentAuthor, Document, RelatedDocHistory, +from .models import (StateType, State, RelatedDocument, DocumentAuthor, Document, RelatedDocHistory, DocHistoryAuthor, DocHistory, DocAlias, DocReminder, DocEvent, NewRevisionDocEvent, StateDocEvent, ConsensusDocEvent, BallotType, BallotDocEvent, WriteupDocEvent, LastCallDocEvent, TelechatDocEvent, BallotPositionDocEvent, ReviewRequestDocEvent, InitialReviewDocEvent, @@ -155,7 +155,7 @@ admin.site.register(EditedAuthorsDocEvent, DocEventAdmin) class DeletedEventAdmin(admin.ModelAdmin): - list_display = [u'id', 'content_type', 'json', 'by', 'time'] + list_display = ['id', 'content_type', 'json', 'by', 'time'] list_filter = ['time'] raw_id_fields = ['content_type', 'by'] admin.site.register(DeletedEvent, DeletedEventAdmin) diff --git a/ietf/doc/expire.py b/ietf/doc/expire.py index a99e62bb4..5a060048d 100644 --- a/ietf/doc/expire.py +++ b/ietf/doc/expire.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved # expiry of Internet Drafts from django.conf import settings @@ -92,7 +93,7 @@ def send_expire_warning_for_draft(doc): request = None if to or cc: send_mail(request, to, frm, - u"Expiration impending: %s" % doc.file_tag(), + "Expiration impending: %s" % doc.file_tag(), "doc/draft/expire_warning_email.txt", dict(doc=doc, state=state, @@ -112,7 +113,7 @@ def send_expire_notice_for_draft(doc): (to,cc) = gather_address_lists('doc_expired',doc=doc) send_mail(request, to, "I-D Expiring System ", - u"I-D was expired %s" % doc.file_tag(), + "I-D was expired %s" % doc.file_tag(), "doc/draft/id_expired_email.txt", dict(doc=doc, state=state, diff --git a/ietf/doc/feeds.py b/ietf/doc/feeds.py index 2c7f6791f..108f3112a 100644 --- a/ietf/doc/feeds.py +++ b/ietf/doc/feeds.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved import datetime @@ -35,7 +35,7 @@ class DocumentChangesFeed(Feed): return events def item_title(self, item): - return u"[%s] %s [rev. %s]" % (item.by, truncatewords(strip_tags(item.desc), 15), item.rev) + return "[%s] %s [rev. %s]" % (item.by, truncatewords(strip_tags(item.desc), 15), item.rev) def item_description(self, item): return truncatewords_html(format_textarea(item.desc), 20) @@ -44,7 +44,7 @@ class DocumentChangesFeed(Feed): return item.time def item_author_name(self, item): - return unicode(item.by) + return str(item.by) def item_link(self, item): return urlreverse('ietf.doc.views_doc.document_history', kwargs=dict(name=item.doc.canonical_name())) + "#history-%s" % item.pk @@ -67,7 +67,7 @@ class InLastCallFeed(Feed): return docs def item_title(self, item): - return u"%s (%s - %s)" % (item.name, + return "%s (%s - %s)" % (item.name, datefilter(item.lc_event.time, "F j"), datefilter(item.lc_event.expires, "F j, Y")) diff --git a/ietf/doc/fields.py b/ietf/doc/fields.py index a797917dc..0cdb1830d 100644 --- a/ietf/doc/fields.py +++ b/ietf/doc/fields.py @@ -53,9 +53,9 @@ class SearchableDocumentsField(forms.CharField): def prepare_value(self, value): if not value: value = "" - if isinstance(value, (int, long)): + if isinstance(value, int): value = str(value) - if isinstance(value, basestring): + if isinstance(value, str): items = self.parse_select2_value(value) # accept both names and pks here names = [ i for i in items if not i.isdigit() ] @@ -79,7 +79,7 @@ class SearchableDocumentsField(forms.CharField): "model_name": self.model.__name__.lower() }) - return u",".join(unicode(o.pk) for o in value) + return ",".join(str(o.pk) for o in value) def clean(self, value): value = super(SearchableDocumentsField, self).clean(value) @@ -90,10 +90,10 @@ class SearchableDocumentsField(forms.CharField): found_pks = [ str(o.pk) for o in objs ] failed_pks = [ x for x in pks if x not in found_pks ] if failed_pks: - raise forms.ValidationError(u"Could not recognize the following documents: {names}. You can only input documents already registered in the Datatracker.".format(names=", ".join(failed_pks))) + raise forms.ValidationError("Could not recognize the following documents: {names}. You can only input documents already registered in the Datatracker.".format(names=", ".join(failed_pks))) if self.max_entries != None and len(objs) > self.max_entries: - raise forms.ValidationError(u"You can select at most %s entries." % self.max_entries) + raise forms.ValidationError("You can select at most %s entries." % self.max_entries) return objs diff --git a/ietf/doc/forms.py b/ietf/doc/forms.py index c007d6998..a9c0e1e19 100644 --- a/ietf/doc/forms.py +++ b/ietf/doc/forms.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2013-2019, All Rights Reserved + -from __future__ import unicode_literals import datetime import debug #pyflakes:ignore diff --git a/ietf/doc/mails.py b/ietf/doc/mails.py index a4a8fa6d7..b42a03a32 100644 --- a/ietf/doc/mails.py +++ b/ietf/doc/mails.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved # generation of mails import textwrap, datetime @@ -55,7 +56,7 @@ def email_stream_changed(request, doc, old_stream, new_stream, text=""): return if not text: - text = u"Stream changed to %s from %s" % (new_stream, old_stream) + text = "Stream changed to %s from %s" % (new_stream, old_stream) text = strip_tags(text) send_mail(request, to, None, @@ -119,8 +120,8 @@ def generate_ballot_writeup(request, doc): e.by = request.user.person e.doc = doc e.rev = doc.rev - e.desc = u"Ballot writeup was generated" - e.text = unicode(render_to_string("doc/mail/ballot_writeup.txt", {'iana': iana})) + e.desc = "Ballot writeup was generated" + e.text = str(render_to_string("doc/mail/ballot_writeup.txt", {'iana': iana})) # caller is responsible for saving, if necessary return e @@ -131,8 +132,8 @@ def generate_ballot_rfceditornote(request, doc): e.by = request.user.person e.doc = doc e.rev = doc.rev - e.desc = u"RFC Editor Note for ballot was generated" - e.text = unicode(render_to_string("doc/mail/ballot_rfceditornote.txt")) + e.desc = "RFC Editor Note for ballot was generated" + e.text = str(render_to_string("doc/mail/ballot_rfceditornote.txt")) e.save() return e @@ -176,8 +177,8 @@ def generate_last_call_announcement(request, doc): e.by = request.user.person e.doc = doc e.rev = doc.rev - e.desc = u"Last call announcement was generated" - e.text = unicode(mail) + e.desc = "Last call announcement was generated" + e.text = str(mail) # caller is responsible for saving, if necessary return e @@ -196,8 +197,8 @@ def generate_approval_mail(request, doc): e.by = request.user.person e.doc = doc e.rev = doc.rev - e.desc = u"Ballot approval text was generated" - e.text = unicode(mail) + e.desc = "Ballot approval text was generated" + e.text = str(mail) # caller is responsible for saving, if necessary return e @@ -374,7 +375,7 @@ def generate_issue_ballot_mail(request, doc, ballot): last_call_has_expired=last_call_has_expired, needed_ballot_positions= needed_ballot_positions(doc, - doc.active_ballot().active_ad_positions().values() + list(doc.active_ballot().active_ad_positions().values()) ), ) ) @@ -451,7 +452,7 @@ def email_adopted(request, doc, prev_state, new_state, by, comment=""): state_type = (prev_state or new_state).type send_mail(request, to, settings.DEFAULT_FROM_EMAIL, - u'The %s %s has placed %s in state "%s"' % + 'The %s %s has placed %s in state "%s"' % (doc.group.acronym.upper(),doc.group.type_id.upper(), doc.name, new_state or "None"), 'doc/mail/doc_adopted_email.txt', dict(doc=doc, @@ -469,7 +470,7 @@ def email_stream_state_changed(request, doc, prev_state, new_state, by, comment= state_type = (prev_state or new_state).type send_mail(request, to, settings.DEFAULT_FROM_EMAIL, - u"%s changed for %s" % (state_type.label, doc.name), + "%s changed for %s" % (state_type.label, doc.name), 'doc/mail/stream_state_changed_email.txt', dict(doc=doc, url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(), @@ -485,7 +486,7 @@ def email_stream_tags_changed(request, doc, added_tags, removed_tags, by, commen (to, cc) = gather_address_lists('doc_stream_state_edited',doc=doc) send_mail(request, to, settings.DEFAULT_FROM_EMAIL, - u"Tags changed for %s" % doc.name, + "Tags changed for %s" % doc.name, 'doc/mail/stream_tags_changed_email.txt', dict(doc=doc, url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(), diff --git a/ietf/doc/management/commands/generate_draft_bibxml_files.py b/ietf/doc/management/commands/generate_draft_bibxml_files.py index 2057cf67f..171026b67 100644 --- a/ietf/doc/management/commands/generate_draft_bibxml_files.py +++ b/ietf/doc/management/commands/generate_draft_bibxml_files.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import sys import os @@ -21,7 +22,7 @@ def write(fn, new): f.close() class Command(BaseCommand): - help = (u'Generate draft bibxml files, for xml2rfc references') + help = ('Generate draft bibxml files, for xml2rfc references') def handle(self, *args, **options): documents = Document.objects.filter(type__slug='draft') diff --git a/ietf/doc/migrations/0001_initial.py b/ietf/doc/migrations/0001_initial.py index ba3edeef3..71caeb27c 100644 --- a/ietf/doc/migrations/0001_initial.py +++ b/ietf/doc/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import datetime import django.core.validators diff --git a/ietf/doc/migrations/0002_auto_20180220_1052.py b/ietf/doc/migrations/0002_auto_20180220_1052.py index 6cce3e312..47e409a96 100644 --- a/ietf/doc/migrations/0002_auto_20180220_1052.py +++ b/ietf/doc/migrations/0002_auto_20180220_1052.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/doc/migrations/0003_auto_20180401_1231.py b/ietf/doc/migrations/0003_auto_20180401_1231.py index f277b40df..a6bc98fb2 100644 --- a/ietf/doc/migrations/0003_auto_20180401_1231.py +++ b/ietf/doc/migrations/0003_auto_20180401_1231.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.11 on 2018-04-01 12:31 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0004_add_draft_stream_replaced_states.py b/ietf/doc/migrations/0004_add_draft_stream_replaced_states.py index 155596f50..7d09d7ea2 100644 --- a/ietf/doc/migrations/0004_add_draft_stream_replaced_states.py +++ b/ietf/doc/migrations/0004_add_draft_stream_replaced_states.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-05-03 11:50 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/doc/migrations/0005_fix_replaced_iab_irtf_stream_docs.py b/ietf/doc/migrations/0005_fix_replaced_iab_irtf_stream_docs.py index 3b339094f..18840a621 100644 --- a/ietf/doc/migrations/0005_fix_replaced_iab_irtf_stream_docs.py +++ b/ietf/doc/migrations/0005_fix_replaced_iab_irtf_stream_docs.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-05-03 12:16 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/doc/migrations/0006_ballotpositiondocevent_send_email.py b/ietf/doc/migrations/0006_ballotpositiondocevent_send_email.py index fbae0042a..7da218deb 100644 --- a/ietf/doc/migrations/0006_ballotpositiondocevent_send_email.py +++ b/ietf/doc/migrations/0006_ballotpositiondocevent_send_email.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-10-03 06:39 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0007_idexists.py b/ietf/doc/migrations/0007_idexists.py index edba831de..f943a380a 100644 --- a/ietf/doc/migrations/0007_idexists.py +++ b/ietf/doc/migrations/0007_idexists.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-11-04 10:56 -from __future__ import unicode_literals + from tqdm import tqdm diff --git a/ietf/doc/migrations/0008_add_uploaded_filename.py b/ietf/doc/migrations/0008_add_uploaded_filename.py index 769139f42..97c149bb3 100644 --- a/ietf/doc/migrations/0008_add_uploaded_filename.py +++ b/ietf/doc/migrations/0008_add_uploaded_filename.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.17 on 2018-12-28 13:11 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0009_move_non_url_externalurls_to_uploaded_filename.py b/ietf/doc/migrations/0009_move_non_url_externalurls_to_uploaded_filename.py index f8a6fd083..c05baa5d6 100644 --- a/ietf/doc/migrations/0009_move_non_url_externalurls_to_uploaded_filename.py +++ b/ietf/doc/migrations/0009_move_non_url_externalurls_to_uploaded_filename.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.17 on 2018-12-28 13:33 -from __future__ import unicode_literals + from django.db import migrations from django.db.models import F diff --git a/ietf/doc/migrations/0010_auto_20190225_1302.py b/ietf/doc/migrations/0010_auto_20190225_1302.py index 74c3b3bd4..dcad974fb 100644 --- a/ietf/doc/migrations/0010_auto_20190225_1302.py +++ b/ietf/doc/migrations/0010_auto_20190225_1302.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-02-25 13:02 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0011_reviewassignmentdocevent.py b/ietf/doc/migrations/0011_reviewassignmentdocevent.py index 63df9a962..ac04a7577 100644 --- a/ietf/doc/migrations/0011_reviewassignmentdocevent.py +++ b/ietf/doc/migrations/0011_reviewassignmentdocevent.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-11 11:22 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/doc/migrations/0012_add_event_type_closed_review_assignment.py b/ietf/doc/migrations/0012_add_event_type_closed_review_assignment.py index 7b1e55970..c946e3e12 100644 --- a/ietf/doc/migrations/0012_add_event_type_closed_review_assignment.py +++ b/ietf/doc/migrations/0012_add_event_type_closed_review_assignment.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-01 04:43 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0013_add_document_docalias_id.py b/ietf/doc/migrations/0013_add_document_docalias_id.py index e86c4270b..75700530c 100644 --- a/ietf/doc/migrations/0013_add_document_docalias_id.py +++ b/ietf/doc/migrations/0013_add_document_docalias_id.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 08:41 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0014_set_document_docalias_id.py b/ietf/doc/migrations/0014_set_document_docalias_id.py index 06ff9b89e..5c97c81e5 100644 --- a/ietf/doc/migrations/0014_set_document_docalias_id.py +++ b/ietf/doc/migrations/0014_set_document_docalias_id.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 08:42 -from __future__ import unicode_literals + import sys diff --git a/ietf/doc/migrations/0015_1_add_fk_to_document_id.py b/ietf/doc/migrations/0015_1_add_fk_to_document_id.py index a60d9864f..fff0c56af 100644 --- a/ietf/doc/migrations/0015_1_add_fk_to_document_id.py +++ b/ietf/doc/migrations/0015_1_add_fk_to_document_id.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 10:29 -from __future__ import unicode_literals + import django.core.validators from django.db import migrations, models diff --git a/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py b/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py index 5e62dbf26..8b426b77d 100644 --- a/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py +++ b/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-28 12:42 -from __future__ import unicode_literals + import sys, time diff --git a/ietf/doc/migrations/0016_set_document_docalias_fk.py b/ietf/doc/migrations/0016_set_document_docalias_fk.py index ac1376b76..31b244591 100644 --- a/ietf/doc/migrations/0016_set_document_docalias_fk.py +++ b/ietf/doc/migrations/0016_set_document_docalias_fk.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 14:04 -from __future__ import unicode_literals + import sys @@ -15,7 +15,7 @@ def forward(apps, schema_editor): n = getattr(o, a+'_id') if n: i = nameid[n] - if not isinstance(i, (int, long)): + if not isinstance(i, int): raise ValueError("Inappropriate value: %s: nameid[%s]: %s" % (o.__class__.__name__, n, i)) if getattr(o, a+'2_id') != i: setattr(o, a+'2_id', i) @@ -44,7 +44,7 @@ def forward(apps, schema_editor): # Document id fixup ------------------------------------------------------------ objs = Document.objects.in_bulk() - nameid = { o.name: o.id for id, o in objs.iteritems() } + nameid = { o.name: o.id for id, o in objs.items() } sys.stderr.write('\n') @@ -78,7 +78,7 @@ def forward(apps, schema_editor): sys.stderr.write('\n') objs = DocAlias.objects.in_bulk() - nameid = { o.name: o.id for id, o in objs.iteritems() } + nameid = { o.name: o.id for id, o in objs.items() } sys.stderr.write('Setting DocAlias FKs:\n') diff --git a/ietf/doc/migrations/0017_make_document_id_primary_key.py b/ietf/doc/migrations/0017_make_document_id_primary_key.py index 851b2dbeb..57fd2e379 100644 --- a/ietf/doc/migrations/0017_make_document_id_primary_key.py +++ b/ietf/doc/migrations/0017_make_document_id_primary_key.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-09 05:46 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0018_remove_old_document_field.py b/ietf/doc/migrations/0018_remove_old_document_field.py index 146317da2..19a323309 100644 --- a/ietf/doc/migrations/0018_remove_old_document_field.py +++ b/ietf/doc/migrations/0018_remove_old_document_field.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-20 09:53 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/doc/migrations/0019_rename_field_document2.py b/ietf/doc/migrations/0019_rename_field_document2.py index 5b4504d01..f97fd7e52 100644 --- a/ietf/doc/migrations/0019_rename_field_document2.py +++ b/ietf/doc/migrations/0019_rename_field_document2.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 05:31 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/doc/migrations/0020_copy_docs_m2m_table.py b/ietf/doc/migrations/0020_copy_docs_m2m_table.py index 4a6555c71..0817ca716 100644 --- a/ietf/doc/migrations/0020_copy_docs_m2m_table.py +++ b/ietf/doc/migrations/0020_copy_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 05:31 -from __future__ import unicode_literals + import sys, time diff --git a/ietf/doc/migrations/0021_remove_docs2_m2m.py b/ietf/doc/migrations/0021_remove_docs2_m2m.py index c11464cdc..b89aba803 100644 --- a/ietf/doc/migrations/0021_remove_docs2_m2m.py +++ b/ietf/doc/migrations/0021_remove_docs2_m2m.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-30 03:36 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/doc/migrations/0022_document_primary_key_cleanup.py b/ietf/doc/migrations/0022_document_primary_key_cleanup.py index 23d74f13a..3700228fc 100644 --- a/ietf/doc/migrations/0022_document_primary_key_cleanup.py +++ b/ietf/doc/migrations/0022_document_primary_key_cleanup.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-06-10 03:47 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/doc/migrations/0023_one_to_many_docalias.py b/ietf/doc/migrations/0023_one_to_many_docalias.py index 90b88bcd8..9e0d3de26 100644 --- a/ietf/doc/migrations/0023_one_to_many_docalias.py +++ b/ietf/doc/migrations/0023_one_to_many_docalias.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-06-10 04:36 -from __future__ import unicode_literals + import sys diff --git a/ietf/doc/models.py b/ietf/doc/models.py index fdc015bc2..58cbed06e 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007-2019, All Rights Reserved +# Copyright The IETF Trust 2010-2019, All Rights Reserved # -*- coding: utf-8 -*- import datetime @@ -372,7 +372,7 @@ class DocumentInfo(models.Model): return self.rfc_number() def author_list(self): - return u", ".join(author.email_id for author in self.documentauthor_set.all() if author.email_id) + return ", ".join(author.email_id for author in self.documentauthor_set.all() if author.email_id) def authors(self): return [ a.person for a in self.documentauthor_set.all() ] @@ -531,7 +531,7 @@ class RelatedDocument(models.Model): def action(self): return self.relationship.name def __unicode__(self): - return u"%s %s %s" % (self.source.name, self.relationship.name.lower(), self.target.name) + return "%s %s %s" % (self.source.name, self.relationship.name.lower(), self.target.name) def is_downref(self): @@ -601,7 +601,7 @@ class DocumentAuthor(DocumentAuthorInfo): document = ForeignKey('Document') def __unicode__(self): - return u"%s %s (%s)" % (self.document.name, self.person, self.order) + return "%s %s (%s)" % (self.document.name, self.person, self.order) validate_docname = RegexValidator( @@ -641,10 +641,10 @@ class Document(DocumentInfo): return self._cached_absolute_url def file_tag(self): - return u"<%s>" % self.filename_with_rev() + return "<%s>" % self.filename_with_rev() def filename_with_rev(self): - return u"%s-%s.txt" % (self.name, self.rev) + return "%s-%s.txt" % (self.name, self.rev) def latest_event(self, *args, **filter_args): """Get latest event of optional Python type and with filter @@ -850,7 +850,7 @@ class RelatedDocHistory(models.Model): target = ForeignKey('DocAlias', related_name="reversely_related_document_history_set") relationship = ForeignKey(DocRelationshipName) def __unicode__(self): - return u"%s %s %s" % (self.source.doc.name, self.relationship.name.lower(), self.target.name) + return "%s %s %s" % (self.source.doc.name, self.relationship.name.lower(), self.target.name) class DocHistoryAuthor(DocumentAuthorInfo): # use same naming convention as non-history version to make it a bit @@ -858,7 +858,7 @@ class DocHistoryAuthor(DocumentAuthorInfo): document = ForeignKey('DocHistory', related_name="documentauthor_set") def __unicode__(self): - return u"%s %s (%s)" % (self.document.doc.name, self.person, self.order) + return "%s %s (%s)" % (self.document.doc.name, self.person, self.order) class DocHistory(DocumentInfo): doc = ForeignKey(Document, related_name="history_set") @@ -869,7 +869,7 @@ class DocHistory(DocumentInfo): name = models.CharField(max_length=255) def __unicode__(self): - return unicode(self.doc.name) + return str(self.doc.name) def canonical_name(self): if hasattr(self, '_canonical_name'): @@ -918,7 +918,7 @@ class DocAlias(models.Model): return self.docs.first() def __unicode__(self): - return "%s-->%s" % (self.name, ','.join([unicode(d.name) for d in self.docs.all() if isinstance(d, Document) ])) + return "%s-->%s" % (self.name, ','.join([str(d.name) for d in self.docs.all() if isinstance(d, Document) ])) document_link = admin_link("document") class Meta: verbose_name = "document alias" @@ -1024,7 +1024,7 @@ class DocEvent(models.Model): return DocHistory.objects.filter(time__lte=self.time,doc__name=self.doc.name).order_by('-time', '-pk').first() def __unicode__(self): - return u"%s %s by %s at %s" % (self.doc.name, self.get_type_display().lower(), self.by.plain_name(), self.time) + return "%s %s by %s at %s" % (self.doc.name, self.get_type_display().lower(), self.by.plain_name(), self.time) def save(self, *args, **kwargs): super(DocEvent, self).save(*args, **kwargs) @@ -1057,7 +1057,7 @@ class BallotType(models.Model): positions = models.ManyToManyField(BallotPositionName, blank=True) def __unicode__(self): - return u"%s: %s" % (self.name, self.doc_type.name) + return "%s: %s" % (self.name, self.doc_type.name) class Meta: ordering = ['order'] @@ -1184,7 +1184,7 @@ class DeletedEvent(models.Model): time = models.DateTimeField(default=datetime.datetime.now) def __unicode__(self): - return u"%s by %s %s" % (self.content_type, self.by, self.time) + return "%s by %s %s" % (self.content_type, self.by, self.time) class EditedAuthorsDocEvent(DocEvent): """ Capture the reasoning or authority for changing a document author list. diff --git a/ietf/doc/templatetags/ietf_filters.py b/ietf/doc/templatetags/ietf_filters.py index 66f0e82ac..0ab6d4452 100644 --- a/ietf/doc/templatetags/ietf_filters.py +++ b/ietf/doc/templatetags/ietf_filters.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved import bleach import datetime @@ -64,7 +64,7 @@ def parse_email_list(value): """ - if value and isinstance(value, (types.StringType,types.UnicodeType)): # testing for 'value' being true isn't necessary; it's a fast-out route + if value and isinstance(value, (bytes,str)): # testing for 'value' being true isn't necessary; it's a fast-out route addrs = re.split(", ?", value) ret = [] for addr in addrs: @@ -109,7 +109,7 @@ def make_one_per_line(value): >>> make_one_per_line(None) """ - if value and isinstance(value, (types.StringType,types.UnicodeType)): + if value and isinstance(value, (bytes,str)): return re.sub(", ?", "\n", value) else: return value @@ -145,7 +145,7 @@ def sanitize(value): @register.filter(name='bracket') def square_brackets(value): """Adds square brackets around text.""" - if isinstance(value, (types.StringType,types.UnicodeType)): + if isinstance(value, (bytes,str)): if value == "": value = " " return "[ %s ]" % value @@ -195,7 +195,7 @@ def rfcnospace(string): @register.filter def prettystdname(string): from ietf.doc.utils import prettify_std_name - return prettify_std_name(unicode(string or "")) + return prettify_std_name(str(string or "")) @register.filter(name='rfcurl') def rfclink(string): @@ -338,7 +338,7 @@ def expires_soon(x,request): @register.filter(name='startswith') def startswith(x, y): - return unicode(x).startswith(y) + return str(x).startswith(y) @register.filter def has_role(user, role_names): @@ -377,14 +377,14 @@ def format_snippet(text, trunc_words=25): full = keep_spacing(collapsebr(linebreaksbr(mark_safe(sanitize_fragment(text))))) snippet = truncatewords_html(full, trunc_words) if snippet != full: - return mark_safe(u'
%s
' % (snippet, full)) + return mark_safe('
%s
' % (snippet, full)) return full @register.simple_tag def doc_edit_button(url_name, *args, **kwargs): """Given URL name/args/kwargs, looks up the URL just like "url" tag and returns a properly formatted button for the document material tables.""" from django.urls import reverse as urlreverse - return mark_safe(u'Edit' % (urlreverse(url_name, args=args, kwargs=kwargs))) + return mark_safe('Edit' % (urlreverse(url_name, args=args, kwargs=kwargs))) @register.filter def textify(text): @@ -419,7 +419,7 @@ if __name__ == "__main__": _test() @register.filter -def plural(text, seq, arg=u's'): +def plural(text, seq, arg='s'): "Similar to pluralize, but looks at the text, too" from django.template.defaultfilters import pluralize if text.endswith('s'): @@ -505,9 +505,9 @@ def nbsp(value): @register.filter() def comma_separated_list(seq, end_word="and"): if len(seq) < 2: - return u"".join(seq) + return "".join(seq) else: - return u", ".join(seq[:-1]) + u" %s %s"%(end_word, seq[-1]) + return ", ".join(seq[:-1]) + " %s %s"%(end_word, seq[-1]) @register.filter() def zaptmp(s): diff --git a/ietf/doc/templatetags/managed_groups.py b/ietf/doc/templatetags/managed_groups.py index 225d892d4..c971d21c6 100644 --- a/ietf/doc/templatetags/managed_groups.py +++ b/ietf/doc/templatetags/managed_groups.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2016-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django import template diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index dfe565cc6..66f038e98 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -6,7 +6,7 @@ import shutil import datetime import json import sys -import urlparse +import urllib.parse import bibtexparser if sys.version_info[0] == 2 and sys.version_info[1] < 7: import unittest2 as unittest @@ -14,7 +14,7 @@ else: import unittest from pyquery import PyQuery from tempfile import NamedTemporaryFile -from Cookie import SimpleCookie +from http.cookies import SimpleCookie from django.urls import reverse as urlreverse from django.conf import settings @@ -142,71 +142,71 @@ class SearchTests(TestCase): # exact match r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name=draft.name))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) # prefix match r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(draft.name.split("-")[:-1])))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) # non-prefix match r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(draft.name.split("-")[1:])))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) # other doctypes than drafts doc = Document.objects.get(name='charter-ietf-mars') r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name='charter-ietf-ma'))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) doc = Document.objects.filter(name__startswith='conflict-review-').first() r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(doc.name.split("-")[:-1])))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) doc = Document.objects.filter(name__startswith='status-change-').first() r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(doc.name.split("-")[:-1])))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) doc = Document.objects.filter(name__startswith='agenda-').first() r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(doc.name.split("-")[:-1])))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) doc = Document.objects.filter(name__startswith='minutes-').first() r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(doc.name.split("-")[:-1])))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) doc = Document.objects.filter(name__startswith='slides-').first() r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(doc.name.split("-")[:-1])))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=doc.name))) # match with revision r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name=draft.name + "-" + prev_rev))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name, rev=prev_rev))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name, rev=prev_rev))) # match with non-existing revision r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name=draft.name + "-09"))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) # match with revision and extension r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name=draft.name + "-" + prev_rev + ".txt"))) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name, rev=prev_rev))) + self.assertEqual(urllib.parse.urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name, rev=prev_rev))) # no match r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="draft-ietf-doesnotexist-42"))) self.assertEqual(r.status_code, 302) - parsed = urlparse.urlparse(r["Location"]) + parsed = urllib.parse.urlparse(r["Location"]) self.assertEqual(parsed.path, urlreverse('ietf.doc.views_search.search')) - self.assertEqual(urlparse.parse_qs(parsed.query)["name"][0], "draft-ietf-doesnotexist-42") + self.assertEqual(urllib.parse.parse_qs(parsed.query)["name"][0], "draft-ietf-doesnotexist-42") def test_frontpage(self): r = self.client.get("/") @@ -919,11 +919,11 @@ class DocTestCase(TestCase): url = urlreverse('ietf.doc.views_doc.document_bibtex', kwargs=dict(name=rfc.name)) r = self.client.get(url) entry = bibtexparser.loads(r.content).get_entry_dict()["rfc%s"%num] - self.assertEqual(entry['series'], u'Request for Comments') + self.assertEqual(entry['series'], 'Request for Comments') self.assertEqual(entry['number'], num) - self.assertEqual(entry['doi'], u'10.17487/RFC%s'%num) - self.assertEqual(entry['year'], u'2010') - self.assertEqual(entry['month'], u'oct') + self.assertEqual(entry['doi'], '10.17487/RFC%s'%num) + self.assertEqual(entry['year'], '2010') + self.assertEqual(entry['month'], 'oct') # self.assertNotIn('day', entry) @@ -931,7 +931,7 @@ class DocTestCase(TestCase): stream_id = 'rse', states = [('draft','rfc'),('draft-iesg','pub')], std_level_id = 'ind', - time = datetime.datetime(1990,04,01), + time = datetime.datetime(1990,0o4,0o1), ) num = april1.rfc_number() DocEventFactory.create(doc=april1, type='published_rfc', time = '1990-04-01') @@ -939,20 +939,20 @@ class DocTestCase(TestCase): url = urlreverse('ietf.doc.views_doc.document_bibtex', kwargs=dict(name=april1.name)) r = self.client.get(url) entry = bibtexparser.loads(r.content).get_entry_dict()['rfc%s'%num] - self.assertEqual(entry['series'], u'Request for Comments') + self.assertEqual(entry['series'], 'Request for Comments') self.assertEqual(entry['number'], num) - self.assertEqual(entry['doi'], u'10.17487/RFC%s'%num) - self.assertEqual(entry['year'], u'1990') - self.assertEqual(entry['month'], u'apr') - self.assertEqual(entry['day'], u'1') + self.assertEqual(entry['doi'], '10.17487/RFC%s'%num) + self.assertEqual(entry['year'], '1990') + self.assertEqual(entry['month'], 'apr') + self.assertEqual(entry['day'], '1') draft = IndividualDraftFactory.create() - docname = u'%s-%s' % (draft.name, draft.rev) + docname = '%s-%s' % (draft.name, draft.rev) bibname = docname[6:] # drop the 'draft-' prefix url = urlreverse('ietf.doc.views_doc.document_bibtex', kwargs=dict(name=draft.name)) r = self.client.get(url) entry = bibtexparser.loads(r.content).get_entry_dict()[bibname] - self.assertEqual(entry['note'], u'Work in Progress') + self.assertEqual(entry['note'], 'Work in Progress') self.assertEqual(entry['number'], docname) self.assertEqual(entry['year'], str(draft.pub_date().year)) self.assertEqual(entry['month'], draft.pub_date().strftime('%b').lower()) @@ -1012,11 +1012,11 @@ class ReferencesTest(TestCase): RelatedDocument.objects.get_or_create(source=doc1,target=doc2,relationship=DocRelationshipName.objects.get(slug='refnorm')) url = urlreverse('ietf.doc.views_doc.document_references', kwargs=dict(name=doc1.name)) r = self.client.get(url) - self.assertEquals(r.status_code, 200) + self.assertEqual(r.status_code, 200) self.assertTrue(doc2.name in unicontent(r)) url = urlreverse('ietf.doc.views_doc.document_referenced_by', kwargs=dict(name=doc2.name)) r = self.client.get(url) - self.assertEquals(r.status_code, 200) + self.assertEqual(r.status_code, 200) self.assertTrue(doc1.name in unicontent(r)) diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py index de43c58d1..59e195dfb 100644 --- a/ietf/doc/tests_ballot.py +++ b/ietf/doc/tests_ballot.py @@ -540,8 +540,8 @@ class BallotWriteupsTests(TestCase): e.by = Person.objects.get(name="(System)") e.doc = draft e.rev = draft.rev - e.desc = u"Ballot approval text was generated" - e.text = u"Test approval text." + e.desc = "Ballot approval text was generated" + e.text = "Test approval text." e.save() events.append(e) @@ -550,8 +550,8 @@ class BallotWriteupsTests(TestCase): e.by = Person.objects.get(name="(System)") e.doc = draft e.rev = draft.rev - e.desc = u"Ballot writeup was generated" - e.text = u"Test ballot writeup text." + e.desc = "Ballot writeup was generated" + e.text = "Test ballot writeup text." e.save() events.append(e) @@ -560,8 +560,8 @@ class BallotWriteupsTests(TestCase): e.by = Person.objects.get(name="(System)") e.doc = draft e.rev = draft.rev - e.desc = u"RFC Editor Note for ballot was generated" - e.text = u"Test note to the RFC Editor text." + e.desc = "RFC Editor Note for ballot was generated" + e.text = "Test note to the RFC Editor text." e.save() events.append(e) @@ -588,7 +588,7 @@ class BallotWriteupsTests(TestCase): # RFC Editor Notes for documents in the IRTF Stream e = DocEvent(doc=draft, rev=draft.rev, by=Person.objects.get(name="(System)"), type='changed_stream') - e.desc = u"Changed stream to %s" % 'irtf' + e.desc = "Changed stream to %s" % 'irtf' e.save() draft.stream_id = 'irtf' @@ -603,7 +603,7 @@ class BallotWriteupsTests(TestCase): # RFC Editor Notes for documents in the IAB Stream e = DocEvent(doc=draft, rev=draft.rev, by=Person.objects.get(name="(System)"), type='changed_stream') - e.desc = u"Changed stream to %s" % 'ise' + e.desc = "Changed stream to %s" % 'ise' e.save() draft.stream_id = 'ise' diff --git a/ietf/doc/tests_charter.py b/ietf/doc/tests_charter.py index 30f08dd4b..e30211e78 100644 --- a/ietf/doc/tests_charter.py +++ b/ietf/doc/tests_charter.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# Copyright The IETF Trust 2011, All Rights Reserved +# Copyright The IETF Trust 2011-2019, All Rights Reserved import os, shutil, datetime -from StringIO import StringIO +from io import StringIO from pyquery import PyQuery from django.conf import settings @@ -70,8 +70,8 @@ class EditCharterTests(TestCase): ames = GroupFactory(acronym='ames',state_id='proposed',list_email='ames-wg@ietf.org',parent=area) RoleFactory(name_id='ad',group=ames,person=Person.objects.get(user__username='ad')) - RoleFactory(name_id='chair',group=ames,person__name=u'Ames Man',person__user__email='ameschairman@example.org') - RoleFactory(name_id='secr',group=ames,person__name=u'Secretary',person__user__email='amessecretary@example.org') + RoleFactory(name_id='chair',group=ames,person__name='Ames Man',person__user__email='ameschairman@example.org') + RoleFactory(name_id='secr',group=ames,person__name='Secretary',person__user__email='amessecretary@example.org') CharterFactory(group=ames) mars = GroupFactory(acronym='mars',parent=area) @@ -591,8 +591,8 @@ class EditCharterTests(TestCase): RoleFactory(name_id='ad',group=area,person=Person.objects.get(user__username='ad')) charter = CharterFactory(group__acronym='ames',group__list_email='ames-wg@ietf.org',group__parent=area,group__state_id='bof') group = charter.group - RoleFactory(name_id='chair',group=group,person__name=u'Ames Man',person__user__email='ameschairman@example.org') - RoleFactory(name_id='secr',group=group,person__name=u'Secretary',person__user__email='amessecretary@example.org') + RoleFactory(name_id='chair',group=group,person__name='Ames Man',person__user__email='ameschairman@example.org') + RoleFactory(name_id='secr',group=group,person__name='Secretary',person__user__email='amessecretary@example.org') url = urlreverse('ietf.doc.views_charter.approve', kwargs=dict(name=charter.name)) login_testing_unauthorized(self, "secretary", url) diff --git a/ietf/doc/tests_conflict_review.py b/ietf/doc/tests_conflict_review.py index fc0c2aa27..7dcb33410 100644 --- a/ietf/doc/tests_conflict_review.py +++ b/ietf/doc/tests_conflict_review.py @@ -1,10 +1,11 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved # -*- coding: utf-8 -*- import debug # pyflakes:ignore import os import shutil from pyquery import PyQuery -from StringIO import StringIO +from io import StringIO from textwrap import wrap from django.conf import settings @@ -63,9 +64,9 @@ class ConflictReviewTests(TestCase): self.assertEqual(r.status_code, 302) review_doc = Document.objects.get(name='conflict-review-imaginary-independent-submission') self.assertEqual(review_doc.get_state('conflrev').slug,'needshep') - self.assertEqual(review_doc.rev,u'00') - self.assertEqual(review_doc.ad.name,u'Areað Irector') - self.assertEqual(review_doc.notify,u'ipu@ietf.org') + self.assertEqual(review_doc.rev,'00') + self.assertEqual(review_doc.ad.name,'Areað Irector') + self.assertEqual(review_doc.notify,'ipu@ietf.org') doc = Document.objects.get(name='draft-imaginary-independent-submission') self.assertTrue(doc in [x.target.document for x in review_doc.relateddocument_set.filter(relationship__slug='conflrev')]) @@ -87,34 +88,34 @@ class ConflictReviewTests(TestCase): # can't start conflict reviews on documents not in a stream r = self.client.get(url) - self.assertEquals(r.status_code, 404) + self.assertEqual(r.status_code, 404) # can't start conflict reviews on documents in some other stream doc.stream = StreamName.objects.get(slug='irtf') doc.save_with_history([DocEvent.objects.create(doc=doc, rev=doc.rev, type="changed_stream", by=Person.objects.get(user__username="secretary"), desc="Test")]) r = self.client.get(url) - self.assertEquals(r.status_code, 404) + self.assertEqual(r.status_code, 404) # successful get doc.stream = StreamName.objects.get(slug='ise') doc.save_with_history([DocEvent.objects.create(doc=doc, rev=doc.rev, type="changed_stream", by=Person.objects.get(user__username="secretary"), desc="Test")]) r = self.client.get(url) - self.assertEquals(r.status_code, 200) + self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertEquals(len(q('form input[name=notify]')),1) - self.assertEquals(len(q('form select[name=ad]')),0) + self.assertEqual(len(q('form input[name=notify]')),1) + self.assertEqual(len(q('form select[name=ad]')),0) # successfully starts a review, and notifies the secretariat messages_before = len(outbox) r = self.client.post(url,dict(notify='ipu@ietf.org')) - self.assertEquals(r.status_code, 302) + self.assertEqual(r.status_code, 302) review_doc = Document.objects.get(name='conflict-review-imaginary-independent-submission') - self.assertEquals(review_doc.get_state('conflrev').slug,'needshep') - self.assertEquals(review_doc.rev,u'00') - self.assertEquals(review_doc.telechat_date(),None) - self.assertEquals(review_doc.ad.name,u'Ietf Chair') - self.assertEquals(review_doc.notify,u'ipu@ietf.org') + self.assertEqual(review_doc.get_state('conflrev').slug,'needshep') + self.assertEqual(review_doc.rev,'00') + self.assertEqual(review_doc.telechat_date(),None) + self.assertEqual(review_doc.ad.name,'Ietf Chair') + self.assertEqual(review_doc.notify,'ipu@ietf.org') doc = Document.objects.get(name='draft-imaginary-independent-submission') self.assertTrue(doc in [x.target.document for x in review_doc.relateddocument_set.filter(relationship__slug='conflrev')]) @@ -297,9 +298,9 @@ class ConflictReviewTests(TestCase): self.assertIn('ietf-announce@', outbox[0]['Cc']) self.assertIn('iana@', outbox[0]['Cc']) if approve_type == 'appr-noprob': - self.assertIn( 'IESG has no problem', ''.join(wrap(unicode(outbox[0]),2**16))) + self.assertIn( 'IESG has no problem', ''.join(wrap(str(outbox[0]),2**16))) else: - self.assertIn( 'NOT be published', ''.join(wrap(unicode(outbox[0]),2**16))) + self.assertIn( 'NOT be published', ''.join(wrap(str(outbox[0]),2**16))) def test_approve_reqnopub(self): @@ -330,12 +331,12 @@ class ConflictReviewSubmitTests(TestCase): # sane post using textbox path = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev)) - self.assertEqual(doc.rev,u'00') + self.assertEqual(doc.rev,'00') self.assertFalse(os.path.exists(path)) r = self.client.post(url,dict(content="Some initial review text\n",submit_response="1")) self.assertEqual(r.status_code,302) doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission') - self.assertEqual(doc.rev,u'00') + self.assertEqual(doc.rev,'00') with open(path) as f: self.assertEqual(f.read(),"Some initial review text\n") f.close() @@ -348,7 +349,7 @@ class ConflictReviewSubmitTests(TestCase): # A little additional setup # doc.rev is u'00' per the test setup - double-checking that here - if it fails, the breakage is in setUp - self.assertEqual(doc.rev,u'00') + self.assertEqual(doc.rev,'00') path = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev)) with open(path,'w') as f: f.write('This is the old proposal.') @@ -375,7 +376,7 @@ class ConflictReviewSubmitTests(TestCase): r = self.client.post(url,dict(txt=test_file,submit_response="1")) self.assertEqual(r.status_code, 302) doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission') - self.assertEqual(doc.rev,u'01') + self.assertEqual(doc.rev,'01') path = os.path.join(settings.CONFLICT_REVIEW_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev)) with open(path) as f: self.assertEqual(f.read(),"This is a new proposal.") diff --git a/ietf/doc/tests_downref.py b/ietf/doc/tests_downref.py index d0f4b43fc..e2c6b7652 100644 --- a/ietf/doc/tests_downref.py +++ b/ietf/doc/tests_downref.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.urls import reverse as urlreverse from pyquery import PyQuery diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index 61f371c2d..b063c0260 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -4,7 +4,7 @@ import os import shutil import datetime -import StringIO +import io from pyquery import PyQuery from collections import Counter @@ -458,7 +458,7 @@ class EditInfoTests(TestCase): # reset e = DocEvent(doc=draft, rev=draft.rev, by=Person.objects.get(name="(System)"), type='changed_document') - e.desc = u"Intended Status changed to %s from %s"% (draft.intended_std_level_id, 'bcp') + e.desc = "Intended Status changed to %s from %s"% (draft.intended_std_level_id, 'bcp') e.save() draft.intended_std_level_id = 'bcp' @@ -467,7 +467,7 @@ class EditInfoTests(TestCase): self.assertEqual(r.status_code, 403) # BCPs must have a consensus e = DocEvent(doc=draft, rev=draft.rev, by=Person.objects.get(name="(System)"), type='changed_document') - e.desc = u"Intended Status changed to %s from %s"% (draft.intended_std_level_id, 'inf') + e.desc = "Intended Status changed to %s from %s"% (draft.intended_std_level_id, 'inf') e.save() draft.intended_std_level_id = 'inf' @@ -774,7 +774,7 @@ class ExpireLastCallTests(TestCase): class IndividualInfoFormsTests(TestCase): def setUp(self): - doc = WgDraftFactory(group__acronym='mars',shepherd=PersonFactory(user__username='plain',name=u'Plain Man').email_set.first()) + doc = WgDraftFactory(group__acronym='mars',shepherd=PersonFactory(user__username='plain',name='Plain Man').email_set.first()) self.docname = doc.name def test_doc_change_stream(self): @@ -1056,7 +1056,7 @@ class IndividualInfoFormsTests(TestCase): self.assertTrue(doc.latest_event(WriteupDocEvent,type="changed_protocol_writeup").text.startswith('here is a new writeup')) # file upload - test_file = StringIO.StringIO("This is a different writeup.") + test_file = io.StringIO("This is a different writeup.") test_file.name = "unnamed" r = self.client.post(url,dict(txt=test_file,submit_response="1")) self.assertEqual(r.status_code, 302) @@ -1362,7 +1362,7 @@ class AdoptDraftTests(TestCase): class ChangeStreamStateTests(TestCase): def test_set_tags(self): - role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name=u'WG Cháir Man') + role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name='WG Cháir Man') RoleFactory(name_id='delegate',group=role.group,person__user__email='marsdelegate@example.org') draft = WgDraftFactory(group=role.group,shepherd=PersonFactory(user__username='plain',user__email='plain@example.com').email_set.first()) draft.tags.set(DocTagName.objects.filter(slug="w-expert")) @@ -1399,12 +1399,12 @@ class ChangeStreamStateTests(TestCase): self.assertEqual(draft.docevent_set.count() - events_before, 2) self.assertEqual(len(outbox), mailbox_before + 1) self.assertTrue("tags changed" in outbox[-1]["Subject"].lower()) - self.assertTrue("mars-chairs@ietf.org" in unicode(outbox[-1])) - self.assertTrue("marsdelegate@example.org" in unicode(outbox[-1])) - self.assertTrue("plain@example.com" in unicode(outbox[-1])) + self.assertTrue("mars-chairs@ietf.org" in str(outbox[-1])) + self.assertTrue("marsdelegate@example.org" in str(outbox[-1])) + self.assertTrue("plain@example.com" in str(outbox[-1])) def test_set_initial_state(self): - role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name=u'WG Cháir Man') + role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name='WG Cháir Man') RoleFactory(name_id='delegate',group=role.group,person__user__email='marsdelegate@ietf.org') draft = WgDraftFactory(group=role.group) draft.states.all().delete() @@ -1436,11 +1436,11 @@ class ChangeStreamStateTests(TestCase): self.assertTrue(due - datetime.timedelta(days=1) <= reminder[0].due <= due + datetime.timedelta(days=1)) self.assertEqual(len(outbox), 1) self.assertTrue("state changed" in outbox[0]["Subject"].lower()) - self.assertTrue("mars-chairs@ietf.org" in unicode(outbox[0])) - self.assertTrue("marsdelegate@ietf.org" in unicode(outbox[0])) + self.assertTrue("mars-chairs@ietf.org" in str(outbox[0])) + self.assertTrue("marsdelegate@ietf.org" in str(outbox[0])) def test_set_state(self): - role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name=u'WG Cháir Man') + role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name='WG Cháir Man') RoleFactory(name_id='delegate',group=role.group,person__user__email='marsdelegate@ietf.org') draft = WgDraftFactory(group=role.group) @@ -1481,11 +1481,11 @@ class ChangeStreamStateTests(TestCase): self.assertTrue(due - datetime.timedelta(days=1) <= reminder[0].due <= due + datetime.timedelta(days=1)) self.assertEqual(len(outbox), 1) self.assertTrue("state changed" in outbox[0]["Subject"].lower()) - self.assertTrue("mars-chairs@ietf.org" in unicode(outbox[0])) - self.assertTrue("marsdelegate@ietf.org" in unicode(outbox[0])) + self.assertTrue("mars-chairs@ietf.org" in str(outbox[0])) + self.assertTrue("marsdelegate@ietf.org" in str(outbox[0])) def test_pubreq_validation(self): - role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name=u'WG Cháir Man') + role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name='WG Cháir Man') RoleFactory(name_id='delegate',group=role.group,person__user__email='marsdelegate@ietf.org') draft = WgDraftFactory(group=role.group) @@ -1509,7 +1509,7 @@ class ChangeStreamStateTests(TestCase): class ChangeReplacesTests(TestCase): def setUp(self): - role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name=u'WG Cháir Man') + role = RoleFactory(name_id='chair',group__acronym='mars',group__list_email='mars-wg@ietf.org',person__user__username='marschairman',person__name='WG Cháir Man') RoleFactory(name_id='delegate',group=role.group,person__user__email='marsdelegate@ietf.org') #draft = WgDraftFactory(group=role.group) @@ -1520,7 +1520,7 @@ class ChangeReplacesTests(TestCase): title="Base A", group=mars_wg, ) - p = PersonFactory(name=u"basea_author") + p = PersonFactory(name="basea_author") e = Email.objects.create(address="basea_author@example.com", person=p, origin=p.user.username) self.basea.documentauthor_set.create(person=p, email=e, order=1) @@ -1530,7 +1530,7 @@ class ChangeReplacesTests(TestCase): group=mars_wg, expires = datetime.datetime.now() - datetime.timedelta(days = 365 - settings.INTERNET_DRAFT_DAYS_TO_EXPIRE), ) - p = PersonFactory(name=u"baseb_author") + p = PersonFactory(name="baseb_author") e = Email.objects.create(address="baseb_author@example.com", person=p, origin=p.user.username) self.baseb.documentauthor_set.create(person=p, email=e, order=1) @@ -1539,7 +1539,7 @@ class ChangeReplacesTests(TestCase): title="Replace Base A", group=mars_wg, ) - p = PersonFactory(name=u"replacea_author") + p = PersonFactory(name="replacea_author") e = Email.objects.create(address="replacea_author@example.com", person=p, origin=p.user.username) self.replacea.documentauthor_set.create(person=p, email=e, order=1) @@ -1548,7 +1548,7 @@ class ChangeReplacesTests(TestCase): title="Replace Base A and Base B", group=mars_wg, ) - p = PersonFactory(name=u"replaceboth_author") + p = PersonFactory(name="replaceboth_author") e = Email.objects.create(address="replaceboth_author@example.com", person=p, origin=p.user.username) self.replaceboth.documentauthor_set.create(person=p, email=e, order=1) @@ -1627,15 +1627,15 @@ class ChangeReplacesTests(TestCase): login_testing_unauthorized(self, "secretary", url) r = self.client.get(url) - self.assertEquals(r.status_code, 200) + self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertEquals(len(q('form[name=review-suggested-replaces]')), 1) + self.assertEqual(len(q('form[name=review-suggested-replaces]')), 1) r = self.client.post(url, dict(replaces=[replaced.pk])) - self.assertEquals(r.status_code, 302) + self.assertEqual(r.status_code, 302) self.assertTrue(not self.replacea.related_that_doc("possibly-replaces")) self.assertEqual(len(self.replacea.related_that_doc("replaces")), 1) - self.assertEquals(Document.objects.get(pk=self.basea.pk).get_state().slug, 'repl') + self.assertEqual(Document.objects.get(pk=self.basea.pk).get_state().slug, 'repl') class MoreReplacesTests(TestCase): diff --git a/ietf/doc/tests_material.py b/ietf/doc/tests_material.py index c2d857d70..b6028b4c8 100644 --- a/ietf/doc/tests_material.py +++ b/ietf/doc/tests_material.py @@ -1,10 +1,10 @@ -# Copyright The IETF Trust 2011-2019, All Rights Reserved +# Copyright The IETF Trust 2014-2019, All Rights Reserved # -*- coding: utf-8 -*- import os import shutil import datetime -from StringIO import StringIO +from io import StringIO from pyquery import PyQuery import debug # pyflakes:ignore diff --git a/ietf/doc/tests_review.py b/ietf/doc/tests_review.py index 40fe8da5f..49dd19bd6 100644 --- a/ietf/doc/tests_review.py +++ b/ietf/doc/tests_review.py @@ -5,7 +5,7 @@ import datetime, os, shutil, json import tarfile, tempfile, mailbox import email.mime.multipart, email.mime.text, email.utils -from StringIO import StringIO +from io import StringIO from mock import patch from requests import Response @@ -311,8 +311,8 @@ class ReviewTests(TestCase): def test_assign_reviewer(self): doc = WgDraftFactory(pages=2) review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut")) - rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',person__name=u'Some Reviewer',name_id='reviewer') - RoleFactory(group=review_team,person__user__username='marschairman',person__name=u'WG Cháir Man',name_id='reviewer') + rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',person__name='Some Reviewer',name_id='reviewer') + RoleFactory(group=review_team,person__user__username='marschairman',person__name='WG Cháir Man',name_id='reviewer') RoleFactory(group=review_team,person__user__username='reviewsecretary',person__user__email='reviewsecretary@example.com',name_id='secr') ReviewerSettings.objects.create(team=review_team, person=rev_role.person, min_interval=14, skip_next=0) @@ -353,7 +353,7 @@ class ReviewTests(TestCase): reviewer_settings.save() # Need one more person in review team one so we can test incrementing skip_count without immediately decrementing it - another_reviewer = PersonFactory.create(name = u"Extra TestReviewer") # needs to be lexically greater than the existing one + another_reviewer = PersonFactory.create(name = "Extra TestReviewer") # needs to be lexically greater than the existing one another_reviewer.role_set.create(name_id='reviewer', email=another_reviewer.email(), group=review_req.team) UnavailablePeriod.objects.create( @@ -462,7 +462,7 @@ class ReviewTests(TestCase): login_testing_unauthorized(self, "reviewsecretary", reject_url) r = self.client.get(reject_url) self.assertEqual(r.status_code, 200) - self.assertTrue(unicode(assignment.reviewer.person) in unicontent(r)) + self.assertTrue(str(assignment.reviewer.person) in unicontent(r)) # reject empty_outbox() diff --git a/ietf/doc/tests_status_change.py b/ietf/doc/tests_status_change.py index 36d3415bb..4807b3f5c 100644 --- a/ietf/doc/tests_status_change.py +++ b/ietf/doc/tests_status_change.py @@ -7,7 +7,7 @@ import shutil import debug # pyflakes:ignore from pyquery import PyQuery -from StringIO import StringIO +from io import StringIO from textwrap import wrap from django.conf import settings @@ -73,9 +73,9 @@ class StatusChangeTests(TestCase): self.assertEqual(r.status_code, 302) status_change = Document.objects.get(name='status-change-imaginary-new') self.assertEqual(status_change.get_state('statchg').slug,'adrev') - self.assertEqual(status_change.rev,u'00') - self.assertEqual(status_change.ad.name,u'Areað Irector') - self.assertEqual(status_change.notify,u'ipu@ietf.org') + self.assertEqual(status_change.rev,'00') + self.assertEqual(status_change.ad.name,'Areað Irector') + self.assertEqual(status_change.notify,'ipu@ietf.org') self.assertTrue(status_change.relateddocument_set.filter(relationship__slug='tois',target__docs__name='draft-ietf-random-thing')) def test_change_state(self): @@ -112,10 +112,10 @@ class StatusChangeTests(TestCase): doc.save_with_history([DocEvent.objects.create(doc=doc, rev=doc.rev, type="changed_document", by=Person.objects.get(user__username="secretary"), desc="Test")]) lc_req_pk = str(State.objects.get(slug='lc-req',type__slug='statchg').pk) r = self.client.post(url,dict(new_state=lc_req_pk)) - self.assertEquals(r.status_code, 200) + self.assertEqual(r.status_code, 200) doc = Document.objects.get(name='status-change-imaginary-mid-review') - self.assertEquals(doc.get_state('statchg').slug,'lc-req') - self.assertEquals(len(outbox), messages_before + 1) + self.assertEqual(doc.get_state('statchg').slug,'lc-req') + self.assertEqual(len(outbox), messages_before + 1) self.assertTrue('Last Call:' in outbox[-1]['Subject']) # successful change to IESG Evaluation @@ -171,15 +171,15 @@ class StatusChangeTests(TestCase): # normal get r = self.client.get(url) - self.assertEquals(r.status_code, 200) + self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertEquals(len(q('input[name=title]')),1) + self.assertEqual(len(q('input[name=title]')),1) # change title r = self.client.post(url,dict(title='New title')) - self.assertEquals(r.status_code,302) + self.assertEqual(r.status_code,302) doc = Document.objects.get(name='status-change-imaginary-mid-review') - self.assertEquals(doc.title,'New title') + self.assertEqual(doc.title,'New title') self.assertTrue(doc.latest_event(DocEvent,type="added_comment").desc.startswith('Title changed')) def test_edit_ad(self): @@ -288,7 +288,7 @@ class StatusChangeTests(TestCase): self.assertTrue( 'Last call requested' in ''.join(wrap(r.content,2**16))) self.assertEqual(len(outbox), messages_before + 1) self.assertTrue('Last Call:' in outbox[-1]['Subject']) - self.assertTrue('Last Call Request has been submitted' in ''.join(wrap(unicode(outbox[-1]),2**16))) + self.assertTrue('Last Call Request has been submitted' in ''.join(wrap(str(outbox[-1]),2**16))) def test_approve(self): @@ -328,8 +328,8 @@ class StatusChangeTests(TestCase): self.assertTrue('Action:' in outbox[-1]['Subject']) self.assertTrue('ietf-announce' in outbox[-1]['To']) self.assertTrue('rfc-editor' in outbox[-1]['Cc']) - self.assertTrue('(rfc9998) to Historic' in ''.join(wrap(unicode(outbox[-1])+unicode(outbox[-2]),2**16))) - self.assertTrue('(rfc9999) to Internet Standard' in ''.join(wrap(unicode(outbox[-1])+unicode(outbox[-2]),2**16))) + self.assertTrue('(rfc9998) to Historic' in ''.join(wrap(str(outbox[-1])+str(outbox[-2]),2**16))) + self.assertTrue('(rfc9999) to Internet Standard' in ''.join(wrap(str(outbox[-1])+str(outbox[-2]),2**16))) self.assertTrue(doc.latest_event(DocEvent,type="added_comment").desc.startswith('The following approval message was sent')) @@ -415,12 +415,12 @@ class StatusChangeSubmitTests(TestCase): # sane post using textbox path = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev)) - self.assertEqual(doc.rev,u'00') + self.assertEqual(doc.rev,'00') self.assertFalse(os.path.exists(path)) r = self.client.post(url,dict(content="Some initial review text\n",submit_response="1")) self.assertEqual(r.status_code,302) doc = Document.objects.get(name='status-change-imaginary-mid-review') - self.assertEqual(doc.rev,u'00') + self.assertEqual(doc.rev,'00') with open(path) as f: self.assertEqual(f.read(),"Some initial review text\n") self.assertTrue( "mid-review-00" in doc.latest_event(NewRevisionDocEvent).desc) @@ -432,7 +432,7 @@ class StatusChangeSubmitTests(TestCase): # A little additional setup # doc.rev is u'00' per the test setup - double-checking that here - if it fails, the breakage is in setUp - self.assertEqual(doc.rev,u'00') + self.assertEqual(doc.rev,'00') path = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev)) with open(path,'w') as f: f.write('This is the old proposal.') @@ -464,7 +464,7 @@ class StatusChangeSubmitTests(TestCase): r = self.client.post(url,dict(txt=test_file,submit_response="1")) self.assertEqual(r.status_code, 302) doc = Document.objects.get(name='status-change-imaginary-mid-review') - self.assertEqual(doc.rev,u'01') + self.assertEqual(doc.rev,'01') path = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev)) with open(path) as f: self.assertEqual(f.read(),"This is a new proposal.") diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index d38d00e43..6e5a755fe 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -3,7 +3,7 @@ import os import re -import urllib +import urllib.request, urllib.parse, urllib.error import math import datetime import hashlib @@ -56,7 +56,7 @@ def save_document_in_history(doc): def transfer_fields(obj, HistModel): mfields = get_model_fields_as_dict(item) # map doc -> dochist - for k, v in mfields.iteritems(): + for k, v in mfields.items(): if v == doc: mfields[k] = dochist HistModel.objects.create(**mfields) @@ -209,7 +209,7 @@ def create_ballot(request, doc, by, ballot_slug, time=None): else: e = BallotDocEvent(type="created_ballot", by=by, doc=doc, rev=doc.rev) e.ballot_type = BallotType.objects.get(doc_type=doc.type, slug=ballot_slug) - e.desc = u'Created "%s" ballot' % e.ballot_type.name + e.desc = 'Created "%s" ballot' % e.ballot_type.name e.save() def create_ballot_if_not_open(request, doc, by, ballot_slug, time=None): @@ -220,7 +220,7 @@ def create_ballot_if_not_open(request, doc, by, ballot_slug, time=None): else: e = BallotDocEvent(type="created_ballot", by=by, doc=doc, rev=doc.rev) e.ballot_type = ballot_type - e.desc = u'Created "%s" ballot' % e.ballot_type.name + e.desc = 'Created "%s" ballot' % e.ballot_type.name e.save() return e else: @@ -313,7 +313,7 @@ def add_links_in_new_revision_events(doc, events, diff_revisions): links += "" if prev != None: - links += ' (diff from previous)' % (settings.RFCDIFF_BASE_URL, urllib.quote(prev, safe="~"), urllib.quote(diff_url, safe="~")) + links += ' (diff from previous)' % (settings.RFCDIFF_BASE_URL, urllib.parse.quote(prev, safe="~"), urllib.parse.quote(diff_url, safe="~")) # replace the bold filename part e.desc = re.sub(r"(.+-[0-9][0-9].txt)", links, e.desc) @@ -363,7 +363,7 @@ def get_document_content(key, filename, split=True, markup=True): return text.decode(raw_content) def tags_suffix(tags): - return (u"::" + u"::".join(t.name for t in tags)) if tags else u"" + return ("::" + "::".join(t.name for t in tags)) if tags else "" def add_state_change_event(doc, by, prev_state, new_state, prev_tags=[], new_tags=[], timestamp=None): """Add doc event to explain that state change just happened.""" @@ -551,7 +551,7 @@ def rebuild_reference_relations(doc,filename=None): warnings = [] errors = [] unfound = set() - for ( ref, refType ) in refs.iteritems(): + for ( ref, refType ) in refs.items(): refdoc = DocAlias.objects.filter( name=ref ) count = refdoc.count() if count == 0: @@ -587,9 +587,9 @@ def set_replaces_for_document(request, doc, new_replaces, by, email_subject, com events = [] e = DocEvent(doc=doc, rev=doc.rev, by=by, type='changed_document') - new_replaces_names = u", ".join(d.name for d in new_replaces) or u"None" - old_replaces_names = u", ".join(d.name for d in old_replaces) or u"None" - e.desc = u"This document now replaces %s instead of %s" % (new_replaces_names, old_replaces_names) + new_replaces_names = ", ".join(d.name for d in new_replaces) or "None" + old_replaces_names = ", ".join(d.name for d in old_replaces) or "None" + e.desc = "This document now replaces %s instead of %s" % (new_replaces_names, old_replaces_names) e.save() events.append(e) @@ -661,7 +661,7 @@ def get_initial_notify(doc,extra=None): receivers = [] if extra: - if isinstance(extra,basestring): + if isinstance(extra,str): extra = extra.split(', ') receivers.extend(extra) @@ -759,14 +759,14 @@ def make_rev_history(doc): } if hasattr(e, 'newrevisiondocevent') and doc.history_set.filter(rev=e.newrevisiondocevent.rev).exists(): history[url]['pages'] = doc.history_set.filter(rev=e.newrevisiondocevent.rev).first().pages - history = history.values() + history = list(history.values()) return sorted(history, key=lambda x: x['published']) def get_search_cache_key(params): from ietf.doc.views_search import SearchForm fields = set(SearchForm.base_fields) - set(['sort',]) - kwargs = dict([ (k,v) for (k,v) in params.items() if k in fields ]) + kwargs = dict([ (k,v) for (k,v) in list(params.items()) if k in fields ]) key = "doc:document:search:" + hashlib.sha512(json.dumps(kwargs, sort_keys=True)).hexdigest() return key diff --git a/ietf/doc/utils_charter.py b/ietf/doc/utils_charter.py index 731f234c9..beb96864e 100644 --- a/ietf/doc/utils_charter.py +++ b/ietf/doc/utils_charter.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import re, datetime, os, shutil from django.conf import settings @@ -140,8 +141,8 @@ def generate_ballot_writeup(request, doc): e.by = request.user.person e.doc = doc e.rev = doc.rev, - e.desc = u"Ballot writeup was generated" - e.text = unicode(render_to_string("doc/charter/ballot_writeup.txt")) + e.desc = "Ballot writeup was generated" + e.text = str(render_to_string("doc/charter/ballot_writeup.txt")) # caller is responsible for saving, if necessary return e diff --git a/ietf/doc/utils_search.py b/ietf/doc/utils_search.py index ae25bef31..90093b6ef 100644 --- a/ietf/doc/utils_search.py +++ b/ietf/doc/utils_search.py @@ -16,9 +16,9 @@ def wrap_value(v): def fill_in_telechat_date(docs, doc_dict=None, doc_ids=None): if doc_dict is None: doc_dict = dict((d.pk, d) for d in docs) - doc_ids = doc_dict.keys() + doc_ids = list(doc_dict.keys()) if doc_ids is None: - doc_ids = doc_dict.keys() + doc_ids = list(doc_dict.keys()) seen = set() for e in TelechatDocEvent.objects.filter(doc__id__in=doc_ids, type="scheduled_for_telechat").order_by('-time'): @@ -36,7 +36,7 @@ def fill_in_document_sessions(docs, doc_dict, doc_ids): # get presentations presentations = SessionPresentation.objects.filter(session_id__in=[ s.id for s in sessions ]) session_list = [ (p.document_id, p.session) for p in presentations ] - for d in doc_dict.values(): + for d in list(doc_dict.values()): d.sessions = [] for (i, s) in session_list: if i in doc_ids: @@ -48,7 +48,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): # TODO - this function evolved from something that assumed it was handling only drafts. It still has places where it assumes all docs are drafts where that is not a correct assumption doc_dict = dict((d.pk, d) for d in docs) - doc_ids = doc_dict.keys() + doc_ids = list(doc_dict.keys()) rfc_aliases = dict([ (a.document.id, a.name) for a in DocAlias.objects.filter(name__startswith="rfc", docs__id__in=doc_ids) ]) @@ -112,7 +112,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): # RFCs # errata - erratas = set(Document.objects.filter(tags="errata", name__in=rfc_aliases.keys()).distinct().values_list("name", flat=True)) + erratas = set(Document.objects.filter(tags="errata", name__in=list(rfc_aliases.keys())).distinct().values_list("name", flat=True)) for d in docs: d.has_errata = d.name in erratas @@ -122,7 +122,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): d.obsoleted_by_list = [] d.updated_by_list = [] - xed_by = RelatedDocument.objects.filter(target__name__in=rfc_aliases.values(), + xed_by = RelatedDocument.objects.filter(target__name__in=list(rfc_aliases.values()), relationship__in=("obs", "updates")).select_related('target') rel_rfc_aliases = dict([ (a.document.id, a.name) for a in DocAlias.objects.filter(name__startswith="rfc", docs__id__in=[rel.source_id for rel in xed_by]) ]) for rel in xed_by: diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py index da6db8dfe..85d533442 100644 --- a/ietf/doc/views_ballot.py +++ b/ietf/doc/views_ballot.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved # ballot management (voting, commenting, writeups, ...) for Area # Directors and Secretariat @@ -162,17 +163,17 @@ def save_position(form, doc, ballot, ad, login=None, send_email=False): # figure out a description if not old_pos and pos.pos.slug != "norecord": - pos.desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name()) + pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name()) elif old_pos and pos.pos != old_pos.pos: pos.desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (pos.ad.plain_name(), pos.pos.name, old_pos.pos.name) if not pos.desc and changes: - pos.desc = u"Ballot %s text updated for %s" % (u" and ".join(changes), ad.plain_name()) + pos.desc = "Ballot %s text updated for %s" % (" and ".join(changes), ad.plain_name()) # only add new event if we actually got a change if pos.desc: if login != ad: - pos.desc += u" by %s" % login.plain_name() + pos.desc += " by %s" % login.plain_name() pos.save() @@ -362,7 +363,7 @@ def send_ballot_comment(request, name, ballot_id): if extra_cc: cc.extend(extra_cc) - send_mail_text(request, addrs.to, frm, subject, body, cc=u", ".join(cc)) + send_mail_text(request, addrs.to, frm, subject, body, cc=", ".join(cc)) return HttpResponseRedirect(return_to_url) diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py index 2f6f36e19..0ad038f54 100644 --- a/ietf/doc/views_charter.py +++ b/ietf/doc/views_charter.py @@ -808,7 +808,7 @@ def charter_with_milestones_txt(request, name, rev): try: with open(os.path.join(settings.CHARTER_PATH, filename), 'r') as f: - charter_text = unicode(f.read(), errors='ignore') + charter_text = str(f.read(), errors='ignore') except IOError: charter_text = "Error reading charter text %s" % filename diff --git a/ietf/doc/views_conflict_review.py b/ietf/doc/views_conflict_review.py index 03d06235b..e8f53f899 100644 --- a/ietf/doc/views_conflict_review.py +++ b/ietf/doc/views_conflict_review.py @@ -468,7 +468,7 @@ def start_review_as_secretariat(request, name): notify_addresses = build_notify_addresses(doc_to_review) init = { "ad" : Role.objects.filter(group__acronym='ietf',name='chair')[0].person.id, - "notify" : u', '.join(notify_addresses), + "notify" : ', '.join(notify_addresses), } form = StartReviewForm(initial=init) @@ -502,7 +502,7 @@ def start_review_as_stream_owner(request, name): notify_addresses = build_notify_addresses(doc_to_review) init = { - "notify" : u', '.join(notify_addresses), + "notify" : ', '.join(notify_addresses), } form = SimpleStartReviewForm(initial=init) diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index 343d6e1f4..73df69018 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2016-2019, All Rights Reserved +# Copyright The IETF Trust 2009-2019, All Rights Reserved # -*- coding: utf-8 -*- # Parts Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). @@ -33,7 +33,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os, datetime, urllib, json, glob, re +import os, datetime, urllib.request, urllib.parse, urllib.error, json, glob, re from django.http import HttpResponse, Http404 , HttpResponseForbidden from django.shortcuts import render, get_object_or_404, redirect @@ -251,7 +251,7 @@ def document_main(request, name, rev=None): if iesg_state and iesg_state.slug in IESG_BALLOT_ACTIVE_STATES: active_ballot = doc.active_ballot() if active_ballot: - ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values()) + ballot_summary = needed_ballot_positions(doc, list(active_ballot.active_ad_positions().values())) # submission submission = "" @@ -312,7 +312,7 @@ def document_main(request, name, rev=None): if doc.stream_id == "ietf" and group.type_id == "wg" and group.list_archive: search_archive = group.list_archive - search_archive = urllib.quote(search_archive, safe="~") + search_archive = urllib.parse.quote(search_archive, safe="~") # conflict reviews conflict_reviews = [d.document.name for d in doc.related_that("conflrev")] @@ -458,7 +458,7 @@ def document_main(request, name, rev=None): if doc.get_state_slug() in ("intrev", "iesgrev"): active_ballot = doc.active_ballot() if active_ballot: - ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values()) + ballot_summary = needed_ballot_positions(doc, list(active_ballot.active_ad_positions().values())) else: ballot_summary = "No active ballot found." @@ -493,14 +493,14 @@ def document_main(request, name, rev=None): if doc.rev == "00" and not os.path.isfile(pathname): # This could move to a template - content = u"A conflict review response has not yet been proposed." + content = "A conflict review response has not yet been proposed." else: content = doc.text_or_error() # pyflakes:ignore content = markup_txt.markup(content) ballot_summary = None if doc.get_state_slug() in ("iesgeval") and doc.active_ballot(): - ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values()) + ballot_summary = needed_ballot_positions(doc, list(doc.active_ballot().active_ad_positions().values())) return render(request, "doc/document_conflict_review.html", dict(doc=doc, @@ -521,13 +521,13 @@ def document_main(request, name, rev=None): if doc.rev == "00" and not os.path.isfile(pathname): # This could move to a template - content = u"Status change text has not yet been proposed." + content = "Status change text has not yet been proposed." else: content = doc.text_or_error() # pyflakes:ignore ballot_summary = None if doc.get_state_slug() in ("iesgeval"): - ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values()) + ballot_summary = needed_ballot_positions(doc, list(doc.active_ballot().active_ad_positions().values())) if isinstance(doc,Document): sorted_relations=doc.relateddocument_set.all().order_by('relationship__name') @@ -1263,7 +1263,7 @@ def add_sessionpresentation(request,name): if doc.group: sessions = sorted(sessions,key=lambda x:0 if x.group==doc.group else 1) - session_choices = [(s.pk,unicode(s)) for s in sessions] + session_choices = [(s.pk,str(s)) for s in sessions] if request.method == 'POST': version_form = VersionForm(request.POST,choices=version_choices) diff --git a/ietf/doc/views_downref.py b/ietf/doc/views_downref.py index 91cf88253..662fe87b0 100644 --- a/ietf/doc/views_downref.py +++ b/ietf/doc/views_downref.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved + -from __future__ import unicode_literals from django.urls import reverse as urlreverse from django.http import HttpResponseRedirect diff --git a/ietf/doc/views_draft.py b/ietf/doc/views_draft.py index fc586a452..bb4b4456d 100644 --- a/ietf/doc/views_draft.py +++ b/ietf/doc/views_draft.py @@ -65,10 +65,10 @@ class ChangeStateForm(forms.Form): prev_tag = prev_tag[0] if prev_tag else None if state == prev and tag == prev_tag: - self._errors['comment'] = ErrorList([u'State not changed. Comments entered will be lost with no state change. Please go back and use the Add Comment feature on the history tab to add comments without changing state.']) + self._errors['comment'] = ErrorList(['State not changed. Comments entered will be lost with no state change. Please go back and use the Add Comment feature on the history tab to add comments without changing state.']) if state != '(None)' and state.slug == 'idexists' and tag: - self._errors['substate'] = ErrorList([u'Clear substate before setting the document to the idexists state.']) + self._errors['substate'] = ErrorList(['Clear substate before setting the document to the idexists state.']) return retclean @@ -268,7 +268,7 @@ def change_stream(request, name): events = [] e = DocEvent(doc=doc, rev=doc.rev, by=login, type='changed_document') - e.desc = u"Stream changed to %s from %s"% (new_stream, old_stream or "None") + e.desc = "Stream changed to %s from %s"% (new_stream, old_stream or "None") e.save() events.append(e) @@ -281,7 +281,7 @@ def change_stream(request, name): doc.save_with_history(events) - msg = u"\n".join(e.desc for e in events) + msg = "\n".join(e.desc for e in events) email_stream_changed(request, doc, old_stream, new_stream, msg) @@ -437,7 +437,7 @@ def change_intention(request, name): events = [] e = DocEvent(doc=doc, rev=doc.rev, by=login, type='changed_document') - e.desc = u"Intended Status changed to %s from %s"% (new_level,old_level) + e.desc = "Intended Status changed to %s from %s"% (new_level,old_level) e.save() events.append(e) @@ -459,7 +459,7 @@ def change_intention(request, name): doc.save_with_history(events) - msg = u"\n".join(e.desc for e in events) + msg = "\n".join(e.desc for e in events) email_intended_status_changed(request, doc, msg) @@ -719,9 +719,9 @@ def edit_info(request, name): if r["area"] != doc.group: if r["area"].type_id == "area": - changes.append(u"Assigned to %s" % r["area"].name) + changes.append("Assigned to %s" % r["area"].name) else: - changes.append(u"No longer assigned to any area") + changes.append("No longer assigned to any area") doc.group = r["area"] for c in changes: @@ -1160,9 +1160,9 @@ def edit_document_urls(request, name): res = [] for u in urls: if u.desc: - res.append(u"%s %s (%s)" % (u.tag.slug, u.url, u.desc.strip('()'))) + res.append("%s %s (%s)" % (u.tag.slug, u.url, u.desc.strip('()'))) else: - res.append(u"%s %s" % (u.tag.slug, u.url)) + res.append("%s %s" % (u.tag.slug, u.url)) return fs.join(res) doc = get_object_or_404(Document, name=name) @@ -1376,9 +1376,9 @@ def adopt_draft(request, name): # stream if doc.stream != new_stream: e = DocEvent(type="changed_stream", doc=doc, rev=doc.rev, by=by) - e.desc = u"Changed stream to %s" % new_stream.name + e.desc = "Changed stream to %s" % new_stream.name if doc.stream: - e.desc += u" from %s" % doc.stream.name + e.desc += " from %s" % doc.stream.name e.save() events.append(e) old_stream = doc.stream @@ -1389,7 +1389,7 @@ def adopt_draft(request, name): # group if group != doc.group: e = DocEvent(type="changed_group", doc=doc, rev=doc.rev, by=by) - e.desc = u"Changed group to %s (%s)" % (group.name, group.acronym.upper()) + e.desc = "Changed group to %s (%s)" % (group.name, group.acronym.upper()) if doc.group.type_id != "individ": e.desc += " from %s (%s)" % (doc.group.name, doc.group.acronym.upper()) e.save() @@ -1461,7 +1461,7 @@ def release_draft(request, name): doc.tags.clear() e = DocEvent(type="changed_document", doc=doc, rev=doc.rev, by=by) l = [] - l.append(u"Tag%s %s cleared." % (pluralize(existing_tags), ", ".join(t.name for t in existing_tags))) + l.append("Tag%s %s cleared." % (pluralize(existing_tags), ", ".join(t.name for t in existing_tags))) e.desc = " ".join(l) e.save() events.append(e) @@ -1487,7 +1487,7 @@ def release_draft(request, name): if doc.stream: e = DocEvent(type="changed_stream", doc=doc, rev=doc.rev, by=by) - e.desc = u"Changed stream to None from %s" % doc.stream.name + e.desc = "Changed stream to None from %s" % doc.stream.name e.save() events.append(e) old_stream = doc.stream @@ -1529,9 +1529,9 @@ class ChangeStreamStateForm(forms.Form): f.label = state_type.label if self.stream.slug == 'ietf': if self.can_set_sub_pub: - f.help_text = u"Only select 'Submitted to IESG for Publication' to correct errors. Use the document's main page to request publication." + f.help_text = "Only select 'Submitted to IESG for Publication' to correct errors. Use the document's main page to request publication." else: - f.help_text = u"You may not set the 'Submitted to IESG for Publication' using this form - Use the document's main page to request publication." + f.help_text = "You may not set the 'Submitted to IESG for Publication' using this form - Use the document's main page to request publication." f = self.fields['tags'] f.queryset = f.queryset.filter(slug__in=get_tags_for_stream_id(doc.stream_id)) @@ -1620,9 +1620,9 @@ def change_stream_state(request, name, state_type): removed_tags = existing_tags - new_tags l = [] if added_tags: - l.append(u"Tag%s %s set." % (pluralize(added_tags), ", ".join(t.name for t in added_tags))) + l.append("Tag%s %s set." % (pluralize(added_tags), ", ".join(t.name for t in added_tags))) if removed_tags: - l.append(u"Tag%s %s cleared." % (pluralize(removed_tags), ", ".join(t.name for t in removed_tags))) + l.append("Tag%s %s cleared." % (pluralize(removed_tags), ", ".join(t.name for t in removed_tags))) e.desc = " ".join(l) e.save() events.append(e) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index 5cc5609cb..fdd7ab705 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -51,7 +51,7 @@ class UploadMaterialForm(forms.Form): self.fields["state"].widget = forms.HiddenInput() self.fields["state"].queryset = self.fields["state"].queryset.filter(slug="active") self.fields["state"].initial = self.fields["state"].queryset[0].pk - self.fields["name"].initial = u"%s-%s-" % (doc_type.slug, group.acronym) + self.fields["name"].initial = "%s-%s-" % (doc_type.slug, group.acronym) else: del self.fields["name"] @@ -157,17 +157,17 @@ def edit_material(request, name=None, acronym=None, action=None, doc_type=None): if prev_title != doc.title: e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='changed_document') - e.desc = u"Changed title to %s" % doc.title + e.desc = "Changed title to %s" % doc.title if prev_title: - e.desc += u" from %s" % prev_title + e.desc += " from %s" % prev_title e.save() events.append(e) if prev_abstract != doc.abstract: e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='changed_document') - e.desc = u"Changed abstract to %s" % doc.abstract + e.desc = "Changed abstract to %s" % doc.abstract if prev_abstract: - e.desc += u" from %s" % prev_abstract + e.desc += " from %s" % prev_abstract e.save() events.append(e) diff --git a/ietf/doc/views_review.py b/ietf/doc/views_review.py index cec4fbfbc..f641ebd28 100644 --- a/ietf/doc/views_review.py +++ b/ietf/doc/views_review.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2016-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import os import datetime @@ -771,7 +771,7 @@ def search_mail_archive(request, name, assignment_id): except KeyError as e: res["error"] = "No results found" except Exception as e: - res["error"] = "Retrieval from mail archive failed: %s" % unicode(e) + res["error"] = "Retrieval from mail archive failed: %s" % str(e) # raise # useful when debugging return JsonResponse(res) diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py index d62319fad..2df24b419 100644 --- a/ietf/doc/views_status_change.py +++ b/ietf/doc/views_status_change.py @@ -392,7 +392,7 @@ def clean_helper(form, formtype): new_relations = {} rfc_fields = {} status_fields={} - for k in sorted(form.data.iterkeys()): + for k in sorted(form.data.keys()): v = form.data[k] if k.startswith('new_relation_row'): if re.match('\d{1,4}',v): @@ -634,7 +634,7 @@ def generate_last_call_text(request, doc): e.doc = doc e.rev = doc.rev e.desc = 'Last call announcement was generated' - e.text = unicode(new_text) + e.text = str(new_text) e.save() return e diff --git a/ietf/group/admin.py b/ietf/group/admin.py index ad3056ce1..0073808af 100644 --- a/ietf/group/admin.py +++ b/ietf/group/admin.py @@ -38,7 +38,7 @@ class GroupAdmin(admin.ModelAdmin): roles = Role.objects.filter(group=obj).order_by("name", "person__name").select_related('person') res = [] for r in roles: - res.append(u'%s (%s)' % (r.person.pk, escape(r.person.plain_name()), r.pk, r.name.name)) + res.append('%s (%s)' % (r.person.pk, escape(r.person.plain_name()), r.pk, r.name.name)) return ", ".join(res) role_list.short_description = "Persons" role_list.allow_tags = True @@ -144,7 +144,7 @@ class GroupHistoryAdmin(admin.ModelAdmin): admin.site.register(GroupHistory, GroupHistoryAdmin) class GroupURLAdmin(admin.ModelAdmin): - list_display = [u'id', 'group', 'name', 'url'] + list_display = ['id', 'group', 'name', 'url'] raw_id_fields = ['group'] search_fields = ['name'] admin.site.register(GroupURL, GroupURLAdmin) @@ -157,7 +157,7 @@ admin.site.register(GroupMilestone, GroupMilestoneAdmin) admin.site.register(GroupMilestoneHistory, GroupMilestoneAdmin) class GroupStateTransitionsAdmin(admin.ModelAdmin): - list_display = [u'id', 'group', 'state'] + list_display = ['id', 'group', 'state'] raw_id_fields = ['group', 'state'] admin.site.register(GroupStateTransitions, GroupStateTransitionsAdmin) @@ -183,7 +183,7 @@ class ChangeStateGroupEventAdmin(admin.ModelAdmin): admin.site.register(ChangeStateGroupEvent, ChangeStateGroupEventAdmin) class MilestoneGroupEventAdmin(admin.ModelAdmin): - list_display = [u'id', 'group', 'time', 'type', 'by', 'desc', 'milestone'] + list_display = ['id', 'group', 'time', 'type', 'by', 'desc', 'milestone'] list_filter = ['time'] raw_id_fields = ['group', 'by', 'milestone'] admin.site.register(MilestoneGroupEvent, MilestoneGroupEventAdmin) diff --git a/ietf/group/dot.py b/ietf/group/dot.py index abb5c4efe..a29a509e3 100644 --- a/ietf/group/dot.py +++ b/ietf/group/dot.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2007-2019, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- check-flake8 -*- -from __future__ import unicode_literals, print_function + from django.db.models import Q from django.template.loader import render_to_string diff --git a/ietf/group/feeds.py b/ietf/group/feeds.py index c41b2ada2..aaf8097b7 100644 --- a/ietf/group/feeds.py +++ b/ietf/group/feeds.py @@ -18,7 +18,7 @@ class GroupChangesFeed(Feed): return Group.objects.get(acronym=acronym) def title(self, obj): - return u"Changes for %s %s" % (obj.acronym, obj.type) + return "Changes for %s %s" % (obj.acronym, obj.type) def link(self, obj): if not obj: @@ -47,8 +47,8 @@ class GroupChangesFeed(Feed): return obj.time def item_title(self, obj): - title = u"%s - %s" % (truncatewords(strip_tags(obj.desc), 10), obj.by) + title = "%s - %s" % (truncatewords(strip_tags(obj.desc), 10), obj.by) if isinstance(obj, DocEvent): - title = u"Chartering: %s" % title + title = "Chartering: %s" % title return title diff --git a/ietf/group/forms.py b/ietf/group/forms.py index 81dab5aea..1c4bc550d 100644 --- a/ietf/group/forms.py +++ b/ietf/group/forms.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2007-2019, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + # Stdlib imports import re diff --git a/ietf/group/mails.py b/ietf/group/mails.py index 3db25f464..e4f1042fc 100644 --- a/ietf/group/mails.py +++ b/ietf/group/mails.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved # generation of mails import re @@ -13,7 +14,7 @@ from ietf.mailtrigger.utils import gather_address_lists def email_admin_re_charter(request, group, subject, text, mailtrigger): (to,cc) = gather_address_lists(mailtrigger,group=group) - full_subject = u"Regarding %s %s: %s" % (group.type.name, group.acronym, subject) + full_subject = "Regarding %s %s: %s" % (group.type.name, group.acronym, subject) text = strip_tags(text) send_mail(request, to, None, full_subject, @@ -28,32 +29,32 @@ def email_admin_re_charter(request, group, subject, text, mailtrigger): def email_personnel_change(request, group, text, changed_personnel): (to, cc) = gather_address_lists('group_personnel_change',group=group,changed_personnel=changed_personnel) - full_subject = u"Personnel change for %s %s" % (group.acronym,group.type.name) + full_subject = "Personnel change for %s %s" % (group.acronym,group.type.name) send_mail_text(request, to, None, full_subject, text, cc=cc) def email_milestones_changed(request, group, changes, states): def wrap_up_email(addrs, text): - subject = u"Milestones changed for %s %s" % (group.acronym, group.type.name) + subject = "Milestones changed for %s %s" % (group.acronym, group.type.name) if re.search("Added .* for review, due",text): - subject = u"Review Required - " + subject + subject = "Review Required - " + subject text = wordwrap(strip_tags(text), 78) text += "\n\n" - text += u"URL: %s" % (settings.IDTRACKER_BASE_URL + group.about_url()) + text += "URL: %s" % (settings.IDTRACKER_BASE_URL + group.about_url()) send_mail_text(request, addrs.to, None, subject, text, cc=addrs.cc) # first send to those who should see any edits (such as management and chairs) addrs = gather_address_lists('group_milestones_edited',group=group) if addrs.to or addrs.cc: - wrap_up_email(addrs, u"\n\n".join(c + "." for c in changes)) + wrap_up_email(addrs, "\n\n".join(c + "." for c in changes)) # then send only the approved milestones to those who shouldn't be # bothered with milestones pending approval addrs = gather_address_lists('group_approved_milestones_edited',group=group) - msg = u"\n\n".join(c + "." for c,s in zip(changes,states) if not s == "review") + msg = "\n\n".join(c + "." for c,s in zip(changes,states) if not s == "review") if (addrs.to or addrs.cc) and msg: wrap_up_email(addrs, msg) diff --git a/ietf/group/management/commands/show_group_features.py b/ietf/group/management/commands/show_group_features.py index cdbf5e2d4..e63b7fd66 100644 --- a/ietf/group/management/commands/show_group_features.py +++ b/ietf/group/management/commands/show_group_features.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import collections diff --git a/ietf/group/migrations/0001_initial.py b/ietf/group/migrations/0001_initial.py index 2f45322c1..a0593af8c 100644 --- a/ietf/group/migrations/0001_initial.py +++ b/ietf/group/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import datetime from django.db import migrations, models diff --git a/ietf/group/migrations/0002_groupfeatures_historicalgroupfeatures.py b/ietf/group/migrations/0002_groupfeatures_historicalgroupfeatures.py index d3efd2a42..ac3bf887b 100644 --- a/ietf/group/migrations/0002_groupfeatures_historicalgroupfeatures.py +++ b/ietf/group/migrations/0002_groupfeatures_historicalgroupfeatures.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-07-10 15:58 -from __future__ import unicode_literals + import django.core.validators import django.db.models.deletion diff --git a/ietf/group/migrations/0003_groupfeatures_data.py b/ietf/group/migrations/0003_groupfeatures_data.py index 55b700840..7d971c8b3 100644 --- a/ietf/group/migrations/0003_groupfeatures_data.py +++ b/ietf/group/migrations/0003_groupfeatures_data.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-07-10 15:58 -from __future__ import unicode_literals + from django.conf import settings from django.db import migrations @@ -10,7 +11,7 @@ import debug # pyflakes:ignore from ietf.review.utils import active_review_teams group_type_features = { - u'ag': { + 'ag': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', @@ -25,7 +26,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'area': { + 'area': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', @@ -40,7 +41,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'dir': { + 'dir': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair,secr', 'agenda_type': None, @@ -55,7 +56,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'review': { + 'review': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair,secr', 'agenda_type': None, @@ -70,7 +71,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': True, 'material_types': 'slides'}, - u'iab': { + 'iab': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', @@ -85,7 +86,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'ietf': { + 'ietf': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', @@ -100,7 +101,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'individ': { + 'individ': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': None, @@ -115,7 +116,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'irtf': { + 'irtf': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', @@ -130,7 +131,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'isoc': { + 'isoc': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': None, @@ -145,7 +146,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'nomcom': { + 'nomcom': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'side', @@ -160,7 +161,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'program': { + 'program': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'lead', 'agenda_type': None, @@ -175,7 +176,7 @@ group_type_features = { 'has_milestones': True, 'has_reviews': False, 'material_types': 'slides'}, - u'rfcedtyp': { + 'rfcedtyp': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'side', @@ -190,7 +191,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'rg': { + 'rg': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', @@ -205,7 +206,7 @@ group_type_features = { 'has_milestones': True, 'has_reviews': False, 'material_types': 'slides'}, - u'sdo': { + 'sdo': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': None, @@ -220,7 +221,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'team': { + 'team': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', @@ -235,7 +236,7 @@ group_type_features = { 'has_milestones': False, 'has_reviews': False, 'material_types': 'slides'}, - u'wg': { + 'wg': { 'about_page': 'ietf.group.views.group_about', 'admin_roles': 'chair', 'agenda_type': 'ietf', diff --git a/ietf/group/migrations/0004_add_group_feature_fields.py b/ietf/group/migrations/0004_add_group_feature_fields.py index 6547e6405..8897d7530 100644 --- a/ietf/group/migrations/0004_add_group_feature_fields.py +++ b/ietf/group/migrations/0004_add_group_feature_fields.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2019-01-10 07:51 -from __future__ import unicode_literals + import django.core.validators from django.db import migrations, models diff --git a/ietf/group/migrations/0005_group_features_list_data_to_json.py b/ietf/group/migrations/0005_group_features_list_data_to_json.py index 67e6f9512..9a2309226 100644 --- a/ietf/group/migrations/0005_group_features_list_data_to_json.py +++ b/ietf/group/migrations/0005_group_features_list_data_to_json.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2019-01-09 09:02 -from __future__ import unicode_literals + import json import re diff --git a/ietf/group/migrations/0006_group_features_lists_to_jsonfield.py b/ietf/group/migrations/0006_group_features_lists_to_jsonfield.py index 0cc82763e..26d5cccdd 100644 --- a/ietf/group/migrations/0006_group_features_lists_to_jsonfield.py +++ b/ietf/group/migrations/0006_group_features_lists_to_jsonfield.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2019-01-16 05:53 -from __future__ import unicode_literals + from django.db import migrations, models import jsonfield.fields diff --git a/ietf/group/migrations/0007_new_group_features_data.py b/ietf/group/migrations/0007_new_group_features_data.py index b93e60041..dabdb1d5f 100644 --- a/ietf/group/migrations/0007_new_group_features_data.py +++ b/ietf/group/migrations/0007_new_group_features_data.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2019-01-09 09:02 -from __future__ import unicode_literals + from django.db import migrations @@ -9,7 +9,7 @@ from django.db import migrations import debug # pyflakes:ignore group_type_features = { - u'ag': { + 'ag': { 'custom_group_roles': True, 'has_session_materials': True, 'acts_like_wg': True, @@ -22,7 +22,7 @@ group_type_features = { 'matman_roles': ['ad', 'chair', 'delegate', 'secr'], 'role_order': ['chair', 'secr'], }, - u'area': { + 'area': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -35,7 +35,7 @@ group_type_features = { 'matman_roles': ['ad', 'chair', 'delegate', 'secr'], 'role_order': ['chair', 'secr'], }, - u'dir': { + 'dir': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -48,7 +48,7 @@ group_type_features = { 'matman_roles': ['ad', 'chair', 'delegate', 'secr'], 'role_order': ['chair', 'secr'], }, - u'review': { + 'review': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -61,7 +61,7 @@ group_type_features = { 'matman_roles': ['ad', 'secr'], 'role_order': ['chair', 'secr'], }, - u'iab': { + 'iab': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -74,7 +74,7 @@ group_type_features = { 'matman_roles': ['chair', 'delegate'], 'role_order': ['chair', 'secr'], }, - u'ietf': { + 'ietf': { 'custom_group_roles': True, 'has_session_materials': True, 'acts_like_wg': False, @@ -87,7 +87,7 @@ group_type_features = { 'matman_roles': ['chair', 'delegate'], 'role_order': ['chair', 'secr'], }, - u'individ': { + 'individ': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -100,7 +100,7 @@ group_type_features = { 'matman_roles': [], 'role_order': ['chair', 'secr'], }, - u'irtf': { + 'irtf': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -113,7 +113,7 @@ group_type_features = { 'matman_roles': ['chair', 'delegate', 'secr'], 'role_order': ['chair', 'secr'], }, - u'isoc': { + 'isoc': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -126,7 +126,7 @@ group_type_features = { 'matman_roles': ['chair', 'secr'], 'role_order': ['chair', 'secr'], }, - u'nomcom': { + 'nomcom': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -139,7 +139,7 @@ group_type_features = { 'matman_roles': ['chair'], 'role_order': ['chair', 'member', 'advisor'], }, - u'program': { + 'program': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -152,7 +152,7 @@ group_type_features = { 'matman_roles': ['chair', 'secr'], 'role_order': ['chair', 'secr'], }, - u'rfcedtyp': { + 'rfcedtyp': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -165,7 +165,7 @@ group_type_features = { 'matman_roles': [], 'role_order': ['chair', 'secr'], }, - u'rg': { + 'rg': { 'custom_group_roles': False, 'has_session_materials': True, 'acts_like_wg': True, @@ -178,7 +178,7 @@ group_type_features = { 'matman_roles': ['chair', 'secr'], 'role_order': ['chair', 'secr'], }, - u'sdo': { + 'sdo': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -191,7 +191,7 @@ group_type_features = { 'matman_roles': [], 'role_order': ['liaiman'], }, - u'team': { + 'team': { 'custom_group_roles': True, 'has_session_materials': False, 'acts_like_wg': False, @@ -204,7 +204,7 @@ group_type_features = { 'matman_roles': [], 'role_order': ['chair', 'member', 'matman'], }, - u'wg': { + 'wg': { 'custom_group_roles': False, 'has_session_materials': True, 'acts_like_wg': True, @@ -224,7 +224,7 @@ def forward(apps, schema_editor): for type in group_type_features: features = group_type_features[type] gf = GroupFeatures.objects.get(type=type) - for k,v in features.items(): + for k,v in list(features.items()): setattr(gf, k, v) gf.save() # This migration does not remove or change any previous fields, and executes diff --git a/ietf/group/migrations/0008_group_features_onetoone.py b/ietf/group/migrations/0008_group_features_onetoone.py index f010e77d4..3daed25f2 100644 --- a/ietf/group/migrations/0008_group_features_onetoone.py +++ b/ietf/group/migrations/0008_group_features_onetoone.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2019-01-19 10:08 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/group/migrations/0009_auto_20190122_1012.py b/ietf/group/migrations/0009_auto_20190122_1012.py index 44df99f2b..7b556dd5d 100644 --- a/ietf/group/migrations/0009_auto_20190122_1012.py +++ b/ietf/group/migrations/0009_auto_20190122_1012.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-22 10:12 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/group/migrations/0010_add_group_types.py b/ietf/group/migrations/0010_add_group_types.py index bcc480b5d..98a8a6010 100644 --- a/ietf/group/migrations/0010_add_group_types.py +++ b/ietf/group/migrations/0010_add_group_types.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2019-01-09 09:02 -from __future__ import unicode_literals + from django.db import migrations @@ -128,13 +128,13 @@ def forward(apps, schema_editor): for slug in group_type_features: typename = group_type_features[slug]['grouptypename'] gt, _ = GroupTypeName.objects.get_or_create(slug=slug) - for k,v in typename.items(): + for k,v in list(typename.items()): setattr(gt, k, v) gt.save() # features = group_type_features[slug]['groupfeatures'] gf, _ = GroupFeatures.objects.get_or_create(type_id=slug) - for k,v in features.items(): + for k,v in list(features.items()): setattr(gf, k, v) gf.save() diff --git a/ietf/group/migrations/0011_auto_20190225_1302.py b/ietf/group/migrations/0011_auto_20190225_1302.py index f0349ad9d..5c11c9574 100644 --- a/ietf/group/migrations/0011_auto_20190225_1302.py +++ b/ietf/group/migrations/0011_auto_20190225_1302.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-02-25 13:02 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/group/migrations/0012_add_old_nomcom_announcements.py b/ietf/group/migrations/0012_add_old_nomcom_announcements.py index c13ff9570..8647b3dc5 100644 --- a/ietf/group/migrations/0012_add_old_nomcom_announcements.py +++ b/ietf/group/migrations/0012_add_old_nomcom_announcements.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-03-23 17:50 -from __future__ import unicode_literals + from django.db import migrations @@ -342,7 +343,7 @@ also serves as a non-voting liaison. """) - n.message_set.create(by=p, subject="Announcement of IESG and IAB Nominations Requests", time=datetime(2002,11,05), + n.message_set.create(by=p, subject="Announcement of IESG and IAB Nominations Requests", time=datetime(2002,11,0o5), frm="Phil Roberts ", to="IETF Announcement list ", body=""" The 2002-2003 Nominations Committee is now soliciting nominations for the open diff --git a/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py b/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py index 1ccca9b13..b980f5d0c 100644 --- a/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py +++ b/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-02-25 13:02 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/group/migrations/0014_set_document_m2m_keys.py b/ietf/group/migrations/0014_set_document_m2m_keys.py index e8324f625..520c15e8a 100644 --- a/ietf/group/migrations/0014_set_document_m2m_keys.py +++ b/ietf/group/migrations/0014_set_document_m2m_keys.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-10 06:48 -from __future__ import unicode_literals + import sys @@ -21,7 +21,7 @@ def forward(apps, schema_editor): # Document id fixup ------------------------------------------------------------ objs = Document.objects.in_bulk() - nameid = { o.name: o.id for id, o in objs.iteritems() } + nameid = { o.name: o.id for id, o in objs.items() } sys.stderr.write('\n') diff --git a/ietf/group/migrations/0015_1_del_docs_m2m_table.py b/ietf/group/migrations/0015_1_del_docs_m2m_table.py index 5b2462ce4..1e5e856b3 100644 --- a/ietf/group/migrations/0015_1_del_docs_m2m_table.py +++ b/ietf/group/migrations/0015_1_del_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-22 08:00 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/group/migrations/0015_2_add_docs_m2m_table.py b/ietf/group/migrations/0015_2_add_docs_m2m_table.py index cf01621d8..d66087372 100644 --- a/ietf/group/migrations/0015_2_add_docs_m2m_table.py +++ b/ietf/group/migrations/0015_2_add_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-22 08:00 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/group/migrations/0016_copy_docs_m2m_table.py b/ietf/group/migrations/0016_copy_docs_m2m_table.py index 4eef2b618..9a380f601 100644 --- a/ietf/group/migrations/0016_copy_docs_m2m_table.py +++ b/ietf/group/migrations/0016_copy_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-27 05:57 -from __future__ import unicode_literals + import sys, time diff --git a/ietf/group/migrations/0017_remove_docs2_m2m.py b/ietf/group/migrations/0017_remove_docs2_m2m.py index 26b5784fe..4f67ac8d3 100644 --- a/ietf/group/migrations/0017_remove_docs2_m2m.py +++ b/ietf/group/migrations/0017_remove_docs2_m2m.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-30 03:23 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/group/migrations/0018_remove_old_document_field.py b/ietf/group/migrations/0018_remove_old_document_field.py index 02f85b6d3..0ee29de38 100644 --- a/ietf/group/migrations/0018_remove_old_document_field.py +++ b/ietf/group/migrations/0018_remove_old_document_field.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-25 06:51 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/group/migrations/0019_rename_field_document2.py b/ietf/group/migrations/0019_rename_field_document2.py index c4d25d3e5..2bd82f5bc 100644 --- a/ietf/group/migrations/0019_rename_field_document2.py +++ b/ietf/group/migrations/0019_rename_field_document2.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-25 06:52 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/group/models.py b/ietf/group/models.py index 6b58e36bf..2069d6ca9 100644 --- a/ietf/group/models.py +++ b/ietf/group/models.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007-2019, All Rights Reserved +# Copyright The IETF Trust 2010-2019, All Rights Reserved # -*- coding: utf-8 -*- import datetime @@ -7,7 +7,7 @@ import jsonfield import os import re -from urlparse import urljoin +from urllib.parse import urljoin from django.conf import settings from django.core.validators import RegexValidator @@ -91,7 +91,7 @@ class Group(GroupInfo): return e[0] if e else None def has_role(self, user, role_names): - if isinstance(role_names, str) or isinstance(role_names, unicode): + if isinstance(role_names, str) or isinstance(role_names, str): role_names = [role_names] return user.is_authenticated and self.role_set.filter(name__in=role_names, person__user=user).exists() @@ -253,7 +253,7 @@ class GroupURL(models.Model): url = models.URLField() def __unicode__(self): - return u"%s (%s)" % (self.url, self.name) + return "%s (%s)" % (self.url, self.name) class GroupMilestoneInfo(models.Model): group = ForeignKey(Group) @@ -289,7 +289,7 @@ class GroupStateTransitions(models.Model): next_states = models.ManyToManyField('doc.State', related_name='previous_groupstatetransitions_states') def __unicode__(self): - return u'%s "%s" -> %s' % (self.group.acronym, self.state.name, [s.name for s in self.next_states.all()]) + return '%s "%s" -> %s' % (self.group.acronym, self.state.name, [s.name for s in self.next_states.all()]) GROUP_EVENT_CHOICES = [ ("changed_state", "Changed state"), @@ -310,7 +310,7 @@ class GroupEvent(models.Model): desc = models.TextField() def __unicode__(self): - return u"%s %s at %s" % (self.by.plain_name(), self.get_type_display().lower(), self.time) + return "%s %s at %s" % (self.by.plain_name(), self.get_type_display().lower(), self.time) class Meta: ordering = ['-time', 'id'] @@ -327,7 +327,7 @@ class Role(models.Model): person = ForeignKey(Person) email = ForeignKey(Email, help_text="Email address used by person for this role.") def __unicode__(self): - return u"%s is %s in %s" % (self.person.plain_name(), self.name.name, self.group.acronym or self.group.name) + return "%s is %s in %s" % (self.person.plain_name(), self.name.name, self.group.acronym or self.group.name) def formatted_ascii_email(self): return email.utils.formataddr((self.person.plain_ascii(), self.email.address)) @@ -348,7 +348,7 @@ class RoleHistory(models.Model): person = ForeignKey(Person) email = ForeignKey(Email, help_text="Email address used by person for this role.") def __unicode__(self): - return u"%s is %s in %s" % (self.person.plain_name(), self.name.name, self.group.acronym) + return "%s is %s in %s" % (self.person.plain_name(), self.name.name, self.group.acronym) class Meta: verbose_name_plural = "role histories" diff --git a/ietf/group/tests_info.py b/ietf/group/tests_info.py index 04d2cc21f..d4f347911 100644 --- a/ietf/group/tests_info.py +++ b/ietf/group/tests_info.py @@ -6,7 +6,7 @@ import shutil import calendar import datetime import json -import StringIO +import io import bleach import six @@ -1293,7 +1293,7 @@ class StatusUpdateTests(TestCase): self.assertEqual(response.status_code, 302) self.assertEqual(chair.group.latest_event(type='status_update').desc,'Direct content typed into form') - test_file = StringIO.StringIO("This came from a file.") + test_file = io.StringIO("This came from a file.") test_file.name = "unnamed" response = self.client.post(url,dict(txt=test_file,submit_response="1")) self.assertEqual(response.status_code, 302) diff --git a/ietf/group/tests_review.py b/ietf/group/tests_review.py index 36243d598..fa689dfe7 100644 --- a/ietf/group/tests_review.py +++ b/ietf/group/tests_review.py @@ -151,7 +151,7 @@ class ReviewTests(TestCase): urlreverse(ietf.group.views.reviewer_overview, kwargs={ 'acronym': group.acronym, 'group_type': group.type_id })]: r = self.client.get(url) self.assertEqual(r.status_code, 200) - self.assertIn(unicode(reviewer), unicontent(r)) + self.assertIn(str(reviewer), unicontent(r)) self.assertIn(review_req1.doc.name, unicontent(r)) # without a login, reason for being unavailable should not be seen self.assertNotIn("Availability", unicontent(r)) @@ -178,7 +178,7 @@ class ReviewTests(TestCase): def test_manage_review_requests(self): group = ReviewTeamFactory() RoleFactory(name_id='reviewer',group=group,person__user__username='reviewer').person - marsperson = RoleFactory(name_id='reviewer',group=group,person=PersonFactory(name=u"Mars Anders Chairman",user__username='marschairman')).person + marsperson = RoleFactory(name_id='reviewer',group=group,person=PersonFactory(name="Mars Anders Chairman",user__username='marschairman')).person review_req1 = ReviewRequestFactory(doc__pages=2,doc__shepherd=marsperson.email(),team=group) review_req2 = ReviewRequestFactory(team=group) review_req3 = ReviewRequestFactory(team=group) @@ -188,10 +188,10 @@ class ReviewTests(TestCase): login_testing_unauthorized(self, "secretary", unassigned_url) # Need one more person in review team one so we can test incrementing skip_count without immediately decrementing it - another_reviewer = PersonFactory.create(name = u"Extra TestReviewer") # needs to be lexically greater than the exsting one + another_reviewer = PersonFactory.create(name = "Extra TestReviewer") # needs to be lexically greater than the exsting one another_reviewer.role_set.create(name_id='reviewer', email=another_reviewer.email(), group=review_req1.team) ReviewerSettingsFactory(team=review_req3.team, person = another_reviewer) - yet_another_reviewer = PersonFactory.create(name = u"YetAnotherExtra TestReviewer") # needs to be lexically greater than the exsting one + yet_another_reviewer = PersonFactory.create(name = "YetAnotherExtra TestReviewer") # needs to be lexically greater than the exsting one yet_another_reviewer.role_set.create(name_id='reviewer', email=yet_another_reviewer.email(), group=review_req1.team) ReviewerSettingsFactory(team=review_req3.team, person = yet_another_reviewer) @@ -262,7 +262,7 @@ class ReviewTests(TestCase): q = PyQuery(r.content) generated_text = q("[name=body]").text() self.assertTrue(review_req1.doc.name in generated_text) - self.assertTrue(unicode(Person.objects.get(user__username="marschairman")) in generated_text) + self.assertTrue(str(Person.objects.get(user__username="marschairman")) in generated_text) empty_outbox() r = self.client.post(url, { diff --git a/ietf/group/utils.py b/ietf/group/utils.py index 5c501435d..2a6003de3 100644 --- a/ietf/group/utils.py +++ b/ietf/group/utils.py @@ -20,6 +20,7 @@ from ietf.person.models import Email from ietf.review.utils import can_manage_review_requests_for_team from ietf.utils import log from ietf.utils.history import get_history_object_for, copy_many_to_many_for_history +from functools import reduce def save_group_in_history(group): """This should be called before saving changes to a Group instance, @@ -62,7 +63,7 @@ def get_group_role_emails(group, roles): if not group or not group.acronym or group.acronym == 'none': return set() emails = Email.objects.filter(role__group=group, role__name__in=roles) - return set(filter(None, [e.email_address() for e in emails])) + return set([_f for _f in [e.email_address() for e in emails] if _f]) def get_child_group_role_emails(parent, roles, group_type='wg'): """Get a list of email addresses for a given set of @@ -207,35 +208,35 @@ def construct_group_menu_context(request, group, selected, group_type, others): if group.features.has_milestones: if group.state_id != "proposed" and can_manage: - actions.append((u"Edit milestones", urlreverse('ietf.group.milestones.edit_milestones;current', kwargs=kwargs))) + actions.append(("Edit milestones", urlreverse('ietf.group.milestones.edit_milestones;current', kwargs=kwargs))) if group.features.has_documents: clist = CommunityList.objects.filter(group=group).first() if clist and can_manage_community_list(request.user, clist): import ietf.community.views - actions.append((u'Manage document list', urlreverse(ietf.community.views.manage_list, kwargs=kwargs))) + actions.append(('Manage document list', urlreverse(ietf.community.views.manage_list, kwargs=kwargs))) if group.features.has_nonsession_materials and can_manage_materials(request.user, group): - actions.append((u"Upload material", urlreverse("ietf.doc.views_material.choose_material_type", kwargs=kwargs))) + actions.append(("Upload material", urlreverse("ietf.doc.views_material.choose_material_type", kwargs=kwargs))) if group.features.has_reviews and can_manage_review_requests_for_team(request.user, group): import ietf.group.views - actions.append((u"Manage unassigned reviews", urlreverse(ietf.group.views.manage_review_requests, kwargs=dict(assignment_status="unassigned", **kwargs)))) + actions.append(("Manage unassigned reviews", urlreverse(ietf.group.views.manage_review_requests, kwargs=dict(assignment_status="unassigned", **kwargs)))) #actions.append((u"Manage assigned reviews", urlreverse(ietf.group.views.manage_review_requests, kwargs=dict(assignment_status="assigned", **kwargs)))) if Role.objects.filter(name="secr", group=group, person__user=request.user).exists(): - actions.append((u"Secretary settings", urlreverse(ietf.group.views.change_review_secretary_settings, kwargs=kwargs))) - actions.append((u"Email open assignments summary", urlreverse(ietf.group.views.email_open_review_assignments, kwargs=dict(acronym=group.acronym, group_type=group.type_id)))) + actions.append(("Secretary settings", urlreverse(ietf.group.views.change_review_secretary_settings, kwargs=kwargs))) + actions.append(("Email open assignments summary", urlreverse(ietf.group.views.email_open_review_assignments, kwargs=dict(acronym=group.acronym, group_type=group.type_id)))) if group.state_id != "conclude" and can_manage: can_edit_group = True - actions.append((u"Edit group", urlreverse("ietf.group.views.edit", kwargs=dict(kwargs, action="edit")))) + actions.append(("Edit group", urlreverse("ietf.group.views.edit", kwargs=dict(kwargs, action="edit")))) if group.features.customize_workflow and can_manage: - actions.append((u"Customize workflow", urlreverse("ietf.group.views.customize_workflow", kwargs=kwargs))) + actions.append(("Customize workflow", urlreverse("ietf.group.views.customize_workflow", kwargs=kwargs))) if group.state_id in ("active", "dormant") and not group.type_id in ["sdo", "rfcedtyp", "isoc", ] and can_manage_group_type(request.user, group): - actions.append((u"Request closing group", urlreverse("ietf.group.views.conclude", kwargs=kwargs))) + actions.append(("Request closing group", urlreverse("ietf.group.views.conclude", kwargs=kwargs))) d = { "group": group, diff --git a/ietf/group/views.py b/ietf/group/views.py index 9dd5c523b..0a89d33d9 100644 --- a/ietf/group/views.py +++ b/ietf/group/views.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright The IETF Trust 2007-2019, All Rights Reserved -from __future__ import unicode_literals, print_function +# Copyright The IETF Trust 2009-2019, All Rights Reserved + # Portion Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -150,7 +150,7 @@ def fill_in_charter_info(group, include_drafts=False): personnel["ad"] = ad_roles group.personnel = [] - for role_name_slug, roles in personnel.iteritems(): + for role_name_slug, roles in personnel.items(): label = roles[0].name.name if len(roles) > 1: if label.endswith("y"): @@ -168,7 +168,7 @@ def fill_in_charter_info(group, include_drafts=False): if group.charter: group.charter_text = get_charter_text(group) else: - group.charter_text = u"Not chartered yet." + group.charter_text = "Not chartered yet." def extract_last_name(role): return role.person.name_parts()[3] @@ -268,7 +268,7 @@ def wg_charters_by_acronym(request, group_type): raise Http404 areas = dict((a.id, a) for a in Group.objects.filter(type="area", state="active").order_by("name")) - for area in areas.itervalues(): + for area in areas.values(): area.ads = sorted(roles(area, "ad"), key=extract_last_name) groups = Group.objects.filter(type="wg", state="active").exclude(parent=None).order_by("acronym") @@ -414,7 +414,7 @@ def concluded_groups(request): sections['Review teams'] = Group.objects.filter(type='review', state="conclude").select_related("state", "charter").order_by("parent__name","acronym") sections['Teams'] = Group.objects.filter(type='team', state="conclude").select_related("state", "charter").order_by("parent__name","acronym") - for name, groups in sections.items(): + for name, groups in list(sections.items()): # add start/conclusion date d = dict((g.pk, g) for g in groups) @@ -496,7 +496,7 @@ def group_documents_txt(request, acronym, group_type=None): d.prefix = d.get_state().name for d in docs_related: - d.prefix = u"Related %s" % d.get_state().name + d.prefix = "Related %s" % d.get_state().name rows = [] for d in itertools.chain(docs, docs_related): @@ -506,9 +506,9 @@ def group_documents_txt(request, acronym, group_type=None): else: name = "%s-%s" % (d.name, d.rev) - rows.append(u"\t".join((d.prefix, name, clean_whitespace(d.title)))) + rows.append("\t".join((d.prefix, name, clean_whitespace(d.title)))) - return HttpResponse(u"\n".join(rows), content_type='text/plain; charset=UTF-8') + return HttpResponse("\n".join(rows), content_type='text/plain; charset=UTF-8') def group_about(request, acronym, group_type=None): group = get_group_or_404(acronym, group_type) @@ -679,7 +679,7 @@ def materials(request, acronym, group_type=None): return render(request, 'group/materials.html', construct_group_menu_context(request, group, "materials", group_type, { - "doc_types": doc_types.items(), + "doc_types": list(doc_types.items()), "can_manage_materials": can_manage_materials(request.user, group) })) @@ -853,7 +853,7 @@ def edit(request, group_type=None, acronym=None, action="edit", field=None): res = [] for u in urls: if u.name: - res.append(u"%s (%s)" % (u.url, u.name)) + res.append("%s (%s)" % (u.url, u.name)) else: res.append(u.url) return fs.join(res) @@ -930,7 +930,7 @@ def edit(request, group_type=None, acronym=None, action="edit", field=None): personnel_change_text="" changed_personnel = set() # update roles - for attr, f in form.fields.iteritems(): + for attr, f in form.fields.items(): if not (attr.endswith("_roles") or attr == "ad"): continue @@ -1443,9 +1443,9 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status= saving = form_action.startswith("save") # check for conflicts - review_requests_dict = { unicode(r.pk): r for r in review_requests } + review_requests_dict = { str(r.pk): r for r in review_requests } posted_reqs = set(request.POST.getlist("reviewrequest", [])) - current_reqs = set(review_requests_dict.iterkeys()) + current_reqs = set(review_requests_dict.keys()) closed_reqs = posted_reqs - current_reqs newly_closed = len(closed_reqs) diff --git a/ietf/idindex/generate_all_id2_txt.py b/ietf/idindex/generate_all_id2_txt.py index 10e66b171..edaf12ab4 100755 --- a/ietf/idindex/generate_all_id2_txt.py +++ b/ietf/idindex/generate_all_id2_txt.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved #!/usr/bin/env python # Portions Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -38,4 +39,4 @@ import django django.setup() from ietf.idindex.index import all_id2_txt -print all_id2_txt().encode('utf-8'), +print(all_id2_txt().encode('utf-8'), end=' ') diff --git a/ietf/idindex/generate_all_id_txt.py b/ietf/idindex/generate_all_id_txt.py index 8bef4a9f7..e9d5f8cf5 100755 --- a/ietf/idindex/generate_all_id_txt.py +++ b/ietf/idindex/generate_all_id_txt.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved #!/usr/bin/env python # Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -38,4 +39,4 @@ import django django.setup() from ietf.idindex.index import all_id_txt -print all_id_txt().encode("utf-8"), +print(all_id_txt().encode("utf-8"), end=' ') diff --git a/ietf/idindex/generate_id_abstracts_txt.py b/ietf/idindex/generate_id_abstracts_txt.py index c295991e3..e21a96303 100755 --- a/ietf/idindex/generate_id_abstracts_txt.py +++ b/ietf/idindex/generate_id_abstracts_txt.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved #!/usr/bin/env python # Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -38,4 +39,4 @@ import django django.setup() from ietf.idindex.index import id_index_txt -print id_index_txt(with_abstracts=True).encode('utf-8'), +print(id_index_txt(with_abstracts=True).encode('utf-8'), end=' ') diff --git a/ietf/idindex/generate_id_index_txt.py b/ietf/idindex/generate_id_index_txt.py index f213614fb..7fe969a45 100755 --- a/ietf/idindex/generate_id_index_txt.py +++ b/ietf/idindex/generate_id_index_txt.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved #!/usr/bin/env python # Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -38,4 +39,4 @@ import django django.setup() from ietf.idindex.index import id_index_txt -print id_index_txt().encode('utf-8'), +print(id_index_txt().encode('utf-8'), end=' ') diff --git a/ietf/idindex/index.py b/ietf/idindex/index.py index 547dd6787..0291eda09 100644 --- a/ietf/idindex/index.py +++ b/ietf/idindex/index.py @@ -89,7 +89,7 @@ def all_id_txt(): last_field, ) - return u"\n".join(res) + "\n" + return "\n".join(res) + "\n" def file_types_for_drafts(): """Look in the draft directory and return file types found as dict (name + rev -> [t1, t2, ...]).""" @@ -129,7 +129,7 @@ def all_id2_txt(): else: l = authors[a.document.name] if a.email: - l.append(u'%s <%s>' % (a.person.plain_name().replace("@", ""), a.email.address.replace(",", ""))) + l.append('%s <%s>' % (a.person.plain_name().replace("@", ""), a.email.address.replace(",", ""))) else: l.append(a.person.plain_name()) @@ -191,7 +191,7 @@ def all_id2_txt(): area = d.group.parent.acronym fields.append(area) # 9 responsible AD name - fields.append(unicode(d.ad) if d.ad else "") + fields.append(str(d.ad) if d.ad else "") # 10 fields.append(d.intended_std_level.name if d.intended_std_level else "") # 11 @@ -208,16 +208,16 @@ def all_id2_txt(): # 13 fields.append(clean_whitespace(d.title)) # FIXME: we should make sure this is okay in the database and in submit # 14 - fields.append(u", ".join(authors.get(d.name, []))) + fields.append(", ".join(authors.get(d.name, []))) # 15 fields.append(shepherds.get(d.shepherd_id, "")) # 16 Responsible AD name and email fields.append(ads.get(d.ad_id, "")) # - res.append(u"\t".join(fields)) + res.append("\t".join(fields)) - return render_to_string("idindex/all_id2.txt", {'data': u"\n".join(res) }) + return render_to_string("idindex/all_id2.txt", {'data': "\n".join(res) }) def active_drafts_index_by_group(extra_values=()): """Return active drafts grouped into their corresponding @@ -258,7 +258,7 @@ def active_drafts_index_by_group(extra_values=()): d["authors"].append(a.person.plain_ascii()) # This should probably change to .plain_name() when non-ascii names are permitted # put docs into groups - for d in docs_dict.itervalues(): + for d in docs_dict.values(): group = groups_dict.get(d["group_id"]) if not group: continue @@ -268,7 +268,7 @@ def active_drafts_index_by_group(extra_values=()): group.active_drafts.append(d) - groups = [g for g in groups_dict.itervalues() if hasattr(g, "active_drafts")] + groups = [g for g in groups_dict.values() if hasattr(g, "active_drafts")] groups.sort(key=lambda g: g.acronym) fallback_time = datetime.datetime(1950, 1, 1) diff --git a/ietf/idindex/tests.py b/ietf/idindex/tests.py index b4817d24f..10144d42c 100644 --- a/ietf/idindex/tests.py +++ b/ietf/idindex/tests.py @@ -70,7 +70,7 @@ class IndexTests(TestCase): draft = WgDraftFactory( states=[('draft','active'),('draft-iesg','review-e')], ad=PersonFactory(), - shepherd=EmailFactory(address='shepherd@example.com',person__name=u'Draft δραφτυ Shepherd'), + shepherd=EmailFactory(address='shepherd@example.com',person__name='Draft δραφτυ Shepherd'), group__parent=GroupFactory(type_id='area'), intended_std_level_id = 'ps', authors=[EmailFactory().person] @@ -97,15 +97,15 @@ class IndexTests(TestCase): self.assertEqual(t[6], draft.latest_event(type="new_revision").time.strftime("%Y-%m-%d")) self.assertEqual(t[7], draft.group.acronym) self.assertEqual(t[8], draft.group.parent.acronym) - self.assertEqual(t[9], unicode(draft.ad)) + self.assertEqual(t[9], str(draft.ad)) self.assertEqual(t[10], draft.intended_std_level.name) self.assertEqual(t[11], "") self.assertEqual(t[12], ".pdf,.txt") self.assertEqual(t[13], draft.title) author = draft.documentauthor_set.order_by("order").get() - self.assertEqual(t[14], u"%s <%s>" % (author.person.name, author.email.address)) - self.assertEqual(t[15], u"%s <%s>" % (draft.shepherd.person.plain_ascii(), draft.shepherd.address)) - self.assertEqual(t[16], u"%s <%s>" % (draft.ad.plain_ascii(), draft.ad.email_address())) + self.assertEqual(t[14], "%s <%s>" % (author.person.name, author.email.address)) + self.assertEqual(t[15], "%s <%s>" % (draft.shepherd.person.plain_ascii(), draft.shepherd.address)) + self.assertEqual(t[16], "%s <%s>" % (draft.ad.plain_ascii(), draft.ad.email_address())) # test RFC diff --git a/ietf/iesg/__init__.py b/ietf/iesg/__init__.py index 0dc251ae6..4473dca5e 100644 --- a/ietf/iesg/__init__.py +++ b/ietf/iesg/__init__.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved # coding: latin-1 from types import ModuleType @@ -9,7 +9,7 @@ DEBUG_EMAILS = [ ('Ole Laursen', 'olau@iola.dk'), ] -for k in locals().keys(): +for k in list(locals().keys()): m = locals()[k] if isinstance(m, ModuleType): if hasattr(m, "DEBUG_EMAILS"): diff --git a/ietf/iesg/agenda.py b/ietf/iesg/agenda.py index 0b43ef374..15f9b0f5f 100644 --- a/ietf/iesg/agenda.py +++ b/ietf/iesg/agenda.py @@ -149,7 +149,7 @@ def fill_in_agenda_administrivia(date, sections): with codecs.open(filename, 'r', 'utf-8', 'replace') as f: t = f.read().strip() except IOError: - t = u"(Error reading %s)" % filename + t = "(Error reading %s)" % filename sections[s]["text"] = t @@ -196,13 +196,13 @@ def fill_in_agenda_docs(date, sections, docs=None): sections[number]["docs"].append(doc) # prune empty "For action" sections - empty_for_action = [n for n, section in sections.iteritems() + empty_for_action = [n for n, section in sections.items() if section["title"] == "For action" and not section["docs"]] for num in empty_for_action: del sections[num] # Be careful to keep this the same as what's used in agenda_documents - for s in sections.itervalues(): + for s in sections.values(): if "docs" in s: s["docs"].sort(key=lambda d: d.balloting_started) diff --git a/ietf/iesg/models.py b/ietf/iesg/models.py index 3b43f1cb5..40444a203 100644 --- a/ietf/iesg/models.py +++ b/ietf/iesg/models.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved # Portion Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -51,7 +51,7 @@ class TelechatAgendaItem(models.Model): def __unicode__(self): type_name = self.TYPE_CHOICES_DICT.get(self.type, str(self.type)) - return u'%s: %s' % (type_name, self.title or "") + return '%s: %s' % (type_name, self.title or "") class Telechat(models.Model): telechat_id = models.IntegerField(primary_key=True) @@ -64,7 +64,7 @@ class Telechat(models.Model): mi_frozen = models.IntegerField(null=True, blank=True) class Meta: - db_table = u'telechat' + db_table = 'telechat' def next_telechat_date(): diff --git a/ietf/iesg/tests.py b/ietf/iesg/tests.py index cf1f0e3b9..a7a008cd0 100644 --- a/ietf/iesg/tests.py +++ b/ietf/iesg/tests.py @@ -119,7 +119,7 @@ class IESGAgendaTests(TestCase): self.saved_internet_draft_path = settings.INTERNET_DRAFT_PATH settings.INTERNET_DRAFT_PATH = self.draft_dir - for d in self.telechat_docs.values(): + for d in list(self.telechat_docs.values()): TelechatDocEvent.objects.create(type="scheduled_for_telechat", doc=d, rev=d.rev, @@ -304,7 +304,7 @@ class IESGAgendaTests(TestCase): r = self.client.get("/feed/iesg-agenda/") self.assertEqual(r.status_code, 200) - for d in self.telechat_docs.values(): + for d in list(self.telechat_docs.values()): self.assertTrue(d.name in unicontent(r)) self.assertTrue(d.title in unicontent(r)) @@ -312,7 +312,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(urlreverse("ietf.iesg.views.agenda_json")) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): if d.type_id == "charter": self.assertTrue(d.group.name in unicontent(r), "%s '%s' not in response" % (k, d.group.name)) self.assertTrue(d.group.acronym in unicontent(r), "%s '%s' acronym not in response" % (k, d.group.acronym)) @@ -326,7 +326,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(urlreverse("ietf.iesg.views.agenda")) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): if d.type_id == "charter": self.assertTrue(d.group.name in unicontent(r), "%s '%s' not in response" % (k, d.group.name)) self.assertTrue(d.group.acronym in unicontent(r), "%s '%s' acronym not in response" % (k, d.group.acronym)) @@ -338,7 +338,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(urlreverse("ietf.iesg.views.agenda_txt")) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): if d.type_id == "charter": self.assertTrue(d.group.name in unicontent(r), "%s '%s' not in response" % (k, d.group.name)) self.assertTrue(d.group.acronym in unicontent(r), "%s '%s' acronym not in response" % (k, d.group.acronym)) @@ -350,7 +350,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(urlreverse("ietf.iesg.views.agenda_scribe_template")) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): if d.type_id == "charter": continue # scribe template doesn't contain chartering info @@ -363,7 +363,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): if d.type_id == "charter": self.assertTrue(d.group.name in unicontent(r), "%s '%s' not in response" % (k, d.group.name)) self.assertTrue(d.group.acronym in unicontent(r), "%s '%s' acronym not in response" % (k, d.group.acronym)) @@ -383,7 +383,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): if d.type_id == "charter": self.assertTrue(d.group.name in unicontent(r), "%s '%s' not in response" % (k, d.group.name, )) self.assertTrue(d.group.acronym in unicontent(r), "%s '%s' acronym not in response" % (k, d.group.acronym, )) @@ -396,7 +396,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): self.assertTrue(d.name in unicontent(r), "%s '%s' not in response" % (k, d.name, )) def test_agenda_documents(self): @@ -404,7 +404,7 @@ class IESGAgendaTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): self.assertTrue(d.name in unicontent(r), "%s '%s' not in response" % (k, d.name, )) self.assertTrue(d.title in unicontent(r), "%s '%s' title not in response" % (k, d.title, )) @@ -413,7 +413,7 @@ class IESGAgendaTests(TestCase): # We haven't put any documents on past telechats, so this should be empty r = self.client.get(url) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): self.assertNotIn(d.name, unicontent(r)) self.assertNotIn(d.title, unicontent(r)) # Add the documents to a past telechat @@ -421,7 +421,7 @@ class IESGAgendaTests(TestCase): date = datetime.date.today() - datetime.timedelta(days=14) approved = State.objects.get(type='draft-iesg', slug='approved') iesg_eval = State.objects.get(type='draft-iesg', slug='iesg-eva') - for d in self.telechat_docs.values(): + for d in list(self.telechat_docs.values()): if d.type_id in ['draft', 'charter']: create_ballot_if_not_open(None, d, by, 'approve') TelechatDocEvent.objects.create(type="scheduled_for_telechat", @@ -435,7 +435,7 @@ class IESGAgendaTests(TestCase): # Now check that they are present on the past documents page r = self.client.get(url) self.assertEqual(r.status_code, 200) - for k, d in self.telechat_docs.iteritems(): + for k, d in self.telechat_docs.items(): if d.states.get(type='draft-iesg').slug in ['approved', 'iesg-eva', ]: self.assertIn(d.name, unicontent(r)) else: @@ -455,9 +455,9 @@ class IESGAgendaTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) - import tarfile, StringIO + import tarfile, io - tar = tarfile.open(None, fileobj=StringIO.StringIO(r.content)) + tar = tarfile.open(None, fileobj=io.StringIO(r.content)) names = tar.getnames() self.assertIn(d1_filename, names) self.assertNotIn(d2_filename, names) diff --git a/ietf/iesg/views.py b/ietf/iesg/views.py index 415f71925..029e33d59 100644 --- a/ietf/iesg/views.py +++ b/ietf/iesg/views.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved # Portion Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -35,7 +35,7 @@ import os import datetime import tarfile -import StringIO +import io import time import itertools import json @@ -80,7 +80,7 @@ def review_decisions(request, year=None): #proto_levels = ["bcp", "ds", "ps", "std"] #doc_levels = ["exp", "inf"] - timeframe = u"%s" % year if year else u"the past 6 months" + timeframe = "%s" % year if year else "the past 6 months" return render(request, 'iesg/review_decisions.html', dict(events=events, @@ -99,7 +99,7 @@ def agenda_json(request, date=None): "sections": {}, } - for num, section in data["sections"].iteritems(): + for num, section in data["sections"].items(): s = res["sections"][num] = { "title": section["title"], } @@ -198,7 +198,7 @@ def agenda(request, date=None): request.session['ballot_edit_return_point'] = request.path_info return render(request, "iesg/agenda.html", { "date": data["date"], - "sections": sorted(data["sections"].iteritems()), + "sections": sorted(data["sections"].items()), "settings": settings, } ) @@ -206,13 +206,13 @@ def agenda_txt(request, date=None): data = agenda_data(date) return render(request, "iesg/agenda.txt", { "date": data["date"], - "sections": sorted(data["sections"].iteritems()), + "sections": sorted(data["sections"].items()), "domain": Site.objects.get_current().domain, }, content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET) def agenda_scribe_template(request, date=None): data = agenda_data(date) - sections = sorted((num, section) for num, section in data["sections"].iteritems() if "2" <= num < "4") + sections = sorted((num, section) for num, section in data["sections"].items() if "2" <= num < "4") appendix_docs = [] for num, section in sections: if "docs" in section: @@ -237,7 +237,7 @@ def agenda_moderator_package(request, date=None): or (num == "6" and "6.1" not in data["sections"])) # sort and prune non-leaf headlines - sections = sorted((num, section) for num, section in data["sections"].iteritems() + sections = sorted((num, section) for num, section in data["sections"].items() if leaf_section(num, section)) # add parents field to each section @@ -245,7 +245,7 @@ def agenda_moderator_package(request, date=None): s["parents"] = [] split = num.split(".") - for i in xrange(num.count(".")): + for i in range(num.count(".")): parent_num = ".".join(split[:i + 1]) parent = data["sections"].get(parent_num) if parent: @@ -281,12 +281,12 @@ def agenda_package(request, date=None): data = agenda_data(date) return render(request, "iesg/agenda_package.txt", { "date": data["date"], - "sections": sorted(data["sections"].iteritems()), + "sections": sorted(data["sections"].items()), "roll_call": data["sections"]["1.1"]["text"], "roll_call_url": settings.IESG_ROLL_CALL_URL, "minutes": data["sections"]["1.3"]["text"], "minutes_url": settings.IESG_MINUTES_URL, - "management_items": [(num, section) for num, section in data["sections"].iteritems() if "6" < num < "7"], + "management_items": [(num, section) for num, section in data["sections"].items() if "6" < num < "7"], }, content_type='text/plain') @@ -311,14 +311,14 @@ def agenda_documents_txt(request): row = ( d.computed_telechat_date.isoformat(), d.name, - unicode(d.intended_std_level), + str(d.intended_std_level), "1" if d.stream_id in ("ise", "irtf") else "0", - unicode(d.area_acronym()).lower(), + str(d.area_acronym()).lower(), d.ad.plain_name() if d.ad else "None Assigned", d.rev, ) rows.append("\t".join(row)) - return HttpResponse(u"\n".join(rows), content_type='text/plain') + return HttpResponse("\n".join(rows), content_type='text/plain') class RescheduleForm(forms.Form): telechat_date = forms.TypedChoiceField(coerce=lambda x: datetime.datetime.strptime(x, '%Y-%m-%d').date(), empty_value=None, required=False) @@ -378,7 +378,7 @@ def agenda_documents(request): reschedule_status = { "changed": False } - for i in itertools.chain(*docs_by_date.values()): + for i in itertools.chain(*list(docs_by_date.values())): i.reschedule_form = handle_reschedule_form(request, i, dates, reschedule_status) if reschedule_status["changed"]: @@ -397,7 +397,7 @@ def agenda_documents(request): telechats.append({ "date": date, "pages": pages, - "sections": sorted((num, section) for num, section in sections.iteritems() + "sections": sorted((num, section) for num, section in sections.items() if "2" <= num < "5") }) request.session['ballot_edit_return_point'] = request.path_info @@ -454,7 +454,7 @@ def telechat_docs_tarfile(request, date): tarstream = tarfile.open('', 'w:gz', response) - manifest = StringIO.StringIO() + manifest = io.StringIO() for doc in docs: doc_path = os.path.join(doc.get_file_path(), doc.name + "-" + doc.rev + ".txt") @@ -524,10 +524,10 @@ def milestones_needing_review(request): milestones.append(m) ad_list = [] - for ad, groups in ads.iteritems(): + for ad, groups in ads.items(): ad_list.append(ad) ad.groups_needing_review = sorted(groups, key=lambda g: g.acronym) - for g, milestones in groups.iteritems(): + for g, milestones in groups.items(): g.milestones_needing_review = sorted(milestones, key=lambda m: m.due) return render(request, 'iesg/milestones_needing_review.html', diff --git a/ietf/ietfauth/forms.py b/ietf/ietfauth/forms.py index 65bad7dfe..ab550a52a 100644 --- a/ietf/ietfauth/forms.py +++ b/ietf/ietfauth/forms.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2011-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import re from unidecode import unidecode @@ -126,7 +126,7 @@ def get_person_form(*args, **kwargs): self.unidecoded_ascii = name != reconstructed_name def clean_name(self): - name = self.cleaned_data.get("name") or u"" + name = self.cleaned_data.get("name") or "" prevent_at_symbol(name) prevent_system_name(name) return name @@ -135,13 +135,13 @@ def get_person_form(*args, **kwargs): if self.unidecoded_ascii: raise forms.ValidationError("Name contained non-ASCII characters, and was automatically reconstructed using only Latin characters. Check the result - if you are happy, just hit Submit again.") - name = self.cleaned_data.get("ascii") or u"" + name = self.cleaned_data.get("ascii") or "" prevent_at_symbol(name) prevent_system_name(name) return ascii_cleaner(name) def clean_ascii_short(self): - name = self.cleaned_data.get("ascii_short") or u"" + name = self.cleaned_data.get("ascii_short") or "" prevent_at_symbol(name) prevent_system_name(name) return ascii_cleaner(name) @@ -184,11 +184,11 @@ class RoleEmailForm(forms.Form): super(RoleEmailForm, self).__init__(*args, **kwargs) f = self.fields["email"] - f.label = u"%s in %s" % (role.name, role.group.acronym.upper()) - f.help_text = u"Email to use for %s role in %s" % (role.name, role.group.name) + f.label = "%s in %s" % (role.name, role.group.acronym.upper()) + f.help_text = "Email to use for %s role in %s" % (role.name, role.group.name) f.queryset = f.queryset.filter(models.Q(person=role.person_id) | models.Q(role=role)).distinct() f.initial = role.email_id - f.choices = [(e.pk, e.address if e.active else u"({})".format(e.address)) for e in f.queryset] + f.choices = [(e.pk, e.address if e.active else "({})".format(e.address)) for e in f.queryset] class ResetPasswordForm(forms.Form): diff --git a/ietf/ietfauth/management/commands/send_apikey_usage_emails.py b/ietf/ietfauth/management/commands/send_apikey_usage_emails.py index 2718ef02a..ead143e92 100644 --- a/ietf/ietfauth/management/commands/send_apikey_usage_emails.py +++ b/ietf/ietfauth/management/commands/send_apikey_usage_emails.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright The IETF Trust 2017, All Rights Reserved -from __future__ import print_function, unicode_literals +# Copyright The IETF Trust 2017-2019, All Rights Reserved + import datetime diff --git a/ietf/ietfauth/tests.py b/ietf/ietfauth/tests.py index e01952734..03cbe9ef5 100644 --- a/ietf/ietfauth/tests.py +++ b/ietf/ietfauth/tests.py @@ -1,9 +1,9 @@ -# Copyright The IETF Trust 2017-2019, All Rights Reserved +# Copyright The IETF Trust 2009-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import os, shutil, time, datetime -from urlparse import urlsplit +from urllib.parse import urlsplit from pyquery import PyQuery from unittest import skipIf @@ -216,9 +216,9 @@ class IetfAuthTests(TestCase): self.assertEqual(len(q('[name="active_emails"][value="%s"][checked]' % email_address)), 1) base_data = { - "name": u"Test Nãme", - "ascii": u"Test Name", - "ascii_short": u"T. Name", + "name": "Test Nãme", + "ascii": "Test Name", + "ascii_short": "T. Name", "affiliation": "Test Org", "active_emails": email_address, "consent": True, @@ -226,7 +226,7 @@ class IetfAuthTests(TestCase): # edit details - faulty ASCII faulty_ascii = base_data.copy() - faulty_ascii["ascii"] = u"Test Nãme" + faulty_ascii["ascii"] = "Test Nãme" r = self.client.post(url, faulty_ascii) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) @@ -234,7 +234,7 @@ class IetfAuthTests(TestCase): # edit details - blank ASCII blank_ascii = base_data.copy() - blank_ascii["ascii"] = u"" + blank_ascii["ascii"] = "" r = self.client.post(url, blank_ascii) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) @@ -245,14 +245,14 @@ class IetfAuthTests(TestCase): r = self.client.post(url, base_data) self.assertEqual(r.status_code, 200) person = Person.objects.get(user__username=username) - self.assertEqual(person.name, u"Test Nãme") - self.assertEqual(person.ascii, u"Test Name") - self.assertEqual(Person.objects.filter(alias__name=u"Test Name", user__username=username).count(), 1) - self.assertEqual(Person.objects.filter(alias__name=u"Test Nãme", user__username=username).count(), 1) + self.assertEqual(person.name, "Test Nãme") + self.assertEqual(person.ascii, "Test Name") + self.assertEqual(Person.objects.filter(alias__name="Test Name", user__username=username).count(), 1) + self.assertEqual(Person.objects.filter(alias__name="Test Nãme", user__username=username).count(), 1) self.assertEqual(Email.objects.filter(address=email_address, person__user__username=username, active=True).count(), 1) # deactivate address - without_email_address = { k: v for k, v in base_data.iteritems() if k != "active_emails" } + without_email_address = { k: v for k, v in base_data.items() if k != "active_emails" } r = self.client.post(url, without_email_address) self.assertEqual(r.status_code, 200) @@ -460,7 +460,7 @@ class IetfAuthTests(TestCase): self.assertRedirects(r, prof_url) # refresh user object user = User.objects.get(username="someone@example.com") - self.assertTrue(user.check_password(u'foobar')) + self.assertTrue(user.check_password('foobar')) def test_change_username(self): @@ -508,7 +508,7 @@ class IetfAuthTests(TestCase): prev = user user = User.objects.get(username="othername@example.org") self.assertEqual(prev, user) - self.assertTrue(user.check_password(u'password')) + self.assertTrue(user.check_password('password')) def test_apikey_management(self): person = PersonFactory() diff --git a/ietf/ietfauth/utils.py b/ietf/ietfauth/utils.py index 010f3fbd2..d6e1bd80a 100644 --- a/ietf/ietfauth/utils.py +++ b/ietf/ietfauth/utils.py @@ -30,7 +30,7 @@ def has_role(user, role_names, *args, **kwargs): """Determines whether user has any of the given standard roles given. Role names must be a list or, in case of a single value, a string.""" - if isinstance(role_names, str) or isinstance(role_names, unicode): + if isinstance(role_names, str) or isinstance(role_names, str): role_names = [ role_names ] if not user or not user.is_authenticated: diff --git a/ietf/ietfauth/views.py b/ietf/ietfauth/views.py index 4fe2e1349..21c4e11a3 100644 --- a/ietf/ietfauth/views.py +++ b/ietf/ietfauth/views.py @@ -1,3 +1,5 @@ +# Copyright The IETF Trust 2007-2019, All Rights Reserved + # Portions Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen # @@ -30,8 +32,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# Copyright The IETF Trust 2007, All Rights Reserved - import importlib from datetime import datetime as DateTime, timedelta as TimeDelta, date as Date @@ -228,7 +228,7 @@ def profile(request): auth = django.core.signing.dumps([person.user.username, to_email], salt="add_email") domain = Site.objects.get_current().domain - subject = u'Confirm email address for %s' % person.name + subject = 'Confirm email address for %s' % person.name from_email = settings.DEFAULT_FROM_EMAIL send_mail(request, to_email, from_email, subject, 'registration/add_email_email.txt', { diff --git a/ietf/ipr/admin.py b/ietf/ipr/admin.py index e47f20679..72201b726 100644 --- a/ietf/ipr/admin.py +++ b/ietf/ipr/admin.py @@ -43,7 +43,7 @@ class IprDisclosureBaseAdmin(admin.ModelAdmin): inlines = [IprDocRelInline,RelatedIprInline] def related_docs(self, obj): - return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) + return ", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) admin.site.register(IprDisclosureBase, IprDisclosureBaseAdmin) @@ -53,7 +53,7 @@ class HolderIprDisclosureAdmin(admin.ModelAdmin): inlines = [IprDocRelInline,RelatedIprInline] def related_docs(self, obj): - return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) + return ", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) admin.site.register(HolderIprDisclosure, HolderIprDisclosureAdmin) @@ -63,7 +63,7 @@ class ThirdPartyIprDisclosureAdmin(admin.ModelAdmin): inlines = [IprDocRelInline,RelatedIprInline] def related_docs(self, obj): - return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) + return ", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) admin.site.register(ThirdPartyIprDisclosure, ThirdPartyIprDisclosureAdmin) @@ -73,7 +73,7 @@ class GenericIprDisclosureAdmin(admin.ModelAdmin): inlines = [RelatedIprInline] def related_docs(self, obj): - return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) + return ", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) admin.site.register(GenericIprDisclosure, GenericIprDisclosureAdmin) @@ -83,7 +83,7 @@ class NonDocSpecificIprDisclosureAdmin(admin.ModelAdmin): inlines = [RelatedIprInline] def related_docs(self, obj): - return u", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) + return ", ".join(a.formatted_name() for a in IprDocRel.objects.filter(disclosure=obj).order_by("id").select_related("document")) admin.site.register(NonDocSpecificIprDisclosure, NonDocSpecificIprDisclosureAdmin) @@ -105,7 +105,7 @@ class IprEventAdmin(admin.ModelAdmin): admin.site.register(IprEvent, IprEventAdmin) class LegacyMigrationIprEventAdmin(admin.ModelAdmin): - list_display = [u'id', 'time', 'type', 'by', 'disclosure', 'desc', 'message', 'in_reply_to', 'response_due'] + list_display = ['id', 'time', 'type', 'by', 'disclosure', 'desc', 'message', 'in_reply_to', 'response_due'] list_filter = ['time', 'type', 'response_due'] raw_id_fields = ['by', 'disclosure', 'message', 'in_reply_to'] admin.site.register(LegacyMigrationIprEvent, LegacyMigrationIprEventAdmin) diff --git a/ietf/ipr/feeds.py b/ietf/ipr/feeds.py index 0da26c542..7d1c8ac81 100644 --- a/ietf/ipr/feeds.py +++ b/ietf/ipr/feeds.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved from django.contrib.syndication.views import Feed from django.utils.feedgenerator import Atom1Feed @@ -22,7 +22,7 @@ class LatestIprDisclosuresFeed(Feed): return mark_safe(item.title) def item_description(self, item): - return unicode(item.title) + return str(item.title) def item_pubdate(self, item): return item.time diff --git a/ietf/ipr/fields.py b/ietf/ipr/fields.py index e6c61d3b6..775205772 100644 --- a/ietf/ipr/fields.py +++ b/ietf/ipr/fields.py @@ -10,7 +10,7 @@ from django.urls import reverse as urlreverse from ietf.ipr.models import IprDisclosureBase def select2_id_ipr_title_json(value): - return json.dumps([{ "id": o.pk, "text": escape(u"%s <%s>" % (o.title, o.time.date().isoformat())) } for o in value]) + return json.dumps([{ "id": o.pk, "text": escape("%s <%s>" % (o.title, o.time.date().isoformat())) } for o in value]) class SearchableIprDisclosuresField(forms.CharField): """Server-based multi-select field for choosing documents using @@ -48,7 +48,7 @@ class SearchableIprDisclosuresField(forms.CharField): def prepare_value(self, value): if not value: value = "" - if isinstance(value, basestring): + if isinstance(value, str): pks = self.parse_select2_value(value) # if the user posted a non integer value we need to remove it for key in pks: @@ -64,23 +64,23 @@ class SearchableIprDisclosuresField(forms.CharField): # patterns may not have been fully constructed there yet self.widget.attrs["data-ajax-url"] = urlreverse('ietf.ipr.views.ajax_search') - return u",".join(unicode(e.pk) for e in value) + return ",".join(str(e.pk) for e in value) def clean(self, value): value = super(SearchableIprDisclosuresField, self).clean(value) pks = self.check_pks(self.parse_select2_value(value)) if not all([ key.isdigit() for key in pks ]): - raise forms.ValidationError(u'You must enter IPR ID(s) as integers') + raise forms.ValidationError('You must enter IPR ID(s) as integers') objs = self.model.objects.filter(pk__in=pks) found_pks = [str(o.pk) for o in objs] failed_pks = [x for x in pks if x not in found_pks] if failed_pks: - raise forms.ValidationError(u"Could not recognize the following {model_name}s: {pks}. You can only input {model_name}s already registered in the Datatracker.".format(pks=", ".join(failed_pks), model_name=self.model.__name__.lower())) + raise forms.ValidationError("Could not recognize the following {model_name}s: {pks}. You can only input {model_name}s already registered in the Datatracker.".format(pks=", ".join(failed_pks), model_name=self.model.__name__.lower())) if self.max_entries != None and len(objs) > self.max_entries: - raise forms.ValidationError(u"You can select at most %s entries only." % self.max_entries) + raise forms.ValidationError("You can select at most %s entries only." % self.max_entries) return objs diff --git a/ietf/ipr/mail.py b/ietf/ipr/mail.py index f37552f51..809af13e8 100644 --- a/ietf/ipr/mail.py +++ b/ietf/ipr/mail.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved import base64 import email import datetime @@ -194,5 +195,5 @@ def process_response_email(msg): in_reply_to = to_message ) - log(u"Received IPR email from %s" % ietf_message.frm) + log("Received IPR email from %s" % ietf_message.frm) return ietf_message diff --git a/ietf/ipr/management/commands/process_email.py b/ietf/ipr/management/commands/process_email.py index 2ca42ddfb..c307ebc8f 100644 --- a/ietf/ipr/management/commands/process_email.py +++ b/ietf/ipr/management/commands/process_email.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved import sys from django.core.management.base import BaseCommand, CommandError @@ -7,7 +8,7 @@ from ietf.ipr.mail import process_response_email import debug # pyflakes:ignore class Command(BaseCommand): - help = (u"Process incoming email responses to ipr mail") + help = ("Process incoming email responses to ipr mail") def add_arguments(self, parser): parser.add_argument('--email-file', dest='email', help='File containing email (default: stdin)') diff --git a/ietf/ipr/migrations/0001_initial.py b/ietf/ipr/migrations/0001_initial.py index 369cd2deb..96225f7d2 100644 --- a/ietf/ipr/migrations/0001_initial.py +++ b/ietf/ipr/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/ipr/migrations/0002_auto_20180225_1207.py b/ietf/ipr/migrations/0002_auto_20180225_1207.py index 42983867e..31c1a23fe 100644 --- a/ietf/ipr/migrations/0002_auto_20180225_1207.py +++ b/ietf/ipr/migrations/0002_auto_20180225_1207.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-25 12:07 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py b/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py index a29cede7d..bd1542c61 100644 --- a/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py +++ b/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 11:58 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/ipr/migrations/0004_remove_iprdocrel_document.py b/ietf/ipr/migrations/0004_remove_iprdocrel_document.py index 313973632..d5c538cfb 100644 --- a/ietf/ipr/migrations/0004_remove_iprdocrel_document.py +++ b/ietf/ipr/migrations/0004_remove_iprdocrel_document.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-20 09:53 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/ipr/migrations/0005_rename_field_document2.py b/ietf/ipr/migrations/0005_rename_field_document2.py index 374e6806e..8c55ba473 100644 --- a/ietf/ipr/migrations/0005_rename_field_document2.py +++ b/ietf/ipr/migrations/0005_rename_field_document2.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 05:31 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/ipr/migrations/0006_document_primary_key_cleanup.py b/ietf/ipr/migrations/0006_document_primary_key_cleanup.py index fb31a1b78..caa193771 100644 --- a/ietf/ipr/migrations/0006_document_primary_key_cleanup.py +++ b/ietf/ipr/migrations/0006_document_primary_key_cleanup.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-06-10 03:42 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/ipr/models.py b/ietf/ipr/models.py index 70fa386d1..6e69b5b3e 100644 --- a/ietf/ipr/models.py +++ b/ietf/ipr/models.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved import datetime @@ -174,9 +174,9 @@ class IprDocRel(models.Model): def __unicode__(self): if self.revisions: - return u"%s which applies to %s-%s" % (self.disclosure, self.document.name, self.revisions) + return "%s which applies to %s-%s" % (self.disclosure, self.document.name, self.revisions) else: - return u"%s which applies to %s" % (self.disclosure, self.document.name) + return "%s which applies to %s" % (self.disclosure, self.document.name) class RelatedIpr(models.Model): source = ForeignKey(IprDisclosureBase,related_name='relatedipr_source_set') @@ -184,7 +184,7 @@ class RelatedIpr(models.Model): relationship = ForeignKey(DocRelationshipName) # Re-use; change to a dedicated RelName if needed def __unicode__(self): - return u"%s %s %s" % (self.source.title, self.relationship.name.lower(), self.target.title) + return "%s %s %s" % (self.source.title, self.relationship.name.lower(), self.target.title) class IprEvent(models.Model): time = models.DateTimeField(auto_now_add=True) @@ -197,7 +197,7 @@ class IprEvent(models.Model): response_due= models.DateTimeField(blank=True,null=True) def __unicode__(self): - return u"%s %s by %s at %s" % (self.disclosure.title, self.type.name.lower(), self.by.plain_name(), self.time) + return "%s %s by %s at %s" % (self.disclosure.title, self.type.name.lower(), self.by.plain_name(), self.time) def response_past_due(self): """Returns true if it's beyond the response_due date and no response has been diff --git a/ietf/ipr/templatetags/ipr_filters.py b/ietf/ipr/templatetags/ipr_filters.py index 146fbff7e..424726baa 100644 --- a/ietf/ipr/templatetags/ipr_filters.py +++ b/ietf/ipr/templatetags/ipr_filters.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2014, All Rights Reserved +# Copyright The IETF Trust 2014-2019, All Rights Reserved from django import template from django.utils.html import format_html @@ -11,10 +11,10 @@ def render_message_for_history(msg): """Format message for display in history. Suppress the 'To' line for incoming responses """ if msg.to.startswith('ietf-ipr+'): - return format_html(u'Date: {}
From: {}
Subject: {}
Cc: {}

{}', + return format_html('Date: {}
From: {}
Subject: {}
Cc: {}

{}', msg.time,msg.frm,msg.subject,msg.cc,msg.body) else: - return format_html(u'Date: {}
From: {}
To: {}
Subject: {}
Cc: {}

{}', + return format_html('Date: {}
From: {}
To: {}
Subject: {}
Cc: {}

{}', msg.time,msg.frm,msg.to,msg.subject,msg.cc,msg.body) diff --git a/ietf/ipr/tests.py b/ietf/ipr/tests.py index 9598d7855..557a6a9ac 100644 --- a/ietf/ipr/tests.py +++ b/ietf/ipr/tests.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- import datetime -import urllib +import urllib.request, urllib.parse, urllib.error from pyquery import PyQuery @@ -187,12 +187,12 @@ class IprTests(TestCase): self.assertTrue(ipr.title in unicontent(r)) # find by doc title - r = self.client.get(url + "?submit=doctitle&doctitle=%s" % urllib.quote(draft.title)) + r = self.client.get(url + "?submit=doctitle&doctitle=%s" % urllib.parse.quote(draft.title)) self.assertEqual(r.status_code, 200) self.assertTrue(ipr.title in unicontent(r)) # find by ipr title - r = self.client.get(url + "?submit=iprtitle&iprtitle=%s" % urllib.quote(ipr.title)) + r = self.client.get(url + "?submit=iprtitle&iprtitle=%s" % urllib.parse.quote(ipr.title)) self.assertEqual(r.status_code, 200) self.assertTrue(ipr.title in unicontent(r)) @@ -283,7 +283,7 @@ class IprTests(TestCase): ipr = iprs[0] self.assertEqual(ipr.holder_legal_name, "Test Legal") self.assertEqual(ipr.state.slug, 'pending') - for item in [u'SE12345678901','A method of transfering bits','2000-01-01']: + for item in ['SE12345678901','A method of transfering bits','2000-01-01']: self.assertIn(item, ipr.get_child().patent_info) self.assertTrue(isinstance(ipr.get_child(),HolderIprDisclosure)) self.assertEqual(len(outbox),1) @@ -326,7 +326,7 @@ class IprTests(TestCase): ipr = iprs[0] self.assertEqual(ipr.holder_legal_name, "Test Legal") self.assertEqual(ipr.state.slug, "pending") - for item in [u'SE12345678901','A method of transfering bits','2000-01-01' ]: + for item in ['SE12345678901','A method of transfering bits','2000-01-01' ]: self.assertIn(item, ipr.get_child().patent_info) self.assertTrue(isinstance(ipr.get_child(),ThirdPartyIprDisclosure)) self.assertEqual(len(outbox),1) @@ -374,7 +374,7 @@ class IprTests(TestCase): self.assertEqual(len(iprs), 1) ipr = iprs[0].get_child() self.assertEqual(ipr.holder_legal_name, "Test Legal") - patent_info_dict = dict( (k.replace('patent_','').capitalize(), v) for k, v in post_data.items() if k.startswith('patent_') ) + patent_info_dict = dict( (k.replace('patent_','').capitalize(), v) for k, v in list(post_data.items()) if k.startswith('patent_') ) self.assertEqual(text_to_dict(ipr.patent_info), patent_info_dict) self.assertEqual(ipr.state.slug, 'posted') diff --git a/ietf/ipr/views.py b/ietf/ipr/views.py index 2a2a8d139..32f9bc4cd 100644 --- a/ietf/ipr/views.py +++ b/ietf/ipr/views.py @@ -342,11 +342,11 @@ def edit(request, id, updates=None): else: initial = model_to_dict(ipr) - patent_info = text_to_dict(initial.get('patent_info', u'')) - if patent_info.keys(): - patent_dict = dict([ ('patent_'+k.lower(), v) for k,v in patent_info.items() ]) + patent_info = text_to_dict(initial.get('patent_info', '')) + if list(patent_info.keys()): + patent_dict = dict([ ('patent_'+k.lower(), v) for k,v in list(patent_info.items()) ]) else: - patent_dict = {'patent_notes': initial.get('patent_info', u'')} + patent_dict = {'patent_notes': initial.get('patent_info', '')} initial.update(patent_dict) if ipr.updates: initial.update({'updates':[ x.target for x in ipr.updates ]}) @@ -408,7 +408,7 @@ def email(request, id): 'to': addrs.to, 'cc': addrs.cc, 'frm': settings.IPR_EMAIL_FROM, - 'subject': u'Regarding {}'.format(ipr.title), + 'subject': 'Regarding {}'.format(ipr.title), 'reply_to': reply_to, } form = MessageModelForm(initial=initial) @@ -450,9 +450,9 @@ def by_draft_txt(request): docipr[name].append(o.disclosure_id) - lines = [ u"# Machine-readable list of IPR disclosures by draft name" ] - for name, iprs in docipr.iteritems(): - lines.append(name + "\t" + "\t".join(unicode(ipr_id) for ipr_id in sorted(iprs))) + lines = [ "# Machine-readable list of IPR disclosures by draft name" ] + for name, iprs in docipr.items(): + lines.append(name + "\t" + "\t".join(str(ipr_id) for ipr_id in sorted(iprs))) return HttpResponse("\n".join(lines), content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET) @@ -472,9 +472,9 @@ def by_draft_recursive_txt(request): docipr[name] = [] docipr[name].append(o.disclosure_id) - lines = [ u"# Machine-readable list of IPR disclosures by draft name" ] - for name, iprs in docipr.iteritems(): - lines.append(name + "\t" + "\t".join(unicode(ipr_id) for ipr_id in sorted(iprs))) + lines = [ "# Machine-readable list of IPR disclosures by draft name" ] + for name, iprs in docipr.items(): + lines.append(name + "\t" + "\t".join(str(ipr_id) for ipr_id in sorted(iprs))) return HttpResponse("\n".join(lines), content_type="text/plain; charset=%s"%settings.DEFAULT_CHARSET) @@ -546,11 +546,11 @@ def new(request, type, updates=None): original = IprDisclosureBase(id=updates).get_child() initial = model_to_dict(original) initial.update({'updates':str(updates), }) - patent_info = text_to_dict(initial.get('patent_info', u'')) - if patent_info.keys(): - patent_dict = dict([ ('patent_'+k.lower(), v) for k,v in patent_info.items() ]) + patent_info = text_to_dict(initial.get('patent_info', '')) + if list(patent_info.keys()): + patent_dict = dict([ ('patent_'+k.lower(), v) for k,v in list(patent_info.items()) ]) else: - patent_dict = {'patent_notes': initial.get('patent_info', u'')} + patent_dict = {'patent_notes': initial.get('patent_info', '')} initial.update(patent_dict) form = ipr_form_mapping[type](initial=initial) else: diff --git a/ietf/liaisons/__init__.py b/ietf/liaisons/__init__.py index a285c3e43..e4d3e43e0 100644 --- a/ietf/liaisons/__init__.py +++ b/ietf/liaisons/__init__.py @@ -1,15 +1,15 @@ -# Copyright The IETF Trust 2007, All Rights Reserved -# coding: latin-1 +# Copyright The IETF Trust 2007-2019, All Rights Reserved +# -*- coding: utf-8 -*- from types import ModuleType # These people will be sent a stack trace if there's an uncaught exception in # code any of the modules imported above: DEBUG_EMAILS = [ - ('Emilio A. Snchez', 'esanchez@yaco.es'), + ('Emilio A. Sánchez', 'esanchez@yaco.es'), ] -for k in locals().keys(): +for k in list(locals().keys()): m = locals()[k] if isinstance(m, ModuleType): if hasattr(m, "DEBUG_EMAILS"): diff --git a/ietf/liaisons/admin.py b/ietf/liaisons/admin.py index 4fdf7e406..8983cafbf 100644 --- a/ietf/liaisons/admin.py +++ b/ietf/liaisons/admin.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved from django.contrib import admin from django.urls import reverse @@ -29,13 +30,13 @@ class LiaisonStatementAdmin(admin.ModelAdmin): related_to.allow_tags = True class LiaisonStatementAttachmentAdmin(admin.ModelAdmin): - list_display = [u'id', 'statement', 'document', 'removed'] + list_display = ['id', 'statement', 'document', 'removed'] list_filter = ['removed'] raw_id_fields = ['statement', 'document'] admin.site.register(LiaisonStatementAttachment, LiaisonStatementAttachmentAdmin) class RelatedLiaisonStatementAdmin(admin.ModelAdmin): - list_display = [u'id', 'source', 'target', 'relationship'] + list_display = ['id', 'source', 'target', 'relationship'] list_filter = ['relationship'] raw_id_fields = ['source', 'target'] admin.site.register(RelatedLiaisonStatement, RelatedLiaisonStatementAdmin) diff --git a/ietf/liaisons/feeds.py b/ietf/liaisons/feeds.py index adbde6c40..b6ee64e46 100644 --- a/ietf/liaisons/feeds.py +++ b/ietf/liaisons/feeds.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved import re @@ -33,7 +33,7 @@ class LiaisonStatementsFeed(Feed): try: group = Group.objects.get(acronym=search) obj['filter'] = { 'from_groups': group } - obj['title'] = u'Liaison Statements from %s' % group.name + obj['title'] = 'Liaison Statements from %s' % group.name return obj except Group.DoesNotExist: # turn all-nonword characters into one-character @@ -46,7 +46,7 @@ class LiaisonStatementsFeed(Feed): name = statement.from_groups.first().name obj['filter'] = { 'from_name': name } - obj['title'] = u'Liaison Statements from %s' % name + obj['title'] = 'Liaison Statements from %s' % name return obj if kind == 'to': @@ -55,7 +55,7 @@ class LiaisonStatementsFeed(Feed): group = Group.objects.get(acronym=search) obj['filter'] = { 'to_groups': group } - obj['title'] = u'Liaison Statements to %s' % group.name + obj['title'] = 'Liaison Statements to %s' % group.name return obj if kind == 'subject': @@ -70,11 +70,11 @@ class LiaisonStatementsFeed(Feed): def items(self, obj): qs = LiaisonStatement.objects.all().order_by("-id") - if obj.has_key('q'): + if 'q' in obj: qs = qs.filter(*obj['q']) - if obj.has_key('filter'): + if 'filter' in obj: qs = qs.filter(**obj['filter']) - if obj.has_key('limit'): + if 'limit' in obj: qs = qs[:obj['limit']] qs = qs.prefetch_related("attachments") diff --git a/ietf/liaisons/fields.py b/ietf/liaisons/fields.py index 382afdfaa..94f58bff9 100644 --- a/ietf/liaisons/fields.py +++ b/ietf/liaisons/fields.py @@ -10,7 +10,7 @@ from django.urls import reverse as urlreverse from ietf.liaisons.models import LiaisonStatement def select2_id_liaison_json(objs): - return json.dumps([{ "id": o.pk, "text":u"[{}] {}".format(o.pk, escape(o.title)) } for o in objs]) + return json.dumps([{ "id": o.pk, "text":"[{}] {}".format(o.pk, escape(o.title)) } for o in objs]) def select2_id_group_json(objs): return json.dumps([{ "id": o.pk, "text": escape(o.acronym) } for o in objs]) @@ -47,9 +47,9 @@ class SearchableLiaisonStatementsField(forms.CharField): def prepare_value(self, value): if not value: value = "" - if isinstance(value, (int, long)): + if isinstance(value, int): value = str(value) - if isinstance(value, basestring): + if isinstance(value, str): pks = self.parse_select2_value(value) value = self.model.objects.filter(pk__in=pks) if isinstance(value, LiaisonStatement): @@ -61,7 +61,7 @@ class SearchableLiaisonStatementsField(forms.CharField): # patterns may not have been fully constructed there yet self.widget.attrs["data-ajax-url"] = urlreverse("ietf.liaisons.views.ajax_select2_search_liaison_statements") - return u",".join(unicode(o.pk) for o in value) + return ",".join(str(o.pk) for o in value) def clean(self, value): value = super(SearchableLiaisonStatementsField, self).clean(value) @@ -72,9 +72,9 @@ class SearchableLiaisonStatementsField(forms.CharField): found_pks = [str(o.pk) for o in objs] failed_pks = [x for x in pks if x not in found_pks] if failed_pks: - raise forms.ValidationError(u"Could not recognize the following groups: {pks}.".format(pks=", ".join(failed_pks))) + raise forms.ValidationError("Could not recognize the following groups: {pks}.".format(pks=", ".join(failed_pks))) if self.max_entries != None and len(objs) > self.max_entries: - raise forms.ValidationError(u"You can select at most %s entries only." % self.max_entries) + raise forms.ValidationError("You can select at most %s entries only." % self.max_entries) return objs diff --git a/ietf/liaisons/forms.py b/ietf/liaisons/forms.py index c465c1280..23879ba7e 100644 --- a/ietf/liaisons/forms.py +++ b/ietf/liaisons/forms.py @@ -30,6 +30,7 @@ from ietf.person.models import Email from ietf.person.fields import SearchableEmailField from ietf.doc.models import Document, DocAlias from ietf.utils.fields import DatepickerDateField +from functools import reduce ''' NOTES: @@ -209,12 +210,12 @@ class LiaisonModelForm(BetterModelForm): NOTE: from_groups and to_groups are marked as not required because select2 has a problem with validating ''' - from_groups = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),label=u'Groups',required=False) + from_groups = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),label='Groups',required=False) from_contact = forms.EmailField() to_contacts = forms.CharField(label="Contacts", widget=forms.Textarea(attrs={'rows':'3', }), strip=False) - to_groups = forms.ModelMultipleChoiceField(queryset=Group.objects,label=u'Groups',required=False) + to_groups = forms.ModelMultipleChoiceField(queryset=Group.objects,label='Groups',required=False) deadline = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={"autoclose": "1" }, label='Deadline', required=True) - related_to = SearchableLiaisonStatementsField(label=u'Related Liaison Statement', required=False) + related_to = SearchableLiaisonStatementsField(label='Related Liaison Statement', required=False) submitted_date = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={"autoclose": "1" }, label='Submission date', required=True, initial=datetime.date.today()) attachments = CustomModelMultipleChoiceField(queryset=Document.objects,label='Attachments', widget=ShowAttachmentsWidget, required=False) attach_title = forms.CharField(label='Title', required=False) @@ -298,13 +299,13 @@ class LiaisonModelForm(BetterModelForm): def clean(self): if not self.cleaned_data.get('body', None) and not self.has_attachments(): - self._errors['body'] = ErrorList([u'You must provide a body or attachment files']) - self._errors['attachments'] = ErrorList([u'You must provide a body or attachment files']) + self._errors['body'] = ErrorList(['You must provide a body or attachment files']) + self._errors['attachments'] = ErrorList(['You must provide a body or attachment files']) # if purpose=response there must be a related statement purpose = LiaisonStatementPurposeName.objects.get(slug='response') if self.cleaned_data.get('purpose') == purpose and not self.cleaned_data.get('related_to'): - self._errors['related_to'] = ErrorList([u'You must provide a related statement when purpose is In Response']) + self._errors['related_to'] = ErrorList(['You must provide a related statement when purpose is In Response']) return self.cleaned_data def full_clean(self): @@ -313,8 +314,8 @@ class LiaisonModelForm(BetterModelForm): self.reset_required_fields() def has_attachments(self): - for key in self.files.keys(): - if key.startswith('attach_file_') and key.replace('file', 'title') in self.data.keys(): + for key in list(self.files.keys()): + if key.startswith('attach_file_') and key.replace('file', 'title') in list(self.data.keys()): return True return False @@ -351,10 +352,10 @@ class LiaisonModelForm(BetterModelForm): request.POST[attach_title_N] ''' written = self.instance.attachments.all().count() - for key in self.files.keys(): + for key in list(self.files.keys()): title_key = key.replace('file', 'title') attachment_title = self.data.get(title_key) - if not key.startswith('attach_file_') or not title_key in self.data.keys(): + if not key.startswith('attach_file_') or not title_key in list(self.data.keys()): continue attached_file = self.files.get(key) extension=attached_file.name.rsplit('.', 1) @@ -422,7 +423,7 @@ class LiaisonModelForm(BetterModelForm): class IncomingLiaisonForm(LiaisonModelForm): def clean(self): - if 'send' in self.data.keys() and self.get_post_only(): + if 'send' in list(self.data.keys()) and self.get_post_only(): raise forms.ValidationError('As an IETF Liaison Manager you can not send incoming liaison statements, you only can post them') return super(IncomingLiaisonForm, self).clean() @@ -446,7 +447,7 @@ class IncomingLiaisonForm(LiaisonModelForm): self.fields['from_contact'].initial = self.person.role_set.filter(group=queryset[0]).first().email.address self.fields['from_contact'].widget.attrs['readonly'] = True self.fields['from_groups'].queryset = queryset - self.fields['from_groups'].widget.submitter = unicode(self.person) + self.fields['from_groups'].widget.submitter = str(self.person) # if there's only one possibility make it the default if len(queryset) == 1: diff --git a/ietf/liaisons/mails.py b/ietf/liaisons/mails.py index 413a429d4..0c13f51c1 100644 --- a/ietf/liaisons/mails.py +++ b/ietf/liaisons/mails.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import datetime from django.conf import settings @@ -8,7 +9,7 @@ from ietf.group.models import Role from ietf.mailtrigger.utils import gather_address_lists def send_liaison_by_email(request, liaison): - subject = u'New Liaison Statement, "%s"' % (liaison.title) + subject = 'New Liaison Statement, "%s"' % (liaison.title) from_email = settings.LIAISON_UNIVERSAL_FROM (to_email, cc) = gather_address_lists('liaison_statement_posted',liaison=liaison) bcc = ['statements@ietf.org'] @@ -20,7 +21,7 @@ def notify_pending_by_email(request, liaison): '''Send mail requesting approval of pending liaison statement. Send mail to the intersection of approvers for all from_groups ''' - subject = u'New Liaison Statement, "%s" needs your approval' % (liaison.title) + subject = 'New Liaison Statement, "%s" needs your approval' % (liaison.title) from_email = settings.LIAISON_UNIVERSAL_FROM (to, cc) = gather_address_lists('liaison_approval_requested',liaison=liaison) body = render_to_string('liaisons/pending_liaison_mail.txt', dict(liaison=liaison)) @@ -58,7 +59,7 @@ def possibly_send_deadline_reminder(liaison): } days_to_go = (liaison.deadline - datetime.date.today()).days - if not (days_to_go < 0 or days_to_go in PREVIOUS_DAYS.keys()): + if not (days_to_go < 0 or days_to_go in list(PREVIOUS_DAYS.keys())): return None # no reminder if days_to_go < 0: diff --git a/ietf/liaisons/management/commands/check_liaison_deadlines.py b/ietf/liaisons/management/commands/check_liaison_deadlines.py index aebadb46f..10cbc4291 100644 --- a/ietf/liaisons/management/commands/check_liaison_deadlines.py +++ b/ietf/liaisons/management/commands/check_liaison_deadlines.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved import datetime from django.core.management.base import BaseCommand @@ -7,7 +8,7 @@ from ietf.liaisons.mails import possibly_send_deadline_reminder class Command(BaseCommand): - help = (u"Check liaison deadlines and send a reminder if we are close to a deadline") + help = ("Check liaison deadlines and send a reminder if we are close to a deadline") def handle(self, *args, **options): today = datetime.date.today() diff --git a/ietf/liaisons/management/commands/remind_update_sdo_list.py b/ietf/liaisons/management/commands/remind_update_sdo_list.py index a33b069b4..5eae4acd2 100644 --- a/ietf/liaisons/management/commands/remind_update_sdo_list.py +++ b/ietf/liaisons/management/commands/remind_update_sdo_list.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved from django.core.management.base import BaseCommand @@ -6,7 +7,7 @@ from ietf.liaisons.mails import send_sdo_reminder class Command(BaseCommand): - help = (u"Send a remind to each SDO Liaison Manager to update the list of persons authorized to send liaison statements on behalf of his SDO") + help = ("Send a remind to each SDO Liaison Manager to update the list of persons authorized to send liaison statements on behalf of his SDO") def add_arguments(self, parser): parser.add_argument('-s', '--sdo-pk', dest='sdo_pk', @@ -25,16 +26,16 @@ def send_reminders_to_sdos(sdo_pk=None): sdos = sdos.filter(pk=sdo_pk) if not sdos: - print "No SDOs found!" + print("No SDOs found!") msgs = [] for sdo in sdos: body = send_sdo_reminder(sdo) if not body: - msg = u'%05s#: %s has no liaison manager' % (sdo.pk, sdo.name) + msg = '%05s#: %s has no liaison manager' % (sdo.pk, sdo.name) else: - msg = u'%05s#: %s mail sent!' % (sdo.pk, sdo.name) + msg = '%05s#: %s mail sent!' % (sdo.pk, sdo.name) msgs.append(msg) return msgs \ No newline at end of file diff --git a/ietf/liaisons/migrations/0001_initial.py b/ietf/liaisons/migrations/0001_initial.py index cfba2a61f..5d8e78d7a 100644 --- a/ietf/liaisons/migrations/0001_initial.py +++ b/ietf/liaisons/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/liaisons/migrations/0002_auto_20180225_1207.py b/ietf/liaisons/migrations/0002_auto_20180225_1207.py index 94f2fd2b1..c3f679ca9 100644 --- a/ietf/liaisons/migrations/0002_auto_20180225_1207.py +++ b/ietf/liaisons/migrations/0002_auto_20180225_1207.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-25 12:07 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/liaisons/migrations/0003_liaison_document2_fk.py b/ietf/liaisons/migrations/0003_liaison_document2_fk.py index 659899d4f..5105bdf3f 100644 --- a/ietf/liaisons/migrations/0003_liaison_document2_fk.py +++ b/ietf/liaisons/migrations/0003_liaison_document2_fk.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 11:58 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py b/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py index b5438e6b7..52bcd462e 100644 --- a/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py +++ b/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-20 09:53 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/liaisons/migrations/0005_rename_field_document2.py b/ietf/liaisons/migrations/0005_rename_field_document2.py index e5df89916..f6a2b0e1e 100644 --- a/ietf/liaisons/migrations/0005_rename_field_document2.py +++ b/ietf/liaisons/migrations/0005_rename_field_document2.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 05:31 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py b/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py index c61220811..4fc689698 100644 --- a/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py +++ b/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-06-10 03:47 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/liaisons/models.py b/ietf/liaisons/models.py index b42d72044..7af82a5ed 100644 --- a/ietf/liaisons/models.py +++ b/ietf/liaisons/models.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved from django.conf import settings from django.urls import reverse as urlreverse @@ -15,12 +15,12 @@ from ietf.utils.models import ForeignKey # maps (previous state id, new state id) to event type id STATE_EVENT_MAPPING = { - (u'pending','approved'):'approved', - (u'pending','dead'):'killed', - (u'pending','posted'):'posted', - (u'approved','posted'):'posted', - (u'dead','pending'):'resurrected', - (u'pending','pending'):'submitted' + ('pending','approved'):'approved', + ('pending','dead'):'killed', + ('pending','posted'):'posted', + ('approved','posted'):'posted', + ('dead','pending'):'resurrected', + ('pending','pending'):'submitted' } @@ -50,7 +50,7 @@ class LiaisonStatement(models.Model): def __unicode__(self): - return self.title or u"" + return self.title or "" def change_state(self,state_id=None,person=None): '''Helper function to change state of liaison statement and create appropriate @@ -213,7 +213,7 @@ class RelatedLiaisonStatement(models.Model): relationship = ForeignKey(DocRelationshipName) def __unicode__(self): - return u"%s %s %s" % (self.source.title, self.relationship.name.lower(), self.target.title) + return "%s %s %s" % (self.source.title, self.relationship.name.lower(), self.target.title) class LiaisonStatementGroupContacts(models.Model): @@ -222,7 +222,7 @@ class LiaisonStatementGroupContacts(models.Model): cc_contacts = models.CharField(max_length=255,blank=True) def __unicode__(self): - return u"%s" % self.group.name + return "%s" % self.group.name class LiaisonStatementEvent(models.Model): @@ -233,7 +233,7 @@ class LiaisonStatementEvent(models.Model): desc = models.TextField() def __unicode__(self): - return u"%s %s by %s at %s" % (self.statement.title, self.type.slug, self.by.plain_name(), self.time) + return "%s %s by %s at %s" % (self.statement.title, self.type.slug, self.by.plain_name(), self.time) class Meta: ordering = ['-time', '-id'] diff --git a/ietf/liaisons/tests.py b/ietf/liaisons/tests.py index fa2a1bfb2..22cef5911 100644 --- a/ietf/liaisons/tests.py +++ b/ietf/liaisons/tests.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved import datetime, os, shutil import json @@ -7,7 +8,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.urls import reverse as urlreverse from django.db.models import Q -from StringIO import StringIO +from io import StringIO from pyquery import PyQuery from ietf.utils.test_utils import TestCase, login_testing_unauthorized, unicontent @@ -205,7 +206,7 @@ class AjaxTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) data = json.loads(r.content) - self.assertEqual(data["to_contacts"],[u'test@example.com']) + self.assertEqual(data["to_contacts"],['test@example.com']) def test_ajax_select2_search_liaison_statements(self): liaison = LiaisonStatementFactory() diff --git a/ietf/liaisons/views.py b/ietf/liaisons/views.py index d8931d4f1..2f2412ee4 100644 --- a/ietf/liaisons/views.py +++ b/ietf/liaisons/views.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved import json from email.utils import parseaddr @@ -86,7 +86,7 @@ def _find_person_in_emails(liaison, person): def contacts_from_roles(roles): '''Returns contact string for given roles''' - emails = [ u'{} <{}>'.format(r.person.plain_name(),r.email.address) for r in roles ] + emails = [ '{} <{}>'.format(r.person.plain_name(),r.email.address) for r in roles ] return ','.join(emails) def get_cc(group): @@ -106,17 +106,17 @@ def get_cc(group): elif group.type_id == 'area': emails.append(EMAIL_ALIASES['IETFCHAIR']) ad_roles = group.role_set.filter(name='ad') - emails.extend([ u'{} <{}>'.format(r.person.plain_name(),r.email.address) for r in ad_roles ]) + emails.extend([ '{} <{}>'.format(r.person.plain_name(),r.email.address) for r in ad_roles ]) elif group.type_id == 'wg': ad_roles = group.parent.role_set.filter(name='ad') - emails.extend([ u'{} <{}>'.format(r.person.plain_name(),r.email.address) for r in ad_roles ]) + emails.extend([ '{} <{}>'.format(r.person.plain_name(),r.email.address) for r in ad_roles ]) chair_roles = group.role_set.filter(name='chair') - emails.extend([ u'{} <{}>'.format(r.person.plain_name(),r.email.address) for r in chair_roles ]) + emails.extend([ '{} <{}>'.format(r.person.plain_name(),r.email.address) for r in chair_roles ]) if group.list_email: - emails.append(u'{} Discussion List <{}>'.format(group.name,group.list_email)) + emails.append('{} Discussion List <{}>'.format(group.name,group.list_email)) elif group.type_id == 'sdo': liaiman_roles = group.role_set.filter(name='liaiman') - emails.extend([ u'{} <{}>'.format(r.person.plain_name(),r.email.address) for r in liaiman_roles ]) + emails.extend([ '{} <{}>'.format(r.person.plain_name(),r.email.address) for r in liaiman_roles ]) # explicit CCs if group.liaisonstatementgroupcontacts_set.exists() and group.liaisonstatementgroupcontacts_set.first().cc_contacts: @@ -274,7 +274,7 @@ def ajax_select2_search_liaison_statements(request): def redirect_add(request): """Redirects old add urls""" - if 'incoming' in request.GET.keys(): + if 'incoming' in list(request.GET.keys()): return redirect('ietf.liaisons.views.liaison_add', type='incoming') else: return redirect('ietf.liaisons.views.liaison_add', type='outgoing') diff --git a/ietf/liaisons/widgets.py b/ietf/liaisons/widgets.py index ea281cc40..ef4074390 100644 --- a/ietf/liaisons/widgets.py +++ b/ietf/liaisons/widgets.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved from django.urls import reverse as urlreverse from django.db.models.query import QuerySet from django.forms.widgets import Widget @@ -14,29 +15,29 @@ class ButtonWidget(Widget): super(ButtonWidget, self).__init__(*args, **kwargs) def render(self, name, value, attrs=None): - html = u'' % conditional_escape(self.show_on) - html += u'' % conditional_escape(self.label) + html = '' % conditional_escape(self.show_on) + html += '' % conditional_escape(self.label) if self.require: for i in self.require: - html += u'' % conditional_escape(i) - required_str = u'Please fill in %s to attach a new file' % conditional_escape(self.required_label) - html += u'' % conditional_escape(required_str) - html += u'' % conditional_escape(self.label) + html += '' % conditional_escape(i) + required_str = 'Please fill in %s to attach a new file' % conditional_escape(self.required_label) + html += '' % conditional_escape(required_str) + html += '' % conditional_escape(self.label) return mark_safe(html) class ShowAttachmentsWidget(Widget): def render(self, name, value, attrs=None): - html = u'
' % name - html += u'' - html += u'
' + html = '
' % name + html += '' + html += '
' if value and isinstance(value, QuerySet): for attachment in value: - html += u'%s ' % (conditional_escape(attachment.document.href()), conditional_escape(attachment.document.title)) - html += u'Edit '.format(urlreverse("ietf.liaisons.views.liaison_edit_attachment", kwargs={'object_id':attachment.statement.pk,'doc_id':attachment.document.pk})) - html += u'Delete '.format(urlreverse("ietf.liaisons.views.liaison_delete_attachment", kwargs={'object_id':attachment.statement.pk,'attach_id':attachment.pk})) - html += u'
' + html += '%s ' % (conditional_escape(attachment.document.href()), conditional_escape(attachment.document.title)) + html += 'Edit '.format(urlreverse("ietf.liaisons.views.liaison_edit_attachment", kwargs={'object_id':attachment.statement.pk,'doc_id':attachment.document.pk})) + html += 'Delete '.format(urlreverse("ietf.liaisons.views.liaison_delete_attachment", kwargs={'object_id':attachment.statement.pk,'attach_id':attachment.pk})) + html += '
' else: - html += u'No files attached' - html += u'
' + html += 'No files attached' + html += '
' return mark_safe(html) diff --git a/ietf/mailinglists/factories.py b/ietf/mailinglists/factories.py index c2942fdbd..10f41c8da 100644 --- a/ietf/mailinglists/factories.py +++ b/ietf/mailinglists/factories.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2018, All Rights Reserved +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import factory import random diff --git a/ietf/mailinglists/migrations/0001_initial.py b/ietf/mailinglists/migrations/0001_initial.py index 9efd709e9..f53f00a9f 100644 --- a/ietf/mailinglists/migrations/0001_initial.py +++ b/ietf/mailinglists/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import django.core.validators from django.db import migrations, models diff --git a/ietf/mailinglists/tests.py b/ietf/mailinglists/tests.py index 82629d1b2..29cd06518 100644 --- a/ietf/mailinglists/tests.py +++ b/ietf/mailinglists/tests.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2009-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + from pyquery import PyQuery diff --git a/ietf/mailtrigger/migrations/0001_initial.py b/ietf/mailtrigger/migrations/0001_initial.py index a563fa2e3..1b41575fc 100644 --- a/ietf/mailtrigger/migrations/0001_initial.py +++ b/ietf/mailtrigger/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/mailtrigger/migrations/0002_conflrev_changes.py b/ietf/mailtrigger/migrations/0002_conflrev_changes.py index 8fc3090b9..c801f6fe9 100644 --- a/ietf/mailtrigger/migrations/0002_conflrev_changes.py +++ b/ietf/mailtrigger/migrations/0002_conflrev_changes.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-05-21 12:07 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/mailtrigger/migrations/0003_add_review_notify_ad.py b/ietf/mailtrigger/migrations/0003_add_review_notify_ad.py index fbcf0ca1f..3389d050d 100644 --- a/ietf/mailtrigger/migrations/0003_add_review_notify_ad.py +++ b/ietf/mailtrigger/migrations/0003_add_review_notify_ad.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-11-02 11:34 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/mailtrigger/migrations/0004_ballot_rfceditornote_changed_postapproval.py b/ietf/mailtrigger/migrations/0004_ballot_rfceditornote_changed_postapproval.py index 592afe92b..097ebd6a3 100644 --- a/ietf/mailtrigger/migrations/0004_ballot_rfceditornote_changed_postapproval.py +++ b/ietf/mailtrigger/migrations/0004_ballot_rfceditornote_changed_postapproval.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-11-03 00:24 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/mailtrigger/migrations/0005_slides_proposed.py b/ietf/mailtrigger/migrations/0005_slides_proposed.py index f701b81d2..8c1e71f8d 100644 --- a/ietf/mailtrigger/migrations/0005_slides_proposed.py +++ b/ietf/mailtrigger/migrations/0005_slides_proposed.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-03-25 06:11 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/mailtrigger/migrations/0006_sub_new_wg_00.py b/ietf/mailtrigger/migrations/0006_sub_new_wg_00.py index 0169c456b..712803015 100644 --- a/ietf/mailtrigger/migrations/0006_sub_new_wg_00.py +++ b/ietf/mailtrigger/migrations/0006_sub_new_wg_00.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/mailtrigger/models.py b/ietf/mailtrigger/models.py index 3e3a6e373..6f5abaffb 100644 --- a/ietf/mailtrigger/models.py +++ b/ietf/mailtrigger/models.py @@ -18,7 +18,7 @@ def clean_duplicates(addrlist): # name from the last one: address_info[addr] = (name, a) addresses = [] - for addr, info in address_info.items(): + for addr, info in list(address_info.items()): name, a = info if (name,addr)==('',''): addresses.append(a) @@ -265,7 +265,7 @@ class Recipient(models.Model): doc = kwargs['doc'] active_ballot = doc.active_ballot() if active_ballot: - for ad, pos in active_ballot.active_ad_positions().iteritems(): + for ad, pos in active_ballot.active_ad_positions().items(): if pos and pos.pos_id == "discuss": addrs.append(ad.role_email("ad").address) return addrs diff --git a/ietf/meeting/admin.py b/ietf/meeting/admin.py index 1713d0215..d6ea3a5ee 100644 --- a/ietf/meeting/admin.py +++ b/ietf/meeting/admin.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved from django.contrib import admin from ietf.meeting.models import (Meeting, Room, Session, TimeSlot, Constraint, Schedule, @@ -37,7 +38,7 @@ class MeetingAdmin(admin.ModelAdmin): if instance.country: loc.append(instance.get_country_display()) - return u", ".join(loc) + return ", ".join(loc) admin.site.register(Meeting, MeetingAdmin) @@ -53,7 +54,7 @@ class TimeSlotAdmin(admin.ModelAdmin): if instance.session.name: return instance.session.name elif instance.session.group: - return u"%s (%s)" % (instance.session.group.name, instance.session.group.acronym) + return "%s (%s)" % (instance.session.group.name, instance.session.group.acronym) return "" session_desc.short_description = "session" diff --git a/ietf/meeting/factories.py b/ietf/meeting/factories.py index 44f8e4145..9eb6d6b56 100644 --- a/ietf/meeting/factories.py +++ b/ietf/meeting/factories.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved import factory import random import datetime @@ -146,8 +147,8 @@ class FloorPlanFactory(factory.DjangoModelFactory): class Meta: model = FloorPlan - name = factory.Sequence(lambda n: u'Venue Floor %d' % n) - short = factory.Sequence(lambda n: u'%d' % n) + name = factory.Sequence(lambda n: 'Venue Floor %d' % n) + short = factory.Sequence(lambda n: '%d' % n) meeting = factory.SubFactory(MeetingFactory) order = factory.Sequence(lambda n: n) image = factory.LazyAttribute( diff --git a/ietf/meeting/feeds.py b/ietf/meeting/feeds.py index a2780065d..bc9fa4ecd 100644 --- a/ietf/meeting/feeds.py +++ b/ietf/meeting/feeds.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2007-2019, All Rights Reserved import os from django.contrib.syndication.views import Feed @@ -33,7 +34,7 @@ class LatestMeetingMaterialFeed(Feed): return "Meeting Materials Activity" def item_title(self, item): - return u"%s: %s" % (item["group_acronym"], escape(item["title"])) + return "%s: %s" % (item["group_acronym"], escape(item["title"])) def item_description(self, item): return "" diff --git a/ietf/meeting/helpers.py b/ietf/meeting/helpers.py index ee6b5cff7..6d8300e45 100644 --- a/ietf/meeting/helpers.py +++ b/ietf/meeting/helpers.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime import os @@ -288,13 +288,13 @@ def agenda_permissions(meeting, schedule, user): return cansee, canedit, secretariat def session_constraint_expire(request,session): - from ajax import session_constraints + from .ajax import session_constraints path = reverse(session_constraints, args=[session.meeting.number, session.pk]) temp_request = HttpRequest() temp_request.path = path temp_request.META['HTTP_HOST'] = request.META['HTTP_HOST'] key = get_cache_key(temp_request) - if key is not None and cache.has_key(key): + if key is not None and key in cache: cache.delete(key) # ------------------------------------------------- diff --git a/ietf/meeting/management/commands/update_important_dates.py b/ietf/meeting/management/commands/update_important_dates.py index d5668c1b4..656cbdb02 100644 --- a/ietf/meeting/management/commands/update_important_dates.py +++ b/ietf/meeting/management/commands/update_important_dates.py @@ -1,5 +1,5 @@ -# Copyright The IETF Trust 2018, All Rights Reserved -from __future__ import unicode_literals +# Copyright The IETF Trust 2018-2019, All Rights Reserved + import datetime diff --git a/ietf/meeting/migrations/0001_initial.py b/ietf/meeting/migrations/0001_initial.py index ce77e14d6..e71b0ae90 100644 --- a/ietf/meeting/migrations/0001_initial.py +++ b/ietf/meeting/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import datetime import django.core.validators diff --git a/ietf/meeting/migrations/0002_auto_20180225_1207.py b/ietf/meeting/migrations/0002_auto_20180225_1207.py index d6082a214..6f5aab8af 100644 --- a/ietf/meeting/migrations/0002_auto_20180225_1207.py +++ b/ietf/meeting/migrations/0002_auto_20180225_1207.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-25 12:07 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/meeting/migrations/0003_rename_modified_fields.py b/ietf/meeting/migrations/0003_rename_modified_fields.py index 98d3f66e3..dea714019 100644 --- a/ietf/meeting/migrations/0003_rename_modified_fields.py +++ b/ietf/meeting/migrations/0003_rename_modified_fields.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-03-02 14:33 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/meeting/migrations/0004_meeting_attendees.py b/ietf/meeting/migrations/0004_meeting_attendees.py index 7eca3c2e3..ea7546a5b 100644 --- a/ietf/meeting/migrations/0004_meeting_attendees.py +++ b/ietf/meeting/migrations/0004_meeting_attendees.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.11 on 2018-03-20 09:17 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/meeting/migrations/0005_backfill_old_meetings.py b/ietf/meeting/migrations/0005_backfill_old_meetings.py index 0335adc4e..f56fc33ca 100644 --- a/ietf/meeting/migrations/0005_backfill_old_meetings.py +++ b/ietf/meeting/migrations/0005_backfill_old_meetings.py @@ -1,5 +1,6 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/meeting/migrations/0006_backfill_attendees.py b/ietf/meeting/migrations/0006_backfill_attendees.py index 05dfe4457..5b6a70958 100644 --- a/ietf/meeting/migrations/0006_backfill_attendees.py +++ b/ietf/meeting/migrations/0006_backfill_attendees.py @@ -1,5 +1,6 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/meeting/migrations/0007_auto_20180716_1337.py b/ietf/meeting/migrations/0007_auto_20180716_1337.py index 0521ca185..2fcf4804c 100644 --- a/ietf/meeting/migrations/0007_auto_20180716_1337.py +++ b/ietf/meeting/migrations/0007_auto_20180716_1337.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.14 on 2018-07-16 13:37 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/meeting/migrations/0008_rename_meeting_agenda_note.py b/ietf/meeting/migrations/0008_rename_meeting_agenda_note.py index cda62e1ac..1cef45068 100644 --- a/ietf/meeting/migrations/0008_rename_meeting_agenda_note.py +++ b/ietf/meeting/migrations/0008_rename_meeting_agenda_note.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-10-09 13:09 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/meeting/migrations/0009_add_agenda_info_note.py b/ietf/meeting/migrations/0009_add_agenda_info_note.py index ae1f32676..e9136158f 100644 --- a/ietf/meeting/migrations/0009_add_agenda_info_note.py +++ b/ietf/meeting/migrations/0009_add_agenda_info_note.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-10-09 14:07 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/meeting/migrations/0010_set_ietf_103_agenda_info_note.py b/ietf/meeting/migrations/0010_set_ietf_103_agenda_info_note.py index f1ae68251..14d68538f 100644 --- a/ietf/meeting/migrations/0010_set_ietf_103_agenda_info_note.py +++ b/ietf/meeting/migrations/0010_set_ietf_103_agenda_info_note.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-10-09 14:23 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/meeting/migrations/0011_auto_20190114_0550.py b/ietf/meeting/migrations/0011_auto_20190114_0550.py index 066ece556..bc9a076fa 100644 --- a/ietf/meeting/migrations/0011_auto_20190114_0550.py +++ b/ietf/meeting/migrations/0011_auto_20190114_0550.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-14 05:50 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/meeting/migrations/0012_add_slide_submissions.py b/ietf/meeting/migrations/0012_add_slide_submissions.py index 9ae818c08..659b8f475 100644 --- a/ietf/meeting/migrations/0012_add_slide_submissions.py +++ b/ietf/meeting/migrations/0012_add_slide_submissions.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-03-23 07:41 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/meeting/migrations/0013_make_separate_break_sessobj.py b/ietf/meeting/migrations/0013_make_separate_break_sessobj.py index 3d2e77c64..c7af0cf0b 100644 --- a/ietf/meeting/migrations/0013_make_separate_break_sessobj.py +++ b/ietf/meeting/migrations/0013_make_separate_break_sessobj.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-03-23 06:11 -from __future__ import unicode_literals + import datetime from django.db import migrations diff --git a/ietf/meeting/migrations/0014_auto_20190426_0305.py b/ietf/meeting/migrations/0014_auto_20190426_0305.py index c83544689..84f4dc4fc 100644 --- a/ietf/meeting/migrations/0014_auto_20190426_0305.py +++ b/ietf/meeting/migrations/0014_auto_20190426_0305.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-04-26 03:05 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py b/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py index bd13536ea..8897f0b44 100644 --- a/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py +++ b/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 11:58 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py b/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py index 228c63ed2..741153eb5 100644 --- a/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py +++ b/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 03:57 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/meeting/migrations/0017_rename_field_document2.py b/ietf/meeting/migrations/0017_rename_field_document2.py index a857a074f..672112a91 100644 --- a/ietf/meeting/migrations/0017_rename_field_document2.py +++ b/ietf/meeting/migrations/0017_rename_field_document2.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 05:31 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/meeting/migrations/0018_document_primary_key_cleanup.py b/ietf/meeting/migrations/0018_document_primary_key_cleanup.py index 491a34f93..08b1f5ab0 100644 --- a/ietf/meeting/migrations/0018_document_primary_key_cleanup.py +++ b/ietf/meeting/migrations/0018_document_primary_key_cleanup.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-06-10 03:47 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index 5b3478cae..145e0935f 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -5,7 +5,7 @@ import pytz import datetime -from urlparse import urljoin +from urllib.parse import urljoin import os import re import string @@ -33,7 +33,7 @@ from ietf.utils.text import xslugify from ietf.utils.timezone import date2datetime from ietf.utils.models import ForeignKey -countries = pytz.country_names.items() +countries = list(pytz.country_names.items()) countries.sort(lambda x,y: cmp(x[1], y[1])) timezones = [] @@ -100,12 +100,12 @@ class Meeting(models.Model): agenda_warning_note = models.TextField(blank=True, help_text="Text in this field will be placed more prominently at the top of the html agenda page for the meeting. HTML can be used, but will not be validated.") agenda = ForeignKey('Schedule',null=True,blank=True, related_name='+') session_request_lock_message = models.CharField(blank=True,max_length=255) # locked if not empty - proceedings_final = models.BooleanField(default=False, help_text=u"Are the proceedings for this meeting complete?") + proceedings_final = models.BooleanField(default=False, help_text="Are the proceedings for this meeting complete?") acknowledgements = models.TextField(blank=True, help_text="Acknowledgements for use in meeting proceedings. Use ReStructuredText markup.") overview = ForeignKey(DBTemplate, related_name='overview', null=True, editable=False) show_important_dates = models.BooleanField(default=False) attendees = models.IntegerField(blank=True, null=True, default=None, - help_text=u"Number of Attendees for backfilled meetings, leave it blank for new meetings, and then it is calculated from the registrations") + help_text="Number of Attendees for backfilled meetings, leave it blank for new meetings, and then it is calculated from the registrations") def __unicode__(self): if self.type_id == "ietf": @@ -413,7 +413,7 @@ class UrlResource(models.Model): def floorplan_path(instance, filename): root, ext = os.path.splitext(filename) - return u"%s/floorplan-%s-%s%s" % (settings.FLOORPLAN_MEDIA_DIR, instance.meeting.number, xslugify(instance.name), ext) + return "%s/floorplan-%s-%s%s" % (settings.FLOORPLAN_MEDIA_DIR, instance.meeting.number, xslugify(instance.name), ext) class FloorPlan(models.Model): name = models.CharField(max_length=255) @@ -444,7 +444,7 @@ class TimeSlot(models.Model): duration = models.DurationField(default=datetime.timedelta(0)) location = ForeignKey(Room, blank=True, null=True) show_location = models.BooleanField(default=True, help_text="Show location in agenda.") - sessions = models.ManyToManyField('Session', related_name='slots', through='SchedTimeSessAssignment', blank=True, help_text=u"Scheduled session, if any.") + sessions = models.ManyToManyField('Session', related_name='slots', through='SchedTimeSessAssignment', blank=True, help_text="Scheduled session, if any.") modified = models.DateTimeField(auto_now=True) # @@ -456,7 +456,7 @@ class TimeSlot(models.Model): @property def time_desc(self): - return u"%s-%s" % (self.time.strftime("%H%M"), (self.time + self.duration).strftime("%H%M")) + return "%s-%s" % (self.time.strftime("%H%M"), (self.time + self.duration).strftime("%H%M")) def meeting_date(self): return self.time.date() @@ -477,7 +477,7 @@ class TimeSlot(models.Model): if not location: location = "(no location)" - return u"%s: %s-%s %s, %s" % (self.meeting.number, self.time.strftime("%m-%d %H:%M"), (self.time + self.duration).strftime("%H:%M"), self.name, location) + return "%s: %s-%s %s, %s" % (self.meeting.number, self.time.strftime("%m-%d %H:%M"), (self.time + self.duration).strftime("%H:%M"), self.name, location) def end_time(self): return self.time + self.duration @@ -611,13 +611,13 @@ class Schedule(models.Model): meeting = ForeignKey(Meeting, null=True) name = models.CharField(max_length=16, blank=False) owner = ForeignKey(Person) - visible = models.BooleanField(default=True, help_text=u"Make this agenda available to those who know about it.") - public = models.BooleanField(default=True, help_text=u"Make this agenda publically available.") + visible = models.BooleanField(default=True, help_text="Make this agenda available to those who know about it.") + public = models.BooleanField(default=True, help_text="Make this agenda publically available.") badness = models.IntegerField(null=True, blank=True) # considering copiedFrom = ForeignKey('Schedule', blank=True, null=True) def __unicode__(self): - return u"%s:%s(%s)" % (self.meeting, self.name, self.owner) + return "%s:%s(%s)" % (self.meeting, self.name, self.owner) def base_url(self): return "/meeting/%s/agenda/%s/%s" % (self.meeting.number, self.owner_email(), self.name) @@ -714,9 +714,9 @@ class SchedTimeSessAssignment(models.Model): a specific person/user. """ timeslot = ForeignKey('TimeSlot', null=False, blank=False, related_name='sessionassignments') - session = ForeignKey('Session', null=True, default=None, related_name='timeslotassignments', help_text=u"Scheduled session.") + session = ForeignKey('Session', null=True, default=None, related_name='timeslotassignments', help_text="Scheduled session.") schedule = ForeignKey('Schedule', null=False, blank=False, related_name='assignments') - extendedfrom = ForeignKey('self', null=True, default=None, help_text=u"Timeslot this session is an extension of.") + extendedfrom = ForeignKey('self', null=True, default=None, help_text="Timeslot this session is an extension of.") modified = models.DateTimeField(auto_now=True) notes = models.TextField(blank=True) badness = models.IntegerField(default=0, blank=True, null=True) @@ -726,7 +726,7 @@ class SchedTimeSessAssignment(models.Model): ordering = ["timeslot__time", "timeslot__type__slug", "session__group__parent__name", "session__group__acronym", "session__name", ] def __unicode__(self): - return u"%s [%s<->%s]" % (self.schedule, self.session, self.timeslot) + return "%s [%s<->%s]" % (self.schedule, self.session, self.timeslot) @property def room_name(self): @@ -807,7 +807,7 @@ class SchedTimeSessAssignment(models.Model): components.append(g.acronym) - return u"-".join(components).lower() + return "-".join(components).lower() class Constraint(models.Model): """ @@ -829,15 +829,15 @@ class Constraint(models.Model): active_status = None def __unicode__(self): - return u"%s %s target=%s person=%s" % (self.source, self.name.name.lower(), self.target, self.person) + return "%s %s target=%s person=%s" % (self.source, self.name.name.lower(), self.target, self.person) def brief_display(self): if self.target and self.person: - return u"%s ; %s" % (self.target.acronym, self.person) + return "%s ; %s" % (self.target.acronym, self.person) elif self.target and not self.person: - return u"%s " % (self.target.acronym) + return "%s " % (self.target.acronym) elif not self.target and self.person: - return u"%s " % (self.person) + return "%s " % (self.person) def json_url(self): return "/meeting/%s/constraint/%s.json" % (self.meeting.number, self.id) @@ -869,7 +869,7 @@ class SessionPresentation(models.Model): unique_together = (('session', 'document'),) def __unicode__(self): - return u"%s -> %s-%s" % (self.session, self.document.name, self.rev) + return "%s -> %s-%s" % (self.session, self.document.name, self.rev) constraint_cache_uses = 0 constraint_cache_initials = 0 @@ -1018,7 +1018,7 @@ class Session(models.Model): ss = self.timeslotassignments.filter(schedule=self.meeting.agenda).order_by('timeslot__time') if ss: ss0name = ','.join([x.timeslot.time.strftime("%a-%H%M") for x in ss]) - return u"%s: %s %s %s" % (self.meeting, self.group.acronym, self.name, ss0name) + return "%s: %s %s %s" % (self.meeting, self.group.acronym, self.name, ss0name) @property def short_name(self): @@ -1028,7 +1028,7 @@ class Session(models.Model): return self.short if self.group: return self.group.acronym - return u"req#%u" % (id) + return "req#%u" % (id) @property def special_request_token(self): @@ -1155,7 +1155,7 @@ class ImportantDate(models.Model): ordering = ["-meeting_id","date", ] def __unicode__(self): - return u'%s : %s : %s' % ( self.meeting, self.name, self.date ) + return '%s : %s : %s' % ( self.meeting, self.name, self.date ) class SlideSubmission(models.Model): session = ForeignKey(Session) diff --git a/ietf/meeting/templatetags/agenda_custom_tags.py b/ietf/meeting/templatetags/agenda_custom_tags.py index b6e17aa1a..5adeb314c 100644 --- a/ietf/meeting/templatetags/agenda_custom_tags.py +++ b/ietf/meeting/templatetags/agenda_custom_tags.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved from django import template register = template.Library() @@ -42,7 +43,7 @@ def durationFormat(inp): def callMethod(obj, methodName): method = getattr(obj, methodName) - if obj.__dict__.has_key("__callArg"): + if "__callArg" in obj.__dict__: ret = method(*obj.__callArg) del obj.__callArg return ret @@ -50,7 +51,7 @@ def callMethod(obj, methodName): @register.filter(name="args") def args(obj, arg): - if not obj.__dict__.has_key("__callArg"): + if "__callArg" not in obj.__dict__: obj.__callArg = [] obj.__callArg += [arg] diff --git a/ietf/meeting/tests_api.py b/ietf/meeting/tests_api.py index 0bf6da2e7..bc746bdfb 100644 --- a/ietf/meeting/tests_api.py +++ b/ietf/meeting/tests_api.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime import json -from urlparse import urlsplit +from urllib.parse import urlsplit from django.urls import reverse as urlreverse diff --git a/ietf/meeting/tests_js.py b/ietf/meeting/tests_js.py index 230c960f9..914833f78 100644 --- a/ietf/meeting/tests_js.py +++ b/ietf/meeting/tests_js.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2014-2019, All Rights Reserved import sys import time @@ -148,7 +148,7 @@ class SlideReorderTests(StaticLiveServerTestCase): time.sleep(0.1) # The API that modifies the database runs async names=self.session.sessionpresentation_set.values_list('document__name',flat=True) - self.assertEqual(list(names),[u'one',u'three',u'two']) + self.assertEqual(list(names),['one','three','two']) # The following are useful debugging tools diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index bf01e458b..6b67f4009 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -5,7 +5,7 @@ import json import os import shutil import datetime -import urlparse +import urllib.parse import random from unittest import skipIf @@ -17,7 +17,7 @@ from django.contrib.auth.models import User from mock import patch from pyquery import PyQuery -from StringIO import StringIO +from io import StringIO from bs4 import BeautifulSoup from ietf.doc.models import Document @@ -134,7 +134,7 @@ class MeetingTests(TestCase): # future meeting, no agenda r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=future_meeting.number))) self.assertEqual(r.status_code, 200) - self.assertContains(r, u"There is no agenda available yet.") + self.assertContains(r, "There is no agenda available yet.") self.assertTemplateUsed(r, 'meeting/no-agenda.html') # text @@ -618,7 +618,7 @@ class EditTests(TestCase): }) self.assertEqual(r.status_code, 302) # Verify that we actually got redirected to a new place. - self.assertNotEqual(urlparse.urlparse(r.url).path, url) + self.assertNotEqual(urllib.parse.urlparse(r.url).path, url) # get schedule = meeting.get_schedule_by_name("foo") @@ -664,7 +664,7 @@ class EditTests(TestCase): 'saveas': "saveas", }) self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r.url).path, url) + self.assertEqual(urllib.parse.urlparse(r.url).path, url) # TODO: Verify that an error message was in fact returned. r = self.client.post(url, { @@ -673,16 +673,16 @@ class EditTests(TestCase): }) # TODO: Verify that an error message was in fact returned. self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r.url).path, url) + self.assertEqual(urllib.parse.urlparse(r.url).path, url) # Non-ASCII alphanumeric characters r = self.client.post(url, { - 'savename': u"f\u00E9ling", + 'savename': "f\u00E9ling", 'saveas': "saveas", }) # TODO: Verify that an error message was in fact returned. self.assertEqual(r.status_code, 302) - self.assertEqual(urlparse.urlparse(r.url).path, url) + self.assertEqual(urllib.parse.urlparse(r.url).path, url) def test_edit_timeslots(self): @@ -1749,7 +1749,7 @@ class MaterialsTests(TestCase): soup = BeautifulSoup(page, 'html.parser') for a in soup('a'): href = a.get('href') - path = urlparse.urlparse(href).path + path = urllib.parse.urlparse(href).path if (path and path not in seen and path.startswith(top)): follow(path) follow(url) @@ -1761,7 +1761,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Upload' in unicode(q("title"))) + self.assertTrue('Upload' in str(q("title"))) self.assertFalse(session.sessionpresentation_set.exists()) test_file = StringIO(b'%PDF-1.4\n%âãÏÓ\nthis is some text for a test') test_file.name = "not_really.pdf" @@ -1772,7 +1772,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Revise' in unicode(q("title"))) + self.assertTrue('Revise' in str(q("title"))) test_file = StringIO('%PDF-1.4\n%âãÏÓ\nthis is some different text for a test') test_file.name = "also_not_really.pdf" r = self.client.post(url,dict(file=test_file)) @@ -1796,7 +1796,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Upload' in unicode(q("title"))) + self.assertTrue('Upload' in str(q("title"))) self.assertFalse(session.sessionpresentation_set.exists()) test_file = StringIO(b'%PDF-1.4\n%âãÏÓ\nthis is some text for a test') test_file.name = "not_really.pdf" @@ -1814,7 +1814,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Upload' in unicode(q("title"))) + self.assertTrue('Upload' in str(q("title"))) def test_upload_minutes_agenda(self): @@ -1829,7 +1829,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Upload' in unicode(q("Title"))) + self.assertTrue('Upload' in str(q("Title"))) self.assertFalse(session.sessionpresentation_set.exists()) self.assertFalse(q('form input[type="checkbox"]')) @@ -1872,7 +1872,7 @@ class MaterialsTests(TestCase): self.assertNotIn('
', text) self.assertIn('charset="utf-8"', text) - test_file = StringIO(u'This is some text for a test, with the word\nvirtual at the beginning of a line.') + test_file = StringIO('This is some text for a test, with the word\nvirtual at the beginning of a line.') test_file.name = "not_really.txt" r = self.client.post(url,dict(file=test_file,apply_to_all=False)) self.assertEqual(r.status_code, 302) @@ -1883,7 +1883,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Revise' in unicode(q("Title"))) + self.assertTrue('Revise' in str(q("Title"))) test_file = StringIO('this is some different text for a test') test_file.name = "also_not_really.txt" r = self.client.post(url,dict(file=test_file,apply_to_all=True)) @@ -1893,7 +1893,7 @@ class MaterialsTests(TestCase): self.assertTrue(session2.sessionpresentation_set.filter(document__type_id=doctype)) # Test bad encoding - test_file = StringIO(u'

Title

Some\x93text
'.encode('latin1')) + test_file = StringIO('

Title

Some\x93text
'.encode('latin1')) test_file.name = "some.html" r = self.client.post(url,dict(file=test_file)) self.assertContains(r, 'Could not identify the file encoding') @@ -1917,7 +1917,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Upload' in unicode(q("Title"))) + self.assertTrue('Upload' in str(q("Title"))) self.assertFalse(session.sessionpresentation_set.exists()) self.assertFalse(q('form input[type="checkbox"]')) @@ -1938,7 +1938,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Upload' in unicode(q("title"))) + self.assertTrue('Upload' in str(q("title"))) self.assertFalse(session.sessionpresentation_set.filter(document__type_id=doctype)) test_file = StringIO('this is some text for a test') test_file.name = "not_really.txt" @@ -1961,7 +1961,7 @@ class MaterialsTests(TestCase): r = self.client.get(url) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Upload' in unicode(q("title"))) + self.assertTrue('Upload' in str(q("title"))) self.assertFalse(session1.sessionpresentation_set.filter(document__type_id='slides')) test_file = StringIO('this is not really a slide') test_file.name = 'not_really.txt' @@ -1982,14 +1982,14 @@ class MaterialsTests(TestCase): self.assertEqual(session2.sessionpresentation_set.count(),2) sp = session2.sessionpresentation_set.get(document__name__endswith='-a-different-slide-file') self.assertEqual(sp.order,2) - self.assertEqual(sp.rev,u'00') - self.assertEqual(sp.document.rev,u'00') + self.assertEqual(sp.rev,'00') + self.assertEqual(sp.document.rev,'00') url = urlreverse('ietf.meeting.views.upload_session_slides',kwargs={'num':session2.meeting.number,'session_id':session2.id,'name':session2.sessionpresentation_set.get(order=2).document.name}) r = self.client.get(url) self.assertTrue(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Revise' in unicode(q("title"))) + self.assertTrue('Revise' in str(q("title"))) test_file = StringIO('new content for the second slide deck') test_file.name = 'doesnotmatter.txt' r = self.client.post(url,dict(file=test_file,title='rename the presentation',apply_to_all=False)) @@ -1997,8 +1997,8 @@ class MaterialsTests(TestCase): self.assertEqual(session1.sessionpresentation_set.count(),1) self.assertEqual(session2.sessionpresentation_set.count(),2) sp = session2.sessionpresentation_set.get(order=2) - self.assertEqual(sp.rev,u'01') - self.assertEqual(sp.document.rev,u'01') + self.assertEqual(sp.rev,'01') + self.assertEqual(sp.document.rev,'01') def test_remove_sessionpresentation(self): session = SessionFactory(meeting__type_id='ietf') diff --git a/ietf/meeting/utils.py b/ietf/meeting/utils.py index f57d3b625..296e9ac08 100644 --- a/ietf/meeting/utils.py +++ b/ietf/meeting/utils.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved import datetime import json -import urllib2 +import urllib.request, urllib.error, urllib.parse from django.conf import settings from django.template.loader import render_to_string @@ -87,8 +88,8 @@ def create_proceedings_templates(meeting): # Get meeting attendees from registration system url = settings.STATS_REGISTRATION_ATTENDEES_JSON_URL.format(number=meeting.number) try: - attendees = json.load(urllib2.urlopen(url)) - except (ValueError, urllib2.HTTPError): + attendees = json.load(urllib.request.urlopen(url)) + except (ValueError, urllib.error.HTTPError): attendees = [] if attendees: diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 585dba5a5..95a444340 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -9,7 +9,7 @@ import os import pytz import re import tarfile -import urllib +import urllib.request, urllib.parse, urllib.error from calendar import timegm from collections import OrderedDict, Counter, deque @@ -523,7 +523,7 @@ def agenda_csv(schedule, filtered_assignments): headings = ["Date", "Start", "End", "Session", "Room", "Area", "Acronym", "Type", "Description", "Session ID", "Agenda", "Slides"] def write_row(row): - encoded_row = [v.encode('utf-8') if isinstance(v, unicode) else v for v in row] + encoded_row = [v.encode('utf-8') if isinstance(v, str) else v for v in row] while len(encoded_row) < len(headings): encoded_row.append(None) # produce empty entries at the end as necessary @@ -693,7 +693,7 @@ def session_draft_tarfile(request, num, acronym): try: tarstream.add(pdf_path, str(doc_name + ".pdf")) manifest.write("Included: "+pdf_path+"\n") - except Exception, e: + except Exception as e: manifest.write(("Failed (%s): "%e)+pdf_path+"\n") else: manifest.write("Not found: "+pdf_path+"\n") @@ -873,7 +873,7 @@ def ical_agenda(request, num=None, name=None, acronym=None, session_id=None): raise Http404 q = request.META.get('QUERY_STRING','') or "" - filter = set(urllib.unquote(q).lower().split(',')) + filter = set(urllib.parse.unquote(q).lower().split(',')) include = [ i for i in filter if not (i.startswith('-') or i.startswith('~')) ] include_types = set(["plenary","other"]) exclude = [] diff --git a/ietf/message/migrations/0001_initial.py b/ietf/message/migrations/0001_initial.py index 6a004fd87..dad23f182 100644 --- a/ietf/message/migrations/0001_initial.py +++ b/ietf/message/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import datetime from django.db import migrations, models diff --git a/ietf/message/migrations/0002_add_message_docs2_m2m.py b/ietf/message/migrations/0002_add_message_docs2_m2m.py index 6cb7f27a0..9f65c4a84 100644 --- a/ietf/message/migrations/0002_add_message_docs2_m2m.py +++ b/ietf/message/migrations/0002_add_message_docs2_m2m.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 14:23 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/message/migrations/0003_set_document_m2m_keys.py b/ietf/message/migrations/0003_set_document_m2m_keys.py index a6da567d4..70d1b08fa 100644 --- a/ietf/message/migrations/0003_set_document_m2m_keys.py +++ b/ietf/message/migrations/0003_set_document_m2m_keys.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 14:27 -from __future__ import unicode_literals + import sys @@ -20,7 +20,7 @@ def forward(apps, schema_editor): # Document id fixup ------------------------------------------------------------ objs = Document.objects.in_bulk() - nameid = { o.name: o.id for id, o in objs.iteritems() } + nameid = { o.name: o.id for id, o in objs.items() } sys.stderr.write('\n') diff --git a/ietf/message/migrations/0004_1_del_docs_m2m_table.py b/ietf/message/migrations/0004_1_del_docs_m2m_table.py index 328b6cdcf..38e160a91 100644 --- a/ietf/message/migrations/0004_1_del_docs_m2m_table.py +++ b/ietf/message/migrations/0004_1_del_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-22 08:01 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/message/migrations/0004_2_add_docs_m2m_table.py b/ietf/message/migrations/0004_2_add_docs_m2m_table.py index 064b2e085..8fc173e5a 100644 --- a/ietf/message/migrations/0004_2_add_docs_m2m_table.py +++ b/ietf/message/migrations/0004_2_add_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-22 08:01 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/message/migrations/0005_copy_docs_m2m_table.py b/ietf/message/migrations/0005_copy_docs_m2m_table.py index 7959d0365..4a52e9096 100644 --- a/ietf/message/migrations/0005_copy_docs_m2m_table.py +++ b/ietf/message/migrations/0005_copy_docs_m2m_table.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-27 05:56 -from __future__ import unicode_literals + import sys, time diff --git a/ietf/message/migrations/0006_remove_docs2_m2m.py b/ietf/message/migrations/0006_remove_docs2_m2m.py index 527eb5595..c3e54f232 100644 --- a/ietf/message/migrations/0006_remove_docs2_m2m.py +++ b/ietf/message/migrations/0006_remove_docs2_m2m.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-30 03:32 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/message/models.py b/ietf/message/models.py index 6fc243dc0..3e06e7da4 100644 --- a/ietf/message/models.py +++ b/ietf/message/models.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import datetime import email.utils @@ -67,7 +68,7 @@ class SendQueue(models.Model): ordering = ['time'] def __unicode__(self): - return u"'%s' %s -> %s (sent at %s)" % (self.message.subject, self.message.frm, self.message.to, self.sent_at or "") + return "'%s' %s -> %s (sent at %s)" % (self.message.subject, self.message.frm, self.message.to, self.sent_at or "") class AnnouncementFrom(models.Model): diff --git a/ietf/message/tests.py b/ietf/message/tests.py index 5a69b3cd8..a9ca78b67 100644 --- a/ietf/message/tests.py +++ b/ietf/message/tests.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime from django.urls import reverse as urlreverse @@ -40,7 +41,7 @@ class SendScheduledAnnouncementsTests(TestCase): frm="testmonkey@example.com", cc="cc.a@example.com, cc.b@example.com", bcc="bcc@example.com", - body=u"Hello World!", + body="Hello World!", content_type="", ) @@ -66,7 +67,7 @@ class SendScheduledAnnouncementsTests(TestCase): frm="testmonkey@example.com", cc="cc.a@example.com, cc.b@example.com", bcc="bcc@example.com", - body=u'--NextPart\r\n\r\nA New Internet-Draft is available from the on-line Internet-Drafts directories.\r\n--NextPart\r\nContent-Type: Message/External-body;\r\n\tname="draft-huang-behave-bih-01.txt";\r\n\tsite="ftp.ietf.org";\r\n\taccess-type="anon-ftp";\r\n\tdirectory="internet-drafts"\r\n\r\nContent-Type: text/plain\r\nContent-ID: <2010-07-30001541.I-D@ietf.org>\r\n\r\n--NextPart--', + body='--NextPart\r\n\r\nA New Internet-Draft is available from the on-line Internet-Drafts directories.\r\n--NextPart\r\nContent-Type: Message/External-body;\r\n\tname="draft-huang-behave-bih-01.txt";\r\n\tsite="ftp.ietf.org";\r\n\taccess-type="anon-ftp";\r\n\tdirectory="internet-drafts"\r\n\r\nContent-Type: text/plain\r\nContent-ID: <2010-07-30001541.I-D@ietf.org>\r\n\r\n--NextPart--', content_type='Multipart/Mixed; Boundary="NextPart"', ) diff --git a/ietf/middleware.py b/ietf/middleware.py index b8098d2df..fcb7687c4 100644 --- a/ietf/middleware.py +++ b/ietf/middleware.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved from django.db import connection from django.db.utils import OperationalError @@ -58,7 +58,7 @@ def unicode_nfkc_normalization_middleware(get_response): def unicode_nfkc_normalization(request): """Do Unicode NFKC normalization to turn ligatures into individual characters. This was prompted by somebody actually requesting an url for /wg/ipfix/charter - where the 'fi' was composed of an \ufb01 ligature... + where the 'fi' was composed of an \\ufb01 ligature... There are probably other elements of a request which may need this normalization too, but let's put that in as it comes up, rather than guess ahead. diff --git a/ietf/name/migrations/0001_initial.py b/ietf/name/migrations/0001_initial.py index fab75d062..b7e31cf98 100644 --- a/ietf/name/migrations/0001_initial.py +++ b/ietf/name/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/name/migrations/0002_agendatypename.py b/ietf/name/migrations/0002_agendatypename.py index 11fd824df..4089f9b73 100644 --- a/ietf/name/migrations/0002_agendatypename.py +++ b/ietf/name/migrations/0002_agendatypename.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-07-10 13:47 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/name/migrations/0003_agendatypename_data.py b/ietf/name/migrations/0003_agendatypename_data.py index 175ffb66e..c5d224bab 100644 --- a/ietf/name/migrations/0003_agendatypename_data.py +++ b/ietf/name/migrations/0003_agendatypename_data.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-07-10 13:47 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/name/migrations/0004_add_prefix_to_doctypenames.py b/ietf/name/migrations/0004_add_prefix_to_doctypenames.py index 2749f561f..31a3d60cc 100644 --- a/ietf/name/migrations/0004_add_prefix_to_doctypenames.py +++ b/ietf/name/migrations/0004_add_prefix_to_doctypenames.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-10-19 11:34 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/name/migrations/0005_reviewassignmentstatename.py b/ietf/name/migrations/0005_reviewassignmentstatename.py index dbf253e51..9b2567e0c 100644 --- a/ietf/name/migrations/0005_reviewassignmentstatename.py +++ b/ietf/name/migrations/0005_reviewassignmentstatename.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-04 13:59 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/name/migrations/0006_adjust_statenames.py b/ietf/name/migrations/0006_adjust_statenames.py index f3954906d..763034d76 100644 --- a/ietf/name/migrations/0006_adjust_statenames.py +++ b/ietf/name/migrations/0006_adjust_statenames.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-04 14:02 -from __future__ import unicode_literals + from django.db import migrations @@ -78,7 +79,7 @@ def forward(apps, schema_editor): for entry in assignment_states: name, created = ReviewAssignmentStateName.objects.get_or_create(slug=entry['slug']) if created: - for k, v in entry.items(): + for k, v in list(entry.items()): setattr(name, k, v) name.save() diff --git a/ietf/nomcom/admin.py b/ietf/nomcom/admin.py index d6e0170d9..6e25736e0 100644 --- a/ietf/nomcom/admin.py +++ b/ietf/nomcom/admin.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved from django.contrib import admin from ietf.nomcom.models import ( ReminderDates, NomCom, Nomination, Nominee, NomineePosition, @@ -43,7 +44,7 @@ admin.site.register(Position, PositionAdmin) class FeedbackAdmin(admin.ModelAdmin): def nominee(self, obj): - return u", ".join(n.person.ascii for n in obj.nominees.all()) + return ", ".join(n.person.ascii for n in obj.nominees.all()) nominee.admin_order_field = 'nominees__person__ascii' list_display = ['id', 'nomcom', 'author', 'nominee', 'subject', 'type', 'user', 'time'] diff --git a/ietf/nomcom/decorators.py b/ietf/nomcom/decorators.py index 231661799..99d85d487 100644 --- a/ietf/nomcom/decorators.py +++ b/ietf/nomcom/decorators.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import functools from django.urls import reverse @@ -9,7 +10,7 @@ def nomcom_private_key_required(view_func): def inner(request, *args, **kwargs): year = kwargs.get('year', None) if not year: - raise Exception, 'View decorated with nomcom_private_key_required must receive a year argument' + raise Exception('View decorated with nomcom_private_key_required must receive a year argument') if not 'NOMCOM_PRIVATE_KEY_%s' % year in request.session: return HttpResponseRedirect('%s?back_to=%s' % (reverse('ietf.nomcom.views.private_key', None, args=(year, )), urlquote(request.get_full_path()))) else: diff --git a/ietf/nomcom/forms.py b/ietf/nomcom/forms.py index e7791f12e..c343c5d11 100644 --- a/ietf/nomcom/forms.py +++ b/ietf/nomcom/forms.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved from django.conf import settings from django import forms from django.urls import reverse @@ -32,12 +33,12 @@ class PositionNomineeField(forms.ChoiceField): results = [] for position in positions: accepted_nominees = [np.nominee for np in NomineePosition.objects.filter(position=position,state='accepted').exclude(nominee__duplicated__isnull=False)] - nominees = [('%s_%s' % (position.id, i.id), unicode(i)) for i in accepted_nominees] + nominees = [('%s_%s' % (position.id, i.id), str(i)) for i in accepted_nominees] if nominees: results.append((position.name+" (Accepted)", nominees)) for position in positions: other_nominees = [np.nominee for np in NomineePosition.objects.filter(position=position).exclude(state='accepted').exclude(nominee__duplicated__isnull=False)] - nominees = [('%s_%s' % (position.id, i.id), unicode(i)) for i in other_nominees] + nominees = [('%s_%s' % (position.id, i.id), str(i)) for i in other_nominees] if nominees: results.append((position.name+" (Declined or Pending)", nominees)) kwargs['choices'] = results diff --git a/ietf/nomcom/management/commands/feedback_email.py b/ietf/nomcom/management/commands/feedback_email.py index 99a003bd9..3c4ae9f96 100644 --- a/ietf/nomcom/management/commands/feedback_email.py +++ b/ietf/nomcom/management/commands/feedback_email.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import sys from django.core.management.base import BaseCommand, CommandError @@ -10,7 +11,7 @@ from ietf.nomcom.fields import EncryptedException import debug # pyflakes:ignore class Command(BaseCommand): - help = (u"Receive nomcom email, encrypt and save it.") + help = ("Receive nomcom email, encrypt and save it.") def add_arguments(self, parser): parser.add_argument('--nomcom-year', dest='year', help='NomCom year') @@ -40,6 +41,6 @@ class Command(BaseCommand): try: feedback = create_feedback_email(nomcom, msg) - log(u"Received nomcom email from %s" % feedback.author) + log("Received nomcom email from %s" % feedback.author) except (EncryptedException, ValueError) as e: raise CommandError(e) diff --git a/ietf/nomcom/management/commands/make_dummy_nomcom.py b/ietf/nomcom/management/commands/make_dummy_nomcom.py index a6724a326..bb55ba9f2 100644 --- a/ietf/nomcom/management/commands/make_dummy_nomcom.py +++ b/ietf/nomcom/management/commands/make_dummy_nomcom.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import socket @@ -14,7 +14,7 @@ from ietf.group.models import Group from ietf.person.models import User class Command(BaseCommand): - help = (u"Create (or delete) a dummy nomcom for test and development purposes.") + help = ("Create (or delete) a dummy nomcom for test and development purposes.") def add_arguments(self, parser): parser.add_argument('--delete', dest='delete', action='store_true', help='Delete the test and development dummy nomcom') @@ -39,22 +39,22 @@ class Command(BaseCommand): populate_personnel=False, populate_positions=False)) - e = EmailFactory(person__name=u'Dummy Chair', address=u'dummychair@example.com', person__user__username=u'dummychair', person__default_emails=False, origin='dummychair') + e = EmailFactory(person__name='Dummy Chair', address='dummychair@example.com', person__user__username='dummychair', person__default_emails=False, origin='dummychair') e.person.user.set_password('password') e.person.user.save() - nc.group.role_set.create(name_id=u'chair',person=e.person,email=e) + nc.group.role_set.create(name_id='chair',person=e.person,email=e) - e = EmailFactory(person__name=u'Dummy Member', address=u'dummymember@example.com', person__user__username=u'dummymember', person__default_emails=False, origin='dummymember') + e = EmailFactory(person__name='Dummy Member', address='dummymember@example.com', person__user__username='dummymember', person__default_emails=False, origin='dummymember') e.person.user.set_password('password') e.person.user.save() - nc.group.role_set.create(name_id=u'member',person=e.person,email=e) + nc.group.role_set.create(name_id='member',person=e.person,email=e) - e = EmailFactory(person__name=u'Dummy Candidate', address=u'dummycandidate@example.com', person__user__username=u'dummycandidate', person__default_emails=False, origin='dummycandidate') + e = EmailFactory(person__name='Dummy Candidate', address='dummycandidate@example.com', person__user__username='dummycandidate', person__default_emails=False, origin='dummycandidate') e.person.user.set_password('password') e.person.user.save() NomineePositionFactory(nominee__nomcom=nc, nominee__person=e.person, - position__nomcom=nc, position__name=u'Dummy Area Director', + position__nomcom=nc, position__name='Dummy Area Director', ) self.stdout.write("%s\n" % key) diff --git a/ietf/nomcom/management/commands/send_reminders.py b/ietf/nomcom/management/commands/send_reminders.py index b8e83fd09..85318df60 100644 --- a/ietf/nomcom/management/commands/send_reminders.py +++ b/ietf/nomcom/management/commands/send_reminders.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime import syslog @@ -17,7 +18,7 @@ def is_time_to_send(nomcom,send_date,nomination_date): return bool(nomcom.reminderdates_set.filter(date=send_date)) class Command(BaseCommand): - help = (u"Send acceptance and questionnaire reminders to nominees") + help = ("Send acceptance and questionnaire reminders to nominees") def handle(self, *args, **options): for nomcom in NomCom.objects.filter(group__state__slug='active'): diff --git a/ietf/nomcom/migrations/0001_initial.py b/ietf/nomcom/migrations/0001_initial.py index ca498d684..d45a1a33b 100644 --- a/ietf/nomcom/migrations/0001_initial.py +++ b/ietf/nomcom/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.conf import settings from django.db import migrations, models diff --git a/ietf/nomcom/migrations/0002_auto_20180918_0550.py b/ietf/nomcom/migrations/0002_auto_20180918_0550.py index ad4b76928..9c68a359a 100644 --- a/ietf/nomcom/migrations/0002_auto_20180918_0550.py +++ b/ietf/nomcom/migrations/0002_auto_20180918_0550.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-18 05:50 -from __future__ import unicode_literals + from django.conf import settings from django.db import migrations diff --git a/ietf/nomcom/migrations/0003_nomcom_show_accepted_nominees.py b/ietf/nomcom/migrations/0003_nomcom_show_accepted_nominees.py index a6691afd2..ec16a045f 100644 --- a/ietf/nomcom/migrations/0003_nomcom_show_accepted_nominees.py +++ b/ietf/nomcom/migrations/0003_nomcom_show_accepted_nominees.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-26 11:10 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/nomcom/migrations/0004_set_show_accepted_nominees_false_on_existing_nomcoms.py b/ietf/nomcom/migrations/0004_set_show_accepted_nominees_false_on_existing_nomcoms.py index 49bf943d9..05245b4c0 100644 --- a/ietf/nomcom/migrations/0004_set_show_accepted_nominees_false_on_existing_nomcoms.py +++ b/ietf/nomcom/migrations/0004_set_show_accepted_nominees_false_on_existing_nomcoms.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-26 11:12 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/nomcom/migrations/0005_auto_20181008_0602.py b/ietf/nomcom/migrations/0005_auto_20181008_0602.py index e35b95660..3a6f42805 100644 --- a/ietf/nomcom/migrations/0005_auto_20181008_0602.py +++ b/ietf/nomcom/migrations/0005_auto_20181008_0602.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-10-08 06:02 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/nomcom/models.py b/ietf/nomcom/models.py index 9429d2541..8f8901e83 100644 --- a/ietf/nomcom/models.py +++ b/ietf/nomcom/models.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved # -*- coding: utf-8 -*- import os @@ -108,7 +109,7 @@ class Nomination(models.Model): verbose_name_plural = 'Nominations' def __unicode__(self): - return u"%s (%s)" % (self.candidate_name, self.candidate_email) + return "%s (%s)" % (self.candidate_name, self.candidate_email) class Nominee(models.Model): @@ -128,13 +129,13 @@ class Nominee(models.Model): def __unicode__(self): if self.email.person and self.email.person.name: - return u'%s <%s> %s' % (self.email.person.plain_name(), self.email.address, self.nomcom.year()) + return '%s <%s> %s' % (self.email.person.plain_name(), self.email.address, self.nomcom.year()) else: - return u'%s %s' % (self.email.address, self.nomcom.year()) + return '%s %s' % (self.email.address, self.nomcom.year()) def name(self): if self.email.person and self.email.person.name: - return u'%s' % (self.email.person.plain_name(),) + return '%s' % (self.email.person.plain_name(),) else: return self.email.address @@ -159,7 +160,7 @@ class NomineePosition(models.Model): super(NomineePosition, self).save(**kwargs) def __unicode__(self): - return u"%s - %s - %s" % (self.nominee, self.state, self.position) + return "%s - %s - %s" % (self.nominee, self.state, self.position) @property def questionnaires(self): @@ -257,7 +258,7 @@ class Feedback(models.Model): objects = FeedbackManager() def __unicode__(self): - return u"from %s" % self.author + return "from %s" % self.author class Meta: ordering = ['time'] diff --git a/ietf/nomcom/tests.py b/ietf/nomcom/tests.py index a6d312a0d..6785e3b05 100644 --- a/ietf/nomcom/tests.py +++ b/ietf/nomcom/tests.py @@ -1,9 +1,10 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved # -*- coding: utf-8 -*- #import tempfile import datetime import random import shutil -import urlparse +import urllib.parse from pyquery import PyQuery from django.db import IntegrityError @@ -175,10 +176,10 @@ class NomcomViewsTest(TestCase): def test_private_merge_view(self): """Verify private nominee merge view""" - nominees = [u'nominee0@example.com', - u'nominee1@example.com', - u'nominee2@example.com', - u'nominee3@example.com'] + nominees = ['nominee0@example.com', + 'nominee1@example.com', + 'nominee2@example.com', + 'nominee3@example.com'] # do nominations login_testing_unauthorized(self, COMMUNITY_USER, self.public_nominate_url) @@ -333,7 +334,7 @@ class NomcomViewsTest(TestCase): response = self.client.post(self.private_merge_nominee_url, test_data) self.assertEqual(response.status_code, 302) redirect_url = response["Location"] - redirect_path = urlparse.urlparse(redirect_url).path + redirect_path = urllib.parse.urlparse(redirect_url).path self.assertEqual(redirect_path, reverse('ietf.nomcom.views.private_index', kwargs={"year": NOMCOM_YEAR})) response = self.client.get(redirect_url) @@ -369,16 +370,16 @@ class NomcomViewsTest(TestCase): # Check nominations state self.assertEqual(NomineePosition.objects.get(position__name='TSV', - nominee=nominee).state.slug, u'accepted') + nominee=nominee).state.slug, 'accepted') self.assertEqual(NomineePosition.objects.get(position__name='IAOC', - nominee=nominee).state.slug, u'accepted') + nominee=nominee).state.slug, 'accepted') self.assertEqual(NomineePosition.objects.get(position__name='IAB', - nominee=nominee).state.slug, u'declined') + nominee=nominee).state.slug, 'declined') self.client.logout() def change_members(self, members): - members_emails = u','.join(['%s%s' % (member, EMAIL_DOMAIN) for member in members]) + members_emails = ','.join(['%s%s' % (member, EMAIL_DOMAIN) for member in members]) test_data = {'members': members_emails,} self.client.post(self.edit_members_url, test_data) @@ -421,7 +422,7 @@ class NomcomViewsTest(TestCase): nominee = Nominee.objects.get(email__person__user__username=COMMUNITY_USER) position = Position.objects.get(name='OAM') - comments = u'Plain text. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' + comments = 'Plain text. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' nomcom = get_nomcom_by_year(self.year) feedback = Feedback.objects.create(nomcom=nomcom, comments=comments, @@ -436,7 +437,7 @@ class NomcomViewsTest(TestCase): # Check that the set reminder date is present reminder_dates = dict([ (d.id,str(d.date)) for d in nomcom.reminderdates_set.all() ]) - self.assertIn(reminder_date, reminder_dates.values()) + self.assertIn(reminder_date, list(reminder_dates.values())) # Remove reminder date q = PyQuery(response.content) # from previous post @@ -444,14 +445,14 @@ class NomcomViewsTest(TestCase): 'reminderdates_set-TOTAL_FORMS': q('input[name="reminderdates_set-TOTAL_FORMS"]').val(), 'reminderdates_set-INITIAL_FORMS': q('input[name="reminderdates_set-INITIAL_FORMS"]').val(), 'reminderdates_set-MAX_NUM_FORMS': q('input[name="reminderdates_set-MAX_NUM_FORMS"]').val(), - 'reminderdates_set-0-id': str(reminder_dates.keys()[0]), + 'reminderdates_set-0-id': str(list(reminder_dates.keys())[0]), 'reminderdates_set-0-date': '', }) self.assertEqual(r.status_code, 200) # Check that reminder date has been removed reminder_dates = dict([ (d.id,str(d.date)) for d in ReminderDates.objects.filter(nomcom=nomcom) ]) - self.assertNotIn(reminder_date, reminder_dates.values()) + self.assertNotIn(reminder_date, list(reminder_dates.values())) self.client.logout() @@ -519,7 +520,7 @@ class NomcomViewsTest(TestCase): self.assertEqual('Nomination receipt', outbox[-1]['Subject']) self.assertEqual(self.email_from, outbox[-1]['From']) self.assertIn('plain', outbox[-1]['To']) - self.assertIn(u'Comments with accents äöå', unicode(outbox[-1].get_payload(decode=True),"utf-8","replace")) + self.assertIn('Comments with accents äöå', str(outbox[-1].get_payload(decode=True),"utf-8","replace")) # Nominate the same person for the same position again without asking for confirmation @@ -560,7 +561,7 @@ class NomcomViewsTest(TestCase): self.assertEqual('Nomination receipt', outbox[-1]['Subject']) self.assertEqual(self.email_from, outbox[-1]['From']) self.assertIn('plain', outbox[-1]['To']) - self.assertIn(u'Comments with accents äöå', unicode(outbox[-1].get_payload(decode=True),"utf-8","replace")) + self.assertIn('Comments with accents äöå', str(outbox[-1].get_payload(decode=True),"utf-8","replace")) # Nominate the same person for the same position again without asking for confirmation @@ -594,7 +595,7 @@ class NomcomViewsTest(TestCase): def nominate_view(self, *args, **kwargs): public = kwargs.pop('public', True) searched_email = kwargs.pop('searched_email', None) - nominee_email = kwargs.pop('nominee_email', u'nominee@example.com') + nominee_email = kwargs.pop('nominee_email', 'nominee@example.com') if not searched_email: searched_email = Email.objects.filter(address=nominee_email).first() if not searched_email: @@ -628,8 +629,8 @@ class NomcomViewsTest(TestCase): self.assertEqual(len(q("#nominate-form")), 1) position = Position.objects.get(name=position_name) - comments = u'Test nominate view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' - candidate_phone = u'123456' + comments = 'Test nominate view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' + candidate_phone = '123456' test_data = {'searched_email': searched_email.pk, 'candidate_phone': candidate_phone, @@ -667,7 +668,7 @@ class NomcomViewsTest(TestCase): def nominate_newperson_view(self, *args, **kwargs): public = kwargs.pop('public', True) - nominee_email = kwargs.pop('nominee_email', u'nominee@example.com') + nominee_email = kwargs.pop('nominee_email', 'nominee@example.com') nominator_email = kwargs.pop('nominator_email', "%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN)) position_name = kwargs.pop('position', 'IAOC') confirmation = kwargs.pop('confirmation', False) @@ -695,9 +696,9 @@ class NomcomViewsTest(TestCase): position = Position.objects.get(name=position_name) candidate_email = nominee_email - candidate_name = u'nominee' - comments = u'Test nominate view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' - candidate_phone = u'123456' + candidate_name = 'nominee' + comments = 'Test nominate view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' + candidate_phone = '123456' test_data = {'candidate_name': candidate_name, 'candidate_email': candidate_email, @@ -744,7 +745,7 @@ class NomcomViewsTest(TestCase): def add_questionnaire(self, *args, **kwargs): public = kwargs.pop('public', False) - nominee_email = kwargs.pop('nominee_email', u'nominee@example.com') + nominee_email = kwargs.pop('nominee_email', 'nominee@example.com') nominator_email = kwargs.pop('nominator_email', "%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN)) position_name = kwargs.pop('position', 'IAOC') @@ -771,7 +772,7 @@ class NomcomViewsTest(TestCase): position = Position.objects.get(name=position_name) nominee = Nominee.objects.get(email__address=nominee_email) - comments = u'Test add questionnaire view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' + comments = 'Test add questionnaire view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' test_data = {'comments': comments, 'nominee': '%s_%s' % (position.id, nominee.id)} @@ -806,7 +807,7 @@ class NomcomViewsTest(TestCase): self.assertNotIn('$', email_body) self.assertEqual(self.email_from, outbox[-2]['From']) self.assertIn('plain', outbox[2]['To']) - self.assertIn(u'Comments with accents äöå', unicode(outbox[2].get_payload(decode=True),"utf-8","replace")) + self.assertIn('Comments with accents äöå', str(outbox[2].get_payload(decode=True),"utf-8","replace")) empty_outbox() self.feedback_view(public=True) @@ -819,7 +820,7 @@ class NomcomViewsTest(TestCase): def feedback_view(self, *args, **kwargs): public = kwargs.pop('public', True) - nominee_email = kwargs.pop('nominee_email', u'nominee@example.com') + nominee_email = kwargs.pop('nominee_email', 'nominee@example.com') nominator_email = kwargs.pop('nominator_email', "%s%s" % (COMMUNITY_USER, EMAIL_DOMAIN)) position_name = kwargs.pop('position', 'IAOC') confirmation = kwargs.pop('confirmation', False) @@ -856,7 +857,7 @@ class NomcomViewsTest(TestCase): self.assertEqual(response.status_code, 200) self.assertContains(response, "feedbackform") - comments = u'Test feedback view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' + comments = 'Test feedback view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' test_data = {'comments': comments, 'position_name': position.name, @@ -960,7 +961,7 @@ class FeedbackTest(TestCase): #nomcom.public_key.storage.location = tempfile.gettempdir() nomcom.public_key.save('cert', File(open(self.cert_file.name, 'r'))) - comments = u'Plain text. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' + comments = 'Plain text. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.' feedback = Feedback.objects.create(nomcom=nomcom, comments=comments, type=FeedbackTypeName.objects.get(slug='nomina')) @@ -989,8 +990,8 @@ class ReminderTest(TestCase): today = datetime.date.today() t_minus_3 = today - datetime.timedelta(days=3) t_minus_4 = today - datetime.timedelta(days=4) - e1 = EmailFactory(address="nominee1@example.org", person=PersonFactory(name=u"Nominee 1"), origin='test') - e2 = EmailFactory(address="nominee2@example.org", person=PersonFactory(name=u"Nominee 2"), origin='test') + e1 = EmailFactory(address="nominee1@example.org", person=PersonFactory(name="Nominee 1"), origin='test') + e2 = EmailFactory(address="nominee2@example.org", person=PersonFactory(name="Nominee 2"), origin='test') n = make_nomineeposition(self.nomcom,e1.person,gen,None) np = n.nomineeposition_set.get(position=gen) np.time = t_minus_3 @@ -1103,7 +1104,7 @@ class InactiveNomcomTests(TestCase): empty_outbox() fb_before = self.nc.feedback_set.count() - test_data = {'comments': u'Test feedback view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.', + test_data = {'comments': 'Test feedback view. Comments with accents äöåÄÖÅ éáíóú âêîôû ü àèìòù.', 'nominator_email': self.plain_person.email_set.first().address, 'confirmation': True} response = self.client.post(url, test_data) diff --git a/ietf/nomcom/utils.py b/ietf/nomcom/utils.py index c95b5cd57..43be9b204 100644 --- a/ietf/nomcom/utils.py +++ b/ietf/nomcom/utils.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import datetime import hashlib import os @@ -399,9 +400,9 @@ def getheader(header_text, default="ascii"): """Decode the specified header""" headers = decode_header(header_text) - header_sections = [unicode(text, charset or default) + header_sections = [str(text, charset or default) for text, charset in headers] - return u"".join(header_sections) + return "".join(header_sections) def get_charset(message, default="ascii"): @@ -427,22 +428,22 @@ def get_body(message): body = [] for part in text_parts: charset = get_charset(part, get_charset(message)) - body.append(unicode(part.get_payload(decode=True), + body.append(str(part.get_payload(decode=True), charset, "replace")) - return u"\n".join(body).strip() + return "\n".join(body).strip() else: # if it is not multipart, the payload will be a string # representing the message body - body = unicode(message.get_payload(decode=True), + body = str(message.get_payload(decode=True), get_charset(message), "replace") return body.strip() def parse_email(text): - if isinstance(text, unicode): + if isinstance(text, str): text = smart_str(text) msg = message_from_string(text) diff --git a/ietf/nomcom/views.py b/ietf/nomcom/views.py index ba4a7f140..2da08cf68 100644 --- a/ietf/nomcom/views.py +++ b/ietf/nomcom/views.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import datetime import re from collections import OrderedDict, Counter @@ -179,7 +180,7 @@ def private_index(request, year): 'position__id':p.pk, 'position': p, } for p in positions] - states = list(NomineePositionStateName.objects.values('slug', 'name')) + [{'slug': questionnaire_state, 'name': u'Questionnaire'}] + states = list(NomineePositionStateName.objects.values('slug', 'name')) + [{'slug': questionnaire_state, 'name': 'Questionnaire'}] positions = set([ n.position for n in all_nominee_positions.order_by('position__name') ]) for s in stats: for state in states: diff --git a/ietf/person/factories.py b/ietf/person/factories.py index 627c9ed6a..e92b132c6 100644 --- a/ietf/person/factories.py +++ b/ietf/person/factories.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2014-2018, All Rights Reserved +# Copyright The IETF Trust 2015-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import os import factory @@ -53,11 +53,11 @@ class PersonFactory(factory.DjangoModelFactory): model = Person user = factory.SubFactory(UserFactory) - name = factory.LazyAttribute(lambda p: normalize_name(u'%s %s'%(p.user.first_name, p.user.last_name))) - ascii = factory.LazyAttribute(lambda p: unicode(unidecode_name(p.name))) + name = factory.LazyAttribute(lambda p: normalize_name('%s %s'%(p.user.first_name, p.user.last_name))) + ascii = factory.LazyAttribute(lambda p: str(unidecode_name(p.name))) class Params: - with_bio = factory.Trait(biography = u"\n\n".join(fake.paragraphs())) + with_bio = factory.Trait(biography = "\n\n".join(fake.paragraphs())) @factory.post_generation def default_aliases(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument @@ -82,7 +82,7 @@ class PersonFactory(factory.DjangoModelFactory): import atexit if obj.biography: photo_name = obj.photo_name() - media_name = u"%s/%s.jpg" % (settings.PHOTOS_DIRNAME, photo_name) + media_name = "%s/%s.jpg" % (settings.PHOTOS_DIRNAME, photo_name) obj.photo = media_name obj.photo_thumb = media_name photosrc = os.path.join(settings.TEST_DATA_DIR, "profile-default.jpg") diff --git a/ietf/person/fields.py b/ietf/person/fields.py index 1800179d1..c0c81c6be 100644 --- a/ietf/person/fields.py +++ b/ietf/person/fields.py @@ -1,8 +1,9 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import json import six from collections import Counter -from urllib import urlencode +from urllib.parse import urlencode from django.utils.html import escape from django import forms @@ -14,7 +15,7 @@ from ietf.person.models import Email, Person def select2_id_name_json(objs): def format_email(e): - return escape(u"%s <%s>" % (e.person.name, e.address)) + return escape("%s <%s>" % (e.person.name, e.address)) def format_person(p): if p.name_count > 1: return escape('%s (%s)' % (p.name,p.email().address if p.email() else 'no email address')) @@ -73,7 +74,7 @@ class SearchablePersonsField(forms.CharField): def prepare_value(self, value): if not value: value = "" - if isinstance(value, basestring): + if isinstance(value, str): pks = self.parse_select2_value(value) if self.model == Person: value = self.model.objects.filter(pk__in=pks) @@ -95,7 +96,7 @@ class SearchablePersonsField(forms.CharField): if query_args: self.widget.attrs["data-ajax-url"] += "?%s" % urlencode(query_args) - return u",".join(str(p.pk) for p in value) + return ",".join(str(p.pk) for p in value) def clean(self, value): value = super(SearchablePersonsField, self).clean(value) @@ -112,10 +113,10 @@ class SearchablePersonsField(forms.CharField): found_pks = [ six.text_type(o.pk) for o in objs] failed_pks = [x for x in pks if x not in found_pks] if failed_pks: - raise forms.ValidationError(u"Could not recognize the following {model_name}s: {pks}. You can only input {model_name}s already registered in the Datatracker.".format(pks=", ".join(failed_pks), model_name=self.model.__name__.lower())) + raise forms.ValidationError("Could not recognize the following {model_name}s: {pks}. You can only input {model_name}s already registered in the Datatracker.".format(pks=", ".join(failed_pks), model_name=self.model.__name__.lower())) if self.max_entries != None and len(objs) > self.max_entries: - raise forms.ValidationError(u"You can select at most %s entries only." % self.max_entries) + raise forms.ValidationError("You can select at most %s entries only." % self.max_entries) return objs @@ -162,9 +163,9 @@ class PersonEmailChoiceField(forms.ModelChoiceField): def label_from_instance(self, email): if self.label_with == "person": - return unicode(email.person) + return str(email.person) elif self.label_with == "email": return email.address else: - return u"{} <{}>".format(email.person, email.address) + return "{} <{}>".format(email.person, email.address) diff --git a/ietf/person/forms.py b/ietf/person/forms.py index aa7015b5c..2759c2ea7 100644 --- a/ietf/person/forms.py +++ b/ietf/person/forms.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2018-2019, All Rights Reserved + -from __future__ import unicode_literals from django import forms from ietf.person.models import Person diff --git a/ietf/person/management/commands/deactivate_email_addresses.py b/ietf/person/management/commands/deactivate_email_addresses.py index 0218630ed..e5ec9e348 100644 --- a/ietf/person/management/commands/deactivate_email_addresses.py +++ b/ietf/person/management/commands/deactivate_email_addresses.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import flufl.bounce import mailbox @@ -18,7 +18,7 @@ from ietf.person.models import Email, PersonEvent class Command(BaseCommand): - help = (u""" + help = (""" Deactivate bouncing email addresses. Take one or more email addresses to deactivate from the command line, diff --git a/ietf/person/migrations/0001_initial.py b/ietf/person/migrations/0001_initial.py index f04d7b4e4..f406c4221 100644 --- a/ietf/person/migrations/0001_initial.py +++ b/ietf/person/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import datetime from django.conf import settings diff --git a/ietf/person/migrations/0002_auto_20180330_0808.py b/ietf/person/migrations/0002_auto_20180330_0808.py index 6c852f67c..03ffc8363 100644 --- a/ietf/person/migrations/0002_auto_20180330_0808.py +++ b/ietf/person/migrations/0002_auto_20180330_0808.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.11 on 2018-03-30 08:08 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/person/migrations/0003_auto_20180504_1519.py b/ietf/person/migrations/0003_auto_20180504_1519.py index 7abd048e2..db7d6ca55 100644 --- a/ietf/person/migrations/0003_auto_20180504_1519.py +++ b/ietf/person/migrations/0003_auto_20180504_1519.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.12 on 2018-05-04 15:19 -from __future__ import unicode_literals + import datetime from django.conf import settings diff --git a/ietf/person/migrations/0004_populate_email_origin.py b/ietf/person/migrations/0004_populate_email_origin.py index 3d30f9abb..55a926665 100644 --- a/ietf/person/migrations/0004_populate_email_origin.py +++ b/ietf/person/migrations/0004_populate_email_origin.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.12 on 2018-05-10 05:28 -from __future__ import unicode_literals + import sys diff --git a/ietf/person/migrations/0005_populate_person_name_from_draft.py b/ietf/person/migrations/0005_populate_person_name_from_draft.py index 62caa3868..3eb26ce63 100644 --- a/ietf/person/migrations/0005_populate_person_name_from_draft.py +++ b/ietf/person/migrations/0005_populate_person_name_from_draft.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.12 on 2018-05-10 05:28 -from __future__ import unicode_literals + import sys diff --git a/ietf/person/migrations/0006_auto_20180910_0719.py b/ietf/person/migrations/0006_auto_20180910_0719.py index cfdb07b6e..44d280305 100644 --- a/ietf/person/migrations/0006_auto_20180910_0719.py +++ b/ietf/person/migrations/0006_auto_20180910_0719.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.13 on 2018-09-10 07:19 -from __future__ import unicode_literals + from django.conf import settings from django.db import migrations diff --git a/ietf/person/migrations/0007_auto_20180929_1303.py b/ietf/person/migrations/0007_auto_20180929_1303.py index c8440c6a5..de1b3660f 100644 --- a/ietf/person/migrations/0007_auto_20180929_1303.py +++ b/ietf/person/migrations/0007_auto_20180929_1303.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-29 13:03 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/person/migrations/0008_auto_20181014_1448.py b/ietf/person/migrations/0008_auto_20181014_1448.py index 8c0292974..8a7116e8a 100644 --- a/ietf/person/migrations/0008_auto_20181014_1448.py +++ b/ietf/person/migrations/0008_auto_20181014_1448.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-10-14 14:48 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/person/migrations/0009_auto_20190118_0725.py b/ietf/person/migrations/0009_auto_20190118_0725.py index e3a1e4233..24c6148b4 100644 --- a/ietf/person/migrations/0009_auto_20190118_0725.py +++ b/ietf/person/migrations/0009_auto_20190118_0725.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-18 07:25 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/person/models.py b/ietf/person/models.py index d0159c69c..ef0ea7b3d 100644 --- a/ietf/person/models.py +++ b/ietf/person/models.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2010-2019, All Rights Reserved import datetime import email.utils @@ -7,7 +7,7 @@ import six import uuid from hashids import Hashids -from urlparse import urljoin +from urllib.parse import urljoin from django.conf import settings @@ -83,7 +83,7 @@ class Person(models.Model): else: ascii = unidecode_name(self.name) prefix, first, middle, last, suffix = name_parts(ascii) - self._cached_plain_ascii = u" ".join([first, last]) + self._cached_plain_ascii = " ".join([first, last]) return self._cached_plain_ascii def initials(self): return initials(self.ascii or self.name) @@ -96,7 +96,7 @@ class Person(models.Model): may be an object or the group acronym.""" if group: from ietf.group.models import Group - if isinstance(group, str) or isinstance(group, unicode): + if isinstance(group, str) or isinstance(group, str): group = Group.objects.get(acronym=group) e = Email.objects.filter(person=self, role__group=group, role__name=role_name) else: @@ -144,7 +144,7 @@ class Person(models.Model): def photo_name(self,thumb=False): hasher = Hashids(salt='Person photo name salt',min_length=5) _, first, _, last, _ = name_parts(self.ascii) - return u'%s-%s%s' % ( slugify(u"%s %s" % (first, last)), hasher.encode(self.id), '-th' if thumb else '' ) + return '%s-%s%s' % ( slugify("%s %s" % (first, last)), hasher.encode(self.id), '-th' if thumb else '' ) def has_drafts(self): from ietf.doc.models import Document @@ -281,9 +281,9 @@ class Email(models.Model): Use self.formatted_email() for that. """ if self.person: - return u"%s <%s>" % (self.person.plain_name(), self.address) + return "%s <%s>" % (self.person.plain_name(), self.address) else: - return u"<%s>" % self.address + return "<%s>" % self.address def formatted_email(self): """ @@ -376,7 +376,7 @@ class PersonEvent(models.Model): desc = models.TextField() def __unicode__(self): - return u"%s %s at %s" % (self.person.plain_name(), self.get_type_display().lower(), self.time) + return "%s %s at %s" % (self.person.plain_name(), self.get_type_display().lower(), self.time) class Meta: ordering = ['-time', '-id'] diff --git a/ietf/person/name.py b/ietf/person/name.py index 4c16256a5..e01f0c343 100644 --- a/ietf/person/name.py +++ b/ietf/person/name.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import re import unidecode @@ -8,7 +9,7 @@ def name_particle_match(name): return re.search(r" (af|al|Al|de|der|di|Di|du|el|El|Hadi|in 't|Le|st\.?|St\.?|ten|ter|van|van der|van 't|Van|von|von der|Von|zu) ", name) def name_parts(name): - prefix, first, middle, last, suffix = u"", u"", u"", u"", u"" + prefix, first, middle, last, suffix = "", "", "", "", "" if not name.strip(): return prefix, first, middle, last, suffix @@ -36,7 +37,7 @@ def name_parts(name): parts = parts[:-1] if len(parts) > 2: # Check if we have a surname with nobiliary particle - full = u" ".join(parts) + full = " ".join(parts) if full.upper() == full: full = full.lower() # adjust case for all-uppercase input # This is an incomplete list. Adjust as needed to handle known ietf @@ -48,7 +49,7 @@ def name_parts(name): if len(parts) > 2: first = parts[0] last = parts[-1] - middle = u" ".join(parts[1:-1]) + middle = " ".join(parts[1:-1]) elif len(parts) == 2: first, last = parts else: @@ -63,16 +64,16 @@ def initials(name): prefix, first, middle, last, suffix = name_parts(name) given = first if middle: - given += u" "+middle + given += " "+middle # Don't use non-word characters as initials. # Example: The Bulgarian transcribed name "'Rnest Balkanska" should not have an initial of "'". given = re.sub('[^ .\w]', '', given) - initials = u" ".join([ n[0].upper()+'.' for n in given.split() ]) + initials = " ".join([ n[0].upper()+'.' for n in given.split() ]) return initials def plain_name(name): prefix, first, middle, last, suffix = name_parts(name) - return u" ".join( n for n in (first, last) if n) + return " ".join( n for n in (first, last) if n) def capfirst(s): # Capitalize the first word character, skipping non-word characters and @@ -127,7 +128,7 @@ def normalize_name(s): if __name__ == "__main__": import sys - name = u" ".join(sys.argv[1:]) - print name_parts(name) - print initials(name) + name = " ".join(sys.argv[1:]) + print(name_parts(name)) + print(initials(name)) diff --git a/ietf/person/tests.py b/ietf/person/tests.py index 7224a7051..75605de32 100644 --- a/ietf/person/tests.py +++ b/ietf/person/tests.py @@ -1,10 +1,11 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + import datetime import json from pyquery import PyQuery -from StringIO import StringIO +from io import StringIO from django.urls import reverse as urlreverse import debug # pyflakes:ignore @@ -68,28 +69,28 @@ class PersonTests(TestCase): self.assertEqual(r.status_code, 200) def test_name_methods(self): - person = PersonFactory(name=u"Dr. Jens F. Möller", ) + person = PersonFactory(name="Dr. Jens F. Möller", ) - self.assertEqual(person.name, u"Dr. Jens F. Möller" ) - self.assertEqual(person.ascii_name(), u"Dr. Jens F. Moller" ) - self.assertEqual(person.plain_name(), u"Jens Möller" ) - self.assertEqual(person.plain_ascii(), u"Jens Moller" ) - self.assertEqual(person.initials(), u"J. F.") - self.assertEqual(person.first_name(), u"Jens" ) - self.assertEqual(person.last_name(), u"Möller" ) + self.assertEqual(person.name, "Dr. Jens F. Möller" ) + self.assertEqual(person.ascii_name(), "Dr. Jens F. Moller" ) + self.assertEqual(person.plain_name(), "Jens Möller" ) + self.assertEqual(person.plain_ascii(), "Jens Moller" ) + self.assertEqual(person.initials(), "J. F.") + self.assertEqual(person.first_name(), "Jens" ) + self.assertEqual(person.last_name(), "Möller" ) - person = PersonFactory(name=u"吴建平") + person = PersonFactory(name="吴建平") # The following are probably incorrect because the given name should # be Jianping and the surname should be Wu ... # TODO: Figure out better handling for names with CJK characters. # Maybe use ietf.person.cjk.* - self.assertEqual(person.ascii_name(), u"Wu Jian Ping") + self.assertEqual(person.ascii_name(), "Wu Jian Ping") def test_duplicate_person_name(self): empty_outbox() p = PersonFactory(name="Föö Bär") PersonFactory(name=p.name) - self.assertTrue("possible duplicate" in unicode(outbox[0]["Subject"]).lower()) + self.assertTrue("possible duplicate" in str(outbox[0]["Subject"]).lower()) def test_merge(self): url = urlreverse("ietf.person.views.merge") diff --git a/ietf/person/utils.py b/ietf/person/utils.py index e72926123..9d250bc17 100755 --- a/ietf/person/utils.py +++ b/ietf/person/utils.py @@ -1,4 +1,5 @@ -from __future__ import unicode_literals, print_function +# Copyright The IETF Trust 2015-2019, All Rights Reserved + import datetime import os import pprint diff --git a/ietf/person/views.py b/ietf/person/views.py index da7b2f960..582b78337 100644 --- a/ietf/person/views.py +++ b/ietf/person/views.py @@ -1,5 +1,6 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import datetime -from StringIO import StringIO +from io import StringIO from django.contrib import messages from django.db.models import Q @@ -109,7 +110,7 @@ def merge(request): output = StringIO() success, changes = merge_persons(source, target, file=output) if success: - messages.success(request, u'Merged {} ({}) to {} ({}). {})'.format( + messages.success(request, 'Merged {} ({}) to {} ({}). {})'.format( source.name, source_id, target.name, target.id, changes)) else: messages.error(request, output) diff --git a/ietf/redirects/tests.py b/ietf/redirects/tests.py index 4b8aec2c5..257c12b59 100644 --- a/ietf/redirects/tests.py +++ b/ietf/redirects/tests.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved # Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen # @@ -92,7 +93,7 @@ class RedirectsTests(TestCase): fixtures = ["initial_data.xml", ] def test_redirects(self): - for src, dst in REDIRECT_TESTS.items(): + for src, dst in list(REDIRECT_TESTS.items()): baseurl, args = split_url(src) response = self.client.get(baseurl, args) self.assertTrue(str(response.status_code).startswith("3")) diff --git a/ietf/redirects/views.py b/ietf/redirects/views.py index 3f4bc8520..7258ea880 100644 --- a/ietf/redirects/views.py +++ b/ietf/redirects/views.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved from django.http import HttpResponsePermanentRedirect, Http404, BadHeaderError from django.shortcuts import get_object_or_404 @@ -28,7 +28,7 @@ def redirect(request, path="", script=""): if len(fc) > 1: if rparam.get('command') != fc[1]: continue - if rparam.has_key(fc[0]): + if fc[0] in rparam: remove_args.append(fc[0]) num = re.match('(\d+)', rparam[fc[0]]) if (num and int(num.group(1))) or (num is None): @@ -84,7 +84,7 @@ def redirect(request, path="", script=""): get = request.GET.copy() remove_args += re.findall(r'%\(([^)]+)\)', rest) for arg in remove_args: - if get.has_key(arg): + if arg in get: get.pop(arg) if get: url += '?' + get.urlencode() diff --git a/ietf/release/tests.py b/ietf/release/tests.py index b03d85292..fa91c33ab 100644 --- a/ietf/release/tests.py +++ b/ietf/release/tests.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2012-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + from pyquery import PyQuery diff --git a/ietf/release/urls.py b/ietf/release/urls.py index d33fcbb73..01b90d95e 100644 --- a/ietf/release/urls.py +++ b/ietf/release/urls.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2015-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + from django.views.generic import TemplateView diff --git a/ietf/release/views.py b/ietf/release/views.py index faf560c64..86b4d04e9 100644 --- a/ietf/release/views.py +++ b/ietf/release/views.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2012-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import os import re diff --git a/ietf/review/admin.py b/ietf/review/admin.py index 4fbe41059..3d2541bf3 100644 --- a/ietf/review/admin.py +++ b/ietf/review/admin.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved import simple_history from django.contrib import admin @@ -17,7 +18,7 @@ class ReviewerSettingsAdmin(simple_history.admin.SimpleHistoryAdmin): admin.site.register(ReviewerSettings, ReviewerSettingsAdmin) class ReviewSecretarySettingsAdmin(admin.ModelAdmin): - list_display = [u'id', 'team', 'person', 'remind_days_before_deadline'] + list_display = ['id', 'team', 'person', 'remind_days_before_deadline'] raw_id_fields = ['team', 'person'] admin.site.register(ReviewSecretarySettings, ReviewSecretarySettingsAdmin) diff --git a/ietf/review/mailarch.py b/ietf/review/mailarch.py index 025146f27..13582503c 100644 --- a/ietf/review/mailarch.py +++ b/ietf/review/mailarch.py @@ -1,9 +1,10 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved # various utilities for working with the mailarch mail archive at # mailarchive.ietf.org import datetime, tarfile, mailbox, tempfile, hashlib, base64, email.utils -import urllib -import urllib2, contextlib +import urllib.request, urllib.parse, urllib.error +import urllib.request, urllib.error, urllib.parse, contextlib import debug # pyflakes:ignore import debug # pyflakes:ignore @@ -34,7 +35,7 @@ def construct_query_urls(review_req, query=None): if not query: query = review_req.doc.name - encoded_query = "?" + urllib.urlencode({ + encoded_query = "?" + urllib.parse.urlencode({ "qdr": "c", # custom time frame "start_date": (datetime.date.today() - datetime.timedelta(days=180)).isoformat(), "email_list": list_name, @@ -63,7 +64,7 @@ def retrieve_messages_from_mbox(mbox_fileobj): mbox = mailbox.mbox(mbox_file.name, create=False) for msg in mbox: - content = u"" + content = "" for part in msg.walk(): if part.get_content_type() == "text/plain": @@ -93,7 +94,7 @@ def retrieve_messages(query_data_url): """Retrieve and return selected content from mailarch.""" res = [] - with contextlib.closing(urllib2.urlopen(query_data_url, timeout=15)) as fileobj: + with contextlib.closing(urllib.request.urlopen(query_data_url, timeout=15)) as fileobj: content_type = fileobj.info()["Content-type"] if not content_type.startswith("application/x-tar"): if content_type.startswith("text/html"): diff --git a/ietf/review/migrations/0001_initial.py b/ietf/review/migrations/0001_initial.py index 33928e808..d9b618de3 100644 --- a/ietf/review/migrations/0001_initial.py +++ b/ietf/review/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import datetime from django.db import migrations, models diff --git a/ietf/review/migrations/0002_unavailableperiod_reason.py b/ietf/review/migrations/0002_unavailableperiod_reason.py index ac3f89973..046697e2f 100644 --- a/ietf/review/migrations/0002_unavailableperiod_reason.py +++ b/ietf/review/migrations/0002_unavailableperiod_reason.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.14 on 2018-07-23 15:11 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/review/migrations/0003_add_notify_ad_when.py b/ietf/review/migrations/0003_add_notify_ad_when.py index 8ad40f67a..26f7e3376 100644 --- a/ietf/review/migrations/0003_add_notify_ad_when.py +++ b/ietf/review/migrations/0003_add_notify_ad_when.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-11-02 10:10 -from __future__ import unicode_literals + from django.db import migrations, models import ietf.review.models diff --git a/ietf/review/migrations/0004_reviewteamsettings_secr_mail_alias.py b/ietf/review/migrations/0004_reviewteamsettings_secr_mail_alias.py index 3db6e7b66..315642947 100644 --- a/ietf/review/migrations/0004_reviewteamsettings_secr_mail_alias.py +++ b/ietf/review/migrations/0004_reviewteamsettings_secr_mail_alias.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-11-03 03:10 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/review/migrations/0005_set_secdir_notify_ad_when.py b/ietf/review/migrations/0005_set_secdir_notify_ad_when.py index 89421c849..aa4eeaed2 100644 --- a/ietf/review/migrations/0005_set_secdir_notify_ad_when.py +++ b/ietf/review/migrations/0005_set_secdir_notify_ad_when.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-11-02 10:20 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/review/migrations/0006_historicalreviewersettings.py b/ietf/review/migrations/0006_historicalreviewersettings.py index fe8704405..0d641d733 100644 --- a/ietf/review/migrations/0006_historicalreviewersettings.py +++ b/ietf/review/migrations/0006_historicalreviewersettings.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.16 on 2018-11-09 08:31 -from __future__ import unicode_literals + from django.conf import settings from django.db import migrations, models diff --git a/ietf/review/migrations/0007_allow_notify_ad_when_to_be_blank.py b/ietf/review/migrations/0007_allow_notify_ad_when_to_be_blank.py index ef6abc7ff..ba38a4478 100644 --- a/ietf/review/migrations/0007_allow_notify_ad_when_to_be_blank.py +++ b/ietf/review/migrations/0007_allow_notify_ad_when_to_be_blank.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.17 on 2018-12-06 13:16 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/review/migrations/0008_remove_reviewrequest_old_id.py b/ietf/review/migrations/0008_remove_reviewrequest_old_id.py index f2bc08577..5454b5eaa 100644 --- a/ietf/review/migrations/0008_remove_reviewrequest_old_id.py +++ b/ietf/review/migrations/0008_remove_reviewrequest_old_id.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.17 on 2019-01-03 12:34 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/review/migrations/0009_refactor_review_request.py b/ietf/review/migrations/0009_refactor_review_request.py index 766dc209e..642cf32a6 100644 --- a/ietf/review/migrations/0009_refactor_review_request.py +++ b/ietf/review/migrations/0009_refactor_review_request.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-04 14:27 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/review/migrations/0010_populate_review_assignments.py b/ietf/review/migrations/0010_populate_review_assignments.py index d8f38f24b..d254576be 100644 --- a/ietf/review/migrations/0010_populate_review_assignments.py +++ b/ietf/review/migrations/0010_populate_review_assignments.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.18 on 2019-01-04 14:34 -from __future__ import unicode_literals + import sys @@ -37,8 +38,8 @@ def forward(apps, schema_editor): sys.stderr.write('\n') # introduce a newline before tqdm starts writing for request in tqdm(ReviewRequest.objects.exclude(unused_reviewer__isnull=True)): assignment_state = map_request_state_to_assignment_state(request.state_id) - if not (assignment_state in (u'assigned', u'accepted', u'completed', u'no-response', u'overtaken', u'part-completed', u'rejected', u'withdrawn', u'unknown')): - print ("Trouble with review_request",request.pk,"with state",request.state_id) + if not (assignment_state in ('assigned', 'accepted', 'completed', 'no-response', 'overtaken', 'part-completed', 'rejected', 'withdrawn', 'unknown')): + print(("Trouble with review_request",request.pk,"with state",request.state_id)) exit(-1) ReviewAssignment.objects.create( review_request = request, diff --git a/ietf/review/migrations/0011_review_document2_fk.py b/ietf/review/migrations/0011_review_document2_fk.py index a18e178da..78cc4d87c 100644 --- a/ietf/review/migrations/0011_review_document2_fk.py +++ b/ietf/review/migrations/0011_review_document2_fk.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 11:58 # Copyright The IETF Trust 2019, All Rights Reserved -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/review/migrations/0012_remove_old_document_field.py b/ietf/review/migrations/0012_remove_old_document_field.py index 0028b6bb8..8f6971ce5 100644 --- a/ietf/review/migrations/0012_remove_old_document_field.py +++ b/ietf/review/migrations/0012_remove_old_document_field.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-20 09:53 # Copyright The IETF Trust 2019, All Rights Reserved -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/review/migrations/0013_rename_field_document2.py b/ietf/review/migrations/0013_rename_field_document2.py index a9ce514ea..ba9f556aa 100644 --- a/ietf/review/migrations/0013_rename_field_document2.py +++ b/ietf/review/migrations/0013_rename_field_document2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-21 05:31 # Copyright The IETF Trust 2019, All Rights Reserved -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/review/migrations/0014_document_primary_key_cleanup.py b/ietf/review/migrations/0014_document_primary_key_cleanup.py index d54fb3a9c..818782e4e 100644 --- a/ietf/review/migrations/0014_document_primary_key_cleanup.py +++ b/ietf/review/migrations/0014_document_primary_key_cleanup.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-06-10 03:47 # Copyright The IETF Trust 2019, All Rights Reserved -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/review/models.py b/ietf/review/models.py index 39373cd04..1206c439b 100644 --- a/ietf/review/models.py +++ b/ietf/review/models.py @@ -34,7 +34,7 @@ class ReviewerSettings(models.Model): expertise = models.TextField(verbose_name="Reviewer's expertise in this team's area", max_length=2048, blank=True, help_text="Describe the reviewer's expertise in this team's area", default='') def __unicode__(self): - return u"{} in {}".format(self.person, self.team) + return "{} in {}".format(self.person, self.team) class Meta: verbose_name_plural = "reviewer settings" @@ -46,7 +46,7 @@ class ReviewSecretarySettings(models.Model): remind_days_before_deadline = models.IntegerField(null=True, blank=True, help_text="To get an email reminder in case a reviewer forgets to do an assigned review, enter the number of days before review deadline you want to receive it. Clear the field if you don't want a reminder.") def __unicode__(self): - return u"{} in {}".format(self.person, self.team) + return "{} in {}".format(self.person, self.team) class Meta: verbose_name_plural = "review secretary settings" @@ -79,7 +79,7 @@ class UnavailablePeriod(models.Model): return "future" def __unicode__(self): - return u"{} is unavailable in {} {} - {}".format(self.person, self.team.acronym, self.start_date or "", self.end_date or "") + return "{} is unavailable in {} {} - {}".format(self.person, self.team.acronym, self.start_date or "", self.end_date or "") class ReviewWish(models.Model): """Reviewer wishes to review a document when it becomes available for review.""" @@ -89,7 +89,7 @@ class ReviewWish(models.Model): doc = ForeignKey(Document) def __unicode__(self): - return u"{} wishes to review {} in {}".format(self.person, self.doc.name, self.team.acronym) + return "{} wishes to review {} in {}".format(self.person, self.doc.name, self.team.acronym) class Meta: verbose_name_plural = "review wishes" @@ -100,7 +100,7 @@ class NextReviewerInTeam(models.Model): next_reviewer = ForeignKey(Person) def __unicode__(self): - return u"{} next in {}".format(self.next_reviewer, self.team) + return "{} next in {}".format(self.next_reviewer, self.team) class Meta: verbose_name = "next reviewer in team setting" @@ -122,7 +122,7 @@ class ReviewRequest(models.Model): comment = models.TextField(verbose_name="Requester's comments and instructions", max_length=2048, blank=True, help_text="Provide any additional information to show to the review team secretary and reviewer", default='') def __unicode__(self): - return u"%s review on %s by %s %s" % (self.type, self.doc, self.team, self.state) + return "%s review on %s by %s %s" % (self.type, self.doc, self.team, self.state) def all_completed_assignments_for_doc(self): return ReviewAssignment.objects.filter(review_request__doc=self.doc, state__in=['completed','part-completed']) @@ -143,7 +143,7 @@ class ReviewAssignment(models.Model): mailarch_url = models.URLField(blank=True, null = True) def __unicode__(self): - return u"Assignment for %s (%s) : %s %s of %s" % (self.reviewer.person, self.state, self.review_request.team.acronym, self.review_request.type, self.review_request.doc) + return "Assignment for %s (%s) : %s %s of %s" % (self.reviewer.person, self.state, self.review_request.team.acronym, self.review_request.type, self.review_request.doc) def get_default_review_types(): @@ -162,7 +162,7 @@ class ReviewTeamSettings(models.Model): secr_mail_alias = models.CharField(verbose_name="Email alias for all of the review team secretaries", max_length=255, blank=True, help_text="Email alias for all of the review team secretaries") def __unicode__(self): - return u"%s" % (self.group.acronym,) + return "%s" % (self.group.acronym,) class Meta: verbose_name = "Review team settings" diff --git a/ietf/review/utils.py b/ietf/review/utils.py index 3d2754423..6f6380c5f 100644 --- a/ietf/review/utils.py +++ b/ietf/review/utils.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Copyright The IETF Trust 2016-2019, All Rights Reserved -from __future__ import unicode_literals, print_function + import datetime, re, itertools @@ -128,12 +128,12 @@ def reviewer_rotation_list(team, skip_unavailable=False, dont_skip=[]): reviewers_to_skip = set() unavailable_periods = current_unavailable_periods_for_reviewers(team) - for person_id, periods in unavailable_periods.iteritems(): + for person_id, periods in unavailable_periods.items(): if periods and person_id not in dont_skip: reviewers_to_skip.add(person_id) days_needed_for_reviewers = days_needed_to_fulfill_min_interval_for_reviewers(team) - for person_id, days_needed in days_needed_for_reviewers.iteritems(): + for person_id, days_needed in days_needed_for_reviewers.items(): if person_id not in dont_skip: reviewers_to_skip.add(person_id) @@ -154,7 +154,7 @@ def days_needed_to_fulfill_min_interval_for_reviewers(team): now = datetime.datetime.now() res = {} - for person_id, latest_assignment_time in latest_assignments.iteritems(): + for person_id, latest_assignment_time in latest_assignments.items(): if latest_assignment_time is not None: min_interval = min_intervals.get(person_id) if min_interval is None: @@ -294,11 +294,11 @@ def sum_raw_review_assignment_aggregations(raw_aggregations): for raw_aggr in raw_aggregations: i_state_dict, i_late_state_dict, i_result_dict, i_assignment_to_closure_days_list, i_assignment_to_closure_days_count = raw_aggr - for s, v in i_state_dict.iteritems(): + for s, v in i_state_dict.items(): state_dict[s] += v - for s, v in i_late_state_dict.iteritems(): + for s, v in i_late_state_dict.items(): late_state_dict[s] += v - for r, v in i_result_dict.iteritems(): + for r, v in i_result_dict.items(): result_dict[r] += v assignment_to_closure_days_list.extend(i_assignment_to_closure_days_list) @@ -501,7 +501,7 @@ def assign_review_request_to_reviewer(request, review_req, reviewer, add_skip=Fa if prev_team_reviews.exists(): msg = msg + '\n\nThis team has completed other reviews of this document:\n' for assignment in prev_team_reviews: - msg += u'%s %s -%s %s\n'% ( + msg += '%s %s -%s %s\n'% ( assignment.completed_on.strftime('%d %b %Y'), assignment.reviewer.person.ascii, assignment.reviewed_rev or assignment.review_request.requested_rev, @@ -688,7 +688,7 @@ def suggested_review_requests_for_team(team): # filter those with existing explicit requests existing_requests = defaultdict(list) - for r in ReviewRequest.objects.filter(doc__id__in=requests.iterkeys(), team=team): + for r in ReviewRequest.objects.filter(doc__id__in=iter(requests.keys()), team=team): existing_requests[r.doc_id].append(r) def blocks(existing, request): @@ -706,7 +706,7 @@ def suggested_review_requests_for_team(team): return any([no_review_document, no_review_rev, pending, request_closed, some_assignment_completed]) - res = [r for r in requests.itervalues() + res = [r for r in requests.values() if not any(blocks(e, r) for e in existing_requests[r.doc_id])] res.sort(key=lambda r: (r.deadline, r.doc_id), reverse=True) return res @@ -719,7 +719,7 @@ def extract_revision_ordered_review_assignments_for_documents_and_replaced(revie replaces = extract_complete_replaces_ancestor_mapping_for_docs(names) assignments_for_each_doc = defaultdict(list) - replacement_name_set = set(e for l in replaces.itervalues() for e in l) | names + replacement_name_set = set(e for l in replaces.values() for e in l) | names for r in ( review_assignment_queryset.filter(review_request__doc__name__in=replacement_name_set) .order_by("-reviewed_rev","-assigned_on", "-id").iterator()): assignments_for_each_doc[r.review_request.doc.name].append(r) @@ -767,7 +767,7 @@ def extract_revision_ordered_review_requests_for_documents_and_replaced(review_r replaces = extract_complete_replaces_ancestor_mapping_for_docs(names) requests_for_each_doc = defaultdict(list) - for r in review_request_queryset.filter(doc__name__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-time", "-id").iterator(): + for r in review_request_queryset.filter(doc__name__in=set(e for l in replaces.values() for e in l) | names).order_by("-time", "-id").iterator(): requests_for_each_doc[r.doc.name].append(r) # now collect in breadth-first order to keep the revision order intact @@ -959,9 +959,9 @@ def make_assignment_choices(email_queryset, review_req): if stats: explanations.append(", ".join(stats)) - label = unicode(e.person) + label = str(e.person) if explanations: - label = u"{}: {}".format(label, u"; ".join(explanations)) + label = "{}: {}".format(label, "; ".join(explanations)) ranking.append({ "email": e, @@ -1026,10 +1026,10 @@ def review_assignments_needing_secretary_reminder(remind_date): if (deadline - remind_date).days == remind_days: assignment_pks[a_pk] = secretary_role_pk - review_assignments = { a.pk: a for a in ReviewAssignment.objects.filter(pk__in=assignment_pks.keys()).select_related("reviewer", "reviewer__person", "state", "review_request__team") } - secretary_roles = { r.pk: r for r in Role.objects.filter(pk__in=assignment_pks.values()).select_related("email", "person") } + review_assignments = { a.pk: a for a in ReviewAssignment.objects.filter(pk__in=list(assignment_pks.keys())).select_related("reviewer", "reviewer__person", "state", "review_request__team") } + secretary_roles = { r.pk: r for r in Role.objects.filter(pk__in=list(assignment_pks.values())).select_related("email", "person") } - return [ (review_assignments[a_pk], secretary_roles[secretary_role_pk]) for a_pk, secretary_role_pk in assignment_pks.iteritems() ] + return [ (review_assignments[a_pk], secretary_roles[secretary_role_pk]) for a_pk, secretary_role_pk in assignment_pks.items() ] def email_secretary_reminder(review_request, secretary_role): team = review_request.team diff --git a/ietf/secr/announcement/forms.py b/ietf/secr/announcement/forms.py index 6aaca732d..8be5044e2 100644 --- a/ietf/secr/announcement/forms.py +++ b/ietf/secr/announcement/forms.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved from django import forms from ietf.group.models import Group, Role @@ -37,7 +38,7 @@ def get_from_choices(user): if nomcom_choices: addresses = list(addresses) + nomcom_choices - return zip(addresses, addresses) + return list(zip(addresses, addresses)) def get_nomcom_choices(user): @@ -58,7 +59,7 @@ def get_nomcom_choices(user): def get_to_choices(): - return zip(TO_LIST,TO_LIST) + return list(zip(TO_LIST,TO_LIST)) # --------------------------------------------- @@ -96,7 +97,7 @@ class AnnounceForm(forms.ModelForm): self.initial['reply_to'] = 'ietf@ietf.org' if self.hidden: - for key in self.fields.keys(): + for key in list(self.fields.keys()): self.fields[key].widget = forms.HiddenInput() def clean(self): diff --git a/ietf/secr/console/tests.py b/ietf/secr/console/tests.py index 354be5fe0..2f686a9b1 100644 --- a/ietf/secr/console/tests.py +++ b/ietf/secr/console/tests.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved """ This file demonstrates two different styles of tests (one doctest and one unittest). These will both pass when you run "manage.py test". @@ -12,7 +13,7 @@ class SimpleTest(TestCase): """ Tests that 1 + 1 always equals 2. """ - self.failUnlessEqual(1 + 1, 2) + self.assertEqual(1 + 1, 2) __test__ = {"doctest": """ Another way to test that 1 + 1 is equal to 2. diff --git a/ietf/secr/drafts/forms.py b/ietf/secr/drafts/forms.py index 581e91bbf..076a43575 100644 --- a/ietf/secr/drafts/forms.py +++ b/ietf/secr/drafts/forms.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import re import os @@ -45,11 +46,11 @@ class DocumentField(forms.FileField): if self.filename: # validate filename if base[:-3] != self.filename: - raise forms.ValidationError, "Filename: %s doesn't match Draft filename." % base[:-3] + raise forms.ValidationError("Filename: %s doesn't match Draft filename." % base[:-3]) # validate revision next_revision = str(int(self.rev)+1).zfill(2) if base[-2:] != next_revision: - raise forms.ValidationError, "Expected revision # %s" % (next_revision) + raise forms.ValidationError("Expected revision # %s" % (next_revision)) return file @@ -217,7 +218,7 @@ class EmailForm(forms.Form): super(EmailForm, self).__init__(*args, **kwargs) if self.hidden: - for key in self.fields.keys(): + for key in list(self.fields.keys()): self.fields[key].widget = forms.HiddenInput() class ExtendForm(forms.Form): diff --git a/ietf/secr/drafts/views.py b/ietf/secr/drafts/views.py index f5c343b1b..5fbe61c1c 100644 --- a/ietf/secr/drafts/views.py +++ b/ietf/secr/drafts/views.py @@ -259,7 +259,7 @@ def authors(request, id): authors = draft.documentauthor_set.all() if authors: - order = authors.aggregate(Max('order')).values()[0] + 1 + order = list(authors.aggregate(Max('order')).values())[0] + 1 else: order = 1 DocumentAuthor.objects.create(document=draft, person=person, email=email, affiliation=affiliation, country=country, order=order) @@ -418,7 +418,7 @@ def email(request, id): # other problems with get_email_initial try: form = EmailForm(initial=get_email_initial(draft,action=action,input=data)) - except Exception, e: + except Exception as e: return render(request, 'drafts/error.html', { 'error': e},) return render(request, 'drafts/email.html', { diff --git a/ietf/secr/meetings/tests.py b/ietf/secr/meetings/tests.py index 897ce6a5e..fb63ceaf7 100644 --- a/ietf/secr/meetings/tests.py +++ b/ietf/secr/meetings/tests.py @@ -1,8 +1,9 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime import os import shutil from pyquery import PyQuery -from StringIO import StringIO +from io import StringIO import debug # pyflakes:ignore diff --git a/ietf/secr/proceedings/migrations/0001_initial.py b/ietf/secr/proceedings/migrations/0001_initial.py index cb55ea290..ff57ba5fe 100644 --- a/ietf/secr/proceedings/migrations/0001_initial.py +++ b/ietf/secr/proceedings/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/secr/proceedings/proc_utils.py b/ietf/secr/proceedings/proc_utils.py index a25777b68..d31c15eba 100644 --- a/ietf/secr/proceedings/proc_utils.py +++ b/ietf/secr/proceedings/proc_utils.py @@ -10,7 +10,7 @@ import datetime import os import re import subprocess -from urllib import urlencode +from urllib.parse import urlencode import debug # pyflakes:ignore diff --git a/ietf/secr/proceedings/views.py b/ietf/secr/proceedings/views.py index 571d159c2..1b0178d59 100644 --- a/ietf/secr/proceedings/views.py +++ b/ietf/secr/proceedings/views.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime import glob import itertools @@ -276,7 +277,7 @@ def recording_edit(request, meeting_num, name): by=request.user.person, doc=recording, rev=recording.rev, - desc=u'Changed URL to %s' % recording.external_url, + desc='Changed URL to %s' % recording.external_url, ) recording.save_with_history([e]) diff --git a/ietf/secr/rolodex/forms.py b/ietf/secr/rolodex/forms.py index eafcd5147..4c3351fcb 100644 --- a/ietf/secr/rolodex/forms.py +++ b/ietf/secr/rolodex/forms.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2013-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import re diff --git a/ietf/secr/sreq/forms.py b/ietf/secr/sreq/forms.py index af36026b0..6ed1ca4a9 100644 --- a/ietf/secr/sreq/forms.py +++ b/ietf/secr/sreq/forms.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved from django import forms import debug # pyflakes:ignore @@ -98,7 +99,7 @@ class SessionForm(forms.Form): self.fields['third_session'].initial = True if self.hidden: - for key in self.fields.keys(): + for key in list(self.fields.keys()): self.fields[key].widget = forms.HiddenInput() self.fields['resources'].widget = forms.MultipleHiddenInput() diff --git a/ietf/secr/sreq/tests.py b/ietf/secr/sreq/tests.py index 1327b57a0..ef7908011 100644 --- a/ietf/secr/sreq/tests.py +++ b/ietf/secr/sreq/tests.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved from django.urls import reverse import datetime @@ -176,14 +177,14 @@ class SubmitRequestCase(TestCase): r = self.client.post(url,post_data) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) - self.assertTrue('Confirm' in unicode(q("title"))) + self.assertTrue('Confirm' in str(q("title"))) # confirm post_data['submit'] = 'Submit' r = self.client.post(confirm_url,post_data) self.assertRedirects(r, reverse('ietf.secr.sreq.views.main')) self.assertEqual(len(outbox),len_before+1) notification = outbox[-1] - notification_payload = unicode(notification.get_payload(decode=True),"utf-8","replace") + notification_payload = str(notification.get_payload(decode=True),"utf-8","replace") session = Session.objects.get(meeting=meeting,group=group) self.assertEqual(session.resources.count(),1) self.assertEqual(session.people_constraints.count(),1) diff --git a/ietf/secr/sreq/views.py b/ietf/secr/sreq/views.py index af6edae9a..ef8ebfff9 100644 --- a/ietf/secr/sreq/views.py +++ b/ietf/secr/sreq/views.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime from django.conf import settings @@ -541,7 +542,7 @@ def new(request, acronym): # the "previous" querystring causes the form to be returned # pre-populated with data from last meeeting's session request - elif request.method == 'GET' and request.GET.has_key('previous'): + elif request.method == 'GET' and 'previous' in request.GET: previous_meeting = Meeting.objects.get(number=str(int(meeting.number) - 1)) previous_sessions = Session.objects.filter(meeting=previous_meeting,group=group).exclude(status__in=('notmeet','deleted')).order_by('id') if not previous_sessions: diff --git a/ietf/secr/telechat/views.py b/ietf/secr/telechat/views.py index c845d26ed..c78208ff1 100644 --- a/ietf/secr/telechat/views.py +++ b/ietf/secr/telechat/views.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved import datetime from django.contrib import messages @@ -43,7 +44,7 @@ def get_doc_list(agenda): Document objects in the order they appear in the agenda sections 1-3. ''' docs = [] - for num, section in sorted(agenda['sections'].iteritems()): + for num, section in sorted(agenda['sections'].items()): if "docs" in section: docs.extend(section["docs"]) @@ -96,16 +97,16 @@ def get_section_header(doc, agenda): split = num.split(".") - for i in xrange(num.count(".")): + for i in range(num.count(".")): parent_num = ".".join(split[:i + 1]) parent = agenda["sections"].get(parent_num) if parent: if "." not in parent_num: parent_num += "." - header.append(u"%s %s" % (parent_num, parent["title"])) + header.append("%s %s" % (parent_num, parent["title"])) section = agenda["sections"][num] - header.append(u"%s %s" % (num, section["title"])) + header.append("%s %s" % (num, section["title"])) count = '%s of %s' % (section["docs"].index(doc) + 1, len(section["docs"])) header.append(count) @@ -116,7 +117,7 @@ def get_first_doc(agenda): ''' This function takes an agenda dictionary and returns the first document in the agenda ''' - for num, section in sorted(agenda['sections'].iteritems()): + for num, section in sorted(agenda['sections'].items()): if "docs" in section and section["docs"]: return section["docs"][0] diff --git a/ietf/secr/utils/group.py b/ietf/secr/utils/group.py index 172f1bf3f..ad791a3ec 100644 --- a/ietf/secr/utils/group.py +++ b/ietf/secr/utils/group.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved # Python imports import os @@ -95,7 +96,7 @@ def groups_by_session(user, meeting, types=None): groups_no_session.append(group) if types: - groups_session = filter(lambda x: x.type_id in types,groups_session) - groups_no_session = filter(lambda x: x.type_id in types,groups_no_session) + groups_session = [x for x in groups_session if x.type_id in types] + groups_no_session = [x for x in groups_no_session if x.type_id in types] return groups_session, groups_no_session diff --git a/ietf/secr/utils/test.py b/ietf/secr/utils/test.py index 191b3a986..d0864d230 100644 --- a/ietf/secr/utils/test.py +++ b/ietf/secr/utils/test.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved ''' Functions to aid unit testing ''' @@ -9,7 +10,7 @@ def reset(): me = Person.objects.get(name='Ryan Cross') me.role_set.all().delete() Role.objects.create(person=me,email_id='rcross@amsl.com',name_id='secr',group_id=4) - print me.role_set.all() + print(me.role_set.all()) def copy_roles(person): '''Copy the roles of person''' diff --git a/ietf/settings.py b/ietf/settings.py index c5112b202..12e2fe883 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -1058,7 +1058,7 @@ for app in INSTALLED_APPS: if app.startswith('ietf'): app_settings_file = os.path.join(BASE_DIR, '../', app.replace('.', os.sep), "settings.py") if os.path.exists(app_settings_file): - exec "from %s import *" % (app+".settings") + exec("from %s import *" % (app+".settings")) # Add DEV_APPS to INSTALLED_APPS INSTALLED_APPS += DEV_APPS diff --git a/ietf/settings_releasetest.py b/ietf/settings_releasetest.py index 86826736d..7c2a87889 100644 --- a/ietf/settings_releasetest.py +++ b/ietf/settings_releasetest.py @@ -1,10 +1,11 @@ +# Copyright The IETF Trust 2015-2019, All Rights Reserved # Standard settings except we use SQLite, this is useful for speeding # up tests that depend on the test database, try for instance: # # ./manage.py test --settings=settings_sqlitetest doc.ChangeStateTestCase # -from settings import * # pyflakes:ignore +from .settings import * # pyflakes:ignore # Workaround to avoid spending minutes stepping through the migrations in # every test run. The result of this is to use the 'syncdb' way of creating diff --git a/ietf/settings_sqlitetest.py b/ietf/settings_sqlitetest.py index f6f471ee6..7b1b3a079 100644 --- a/ietf/settings_sqlitetest.py +++ b/ietf/settings_sqlitetest.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved # Standard settings except we use SQLite and skip migrations, this is # useful for speeding up tests that depend on the test database, try # for instance: @@ -6,7 +7,7 @@ # import os -from settings import * # pyflakes:ignore +from .settings import * # pyflakes:ignore import debug # pyflakes:ignore debug.debug = True diff --git a/ietf/settings_testcrawl.py b/ietf/settings_testcrawl.py index 967e3f5b7..5f48abd30 100644 --- a/ietf/settings_testcrawl.py +++ b/ietf/settings_testcrawl.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2015-2019, All Rights Reserved # Standard settings except we enable caching like in the production # environment, this is useful for speeding up the test crawl, try for # instance: @@ -5,8 +6,8 @@ # bin/test-crawl --settings=ietf.settings_testcrawl # -from settings import * # pyflakes:ignore -from settings import TEMPLATES +from .settings import * # pyflakes:ignore +from .settings import TEMPLATES TEMPLATES[0]['OPTIONS']['loaders'] = ( ('django.template.loaders.cached.Loader', ( diff --git a/ietf/stats/backfill_data.py b/ietf/stats/backfill_data.py index 5946abc0c..5bb37bda7 100755 --- a/ietf/stats/backfill_data.py +++ b/ietf/stats/backfill_data.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright The IETF Trust 2017-2019, All Rights Reserved -from __future__ import print_function, unicode_literals + import sys import os @@ -16,7 +16,7 @@ os.environ["DJANGO_SETTINGS_MODULE"] = "ietf.settings" virtualenv_activation = os.path.join(basedir, "env", "bin", "activate_this.py") if os.path.exists(virtualenv_activation): - execfile(virtualenv_activation, dict(__file__=virtualenv_activation)) + exec(compile(open(virtualenv_activation, "rb").read(), virtualenv_activation, 'exec'), dict(__file__=virtualenv_activation)) import django django.setup() @@ -54,7 +54,7 @@ def say(msg): logfile.write(msg) logfile.write('\n') -def unicode(text): +def str(text): if text is None: return text # order matters here: @@ -87,7 +87,7 @@ for doc in docs_qs.prefetch_related("docalias", "formal_languages", "documentaut with open(path, 'rb') as f: say("\nProcessing %s" % doc.name) sys.stdout.flush() - d = Draft(unicode(f.read()), path) + d = Draft(str(f.read()), path) updated = False diff --git a/ietf/stats/migrations/0001_initial.py b/ietf/stats/migrations/0001_initial.py index a83449658..671036647 100644 --- a/ietf/stats/migrations/0001_initial.py +++ b/ietf/stats/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models import django.db.models.deletion diff --git a/ietf/stats/models.py b/ietf/stats/models.py index ac2dfb034..de448f0cd 100644 --- a/ietf/stats/models.py +++ b/ietf/stats/models.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved from django.db import models @@ -18,7 +18,7 @@ class AffiliationAlias(models.Model): name = models.CharField(max_length=255) def __unicode__(self): - return u"{} -> {}".format(self.alias, self.name) + return "{} -> {}".format(self.alias, self.name) def save(self, *args, **kwargs): self.alias = self.alias.lower() @@ -43,7 +43,7 @@ class CountryAlias(models.Model): country = ForeignKey(CountryName, max_length=255) def __unicode__(self): - return u"{} -> {}".format(self.alias, self.country.name) + return "{} -> {}".format(self.alias, self.country.name) class Meta: verbose_name_plural = "country aliases" @@ -59,4 +59,4 @@ class MeetingRegistration(models.Model): email = models.EmailField(blank=True, null=True) def __unicode__(self): - return u"{} {}".format(self.first_name, self.last_name) + return "{} {}".format(self.first_name, self.last_name) diff --git a/ietf/stats/utils.py b/ietf/stats/utils.py index 4b70dcbb2..fd7b939e7 100644 --- a/ietf/stats/utils.py +++ b/ietf/stats/utils.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2017-2019, All Rights Reserved import re import requests from collections import defaultdict @@ -83,7 +84,7 @@ def get_aliased_affiliations(affiliations): # now we just need to pick the most popular uppercase/lowercase # spelling for each affiliation with more than one - for similar_affiliations in affiliations_with_case_spellings.itervalues(): + for similar_affiliations in affiliations_with_case_spellings.values(): if len(similar_affiliations) > 1: most_popular = sorted(similar_affiliations, key=affiliation_sort_key, reverse=True)[0] for affiliation in similar_affiliations: @@ -112,8 +113,8 @@ def get_aliased_countries(countries): return possible_alias known_re_aliases = { - re.compile(u"\\b{}\\b".format(re.escape(alias))): name - for alias, name in known_aliases.iteritems() + re.compile("\\b{}\\b".format(re.escape(alias))): name + for alias, name in known_aliases.items() } # specific hack: check for zip codes from the US since in the @@ -127,7 +128,7 @@ def get_aliased_countries(countries): t = t.strip() if t: return t - return u"" + return "" known_countries = set(CountryName.objects.values_list("name", flat=True)) @@ -177,7 +178,7 @@ def get_aliased_countries(countries): # country name anywhere country_lower = country.lower() found = False - for alias_re, name in known_re_aliases.iteritems(): + for alias_re, name in known_re_aliases.items(): if alias_re.search(country) or alias_re.search(country_lower): res[original_country] = name found = True diff --git a/ietf/stats/views.py b/ietf/stats/views.py index 94e7a30e4..f90c1c05d 100644 --- a/ietf/stats/views.py +++ b/ietf/stats/views.py @@ -43,11 +43,11 @@ def stats_index(request): return render(request, "stats/index.html") def generate_query_string(query_dict, overrides): - query_part = u"" + query_part = "" if query_dict or overrides: d = query_dict.copy() - for k, v in overrides.iteritems(): + for k, v in overrides.items(): if type(v) in (list, tuple): if not v: if k in d: @@ -55,14 +55,14 @@ def generate_query_string(query_dict, overrides): else: d.setlist(k, v) else: - if v is None or v == u"": + if v is None or v == "": if k in d: del d[k] else: d[k] = v if d: - query_part = u"?" + d.urlencode() + query_part = "?" + d.urlencode() return query_part @@ -94,13 +94,13 @@ def put_into_bin(value, bin_size): def prune_unknown_bin_with_known(bins): # remove from the unknown bin all authors within the # named/known bins - all_known = { n for b, names in bins.iteritems() if b for n in names } + all_known = { n for b, names in bins.items() if b for n in names } bins[""] = [name for name in bins[""] if name not in all_known] if not bins[""]: del bins[""] def count_bins(bins): - return len({ n for b, names in bins.iteritems() if b for n in names }) + return len({ n for b, names in bins.items() if b for n in names }) def add_labeled_top_series_from_bins(chart_data, bins, limit): """Take bins on the form (x, label): [name1, name2, ...], figure out @@ -108,13 +108,13 @@ def add_labeled_top_series_from_bins(chart_data, bins, limit): them into sorted series like [(x1, len(names1)), (x2, len(names2)), ...].""" aggregated_bins = defaultdict(set) xs = set() - for (x, label), names in bins.iteritems(): + for (x, label), names in bins.items(): xs.add(x) aggregated_bins[label].update(names) xs = list(sorted(xs)) - sorted_bins = sorted(aggregated_bins.iteritems(), key=lambda t: len(t[1]), reverse=True) + sorted_bins = sorted(iter(aggregated_bins.items()), key=lambda t: len(t[1]), reverse=True) top = [ label for label, names in list(sorted_bins)[:limit]] for label in top: @@ -136,7 +136,7 @@ def document_stats(request, stats_type=None): "stats_type": stats_type if stats_type_override is Ellipsis else stats_type_override, } - return urlreverse(document_stats, kwargs={ k: v for k, v in kwargs.iteritems() if v is not None }) + generate_query_string(request.GET, get_overrides) + return urlreverse(document_stats, kwargs={ k: v for k, v in kwargs.items() if v is not None }) + generate_query_string(request.GET, get_overrides) # the length limitation is to keep the key shorter than memcached's limit # of 250 after django has added the key_prefix and key_version parameters @@ -261,7 +261,7 @@ def document_stats(request, stats_type=None): bins[author_count].add(canonical_name) series_data = [] - for author_count, names in sorted(bins.iteritems(), key=lambda t: t[0]): + for author_count, names in sorted(iter(bins.items()), key=lambda t: t[0]): percentage = len(names) * 100.0 / (total_docs or 1) series_data.append((author_count, percentage)) table_data.append((author_count, percentage, len(names), list(names)[:names_limit])) @@ -277,7 +277,7 @@ def document_stats(request, stats_type=None): bins[pages].add(canonical_name) series_data = [] - for pages, names in sorted(bins.iteritems(), key=lambda t: t[0]): + for pages, names in sorted(iter(bins.items()), key=lambda t: t[0]): percentage = len(names) * 100.0 / (total_docs or 1) if pages is not None: series_data.append((pages, len(names))) @@ -296,7 +296,7 @@ def document_stats(request, stats_type=None): bins[put_into_bin(words, bin_size)].add(canonical_name) series_data = [] - for (value, words), names in sorted(bins.iteritems(), key=lambda t: t[0][0]): + for (value, words), names in sorted(iter(bins.items()), key=lambda t: t[0][0]): percentage = len(names) * 100.0 / (total_docs or 1) if words is not None: series_data.append((value, len(names))) @@ -349,7 +349,7 @@ def document_stats(request, stats_type=None): bins[ext.upper()].add(canonical_name) series_data = [] - for fmt, names in sorted(bins.iteritems(), key=lambda t: t[0]): + for fmt, names in sorted(iter(bins.items()), key=lambda t: t[0]): percentage = len(names) * 100.0 / (total_docs or 1) series_data.append((fmt, len(names))) @@ -366,7 +366,7 @@ def document_stats(request, stats_type=None): bins[formal_language_name].add(canonical_name) series_data = [] - for formal_language, names in sorted(bins.iteritems(), key=lambda t: t[0]): + for formal_language, names in sorted(iter(bins.items()), key=lambda t: t[0]): percentage = len(names) * 100.0 / (total_docs or 1) if formal_language is not None: series_data.append((formal_language, len(names))) @@ -417,7 +417,7 @@ def document_stats(request, stats_type=None): total_persons = count_bins(bins) series_data = [] - for document_count, names in sorted(bins.iteritems(), key=lambda t: t[0]): + for document_count, names in sorted(iter(bins.items()), key=lambda t: t[0]): percentage = len(names) * 100.0 / (total_persons or 1) series_data.append((document_count, percentage)) plain_names = [ plain_name(n) for n in names ] @@ -450,7 +450,7 @@ def document_stats(request, stats_type=None): total_persons = count_bins(bins) series_data = [] - for affiliation, names in sorted(bins.iteritems(), key=lambda t: t[0].lower()): + for affiliation, names in sorted(iter(bins.items()), key=lambda t: t[0].lower()): percentage = len(names) * 100.0 / (total_persons or 1) if affiliation: series_data.append((affiliation, len(names))) @@ -462,7 +462,7 @@ def document_stats(request, stats_type=None): chart_data.append({ "data": series_data }) - for alias, name in sorted(aliases.iteritems(), key=lambda t: t[1]): + for alias, name in sorted(iter(aliases.items()), key=lambda t: t[1]): alias_data.append((name, alias)) elif stats_type == "author/country": @@ -485,7 +485,7 @@ def document_stats(request, stats_type=None): countries = { c.name: c for c in CountryName.objects.all() } eu_name = "EU" - eu_countries = { c for c in countries.itervalues() if c.in_eu } + eu_countries = { c for c in countries.values() if c.in_eu } for name, country in name_country_set: country_name = aliases.get(country, country) @@ -499,7 +499,7 @@ def document_stats(request, stats_type=None): total_persons = count_bins(bins) series_data = [] - for country, names in sorted(bins.iteritems(), key=lambda t: t[0].lower()): + for country, names in sorted(iter(bins.items()), key=lambda t: t[0].lower()): percentage = len(names) * 100.0 / (total_persons or 1) if country: series_data.append((country, len(names))) @@ -511,7 +511,7 @@ def document_stats(request, stats_type=None): chart_data.append({ "data": series_data }) - for alias, country_name in aliases.iteritems(): + for alias, country_name in aliases.items(): alias_data.append((country_name, alias, countries.get(country_name))) alias_data.sort() @@ -541,7 +541,7 @@ def document_stats(request, stats_type=None): total_persons = count_bins(bins) series_data = [] - for continent, names in sorted(bins.iteritems(), key=lambda t: t[0].lower()): + for continent, names in sorted(iter(bins.items()), key=lambda t: t[0].lower()): percentage = len(names) * 100.0 / (total_persons or 1) if continent: series_data.append((continent, len(names))) @@ -568,7 +568,7 @@ def document_stats(request, stats_type=None): total_persons = count_bins(bins) series_data = [] - for citations, names in sorted(bins.iteritems(), key=lambda t: t[0], reverse=True): + for citations, names in sorted(iter(bins.items()), key=lambda t: t[0], reverse=True): percentage = len(names) * 100.0 / (total_persons or 1) series_data.append((citations, percentage)) plain_names = [ plain_name(n) for n in names ] @@ -594,7 +594,7 @@ def document_stats(request, stats_type=None): total_persons = count_bins(bins) series_data = [] - for citations, names in sorted(bins.iteritems(), key=lambda t: t[0], reverse=True): + for citations, names in sorted(iter(bins.items()), key=lambda t: t[0], reverse=True): percentage = len(names) * 100.0 / (total_persons or 1) series_data.append((citations, percentage)) plain_names = [ plain_name(n) for n in names ] @@ -674,7 +674,7 @@ def document_stats(request, stats_type=None): countries = { c.name: c for c in CountryName.objects.all() } eu_name = "EU" - eu_countries = { c for c in countries.itervalues() if c.in_eu } + eu_countries = { c for c in countries.values() if c.in_eu } bins = defaultdict(set) @@ -770,7 +770,7 @@ def meeting_stats(request, num=None, stats_type=None): if number is not None: kwargs["num"] = number - return urlreverse(meeting_stats, kwargs={ k: v for k, v in kwargs.iteritems() if v is not None }) + generate_query_string(request.GET, get_overrides) + return urlreverse(meeting_stats, kwargs={ k: v for k, v in kwargs.items() if v is not None }) + generate_query_string(request.GET, get_overrides) cache_key = ("stats:meeting_stats:%s:%s:%s" % (num, stats_type, slugify(request.META.get('QUERY_STRING',''))))[:228] data = cache.get(cache_key) @@ -808,7 +808,7 @@ def meeting_stats(request, num=None, stats_type=None): } def reg_name(r): - return email.utils.formataddr(((r.first_name + u" " + r.last_name).strip(), r.email)) + return email.utils.formataddr(((r.first_name + " " + r.last_name).strip(), r.email)) if meeting and any(stats_type == t[0] for t in possible_stats_types): attendees = MeetingRegistration.objects.filter(meeting=meeting) @@ -835,7 +835,7 @@ def meeting_stats(request, num=None, stats_type=None): total_attendees = count_bins(bins) series_data = [] - for country, names in sorted(bins.iteritems(), key=lambda t: t[0].lower()): + for country, names in sorted(iter(bins.items()), key=lambda t: t[0].lower()): percentage = len(names) * 100.0 / (total_attendees or 1) if country: series_data.append((country, len(names))) @@ -869,7 +869,7 @@ def meeting_stats(request, num=None, stats_type=None): total_attendees = count_bins(bins) series_data = [] - for continent, names in sorted(bins.iteritems(), key=lambda t: t[0].lower()): + for continent, names in sorted(iter(bins.items()), key=lambda t: t[0].lower()): percentage = len(names) * 100.0 / (total_attendees or 1) if continent: series_data.append((continent, len(names))) @@ -903,14 +903,14 @@ def meeting_stats(request, num=None, stats_type=None): bins[meeting_number].add(name) series_data = {} - for continent in continents.keys(): + for continent in list(continents.keys()): series_data[continent] = [] for m in meetings: country = CountryName.objects.get(slug=m.country) url = build_meeting_stats_url(number=m.number, stats_type_override="country") - for continent in continents.keys(): + for continent in list(continents.keys()): if continent == country.continent.name: d = { "name": "IETF {} - {}, {}".format(int(m.number), m.city, country), @@ -928,7 +928,7 @@ def meeting_stats(request, num=None, stats_type=None): table_data.append((m, url, m.attendees, country)) - for continent in continents.keys(): + for continent in list(continents.keys()): # series_data[continent].sort(key=lambda t: t[0]["x"]) chart_data.append( { "name": continent, "data": series_data[continent] }) diff --git a/ietf/submit/checkers.py b/ietf/submit/checkers.py index dd03abccf..d59203e1c 100644 --- a/ietf/submit/checkers.py +++ b/ietf/submit/checkers.py @@ -1,5 +1,5 @@ -# Copyright The IETF Trust 2016, All Rights Reserved -from __future__ import unicode_literals, print_function +# Copyright The IETF Trust 2016-2019, All Rights Reserved + import os import re @@ -7,7 +7,7 @@ import sys from xym import xym import shutil import tempfile -import StringIO +import io from django.conf import settings @@ -142,8 +142,8 @@ class DraftYangChecker(object): # This places the yang models as files in workdir saved_stdout = sys.stdout saved_stderr = sys.stderr - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() + sys.stdout = io.StringIO() + sys.stderr = io.StringIO() extractor.extract_yang_model(file.readlines()) model_list = extractor.get_extracted_models(False, True) out = sys.stdout.getvalue() diff --git a/ietf/submit/forms.py b/ietf/submit/forms.py index cd99c9439..a773c364d 100644 --- a/ietf/submit/forms.py +++ b/ietf/submit/forms.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import os import re import datetime @@ -32,7 +33,7 @@ from ietf.submit.parsers.xml_parser import XMLParser from ietf.utils.draft import Draft class SubmissionBaseUploadForm(forms.Form): - xml = forms.FileField(label=u'.xml format', required=True) + xml = forms.FileField(label='.xml format', required=True) def __init__(self, request, *args, **kwargs): super(SubmissionBaseUploadForm, self).__init__(*args, **kwargs) @@ -184,10 +185,10 @@ class SubmissionBaseUploadForm(forms.Form): self.revision = None self.filename = draftname self.title = self.xmlroot.findtext('front/title').strip() - if type(self.title) is unicode: + if type(self.title) is str: self.title = unidecode(self.title) self.abstract = (self.xmlroot.findtext('front/abstract') or '').strip() - if type(self.abstract) is unicode: + if type(self.abstract) is str: self.abstract = unidecode(self.abstract) author_info = self.xmlroot.findall('front/author') for author in author_info: @@ -304,7 +305,7 @@ class SubmissionBaseUploadForm(forms.Form): else: name_parts = name.split("-") if len(name_parts) < 3: - raise forms.ValidationError(u"The draft name \"%s\" is missing a third part, please rename it" % name) + raise forms.ValidationError("The draft name \"%s\" is missing a third part, please rename it" % name) if name.startswith('draft-ietf-') or name.startswith("draft-irtf-"): @@ -339,10 +340,10 @@ class SubmissionBaseUploadForm(forms.Form): return None class SubmissionManualUploadForm(SubmissionBaseUploadForm): - xml = forms.FileField(label=u'.xml format', required=False) # xml field with required=False instead of True - txt = forms.FileField(label=u'.txt format', required=False) - pdf = forms.FileField(label=u'.pdf format', required=False) - ps = forms.FileField(label=u'.ps format', required=False) + xml = forms.FileField(label='.xml format', required=False) # xml field with required=False instead of True + txt = forms.FileField(label='.txt format', required=False) + pdf = forms.FileField(label='.pdf format', required=False) + ps = forms.FileField(label='.ps format', required=False) def __init__(self, request, *args, **kwargs): super(SubmissionManualUploadForm, self).__init__(request, *args, **kwargs) @@ -368,7 +369,7 @@ class SubmissionAutoUploadForm(SubmissionBaseUploadForm): class NameEmailForm(forms.Form): name = forms.CharField(required=True) - email = forms.EmailField(label=u'Email address', required=True) + email = forms.EmailField(label='Email address', required=True) def __init__(self, *args, **kwargs): super(NameEmailForm, self).__init__(*args, **kwargs) @@ -392,7 +393,7 @@ class AuthorForm(NameEmailForm): class SubmitterForm(NameEmailForm): #Fields for secretariat only - approvals_received = forms.BooleanField(label=u'Approvals received', required=False, initial=False) + approvals_received = forms.BooleanField(label='Approvals received', required=False, initial=False) def cleaned_line(self): line = self.cleaned_data["name"] @@ -422,13 +423,13 @@ class ReplacesForm(forms.Form): class EditSubmissionForm(forms.ModelForm): title = forms.CharField(required=True, max_length=255) - rev = forms.CharField(label=u'Revision', max_length=2, required=True) + rev = forms.CharField(label='Revision', max_length=2, required=True) document_date = forms.DateField(required=True) pages = forms.IntegerField(required=True) formal_languages = forms.ModelMultipleChoiceField(queryset=FormalLanguageName.objects.filter(used=True), widget=forms.CheckboxSelectMultiple, required=False) abstract = forms.CharField(widget=forms.Textarea, required=True, strip=False) - note = forms.CharField(label=mark_safe(u'Comment to the Secretariat'), widget=forms.Textarea, required=False, strip=False) + note = forms.CharField(label=mark_safe('Comment to the Secretariat'), widget=forms.Textarea, required=False, strip=False) class Meta: model = Submission diff --git a/ietf/submit/mail.py b/ietf/submit/mail.py index dafbd9e9e..661bef8b1 100644 --- a/ietf/submit/mail.py +++ b/ietf/submit/mail.py @@ -82,7 +82,7 @@ def send_approval_request_to_group(request, submission): return all_addrs def send_manual_post_request(request, submission, errors): - subject = u'Manual Post Requested for %s' % submission.name + subject = 'Manual Post Requested for %s' % submission.name from_email = settings.IDSUBMIT_FROM_EMAIL (to_email,cc) = gather_address_lists('sub_manual_post_requested',submission=submission) checker = DraftIdnitsChecker(options=[]) # don't use the default --submitcheck limitation @@ -234,7 +234,7 @@ def process_response_email(msg): save_submission_email_attachments(submission_email_event, parts) - log(u"Received submission email from %s" % msg.frm) + log("Received submission email from %s" % msg.frm) return msg diff --git a/ietf/submit/management/commands/manualpost_email.py b/ietf/submit/management/commands/manualpost_email.py index 710f4a0f9..771da84be 100644 --- a/ietf/submit/management/commands/manualpost_email.py +++ b/ietf/submit/management/commands/manualpost_email.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved import sys from django.core.management.base import BaseCommand, CommandError @@ -7,7 +8,7 @@ from ietf.submit.mail import process_response_email import debug # pyflakes:ignore class Command(BaseCommand): - help = (u"Process incoming manual post email responses") + help = ("Process incoming manual post email responses") def add_arguments(self, parser): parser.add_argument('--email-file', dest='email', help='File containing email (default: stdin)') diff --git a/ietf/submit/migrations/0001_initial.py b/ietf/submit/migrations/0001_initial.py index 1d85ccba4..feeb457b4 100644 --- a/ietf/submit/migrations/0001_initial.py +++ b/ietf/submit/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + import datetime from django.db import migrations, models diff --git a/ietf/submit/migrations/0002_submission_document2_fk.py b/ietf/submit/migrations/0002_submission_document2_fk.py index 153a34559..e6a7c3b7c 100644 --- a/ietf/submit/migrations/0002_submission_document2_fk.py +++ b/ietf/submit/migrations/0002_submission_document2_fk.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-08 11:58 -from __future__ import unicode_literals + from django.db import migrations import django.db.models.deletion diff --git a/ietf/submit/migrations/0003_remove_old_document_field.py b/ietf/submit/migrations/0003_remove_old_document_field.py index 8a5cf2104..a0412cbae 100644 --- a/ietf/submit/migrations/0003_remove_old_document_field.py +++ b/ietf/submit/migrations/0003_remove_old_document_field.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-25 06:44 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/submit/migrations/0004_rename_field_document2.py b/ietf/submit/migrations/0004_rename_field_document2.py index cb8e32f15..0e928dc8c 100644 --- a/ietf/submit/migrations/0004_rename_field_document2.py +++ b/ietf/submit/migrations/0004_rename_field_document2.py @@ -1,7 +1,7 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.20 on 2019-05-25 06:46 -from __future__ import unicode_literals + from django.db import migrations diff --git a/ietf/submit/models.py b/ietf/submit/models.py index 6e6b09c2d..0f84d42b2 100644 --- a/ietf/submit/models.py +++ b/ietf/submit/models.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import datetime import email @@ -55,7 +56,7 @@ class Submission(models.Model): draft = ForeignKey(Document, null=True, blank=True) def __unicode__(self): - return u"%s-%s" % (self.name, self.rev) + return "%s-%s" % (self.name, self.rev) def submitter_parsed(self): return parse_email_line(self.submitter) @@ -95,7 +96,7 @@ class SubmissionEvent(models.Model): desc = models.TextField() def __unicode__(self): - return u"%s %s by %s at %s" % (self.submission.name, self.desc, self.by.plain_name() if self.by else "(unknown)", self.time) + return "%s %s by %s at %s" % (self.submission.name, self.desc, self.by.plain_name() if self.by else "(unknown)", self.time) class Meta: ordering = ("-time", "-id") @@ -116,7 +117,7 @@ class SubmissionEmailEvent(SubmissionEvent): in_reply_to = ForeignKey(Message, null=True, blank=True,related_name='irtomanual') def __unicode__(self): - return u"%s %s by %s at %s" % (self.submission.name, self.desc, self.by.plain_name() if self.by else "(unknown)", self.time) + return "%s %s by %s at %s" % (self.submission.name, self.desc, self.by.plain_name() if self.by else "(unknown)", self.time) class Meta: ordering = ['-time', '-id'] diff --git a/ietf/submit/parsers/base.py b/ietf/submit/parsers/base.py index 94c928a87..24017fec5 100644 --- a/ietf/submit/parsers/base.py +++ b/ietf/submit/parsers/base.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import re import magic @@ -62,21 +63,21 @@ class FileParser(object): regexp = re.compile(r'&|\|\/|;|\*|\s|\$') chars = regexp.findall(name) if chars: - self.parsed_info.add_error(u'Invalid characters were found in the name of the file which was just submitted: %s' % ', '.join(set(chars))) + self.parsed_info.add_error('Invalid characters were found in the name of the file which was just submitted: %s' % ', '.join(set(chars))) def parse_max_size(self): max_size = settings.IDSUBMIT_MAX_DRAFT_SIZE[self.ext] if self.fd.size > max_size: - self.parsed_info.add_error(u'File size is larger than the permitted maximum of %s' % filesizeformat(max_size)) + self.parsed_info.add_error('File size is larger than the permitted maximum of %s' % filesizeformat(max_size)) self.parsed_info.metadata.file_size = self.fd.size def parse_filename_extension(self): if not self.fd.name.lower().endswith('.'+self.ext): - self.parsed_info.add_error(u'Expected the %s file to have extension ".%s", found the name "%s"' % (self.ext.upper(), self.ext, self.fd.name)) + self.parsed_info.add_error('Expected the %s file to have extension ".%s", found the name "%s"' % (self.ext.upper(), self.ext, self.fd.name)) def parse_file_type(self): self.fd.file.seek(0) content = self.fd.file.read() mimetype = magic.from_buffer(content, mime=True) if not mimetype in self.mimetypes: - self.parsed_info.add_error(u'Expected an %s file of type "%s", found one of type "%s"' % (self.ext.upper(), '" or "'.join(self.mimetypes), mimetype)) + self.parsed_info.add_error('Expected an %s file of type "%s", found one of type "%s"' % (self.ext.upper(), '" or "'.join(self.mimetypes), mimetype)) diff --git a/ietf/submit/parsers/plain_parser.py b/ietf/submit/parsers/plain_parser.py index afb65233f..22546d47a 100644 --- a/ietf/submit/parsers/plain_parser.py +++ b/ietf/submit/parsers/plain_parser.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import re from ietf.submit.parsers.base import FileParser @@ -55,16 +56,16 @@ class PlainParser(FileParser): extra_chars = re.sub('[0-9a-z\-]', '', name) if extra_chars: if len(extra_chars) == 1: - self.parsed_info.add_error((u'The document name on the first page, "%s", contains a disallowed character with byte code: %s ' % (name.decode('utf-8','replace'), ord(extra_chars[0]))) + - u'(see https://www.ietf.org/id-info/guidelines.html#naming for details).') + self.parsed_info.add_error(('The document name on the first page, "%s", contains a disallowed character with byte code: %s ' % (name.decode('utf-8','replace'), ord(extra_chars[0]))) + + '(see https://www.ietf.org/id-info/guidelines.html#naming for details).') else: - self.parsed_info.add_error((u'The document name on the first page, "%s", contains disallowed characters with byte codes: %s ' % (name.decode('utf-8','replace'), (', '.join([ str(ord(c)) for c in extra_chars] )))) + - u'(see https://www.ietf.org/id-info/guidelines.html#naming for details).') + self.parsed_info.add_error(('The document name on the first page, "%s", contains disallowed characters with byte codes: %s ' % (name.decode('utf-8','replace'), (', '.join([ str(ord(c)) for c in extra_chars] )))) + + '(see https://www.ietf.org/id-info/guidelines.html#naming for details).') match_revision = revisionre.match(name) if match_revision: self.parsed_info.metadata.rev = match_revision.group(1) else: - self.parsed_info.add_error(u'The name found on the first page of the document does not contain a revision: "%s"' % (name.decode('utf-8','replace'),)) + self.parsed_info.add_error('The name found on the first page of the document does not contain a revision: "%s"' % (name.decode('utf-8','replace'),)) name = re.sub('-\d+$', '', name) self.parsed_info.metadata.name = name return diff --git a/ietf/submit/templatetags/submit_tags.py b/ietf/submit/templatetags/submit_tags.py index 13e93abf7..fb81cdc98 100644 --- a/ietf/submit/templatetags/submit_tags.py +++ b/ietf/submit/templatetags/submit_tags.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved import os from django import template @@ -26,7 +27,7 @@ def show_submission_files(context, submission): @register.filter def two_pages_decorated_with_errors(submission, errors): pages = submission.first_two_pages or '' - if 'rev' not in errors.keys(): + if 'rev' not in list(errors.keys()): return mark_safe('
%s
' % escape(pages)) result = '
\n'
     for line in pages.split('\n'):
diff --git a/ietf/submit/tests.py b/ietf/submit/tests.py
index 08c03dbfa..1302c3b4b 100644
--- a/ietf/submit/tests.py
+++ b/ietf/submit/tests.py
@@ -1,6 +1,6 @@
 # Copyright The IETF Trust 2011-2019, All Rights Reserved
 # -*- coding: utf-8 -*-
-from __future__ import unicode_literals, print_function
+
 
 import datetime
 import email
@@ -10,7 +10,7 @@ import shutil
 import sys
 
 
-from StringIO import StringIO
+from io import StringIO
 from pyquery import PyQuery
 
 from django.conf import settings
@@ -145,7 +145,7 @@ class SubmitTests(TestCase):
 
         status_url = r["Location"]
         for format in formats:
-            self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.%s" % (name, rev, format))))
+            self.assertTrue(os.path.exists(os.path.join(self.staging_dir, "%s-%s.%s" % (name, rev, format))))
         self.assertEqual(Submission.objects.filter(name=name).count(), 1)
         submission = Submission.objects.get(name=name)
         if len(submission.authors) != 1:
@@ -274,8 +274,8 @@ class SubmitTests(TestCase):
         self.assertEqual(new_revision.type, "new_revision")
         self.assertEqual(new_revision.by.name, author.name)
         self.assertTrue(draft.latest_event(type="added_suggested_replaces"))
-        self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
-        self.assertTrue(os.path.exists(os.path.join(self.repository_dir, u"%s-%s.txt" % (name, rev))))
+        self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, "%s-%s.txt" % (name, rev))))
+        self.assertTrue(os.path.exists(os.path.join(self.repository_dir, "%s-%s.txt" % (name, rev))))
         self.assertEqual(draft.type_id, "draft")
         self.assertEqual(draft.stream_id, "ietf")
         self.assertTrue(draft.expires >= datetime.datetime.now() + datetime.timedelta(days=settings.INTERNET_DRAFT_DAYS_TO_EXPIRE - 1))
@@ -289,17 +289,17 @@ class SubmitTests(TestCase):
         self.assertEqual(draft.relations_that_doc("possibly-replaces").count(), 1)
         self.assertTrue(draft.relations_that_doc("possibly-replaces").first().target, sug_replaced_alias)
         self.assertEqual(len(outbox), mailbox_before + 5)
-        self.assertIn((u"I-D Action: %s" % name), outbox[-4]["Subject"])
-        self.assertIn(author.ascii, unicode(outbox[-4]))
-        self.assertIn((u"I-D Action: %s" % name), outbox[-3]["Subject"])
-        self.assertIn(author.ascii, unicode(outbox[-3]))
+        self.assertIn(("I-D Action: %s" % name), outbox[-4]["Subject"])
+        self.assertIn(author.ascii, str(outbox[-4]))
+        self.assertIn(("I-D Action: %s" % name), outbox[-3]["Subject"])
+        self.assertIn(author.ascii, str(outbox[-3]))
         self.assertIn("New Version Notification",outbox[-2]["Subject"])
-        self.assertIn(name, unicode(outbox[-2]))
-        self.assertIn("mars", unicode(outbox[-2]))
+        self.assertIn(name, str(outbox[-2]))
+        self.assertIn("mars", str(outbox[-2]))
         # Check "Review of suggested possible replacements for..." mail
         self.assertIn("review", outbox[-1]["Subject"].lower())
-        self.assertIn(name, unicode(outbox[-1]))
-        self.assertIn(sug_replaced_alias.name, unicode(outbox[-1]))
+        self.assertIn(name, str(outbox[-1]))
+        self.assertIn(sug_replaced_alias.name, str(outbox[-1]))
         self.assertIn("ames-chairs@", outbox[-1]["To"].lower())
         self.assertIn("mars-chairs@", outbox[-1]["To"].lower())
 
@@ -367,7 +367,7 @@ class SubmitTests(TestCase):
         prev_author = draft.documentauthor_set.all()[0]
         if change_authors:
             # Make it such that one of the previous authors has an invalid email address
-            bogus_person, bogus_email = ensure_person_email_info_exists(u'Bogus Person', None, draft.name)
+            bogus_person, bogus_email = ensure_person_email_info_exists('Bogus Person', None, draft.name)
             DocumentAuthor.objects.create(document=draft, person=bogus_person, email=bogus_email, order=draft.documentauthor_set.latest('order').order+1)
 
         # Set the revision needed tag
@@ -407,7 +407,7 @@ class SubmitTests(TestCase):
         self.assertTrue("unknown-email-" not in confirm_email["To"])
         if change_authors:
             # Since authors changed, ensure chairs are copied (and that the message says why)
-            self.assertTrue("chairs have been copied" in unicode(confirm_email))
+            self.assertTrue("chairs have been copied" in str(confirm_email))
             if group_type in ['wg','rg','ag']:
                 self.assertTrue("mars-chairs@" in confirm_email["To"].lower())
             elif group_type == 'area':
@@ -417,7 +417,7 @@ class SubmitTests(TestCase):
             if stream_type=='ise':
                self.assertTrue("rfc-ise@" in confirm_email["To"].lower())
         else:
-            self.assertNotIn("chairs have been copied", unicode(confirm_email))
+            self.assertNotIn("chairs have been copied", str(confirm_email))
             self.assertNotIn("mars-chairs@", confirm_email["To"].lower())
 
         confirm_url = self.extract_confirm_url(confirm_email)
@@ -473,8 +473,8 @@ class SubmitTests(TestCase):
 
         self.assertTrue(not os.path.exists(os.path.join(self.repository_dir, "%s-%s.txt" % (name, old_rev))))
         self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "%s-%s.txt" % (name, old_rev))))
-        self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
-        self.assertTrue(os.path.exists(os.path.join(self.repository_dir, u"%s-%s.txt" % (name, rev))))
+        self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, "%s-%s.txt" % (name, rev))))
+        self.assertTrue(os.path.exists(os.path.join(self.repository_dir, "%s-%s.txt" % (name, rev))))
         self.assertEqual(draft.type_id, "draft")
         if stream_type == 'ietf':
             self.assertEqual(draft.stream_id, "ietf")
@@ -484,19 +484,19 @@ class SubmitTests(TestCase):
         self.assertEqual(len(authors), 1)
         self.assertIn(author, [ a.person for a in authors ])
         self.assertEqual(len(outbox), mailbox_before + 3)
-        self.assertTrue((u"I-D Action: %s" % name) in outbox[-3]["Subject"])
-        self.assertTrue((u"I-D Action: %s" % name) in draft.message_set.order_by("-time")[0].subject)
-        self.assertTrue(author.ascii in unicode(outbox[-3]))
+        self.assertTrue(("I-D Action: %s" % name) in outbox[-3]["Subject"])
+        self.assertTrue(("I-D Action: %s" % name) in draft.message_set.order_by("-time")[0].subject)
+        self.assertTrue(author.ascii in str(outbox[-3]))
         self.assertTrue("i-d-announce@" in outbox[-3]['To'])
         self.assertTrue("New Version Notification" in outbox[-2]["Subject"])
-        self.assertTrue(name in unicode(outbox[-2]))
+        self.assertTrue(name in str(outbox[-2]))
         interesting_address = {'ietf':'mars', 'irtf':'irtf-chair', 'iab':'iab-chair', 'ise':'rfc-ise'}[draft.stream_id]
-        self.assertTrue(interesting_address in unicode(outbox[-2]))
+        self.assertTrue(interesting_address in str(outbox[-2]))
         if draft.stream_id == 'ietf':
-            self.assertTrue(draft.ad.role_email("ad").address in unicode(outbox[-2]))
-            self.assertTrue(ballot_position.ad.role_email("ad").address in unicode(outbox[-2]))
+            self.assertTrue(draft.ad.role_email("ad").address in str(outbox[-2]))
+            self.assertTrue(ballot_position.ad.role_email("ad").address in str(outbox[-2]))
         self.assertTrue("New Version Notification" in outbox[-1]["Subject"])
-        self.assertTrue(name in unicode(outbox[-1]))
+        self.assertTrue(name in str(outbox[-1]))
         r = self.client.get(urlreverse('ietf.doc.views_search.recent_drafts'))
         self.assertEqual(r.status_code, 200)
         self.assertIn(draft.name,  unicontent(r))
@@ -556,7 +556,7 @@ class SubmitTests(TestCase):
         # both submitter and author get email
         self.assertTrue(author.email().address.lower() in confirm_email["To"])
         self.assertTrue("submitter@example.com" in confirm_email["To"])
-        self.assertFalse("chairs have been copied" in unicode(confirm_email))
+        self.assertFalse("chairs have been copied" in str(confirm_email))
 
         confirm_url = self.extract_confirm_url(outbox[-1])
 
@@ -614,7 +614,7 @@ class SubmitTests(TestCase):
         r = self.client.get(status_url)
         self.assertEqual(len(outbox), mailbox_before + 1)
         confirm_url = self.extract_confirm_url(outbox[-1])
-        self.assertFalse("chairs have been copied" in unicode(outbox[-1]))
+        self.assertFalse("chairs have been copied" in str(outbox[-1]))
         mailbox_before = len(outbox)
         r = self.client.post(confirm_url, {'action':'confirm'})
         self.assertEqual(r.status_code, 302)
@@ -696,7 +696,7 @@ class SubmitTests(TestCase):
 
         # cancel
         r = self.client.post(status_url, dict(action=action))
-        self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
+        self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, "%s-%s.txt" % (name, rev))))
 
     def test_edit_submission_and_force_post(self):
         # submit -> edit
@@ -886,15 +886,15 @@ class SubmitTests(TestCase):
 
         self.assertEqual(Submission.objects.filter(name=name).count(), 1)
 
-        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
-        self.assertTrue(name in open(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))).read())
-        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.xml" % (name, rev))))
-        self.assertTrue(name in open(os.path.join(self.staging_dir, u"%s-%s.xml" % (name, rev))).read())
-        self.assertTrue('' in open(os.path.join(self.staging_dir, u"%s-%s.xml" % (name, rev))).read())
-        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.pdf" % (name, rev))))
-        self.assertTrue('This is PDF' in open(os.path.join(self.staging_dir, u"%s-%s.pdf" % (name, rev))).read())
-        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.ps" % (name, rev))))
-        self.assertTrue('This is PostScript' in open(os.path.join(self.staging_dir, u"%s-%s.ps" % (name, rev))).read())
+        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, "%s-%s.txt" % (name, rev))))
+        self.assertTrue(name in open(os.path.join(self.staging_dir, "%s-%s.txt" % (name, rev))).read())
+        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, "%s-%s.xml" % (name, rev))))
+        self.assertTrue(name in open(os.path.join(self.staging_dir, "%s-%s.xml" % (name, rev))).read())
+        self.assertTrue('' in open(os.path.join(self.staging_dir, "%s-%s.xml" % (name, rev))).read())
+        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, "%s-%s.pdf" % (name, rev))))
+        self.assertTrue('This is PDF' in open(os.path.join(self.staging_dir, "%s-%s.pdf" % (name, rev))).read())
+        self.assertTrue(os.path.exists(os.path.join(self.staging_dir, "%s-%s.ps" % (name, rev))))
+        self.assertTrue('This is PostScript' in open(os.path.join(self.staging_dir, "%s-%s.ps" % (name, rev))).read())
 
     def test_expire_submissions(self):
         s = Submission.objects.create(name="draft-ietf-mars-foo",
@@ -925,10 +925,10 @@ class SubmitTests(TestCase):
 
     def test_help_pages(self):
         r = self.client.get(urlreverse("ietf.submit.views.note_well"))
-        self.assertEquals(r.status_code, 200)
+        self.assertEqual(r.status_code, 200)
 
         r = self.client.get(urlreverse("ietf.submit.views.tool_instructions"))
-        self.assertEquals(r.status_code, 200)
+        self.assertEqual(r.status_code, 200)
         
     def test_blackout_access(self):
         # get
@@ -1016,7 +1016,7 @@ class SubmitTests(TestCase):
 
         # submit
         #author = PersonFactory(name=u"Jörgen Nilsson".encode('latin1'))
-        user = UserFactory(first_name=u"Jörgen", last_name=u"Nilsson")
+        user = UserFactory(first_name="Jörgen", last_name="Nilsson")
         author = PersonFactory(user=user)
 
         file, __ = submission_file(name, rev, group, "txt", "test_submission.nonascii", author=author, ascii=False)
@@ -1051,7 +1051,7 @@ class SubmitTests(TestCase):
         r = self.client.get(status_url)
         q = PyQuery(r.content)
         #
-        self.assertContains(r, u'The yang validation returned 1 error')
+        self.assertContains(r, 'The yang validation returned 1 error')
         #
         m = q('#yang-validation-message').text()
         for command in ['xym', 'pyang', 'yanglint']:
@@ -1553,7 +1553,7 @@ Subject: test
 
         status_url = r["Location"]
         for format in formats:
-            self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.%s" % (name, rev, format))))
+            self.assertTrue(os.path.exists(os.path.join(self.staging_dir, "%s-%s.%s" % (name, rev, format))))
         self.assertEqual(Submission.objects.filter(name=name).count(), 1)
         submission = Submission.objects.get(name=name)
         self.assertTrue(all([ c.passed!=False for c in submission.checks.all() ]))
diff --git a/ietf/submit/utils.py b/ietf/submit/utils.py
index 64d20251e..2a30d6838 100644
--- a/ietf/submit/utils.py
+++ b/ietf/submit/utils.py
@@ -200,7 +200,7 @@ def post_submission(request, submission, approvedDesc):
     submitter_parsed = submission.submitter_parsed()
     if submitter_parsed["name"] and submitter_parsed["email"]:
         submitter, _ = ensure_person_email_info_exists(submitter_parsed["name"], submitter_parsed["email"], submission.name)
-        submitter_info = u'%s <%s>' % (submitter_parsed["name"], submitter_parsed["email"])
+        submitter_info = '%s <%s>' % (submitter_parsed["name"], submitter_parsed["email"])
     else:
         submitter = system
         submitter_info = system.name
@@ -470,7 +470,7 @@ def ensure_person_email_info_exists(name, email, docname):
     else:
         # we're in trouble, use a fake one
         active = False
-        addr = u"unknown-email-%s" % person.plain_ascii().replace(" ", "-")
+        addr = "unknown-email-%s" % person.plain_ascii().replace(" ", "-")
 
     try:
         email = person.email_set.get(address=addr)
@@ -523,7 +523,7 @@ def cancel_submission(submission):
 
 def rename_submission_files(submission, prev_rev, new_rev):
     from ietf.submit.forms import SubmissionManualUploadForm
-    for ext in SubmissionManualUploadForm.base_fields.keys():
+    for ext in list(SubmissionManualUploadForm.base_fields.keys()):
         source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.%s' % (submission.name, prev_rev, ext))
         dest = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.%s' % (submission.name, new_rev, ext))
         if os.path.exists(source):
@@ -531,7 +531,7 @@ def rename_submission_files(submission, prev_rev, new_rev):
 
 def move_files_to_repository(submission):
     from ietf.submit.forms import SubmissionManualUploadForm
-    for ext in SubmissionManualUploadForm.base_fields.keys():
+    for ext in list(SubmissionManualUploadForm.base_fields.keys()):
         source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.%s' % (submission.name, submission.rev, ext))
         dest = os.path.join(settings.IDSUBMIT_REPOSITORY_PATH, '%s-%s.%s' % (submission.name, submission.rev, ext))
         if os.path.exists(source):
@@ -600,7 +600,7 @@ def get_draft_meta(form):
     file_name = {}
     abstract = None
     file_size = None
-    for ext in form.fields.keys():
+    for ext in list(form.fields.keys()):
         if not ext in form.formats:
             continue
         f = form.cleaned_data[ext]
@@ -663,9 +663,9 @@ def get_draft_meta(form):
 
             def turn_into_unicode(s):
                 if s is None:
-                    return u""
+                    return ""
 
-                if isinstance(s, unicode):
+                if isinstance(s, str):
                     return s
                 else:
                     try:
@@ -760,8 +760,8 @@ def send_confirmation_emails(request, submission, requires_group_approval, requi
 
         sent_to = send_approval_request_to_group(request, submission)
 
-        desc = "sent approval email to group chairs: %s" % u", ".join(sent_to)
-        docDesc = u"Request for posting approval emailed to group chairs: %s" % u", ".join(sent_to)
+        desc = "sent approval email to group chairs: %s" % ", ".join(sent_to)
+        docDesc = "Request for posting approval emailed to group chairs: %s" % ", ".join(sent_to)
 
     else:
         group_authors_changed = False
@@ -781,11 +781,11 @@ def send_confirmation_emails(request, submission, requires_group_approval, requi
         sent_to = send_submission_confirmation(request, submission, chair_notice=group_authors_changed)
 
         if submission.state_id == "aut-appr":
-            desc = u"sent confirmation email to previous authors: %s" % u", ".join(sent_to)
-            docDesc = "Request for posting confirmation emailed to previous authors: %s" % u", ".join(sent_to)
+            desc = "sent confirmation email to previous authors: %s" % ", ".join(sent_to)
+            docDesc = "Request for posting confirmation emailed to previous authors: %s" % ", ".join(sent_to)
         else:
-            desc = u"sent confirmation email to submitter and authors: %s" % u", ".join(sent_to)
-            docDesc = "Request for posting confirmation emailed to submitter and authors: %s" % u", ".join(sent_to)
+            desc = "sent confirmation email to submitter and authors: %s" % ", ".join(sent_to)
+            docDesc = "Request for posting confirmation emailed to submitter and authors: %s" % ", ".join(sent_to)
     return sent_to, desc, docDesc
 
     
diff --git a/ietf/submit/views.py b/ietf/submit/views.py
index a08c39035..8d234133b 100644
--- a/ietf/submit/views.py
+++ b/ietf/submit/views.py
@@ -1,4 +1,4 @@
-# Copyright The IETF Trust 2007-2019, All Rights Reserved
+# Copyright The IETF Trust 2011-2019, All Rights Reserved
 # -*- coding: utf-8 -*-
 
 import re
@@ -132,7 +132,7 @@ def api_submit(request):
                 requires_prev_authors_approval = Document.objects.filter(name=submission.name)
 
                 sent_to, desc, docDesc = send_confirmation_emails(request, submission, requires_group_approval, requires_prev_authors_approval)
-                msg = u"Set submitter to \"%s\" and %s" % (submission.submitter, desc)
+                msg = "Set submitter to \"%s\" and %s" % (submission.submitter, desc)
                 create_submission_event(request, submission, msg)
                 docevent_from_submission(request, submission, docDesc, who="(System)")
 
@@ -229,7 +229,7 @@ def submission_status(request, submission_id, access_token=None):
     if submission.state_id == "cancel":
         message = ('error', 'This submission has been cancelled, modification is no longer possible.')
     elif submission.state_id == "auth":
-        message = ('success', u'The submission is pending email authentication. An email has been sent to: %s' % ", ".join(confirmation_list))
+        message = ('success', 'The submission is pending email authentication. An email has been sent to: %s' % ", ".join(confirmation_list))
     elif submission.state_id == "grp-appr":
         message = ('success', 'The submission is pending approval by the group chairs.')
     elif submission.state_id == "aut-appr":
@@ -262,12 +262,12 @@ def submission_status(request, submission_id, access_token=None):
                     # go directly to posting submission
                     docevent_from_submission(request, submission, desc="Uploaded new revision")
 
-                    desc = u"Secretariat manually posting. Approvals already received"
+                    desc = "Secretariat manually posting. Approvals already received"
                     post_submission(request, submission, desc)
                     create_submission_event(request, submission, desc)
                 else:
                     sent_to, desc, docDesc = send_confirmation_emails(request, submission, requires_group_approval, requires_prev_authors_approval)
-                    msg = u"Set submitter to \"%s\", replaces to %s and %s" % (
+                    msg = "Set submitter to \"%s\", replaces to %s and %s" % (
                         submission.submitter,
                         ", ".join(prettify_std_name(r.name) for r in replaces) if replaces else "(none)",
                         desc)
@@ -288,9 +288,9 @@ def submission_status(request, submission_id, access_token=None):
         elif action == "sendfullurl" and submission.state_id not in ("cancel", "posted"):
             sent_to = send_full_url(request, submission)
 
-            message = ('success', u'An email has been sent with the full access URL to: %s' % u",".join(confirmation_list))
+            message = ('success', 'An email has been sent with the full access URL to: %s' % ",".join(confirmation_list))
 
-            create_submission_event(request, submission, u"Sent full access URL to: %s" % u", ".join(sent_to))
+            create_submission_event(request, submission, "Sent full access URL to: %s" % ", ".join(sent_to))
 
         elif action == "cancel" and submission.state.next_states.filter(slug="cancel"):
             if not can_cancel:
@@ -418,7 +418,7 @@ def edit_submission(request, submission_id, access_token=None):
             ]
 
             if changed_fields:
-                desc = u"Edited %s and sent request for manual post" % u", ".join(changed_fields)
+                desc = "Edited %s and sent request for manual post" % ", ".join(changed_fields)
             else:
                 desc = "Sent request for manual post"
 
diff --git a/ietf/sync/iana.py b/ietf/sync/iana.py
index 23c88c1dd..58293625d 100644
--- a/ietf/sync/iana.py
+++ b/ietf/sync/iana.py
@@ -1,9 +1,10 @@
+# Copyright The IETF Trust 2012-2019, All Rights Reserved
 import base64
 import datetime
 import email
 import json
 import re
-import urllib2
+import urllib.request, urllib.error, urllib.parse
 
 from django.utils.http import urlquote
 from django.conf import settings
@@ -19,7 +20,7 @@ from ietf.utils.timezone import local_timezone_to_utc, email_time_to_local_timez
 #CHANGES_URL = "https://datatracker.dev.icann.org:8080/data-tracker/changes"
 
 def fetch_protocol_page(url):
-    f = urllib2.urlopen(settings.IANA_SYNC_PROTOCOLS_URL)
+    f = urllib.request.urlopen(settings.IANA_SYNC_PROTOCOLS_URL)
     text = f.read()
     f.close()
     return text
@@ -63,12 +64,12 @@ def update_rfc_log_from_protocol_page(rfc_names, rfc_must_published_later_than):
 def fetch_changes_json(url, start, end):
     url += "?start=%s&end=%s" % (urlquote(local_timezone_to_utc(start).strftime("%Y-%m-%d %H:%M:%S")),
                                  urlquote(local_timezone_to_utc(end).strftime("%Y-%m-%d %H:%M:%S")))
-    request = urllib2.Request(url)
+    request = urllib.request.Request(url)
     # HTTP basic auth
     username = "ietfsync"
     password = settings.IANA_SYNC_PASSWORD
     request.add_header("Authorization", "Basic %s" % base64.encodestring("%s:%s" % (username, password)).replace("\n", ""))
-    f = urllib2.urlopen(request)
+    f = urllib.request.urlopen(request)
     text = f.read()
     f.close()
     return text
diff --git a/ietf/sync/rfceditor.py b/ietf/sync/rfceditor.py
index 8ad50da1f..17fa929a1 100644
--- a/ietf/sync/rfceditor.py
+++ b/ietf/sync/rfceditor.py
@@ -4,8 +4,8 @@
 import re
 import base64
 import datetime
-import urllib
-import urllib2
+import urllib.request, urllib.parse, urllib.error
+import urllib.request, urllib.error, urllib.parse
 import socket
 from xml.dom import pulldom, Node
 
@@ -40,7 +40,7 @@ def get_child_text(parent_node, tag_name):
 
 def fetch_queue_xml(url):
     socket.setdefaulttimeout(30)
-    return urllib2.urlopen(url)
+    return urllib.request.urlopen(url)
 
 def parse_queue(response):
     """Parse RFC Editor queue XML into a bunch of tuples + warnings."""
@@ -217,7 +217,7 @@ def update_drafts_from_queue(drafts):
 
     # remove tags and states for those not in the queue anymore
     for d in Document.objects.exclude(docalias__name__in=names).filter(states__type="draft-rfceditor").distinct():
-        d.tags.remove(*tag_mapping.values())
+        d.tags.remove(*list(tag_mapping.values()))
         d.unset_state("draft-rfceditor")
         # we do not add a history entry here - most likely we already
         # have something that explains what happened
@@ -228,7 +228,7 @@ def update_drafts_from_queue(drafts):
 
 def fetch_index_xml(url):
     socket.setdefaulttimeout(30)
-    return urllib2.urlopen(url)
+    return urllib.request.urlopen(url)
 
 def parse_index(response):
     """Parse RFC Editor index XML into a bunch of tuples."""
@@ -503,7 +503,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None):
                 rev=doc.rev,
                 by=system,
                 type="sync_from_rfc_editor",
-                desc=u"Received changes through RFC Editor sync (%s)" % u", ".join(changes),
+                desc="Received changes through RFC Editor sync (%s)" % ", ".join(changes),
             ))
 
             doc.save_with_history(events)
@@ -517,7 +517,7 @@ def post_approved_draft(url, name):
     the data from the Datatracker and start processing it. Returns
     response and error (empty string if no error)."""
 
-    request = urllib2.Request(url)
+    request = urllib.request.Request(url)
     request.add_header("Content-type", "application/x-www-form-urlencoded")
     request.add_header("Accept", "text/plain")
     # HTTP basic auth
@@ -531,7 +531,7 @@ def post_approved_draft(url, name):
     log("Posting RFC-Editor notifcation of approved draft '%s' to '%s'" % (name, url))
     text = error = ""
     try:
-        f = urllib2.urlopen(request, data=urllib.urlencode({ 'draft': name }), timeout=20)
+        f = urllib.request.urlopen(request, data=urllib.parse.urlencode({ 'draft': name }), timeout=20)
         text = f.read()
         status_code = f.getcode()
         f.close()
@@ -547,6 +547,6 @@ def post_approved_draft(url, name):
         # catch everything so we don't leak exceptions, convert them
         # into string instead
         log("Exception on RFC-Editor notification for draft '%s': '%s'" % (name, e))
-        error = unicode(e)
+        error = str(e)
 
     return text, error
diff --git a/ietf/sync/tests.py b/ietf/sync/tests.py
index fd254ab0c..78bf1bd36 100644
--- a/ietf/sync/tests.py
+++ b/ietf/sync/tests.py
@@ -4,7 +4,7 @@
 import os
 import json
 import datetime
-import StringIO
+import io
 import shutil
 
 from django.conf import settings
@@ -136,8 +136,8 @@ class IANASyncTests(TestCase):
     def test_iana_review_mail(self):
         draft = WgDraftFactory()
 
-        subject_template = u'Subject: [IANA #12345] Last Call: <%(draft)s-%(rev)s.txt> (Long text) to Informational RFC'
-        msg_template = u"""From: "%(person)s via RT" 
+        subject_template = 'Subject: [IANA #12345] Last Call: <%(draft)s-%(rev)s.txt> (Long text) to Informational RFC'
+        msg_template = """From: "%(person)s via RT" 
 Date: Thu, 10 May 2012 12:00:0%(rtime)d +0000
 %(subject)s
 
@@ -306,7 +306,7 @@ class RFCSyncTests(TestCase):
                        area=doc.group.parent.acronym,
                        group=doc.group.acronym)
 
-        data = rfceditor.parse_index(StringIO.StringIO(t))
+        data = rfceditor.parse_index(io.StringIO(t))
         self.assertEqual(len(data), 1)
 
         rfc_number, title, authors, rfc_published_date, current_status, updates, updated_by, obsoletes, obsoleted_by, also, draft, has_errata, stream, wg, file_formats, pages, abstract = data[0]
@@ -387,7 +387,7 @@ class RFCSyncTests(TestCase):
                               group=draft.group.name,
                               ref="draft-ietf-test")
 
-        drafts, warnings = rfceditor.parse_queue(StringIO.StringIO(t))
+        drafts, warnings = rfceditor.parse_queue(io.StringIO(t))
         self.assertEqual(len(drafts), 1)
         self.assertEqual(len(warnings), 0)
 
diff --git a/ietf/utils/admin.py b/ietf/utils/admin.py
index 94c0a9c96..4aebed393 100644
--- a/ietf/utils/admin.py
+++ b/ietf/utils/admin.py
@@ -1,3 +1,4 @@
+# Copyright The IETF Trust 2011-2019, All Rights Reserved
 from django.contrib import admin
 from ietf.utils.models import VersionInfo
 
@@ -8,10 +9,10 @@ def name(obj):
         if callable(obj.name):
             name = obj.name()
         else:
-            name = unicode(obj.name)
+            name = str(obj.name)
         if name:
             return name
-    return unicode(obj)
+    return str(obj)
     
 def admin_link(field, label=None, ordering="", display=name, suffix=""):
     if not label:
@@ -39,15 +40,15 @@ def admin_link(field, label=None, ordering="", display=name, suffix=""):
             app = obj._meta.app_label
             model = obj.__class__.__name__.lower()
             id = obj.pk
-            chunks += [ u'%(display)s' %
+            chunks += [ '%(display)s' %
                 {'app':app, "model": model, "id":id, "display": display(obj), "suffix":suffix, } ]
-        return u", ".join(chunks)
+        return ", ".join(chunks)
     _link.allow_tags = True
     _link.short_description = label
     _link.admin_order_field = ordering
     return _link
 
-from models import DumpInfo
+from .models import DumpInfo
 class DumpInfoAdmin(admin.ModelAdmin):
     list_display = ['date', 'host', 'tz']
     list_filter = ['date']
diff --git a/ietf/utils/aliases.py b/ietf/utils/aliases.py
index bc9a71a12..8068e8d17 100644
--- a/ietf/utils/aliases.py
+++ b/ietf/utils/aliases.py
@@ -1,3 +1,4 @@
+# Copyright The IETF Trust 2013-2019, All Rights Reserved
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 # -*- Python -*-
@@ -38,7 +39,7 @@ def rewrite_address_list(l):
     h = {}
     for address in l:
         #address = address.strip()
-        if h.has_key(address): continue
+        if address in h: continue
         h[address] = True
         yield address
 
@@ -46,12 +47,12 @@ def dump_sublist(afile, vfile, alias, adomains, vdomain, emails):
     if not emails:
         return emails
     # Nones in the list should be skipped
-    emails = filter(None, emails)
+    emails = [_f for _f in emails if _f]
 
     # Make sure emails are sane and eliminate the Nones again for
     # non-sane ones
     emails = [rewrite_email_address(e) for e in emails]
-    emails = filter(None, emails)
+    emails = [_f for _f in emails if _f]
 
     # And we'll eliminate the duplicates too but preserve order
     emails = list(rewrite_address_list(emails))
@@ -71,7 +72,7 @@ def dump_sublist(afile, vfile, alias, adomains, vdomain, emails):
         # If there's unicode in email address, something is badly
         # wrong and we just silently punt
         # XXX - is there better approach?
-        print '# Error encoding', alias, repr(emails)
+        print('# Error encoding', alias, repr(emails))
         return []
     return emails
 
diff --git a/ietf/utils/bootstrap.py b/ietf/utils/bootstrap.py
index 3fb57a9e8..150f92b57 100644
--- a/ietf/utils/bootstrap.py
+++ b/ietf/utils/bootstrap.py
@@ -1,9 +1,10 @@
+# Copyright The IETF Trust 2016-2019, All Rights Reserved
 import bootstrap3.renderers
 
 class SeparateErrorsFromHelpTextFieldRenderer(bootstrap3.renderers.FieldRenderer):
     def append_to_field(self, html):
         if self.field_help:
-            html += u'
{}
'.format(self.field_help) + html += '
{}
'.format(self.field_help) for e in self.field_errors: - html += u'
{}
'.format(e) + html += '
{}
'.format(e) return html diff --git a/ietf/utils/decorators.py b/ietf/utils/decorators.py index 6cce65a6e..f961ca267 100644 --- a/ietf/utils/decorators.py +++ b/ietf/utils/decorators.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2016-2019, All Rights Reserved import datetime @@ -79,7 +79,7 @@ def require_api_key(f, request, *args, **kwargs): def _memoize(func, self, *args, **kwargs): ''''Memoize wrapper for instance methouds. Use @lru_cache for functions.''' if kwargs: # frozenset is used to ensure hashability - key = args, frozenset(kwargs.items()) + key = args, frozenset(list(kwargs.items())) else: key = args # instance method, set up cache if needed diff --git a/ietf/utils/draft.py b/ietf/utils/draft.py index fa12a0458..e4a5ae593 100755 --- a/ietf/utils/draft.py +++ b/ietf/utils/draft.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved #!/usr/bin/python # -*- python -*- """ @@ -30,8 +31,8 @@ COPYRIGHT """ -from __future__ import unicode_literals -from __future__ import print_function + + import datetime import getopt diff --git a/ietf/utils/fields.py b/ietf/utils/fields.py index 9e7351189..6bef06b45 100644 --- a/ietf/utils/fields.py +++ b/ietf/utils/fields.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2012-2019, All Rights Reserved import re import six @@ -19,7 +19,7 @@ class MultiEmailField(forms.Field): if not value: return [] - if isinstance(value, basestring): + if isinstance(value, str): values = value.split(',') return [ x.strip() for x in values if x.strip() ] else: @@ -72,7 +72,7 @@ class DatepickerDateField(forms.DateField): self.widget.attrs["data-date-format"] = date_format if "placeholder" not in self.widget.attrs: self.widget.attrs["placeholder"] = date_format - for k, v in picker_settings.iteritems(): + for k, v in picker_settings.items(): self.widget.attrs["data-date-%s" % k] = v diff --git a/ietf/utils/history.py b/ietf/utils/history.py index 992902572..a4e37e81f 100644 --- a/ietf/utils/history.py +++ b/ietf/utils/history.py @@ -39,7 +39,7 @@ def find_history_replacements_active_at(objects, time): # automatically figure out how to query history model history_model = objects[0].history_set.model # core_filters contains something like "group__exact": obj - relation_name = objects[0].history_set.core_filters.keys()[0].replace("__exact", "") + relation_name = list(objects[0].history_set.core_filters.keys())[0].replace("__exact", "") # now the querying is a bit tricky - we are only interested in the # history version just before time, or if we can't get that, the diff --git a/ietf/utils/html.py b/ietf/utils/html.py index 018246eae..dbbff0303 100644 --- a/ietf/utils/html.py +++ b/ietf/utils/html.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2010-2019, All Rights Reserved # Taken from http://code.google.com/p/soclone/source/browse/trunk/soclone/utils/html.py """Utilities for working with HTML.""" @@ -54,7 +55,7 @@ class Cleaner(lxml.html.clean.Cleaner): # Copied from lxml 4.2.0 and modified to insert charset meta: def clean_html(self, html): result_type = type(html) - if isinstance(html, basestring): + if isinstance(html, str): doc = lxml.html.fromstring(html) else: doc = copy.deepcopy(html) diff --git a/ietf/utils/log.py b/ietf/utils/log.py index d59874bd0..7d15b9d04 100644 --- a/ietf/utils/log.py +++ b/ietf/utils/log.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved import sys import logging @@ -44,7 +44,7 @@ def log(msg): elif settings.DEBUG == True: _logfunc = debug.say _flushfunc = sys.stdout.flush # pyflakes:ignore (intentional redefinition) - if isinstance(msg, unicode): + if isinstance(msg, str): msg = msg.encode('unicode_escape') try: mod, cls, func, file, line = getcaller() diff --git a/ietf/utils/mail.py b/ietf/utils/mail.py index 7ebe32e88..d9c453c61 100644 --- a/ietf/utils/mail.py +++ b/ietf/utils/mail.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2007-2019, All Rights Reserved import copy import datetime @@ -49,11 +49,11 @@ def empty_outbox(): outbox[:] = [] def add_headers(msg): - if not(msg.has_key('Message-ID')): + if not('Message-ID' in msg): msg['Message-ID'] = make_msgid('idtracker') - if not(msg.has_key('Date')): + if not('Date' in msg): msg['Date'] = formatdate(time.time(), True) - if not(msg.has_key('From')): + if not('From' in msg): msg['From'] = settings.DEFAULT_FROM_EMAIL return msg @@ -90,7 +90,7 @@ def send_smtp(msg, bcc=None): addrlist += [bcc] to = [addr for name, addr in getaddresses(addrlist) if ( addr != '' and not addr.startswith('unknown-email-') )] if not to: - log(u"No addressees for email from '%s', subject '%s'. Nothing sent." % (frm, msg.get('Subject', '[no subject]'))) + log("No addressees for email from '%s', subject '%s'. Nothing sent." % (frm, msg.get('Subject', '[no subject]'))) else: if test_mode: outbox.append(msg) @@ -118,7 +118,7 @@ def send_smtp(msg, bcc=None): raise SMTPSomeRefusedRecipients(message="%d addresses were refused"%len(unhandled),original_msg=msg,refusals=unhandled) except Exception as e: # need to improve log message - log(u"Exception while trying to send email from '%s' to %s subject '%s'" % (frm, to, msg.get('Subject', '[no subject]'))) + log("Exception while trying to send email from '%s' to %s subject '%s'" % (frm, to, msg.get('Subject', '[no subject]'))) if isinstance(e, smtplib.SMTPException): e.original_msg=msg raise @@ -129,8 +129,8 @@ def send_smtp(msg, bcc=None): server.quit() except smtplib.SMTPServerDisconnected: pass - subj = msg.get('Subject', u'[no subject]') - log(u"sent email from '%s' to %s id %s subject '%s'" % (frm, to, msg.get('Message-ID', u''), subj)) + subj = msg.get('Subject', '[no subject]') + log("sent email from '%s' to %s id %s subject '%s'" % (frm, to, msg.get('Message-ID', ''), subj)) def copy_email(msg, to, toUser=False, originalBcc=None): ''' @@ -178,7 +178,7 @@ def send_mail(request, to, frm, subject, template, context, *args, **kwargs): return send_mail_text(request, to, frm, subject, txt, *args, **kwargs) def encode_message(txt): - assert isinstance(txt, unicode) + assert isinstance(txt, str) return MIMEText(txt.encode('utf-8'), 'plain', 'UTF-8') def send_mail_text(request, to, frm, subject, txt, cc=None, extra=None, toUser=False, bcc=None, copy=True): @@ -230,7 +230,7 @@ def parseaddr(addr): which case a 2-tuple of ('', '') is returned. """ - addr = u''.join( [ s.decode(m) if m else unicode(s) for (s,m) in decode_header(addr) ] ) + addr = ''.join( [ s.decode(m) if m else str(s) for (s,m) in decode_header(addr) ] ) name, addr = simple_parseaddr(addr) return name, addr @@ -284,7 +284,7 @@ def condition_message(to, frm, subject, msg, cc, extra): msg['Auto-Submitted'] = "auto-generated" msg['Precedence'] = "bulk" if extra: - for k, v in extra.items(): + for k, v in list(extra.items()): if v: assertion('len(list(set(v))) == len(v)') try: @@ -332,7 +332,7 @@ def send_mail_mime(request, to, frm, subject, msg, cc=None, extra=None, toUser=F elif settings.SERVER_MODE == 'test': if toUser: copy_email(msg, to, toUser=True, originalBcc=bcc) - elif request and request.COOKIES.has_key( 'testmailcc' ): + elif request and 'testmailcc' in request.COOKIES: copy_email(msg, request.COOKIES[ 'testmailcc' ],originalBcc=bcc) try: copy_to = settings.EMAIL_COPY_TO @@ -355,7 +355,7 @@ def parse_preformatted(preformatted, extra={}, override={}): msg = message_from_string(preformatted.encode("utf-8")) msg.set_charset('UTF-8') - for k, v in override.iteritems(): + for k, v in override.items(): if k in msg: del msg[k] if v: @@ -368,7 +368,7 @@ def parse_preformatted(preformatted, extra={}, override={}): headers = copy.copy(msg) # don't modify the message for key in ['To', 'From', 'Subject', 'Bcc']: del headers[key] - for k in headers.keys(): + for k in list(headers.keys()): v = headers.get_all(k, []) if k in extra: ev = extra[k] @@ -398,7 +398,7 @@ def parse_preformatted(preformatted, extra={}, override={}): bcc = msg['Bcc'] del msg['Bcc'] - for v in extra.values(): + for v in list(extra.values()): assertion('len(list(set(v))) == len(v)') return (msg, extra, bcc) @@ -427,7 +427,7 @@ def send_mail_message(request, message, extra={}): def exception_components(e): # See if it's a non-smtplib exception that we faked - if len(e.args)==1 and isinstance(e.args[0],dict) and e.args[0].has_key('really'): + if len(e.args)==1 and isinstance(e.args[0],dict) and 'really' in e.args[0]: orig = e.args[0] extype = orig['really'] tb = orig['tb'] diff --git a/ietf/utils/management/commands/check_referential_integrity.py b/ietf/utils/management/commands/check_referential_integrity.py index 66176a386..3b8d7f2a7 100644 --- a/ietf/utils/management/commands/check_referential_integrity.py +++ b/ietf/utils/management/commands/check_referential_integrity.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2015-2019, All Rights Reserved from tqdm import tqdm @@ -25,18 +26,18 @@ class Command(BaseCommand): debug.pprint('dir(field)') raise if verbosity > 1: - print " %s -> %s.%s" % (field.name,foreign_model.__module__,foreign_model.__name__), + print(" %s -> %s.%s" % (field.name,foreign_model.__module__,foreign_model.__name__), end=' ') used = set(field.model.objects.values_list(field.name,flat=True)) used.discard(None) exists = set(foreign_model.objects.values_list('pk',flat=True)) if verbosity > 1: if used - exists: - print " ** Bad key values:",list(used - exists) + print(" ** Bad key values:",list(used - exists)) else: - print " ok" + print(" ok") else: if used - exists: - print "\n%s.%s.%s -> %s.%s ** Bad key values:" % (model.__module__,model.__name__,field.name,foreign_model.__module__,foreign_model.__name__),list(used - exists) + print("\n%s.%s.%s -> %s.%s ** Bad key values:" % (model.__module__,model.__name__,field.name,foreign_model.__module__,foreign_model.__name__),list(used - exists)) def check_reverse_field(field): try: @@ -49,33 +50,33 @@ class Command(BaseCommand): foreign_field_name = field.remote_field.name foreign_accessor_name = field.remote_field.get_accessor_name() if verbosity > 1: - print " %s <- %s -> %s.%s" % (field.model.__name__, field.remote_field.through._meta.db_table, foreign_model.__module__, foreign_model.__name__), + print(" %s <- %s -> %s.%s" % (field.model.__name__, field.remote_field.through._meta.db_table, foreign_model.__module__, foreign_model.__name__), end=' ') try: used = set(foreign_model.objects.values_list(foreign_field_name, flat=True)) except FieldError: try: used = set(foreign_model.objects.values_list(foreign_accessor_name, flat=True)) except FieldError: - print " ** Warning: could not find reverse name for %s.%s -> %s.%s" % (field.model.__module__, field.model.__name__, foreign_model.__name__, foreign_field_name), + print(" ** Warning: could not find reverse name for %s.%s -> %s.%s" % (field.model.__module__, field.model.__name__, foreign_model.__name__, foreign_field_name), end=' ') used.discard(None) exists = set(field.model.objects.values_list('pk',flat=True)) if verbosity > 1: if used - exists: - print " ** Bad key values:\n ",list(used - exists) + print(" ** Bad key values:\n ",list(used - exists)) else: - print " ok" + print(" ok") else: if used - exists: - print "\n%s.%s <- %s -> %s.%s ** Bad key values:\n " % (field.model.__module__, field.model.__name__, field.remote_field.through._meta.db_table, foreign_model.__module__, foreign_model.__name__), list(used - exists) + print("\n%s.%s <- %s -> %s.%s ** Bad key values:\n " % (field.model.__module__, field.model.__name__, field.remote_field.through._meta.db_table, foreign_model.__module__, foreign_model.__name__), list(used - exists)) for conf in tqdm([ c for c in apps.get_app_configs() if c.name.startswith('ietf.')], desc='apps', disable=verbose): if verbosity > 1: - print "Checking", conf.name + print("Checking", conf.name) for model in tqdm(list(conf.get_models()), desc='models', disable=verbose): if model._meta.proxy: continue if verbosity > 1: - print " %s.%s" % (model.__module__,model.__name__) + print(" %s.%s" % (model.__module__,model.__name__)) for field in [f for f in model._meta.fields if isinstance(f, (ForeignKey, OneToOneField)) ]: check_field(field) for field in [f for f in model._meta.many_to_many ]: diff --git a/ietf/utils/management/commands/coverage_changes.py b/ietf/utils/management/commands/coverage_changes.py index c119f9f46..08e0c70e5 100644 --- a/ietf/utils/management/commands/coverage_changes.py +++ b/ietf/utils/management/commands/coverage_changes.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2015-2019, All Rights Reserved import os import json @@ -64,7 +64,7 @@ class Command(BaseCommand): else: file = codecs.open(filename, "r", encoding="utf-8") except IOError as e: - self.stderr.write(u"%s" % e) + self.stderr.write("%s" % e) exit(1) else: file = filename @@ -87,8 +87,8 @@ class Command(BaseCommand): lcoverage = latest_coverage[section]["covered"] lformat = latest_coverage[section].get("format", 1) # - mkeys = mcoverage.keys() - lkeys = lcoverage.keys() + mkeys = list(mcoverage.keys()) + lkeys = list(lcoverage.keys()) # keys = list(lkeys) keys.sort() @@ -181,7 +181,7 @@ class Command(BaseCommand): lcoverage = latest_coverage[section]["covered"] lformat = latest_coverage[section].get("format", 1) # - lkeys = lcoverage.keys() + lkeys = list(lcoverage.keys()) # keys = list(lkeys) keys.sort() diff --git a/ietf/utils/management/commands/create_group_wikis.py b/ietf/utils/management/commands/create_group_wikis.py index c7d239a0a..459ccc47b 100644 --- a/ietf/utils/management/commands/create_group_wikis.py +++ b/ietf/utils/management/commands/create_group_wikis.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved # Copyright 2016 IETF Trust import os @@ -326,7 +327,7 @@ class Command(BaseCommand): if not self.group_list is None: self.group_list = self.group_list.split('.') - if isinstance(self.verbosity, (type(""), type(u""))) and self.verbosity.isdigit(): + if isinstance(self.verbosity, (type(""), type(""))) and self.verbosity.isdigit(): self.verbosity = int(self.verbosity) if self.dummy_run and self.verbosity < 2: diff --git a/ietf/utils/management/commands/dumprelated.py b/ietf/utils/management/commands/dumprelated.py index 48583f0aa..61b38441d 100644 --- a/ietf/utils/management/commands/dumprelated.py +++ b/ietf/utils/management/commands/dumprelated.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved import warnings from collections import OrderedDict @@ -152,7 +153,7 @@ class Command(BaseCommand): Collate the objects to be serialized. If count_only is True, just count the number of objects to be serialized. """ - models = serializers.sort_dependencies(app_list.items()) + models = serializers.sort_dependencies(list(app_list.items())) for model in models: if model in excluded_models: continue diff --git a/ietf/utils/management/commands/loadrelated.py b/ietf/utils/management/commands/loadrelated.py index 31d24dfb2..2e68d2163 100644 --- a/ietf/utils/management/commands/loadrelated.py +++ b/ietf/utils/management/commands/loadrelated.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import gzip import os @@ -26,7 +26,7 @@ import debug # pyflakes:ignore from ietf.community.models import notify_events class Command(loaddata.Command): - help = (u""" + help = (""" Load a fixture of related objects to the database. The fixture is expected to contain a set of related objects, created with the 'dumprelated' management diff --git a/ietf/utils/management/commands/makefixture.py b/ietf/utils/management/commands/makefixture.py index 907ec3185..5046eb7ea 100644 --- a/ietf/utils/management/commands/makefixture.py +++ b/ietf/utils/management/commands/makefixture.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved # From https://github.com/ericholscher/django-test-utils/blob/master/test_utils/management/commands/makefixture.py """ "Make fixture" command. @@ -101,7 +102,7 @@ class Command(LabelCommand): objects = [] for model, slice in models: - if isinstance(slice, basestring) and slice: + if isinstance(slice, str) and slice: objects.extend(model._default_manager.filter(pk__exact=slice)) elif not slice or type(slice) is list: items = model._default_manager.all() @@ -132,7 +133,7 @@ class Command(LabelCommand): related = [] for obj in objects: if DEBUG: - print "Adding %s[%s]" % (model_name(obj), obj.pk) + print("Adding %s[%s]" % (model_name(obj), obj.pk)) # follow forward relation fields for f in obj.__class__._meta.fields + obj.__class__._meta.many_to_many: if isinstance(f, ForeignKey): @@ -150,7 +151,7 @@ class Command(LabelCommand): try: return serializers.serialize(format, all, indent=indent) - except Exception, e: + except Exception as e: if show_traceback: raise raise CommandError("Unable to serialize database: %s" % e) diff --git a/ietf/utils/management/commands/populate_yang_model_dirs.py b/ietf/utils/management/commands/populate_yang_model_dirs.py index 9ea4e9ab4..5d7adea17 100644 --- a/ietf/utils/management/commands/populate_yang_model_dirs.py +++ b/ietf/utils/management/commands/populate_yang_model_dirs.py @@ -1,11 +1,12 @@ -from __future__ import print_function, unicode_literals +# Copyright The IETF Trust 2016-2019, All Rights Reserved + import os import sys import time from pathlib2 import Path -from StringIO import StringIO +from io import StringIO from textwrap import dedent from xym import xym diff --git a/ietf/utils/management/commands/pyflakes.py b/ietf/utils/management/commands/pyflakes.py index 376df9986..449263748 100644 --- a/ietf/utils/management/commands/pyflakes.py +++ b/ietf/utils/management/commands/pyflakes.py @@ -1,4 +1,5 @@ -from __future__ import absolute_import +# Copyright The IETF Trust 2014-2019, All Rights Reserved + import ast import os from pyflakes import checker, messages @@ -50,7 +51,7 @@ def check(codeString, filename, verbosity=1): try: with BlackHole(): tree = ast.parse(codeString, filename) - except SyntaxError, e: + except SyntaxError as e: return [PySyntaxError(filename, e.lineno, e.offset, e.text)] else: # Okay, it's syntactically valid. Now parse it into an ast and check @@ -82,7 +83,7 @@ def checkPath(filename, verbosity): """ try: return check(file(filename, 'U').read() + '\n', filename, verbosity) - except IOError, msg: + except IOError as msg: return ["%s: %s" % (filename, msg.args[1])] except TypeError: pass @@ -97,7 +98,7 @@ def checkPaths(filenames, verbosity): try: warnings.extend(checkPath(os.path.join(dirpath, filename), verbosity)) except TypeError as e: - print("Exception while processing dirpath=%s, filename=%s: %s" % (dirpath, filename,e )) + print(("Exception while processing dirpath=%s, filename=%s: %s" % (dirpath, filename,e ))) raise else: warnings.extend(checkPath(arg, verbosity)) @@ -114,11 +115,11 @@ class Command(BaseCommand): filenames = getattr(settings, 'PYFLAKES_DEFAULT_ARGS', ['.']) verbosity = int(options.get('verbosity')) warnings = checkPaths(filenames, verbosity=verbosity) - print "" + print("") for warning in warnings: - print warning + print(warning) if warnings: - print 'Total warnings: %d' % len(warnings) + print('Total warnings: %d' % len(warnings)) raise SystemExit(1) diff --git a/ietf/utils/management/commands/run_yang_model_checks.py b/ietf/utils/management/commands/run_yang_model_checks.py index 75569e611..8df7e9da8 100644 --- a/ietf/utils/management/commands/run_yang_model_checks.py +++ b/ietf/utils/management/commands/run_yang_model_checks.py @@ -1,4 +1,5 @@ -from __future__ import print_function, unicode_literals +# Copyright The IETF Trust 2017-2019, All Rights Reserved + import sys import json diff --git a/ietf/utils/management/commands/send_apikey_usage_emails.py b/ietf/utils/management/commands/send_apikey_usage_emails.py index 2718ef02a..ead143e92 100644 --- a/ietf/utils/management/commands/send_apikey_usage_emails.py +++ b/ietf/utils/management/commands/send_apikey_usage_emails.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright The IETF Trust 2017, All Rights Reserved -from __future__ import print_function, unicode_literals +# Copyright The IETF Trust 2017-2019, All Rights Reserved + import datetime diff --git a/ietf/utils/management/commands/send_gdpr_consent_request.py b/ietf/utils/management/commands/send_gdpr_consent_request.py index 80b6e174e..b9a37e4a3 100644 --- a/ietf/utils/management/commands/send_gdpr_consent_request.py +++ b/ietf/utils/management/commands/send_gdpr_consent_request.py @@ -1,6 +1,6 @@ -# Copyright The IETF Trust 2016, All Rights Reserved +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import datetime import time @@ -14,7 +14,7 @@ from ietf.person.models import Person, PersonEvent from ietf.utils.mail import send_mail class Command(BaseCommand): - help = (u""" + help = (""" Send GDPR consent request emails to persons who have not indicated consent to having their personal information stored. Each send is logged as a PersonEvent. diff --git a/ietf/utils/management/commands/update_community_list_index.py b/ietf/utils/management/commands/update_community_list_index.py index cecf68e8a..a7d8bcbfe 100644 --- a/ietf/utils/management/commands/update_community_list_index.py +++ b/ietf/utils/management/commands/update_community_list_index.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + from django.core.management.base import BaseCommand @@ -11,7 +11,7 @@ from ietf.community.models import SearchRule from ietf.community.utils import reset_name_contains_index_for_rule class Command(BaseCommand): - help = (u""" + help = (""" Update the index tables for stored regex-based document search rules. """) diff --git a/ietf/utils/management/commands/update_external_command_info.py b/ietf/utils/management/commands/update_external_command_info.py index 04949951c..d950eb01b 100644 --- a/ietf/utils/management/commands/update_external_command_info.py +++ b/ietf/utils/management/commands/update_external_command_info.py @@ -1,4 +1,5 @@ -from __future__ import print_function, unicode_literals +# Copyright The IETF Trust 2017-2019, All Rights Reserved + import sys diff --git a/ietf/utils/markup_txt.py b/ietf/utils/markup_txt.py index fd71a517f..fe69e61e6 100644 --- a/ietf/utils/markup_txt.py +++ b/ietf/utils/markup_txt.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2009-2019, All Rights Reserved # Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen # @@ -42,7 +43,7 @@ from ietf.utils.text import wordwrap def markup_ascii(content, width=None): log.unreachable('2017-12-08') if six.PY2: - assert isinstance(content, basestring) + assert isinstance(content, str) # at this point, "content" is normal string # fix most common non-ASCII characters t1 = string.maketrans("\x91\x92\x93\x94\x95\x96\x97\xc6\xe8\xe9", "\'\'\"\"o--\'ee") diff --git a/ietf/utils/migrations/0001_initial.py b/ietf/utils/migrations/0001_initial.py index 0d4130201..38c7566ae 100644 --- a/ietf/utils/migrations/0001_initial.py +++ b/ietf/utils/migrations/0001_initial.py @@ -1,6 +1,7 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Generated by Django 1.11.10 on 2018-02-20 10:52 -from __future__ import unicode_literals + from django.db import migrations, models diff --git a/ietf/utils/ordereddict.py b/ietf/utils/ordereddict.py index 94cc04e6c..18ec55f8f 100644 --- a/ietf/utils/ordereddict.py +++ b/ietf/utils/ordereddict.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved def insert_after_in_ordered_dict(dictionary, key, value, after): """There's no "insert" in ordered dict so simulate it instead by re-adding entries. Obviously that's not ideal, but for small dicts the @@ -5,7 +6,7 @@ def insert_after_in_ordered_dict(dictionary, key, value, after): dictionary[key] = value reorder = False - l = dictionary.items() # don't mutate the dict while looping + l = list(dictionary.items()) # don't mutate the dict while looping for k, v in l: if reorder and k != key: del dictionary[k] diff --git a/ietf/utils/templatetags/htmlfilters.py b/ietf/utils/templatetags/htmlfilters.py index 4bae6da2a..6d8e666b7 100644 --- a/ietf/utils/templatetags/htmlfilters.py +++ b/ietf/utils/templatetags/htmlfilters.py @@ -1,6 +1,6 @@ -# Copyright the IETF Trust 2017, All Rights Reserved +# Copyright The IETF Trust 2017-2019, All Rights Reserved + -from __future__ import unicode_literals from django.template.library import Library from django.template.defaultfilters import stringfilter diff --git a/ietf/utils/templatetags/textfilters.py b/ietf/utils/templatetags/textfilters.py index 6c8102d5e..63a694199 100644 --- a/ietf/utils/templatetags/textfilters.py +++ b/ietf/utils/templatetags/textfilters.py @@ -1,4 +1,5 @@ -from __future__ import unicode_literals +# Copyright The IETF Trust 2016-2019, All Rights Reserved + import bleach diff --git a/ietf/utils/test_data.py b/ietf/utils/test_data.py index 94e34a030..be8f7b791 100644 --- a/ietf/utils/test_data.py +++ b/ietf/utils/test_data.py @@ -1,7 +1,7 @@ -# Copyright The IETF Trust 2017-2019, All Rights Reserved +# Copyright The IETF Trust 2011-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals + import datetime @@ -98,7 +98,7 @@ def make_immutable_base_data(): # one area area = create_group(name="Far Future", acronym="farfut", type_id="area", parent=ietf) - create_person(area, "ad", name=u"Areað Irector", username="ad", email_address="aread@example.org") + create_person(area, "ad", name="Areað Irector", username="ad", email_address="aread@example.org") # second area opsarea = create_group(name="Operations", acronym="ops", type_id="area", parent=ietf) @@ -421,7 +421,7 @@ def make_review_data(doc): u = User.objects.create(username="reviewer") u.set_password("reviewer+password") u.save() - reviewer = Person.objects.create(name=u"Some Réviewer", ascii="Some Reviewer", user=u) + reviewer = Person.objects.create(name="Some Réviewer", ascii="Some Reviewer", user=u) email = Email.objects.create(address="reviewer@example.com", person=reviewer, origin=u.username) for team in (team1, team2, team3): @@ -444,14 +444,14 @@ def make_review_data(doc): u = User.objects.create(username="reviewsecretary") u.set_password("reviewsecretary+password") u.save() - reviewsecretary = Person.objects.create(name=u"Réview Secretary", ascii="Review Secretary", user=u) + reviewsecretary = Person.objects.create(name="Réview Secretary", ascii="Review Secretary", user=u) reviewsecretary_email = Email.objects.create(address="reviewsecretary@example.com", person=reviewsecretary, origin=u.username) Role.objects.create(name_id="secr", person=reviewsecretary, email=reviewsecretary_email, group=team1) u = User.objects.create(username="reviewsecretary3") u.set_password("reviewsecretary3+password") u.save() - reviewsecretary3 = Person.objects.create(name=u"Réview Secretary3", ascii="Review Secretary3", user=u) + reviewsecretary3 = Person.objects.create(name="Réview Secretary3", ascii="Review Secretary3", user=u) reviewsecretary3_email = Email.objects.create(address="reviewsecretary3@example.com", person=reviewsecretary, origin=u.username) Role.objects.create(name_id="secr", person=reviewsecretary3, email=reviewsecretary3_email, group=team3) diff --git a/ietf/utils/test_runner.py b/ietf/utils/test_runner.py index 67eacab25..252643668 100644 --- a/ietf/utils/test_runner.py +++ b/ietf/utils/test_runner.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007-2019, All Rights Reserved +# Copyright The IETF Trust 2009-2019, All Rights Reserved # -*- coding: utf-8 -*- @@ -93,14 +93,14 @@ def safe_create_test_db(self, verbosity, *args, **kwargs): global test_database_name, old_create keepdb = kwargs.get('keepdb', False) if not keepdb: - print " Creating test database..." + print(" Creating test database...") if settings.DATABASES["default"]["ENGINE"] == 'django.db.backends.mysql': settings.DATABASES["default"]["OPTIONS"] = settings.DATABASE_TEST_OPTIONS - print " Using OPTIONS: %s" % settings.DATABASES["default"]["OPTIONS"] + print(" Using OPTIONS: %s" % settings.DATABASES["default"]["OPTIONS"]) test_database_name = old_create(self, 0, *args, **kwargs) if settings.GLOBAL_TEST_FIXTURES: - print " Loading global test fixtures: %s" % ", ".join(settings.GLOBAL_TEST_FIXTURES) + print(" Loading global test fixtures: %s" % ", ".join(settings.GLOBAL_TEST_FIXTURES)) loadable = [f for f in settings.GLOBAL_TEST_FIXTURES if "." not in f] call_command('loaddata', *loadable, verbosity=int(verbosity)-1, commit=False, database="default") @@ -120,7 +120,7 @@ def safe_destroy_test_db(*args, **kwargs): keepdb = kwargs.get('keepdb', False) if not keepdb: if settings.DATABASES["default"]["NAME"] != test_database_name: - print ' NOT SAFE; Changing settings.DATABASES["default"]["NAME"] from %s to %s' % (settings.DATABASES["default"]["NAME"], test_database_name) + print(' NOT SAFE; Changing settings.DATABASES["default"]["NAME"] from %s to %s' % (settings.DATABASES["default"]["NAME"], test_database_name)) settings.DATABASES["default"]["NAME"] = test_database_name return old_destroy(*args, **kwargs) @@ -296,11 +296,11 @@ class CoverageTest(unittest.TestCase): latest_coverage_version = self.runner.coverage_master["version"] master_data = self.runner.coverage_master[latest_coverage_version][test] - master_missing = [ k for k,v in master_data["covered"].items() if not v ] + master_missing = [ k for k,v in list(master_data["covered"].items()) if not v ] master_coverage = master_data["coverage"] test_data = self.runner.coverage_data[test] - test_missing = [ k for k,v in test_data["covered"].items() if not v ] + test_missing = [ k for k,v in list(test_data["covered"].items()) if not v ] test_coverage = test_data["coverage"] # Assert coverage failure only if we're running the full test suite -- if we're @@ -564,7 +564,7 @@ class IetfTestRunner(DiscoverRunner): self.code_coverage_checker.start() if settings.SITE_ID != 1: - print " Changing SITE_ID to '1' during testing." + print(" Changing SITE_ID to '1' during testing.") settings.SITE_ID = 1 if settings.TEMPLATES[0]['OPTIONS']['string_if_invalid'] != '': @@ -572,7 +572,7 @@ class IetfTestRunner(DiscoverRunner): settings.TEMPLATES[0]['OPTIONS']['string_if_invalid'] = '' if settings.INTERNAL_IPS: - print " Changing INTERNAL_IPS to '[]' during testing." + print(" Changing INTERNAL_IPS to '[]' during testing.") settings.INTERNAL_IPS = [] assert not settings.IDTRACKER_BASE_URL.endswith('/') @@ -586,7 +586,7 @@ class IetfTestRunner(DiscoverRunner): ietf.utils.mail.SMTP_ADDR['port'] = base + offset self.smtpd_driver = SMTPTestServerDriver((ietf.utils.mail.SMTP_ADDR['ip4'],ietf.utils.mail.SMTP_ADDR['port']),None) self.smtpd_driver.start() - print(" Running an SMTP test server on %(ip4)s:%(port)s to catch outgoing email." % ietf.utils.mail.SMTP_ADDR) + print((" Running an SMTP test server on %(ip4)s:%(port)s to catch outgoing email." % ietf.utils.mail.SMTP_ADDR)) break except socket.error: pass @@ -594,9 +594,9 @@ class IetfTestRunner(DiscoverRunner): maybe_create_svn_symlinks(settings) if os.path.exists(settings.UTILS_TEST_RANDOM_STATE_FILE): - print " Loading factory-boy random state from %s" % settings.UTILS_TEST_RANDOM_STATE_FILE + print(" Loading factory-boy random state from %s" % settings.UTILS_TEST_RANDOM_STATE_FILE) else: - print " Saving factory-boy random state to %s" % settings.UTILS_TEST_RANDOM_STATE_FILE + print(" Saving factory-boy random state to %s" % settings.UTILS_TEST_RANDOM_STATE_FILE) with open(settings.UTILS_TEST_RANDOM_STATE_FILE, 'w') as f: s = factory.random.get_random_state() json.dump(s, f) @@ -709,7 +709,7 @@ class IetfTestRunner(DiscoverRunner): if self.run_full_test_suite: print("Test coverage data:") else: - print("Test coverage for this test run across the related app%s (%s):" % (("s" if len(self.test_apps)>1 else ""), ", ".join(self.test_apps))) + print(("Test coverage for this test run across the related app%s (%s):" % (("s" if len(self.test_apps)>1 else ""), ", ".join(self.test_apps)))) for test in ["template", "url", "code"]: latest_coverage_version = self.coverage_master["version"] @@ -724,19 +724,19 @@ class IetfTestRunner(DiscoverRunner): test_coverage = test_data["coverage"] if self.run_full_test_suite: - print(" %8s coverage: %6.2f%% (%s: %6.2f%%)" % - (test.capitalize(), test_coverage*100, latest_coverage_version, master_coverage*100, )) + print((" %8s coverage: %6.2f%% (%s: %6.2f%%)" % + (test.capitalize(), test_coverage*100, latest_coverage_version, master_coverage*100, ))) else: - print(" %8s coverage: %6.2f%%" % - (test.capitalize(), test_coverage*100, )) + print((" %8s coverage: %6.2f%%" % + (test.capitalize(), test_coverage*100, ))) - print(""" + print((""" Per-file code and template coverage and per-url-pattern url coverage data for the latest test run has been written to %s. Per-statement code coverage data has been written to '.coverage', readable by the 'coverage' program. - """.replace(" ","") % (settings.TEST_COVERAGE_LATEST_FILE)) + """.replace(" ","") % (settings.TEST_COVERAGE_LATEST_FILE))) save_test_results(failures, test_labels) diff --git a/ietf/utils/test_utils.py b/ietf/utils/test_utils.py index 4cb5020e6..c7134b970 100644 --- a/ietf/utils/test_utils.py +++ b/ietf/utils/test_utils.py @@ -1,4 +1,4 @@ -# Copyright The IETF Trust 2007, All Rights Reserved +# Copyright The IETF Trust 2009-2019, All Rights Reserved # Portion Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # All rights reserved. Contact: Pasi Eronen @@ -37,7 +37,7 @@ import re import email import html5lib import sys -import urllib2 +import urllib.request, urllib.error, urllib.parse from unittest.util import strclass from bs4 import BeautifulSoup @@ -53,7 +53,7 @@ real_database_name = settings.DATABASES["default"]["NAME"] def split_url(url): if "?" in url: url, args = url.split("?", 1) - args = dict([ map(urllib2.unquote,arg.split("=", 1)) for arg in args.split("&") if "=" in arg ]) + args = dict([ list(map(urllib.parse.unquote,arg.split("=", 1))) for arg in args.split("&") if "=" in arg ]) else: args = {} return url, args @@ -145,7 +145,7 @@ class TestCase(django.test.TestCase): errors = [html.tostring(n).decode() for n in PyQuery(response.content)(error_css_selector)] if errors: - explanation = u"{} != {}\nGot form back with errors:\n----\n".format(response.status_code, 302) + u"----\n".join(errors) + explanation = "{} != {}\nGot form back with errors:\n----\n".format(response.status_code, 302) + "----\n".join(errors) self.assertEqual(response.status_code, 302, explanation) self.assertEqual(response.status_code, 302) diff --git a/ietf/utils/tests.py b/ietf/utils/tests.py index 8be182604..f28fb55da 100644 --- a/ietf/utils/tests.py +++ b/ietf/utils/tests.py @@ -1,6 +1,6 @@ # Copyright The IETF Trust 2014-2019, All Rights Reserved # -*- coding: utf-8 -*- -from __future__ import unicode_literals, print_function + import os.path import types @@ -11,8 +11,8 @@ from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from fnmatch import fnmatch from importlib import import_module -from pipe import pipe -from StringIO import StringIO +from .pipe import pipe +from io import StringIO from textwrap import dedent from unittest import skipIf from tempfile import mkdtemp @@ -115,7 +115,7 @@ class TestSMTPServer(TestCase): def test_address_rejected(self): def send_simple_mail(to): - send_mail_text(None, to=to, frm=None, subject="Test for rejection", txt=u"dummy body") + send_mail_text(None, to=to, frm=None, subject="Test for rejection", txt="dummy body") len_before = len(outbox) send_simple_mail('good@example.com,poison@example.com') @@ -131,7 +131,7 @@ class TestSMTPServer(TestCase): def send_complex_mail(to): msg = MIMEMultipart() - textpart= MIMEText(dedent(u"""\ + textpart= MIMEText(dedent("""\ Sometimes people send mail with things like “smart quotes” in them. Sometimes they have attachments with pictures. """),_charset='utf-8') @@ -139,7 +139,7 @@ class TestSMTPServer(TestCase): img = MIMEImage(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x02\x88IDATx\xda\xa5\x93\xcbO\x13Q\x14\xc6\xbf\xb9\xd32}L\x9fZ\x06\x10Q\x90\x10\x85b\x89\xfe\x01\x06BXK"\xd4hB\xdc\xa0\x06q\xe1c% H1l\xd0\x8dbT6\x1a5\x91\x12#K\x891\xf2\x07\x98\xc8[L\x1ay\xa8@\xdb\xd0\xd2\xe9\x83N;\xbdc\x1f\x11\x03\x04\x17zW\'_\xce\xf9\xdd\xef\x9c\x9c\xc3\xe0?\x1f\xb3S\xf8\xfe\xba\xc2Be\xa9]m\xd6\x9e\xe6x\xde\x9e\xd1\xa4HdF\x0e\xc5G\x89\x8a{X\xec\xfc\x1a\xdc\x1307X\xd4$T\nC\xc6\xfc|\x13\x8d\xa6\x00\xe5O\x16\xd1\xb3\x10}\xbe\x90w\xce\xdbZyeed\x17\xc03(4\x15\x9d(s\x13\xca!\x10\xa6\xb0\x1a\xb6\x9b\x0b\x84\x95\xb4F@\x89\x84\xe5O\x0b\xcdG\xaf\xae\x8dl\x01V\x9f\x1d\xb4q\x16\xde\xa33[\x8d\xe3\x93)\xdc\x7f\x9b\xc4\xf3\x1b\x1c,|\xaex#\n\xb4\x0cH\xb8\xd6\xa8F\xad\x83El# \xc6\x83\xb1\xf2\xa2\x0bK\xfe,`y\xd0\xe6*\x03\xaes\x0c\xea\xaas.\xc6g\x14t\xbcR\xd0P\x03t;\tX\x15\x83\xd5\xf9\xc5\xbe\x926_W6\xe3\xe7ca\xc2Z,82\xb1\xeb\r\x8b\xb1)\x82\xde\xa6\x14\xea\xec4\x0b\xf88K\xd0\xe5fQ_M\xd1s&\x95k\xe9\x87w\xf2\xc0eoM\x16\xe0\x1b*\xdc4XM\x9aL\xfca\x8e\xc5\xbd1\x0e//\xc6`\xd5\xe7Z\x08\xa6[8\xffT\x87\xeb\r\x12\xea\xabr\x80p \x14\xcfo]\xd5f\x01k\x8fl\x9bF3\xaf\xf9=\xb0X\x82\x81.O\xd96\xc4\x9d\x9a\xb8\x11\x89\x17\xb4\xf9s\x80\xe5\x01\xc3\xc4\xfe}FG\\\x064\xaa\xbf/\x0eM3\x92i\x13\xe1\x908Yr3\x9ck\xe1[\xbf\xd6%X\xf4\x9d\xef=z$(\xc1\xa9\xc3Q\xf0\x1c\xddV(\xa7\x18Ly9L\xafq8{\\D0\x14\xbd{\xe4V\xac3\x0bX\xe8\xd7\xdb\xb4,\xf5\x18\xb4j\xe3\xf8\xa2\x1e/\xa6\xac`\x18\x06\x02\x9f\x84\x8a\xa4\x07\x16c\xb1\xbe\xc9\xa2\xf6P\x04-\x8e\x00\x12\xc9\x84(&\xd9\xf2\x8a\x8e\x88\x7fk[\xbet\xe75\x0bzf\x98cI\xd6\xe6\xfc\xba\x06\xd3~\x1d\x12\xe9\x9fK\xcd\x12N\x16\xc4\xa0UQH)\x8a\x95\x08\x9c\xf6^\xc9\xbdk\x95\xe7o\xab\x9c&\xb5\xf2\x84W3\xa6\x9dG\x92\x19_$\xa9\x84\xd6%r\xc9\xde\x97\x1c\xde\xf3\x98\x96\xee\xb0\x16\x99\xd2v\x15\x94\xc6<\xc2Te\xb4\x04Ufe\x85\x8c2\x84<(\xeb\x91\xf7>\xa6\x7fy\xbf\x00\x96T\xff\x11\xf7\xd8R\xb9\x00\x00\x00\x00IEND\xaeB`\x82') msg.attach(img) - send_mail_mime(request=None, to=to, frm=settings.DEFAULT_FROM_EMAIL, subject=u'это сложно', msg=msg, cc=None, extra=None) + send_mail_mime(request=None, to=to, frm=settings.DEFAULT_FROM_EMAIL, subject='это сложно', msg=msg, cc=None, extra=None) len_before = len(outbox) send_complex_mail('good@example.com') @@ -157,12 +157,12 @@ def get_callbacks(urllist): callbacks.update(get_callbacks(entry.url_patterns)) else: if hasattr(entry, '_callback_str'): - callbacks.add(unicode(entry._callback_str)) + callbacks.add(str(entry._callback_str)) if (hasattr(entry, 'callback') and entry.callback and type(entry.callback) in [types.FunctionType, types.MethodType ]): callbacks.add("%s.%s" % (entry.callback.__module__, entry.callback.__name__)) if hasattr(entry, 'name') and entry.name: - callbacks.add(unicode(entry.name)) + callbacks.add(str(entry.name)) # There are some entries we don't handle here, mostly clases # (such as Feed subclasses) @@ -205,7 +205,7 @@ class TemplateChecksTestCase(TestCase): def apply_template_test(self, func, node_type, msg, *args, **kwargs): errors = [] - for path, template in self.templates.items(): + for path, template in list(self.templates.items()): origin = str(template.origin).replace(settings.BASE_DIR, '') for node in template: for child in node.get_nodes_by_type(node_type): @@ -413,13 +413,13 @@ class DraftTests(TestCase): self.assertEqual(self.draft.get_status(),'Informational') def test_get_authors(self): - self.assertTrue(all([u'@' in author for author in self.draft.get_authors()])) + self.assertTrue(all(['@' in author for author in self.draft.get_authors()])) def test_get_authors_with_firm(self): - self.assertTrue(all([u'@' in author for author in self.draft.get_authors_with_firm()])) + self.assertTrue(all(['@' in author for author in self.draft.get_authors_with_firm()])) def test_old_get_refs(self): - self.assertEqual(self.draft.old_get_refs()[1][0],u'rfc2119') + self.assertEqual(self.draft.old_get_refs()[1][0],'rfc2119') def test_get_meta(self): tempdir = mkdtemp() diff --git a/ietf/utils/tests_restapi.py b/ietf/utils/tests_restapi.py index 93f0df687..31f1be70f 100644 --- a/ietf/utils/tests_restapi.py +++ b/ietf/utils/tests_restapi.py @@ -1,4 +1,5 @@ -from __future__ import print_function +# Copyright The IETF Trust 2014-2019, All Rights Reserved + import debug debug.debug = True @@ -73,6 +74,6 @@ class RestApi(ResourceTestCaseMixin, TestCase): for doc in doclist: for key in doc: value = doc[key] - if isinstance(value, basestring) and value.startswith('%s/'%apitop): + if isinstance(value, str) and value.startswith('%s/'%apitop): self.api_client.get(value, format='json') diff --git a/ietf/utils/texescape.py b/ietf/utils/texescape.py index 0c73fea96..83a78812e 100644 --- a/ietf/utils/texescape.py +++ b/ietf/utils/texescape.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2018-2019, All Rights Reserved # -*- coding: utf-8 -*- # Copied from https://github.com/sphinx-doc/sphinx/blob/master/sphinx/util/texescape.py # Copyright and license as indicated in the original and below @@ -11,7 +12,7 @@ :license: BSD, see LICENSE for details. """ -from __future__ import unicode_literals + tex_replacements = [ # map TeX special chars diff --git a/ietf/utils/text.py b/ietf/utils/text.py index 30a38891d..06a4d05e9 100644 --- a/ietf/utils/text.py +++ b/ietf/utils/text.py @@ -1,4 +1,5 @@ -from __future__ import unicode_literals +# Copyright The IETF Trust 2016-2019, All Rights Reserved + import re import textwrap @@ -11,7 +12,7 @@ from django.utils.safestring import mark_safe import debug # pyflakes:ignore -from texescape import init as texescape_init, tex_escape_map +from .texescape import init as texescape_init, tex_escape_map @keep_lazy(six.text_type) def xslugify(value): @@ -57,7 +58,7 @@ def fill(text, width): def wordwrap(text, width=80): """Wraps long lines without loosing the formatting and indentation of short lines""" - if not isinstance(text, (types.StringType,types.UnicodeType)): + if not isinstance(text, (bytes,str)): return text width = int(width) # ensure we have an int, if this is used as a template filter text = re.sub(" *\r\n", "\n", text) # get rid of DOS line endings @@ -173,7 +174,7 @@ def text_to_dict(t): def dict_to_text(d): "Convert a dictionary to RFC2822-formatted text" t = "" - for k, v in d.items(): + for k, v in list(d.items()): t += "%s: %s\n" % (k, v) return t diff --git a/ietf/utils/textupload.py b/ietf/utils/textupload.py index 574342d32..69f2af8b3 100644 --- a/ietf/utils/textupload.py +++ b/ietf/utils/textupload.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved import re from django.core.exceptions import ValidationError @@ -11,7 +12,7 @@ def get_cleaned_text_file_content(uploaded_file): django.core.exceptions.ValidationError exceptions.""" if not uploaded_file: - return u"" + return "" if uploaded_file.size and uploaded_file.size > 10 * 1000 * 1000: raise ValidationError("Text file too large (size %s)." % uploaded_file.size) diff --git a/ietf/utils/validators.py b/ietf/utils/validators.py index f2a6b319e..77e4bbf09 100644 --- a/ietf/utils/validators.py +++ b/ietf/utils/validators.py @@ -1,6 +1,6 @@ # -*- python -*- -# Copyright The IETF Trust 2007, All Rights Reserved -from __future__ import unicode_literals +# Copyright The IETF Trust 2016-2019, All Rights Reserved + import os import re diff --git a/ietf/virtualenv-manage.py b/ietf/virtualenv-manage.py index df6477fd9..dc318c738 100755 --- a/ietf/virtualenv-manage.py +++ b/ietf/virtualenv-manage.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2016-2019, All Rights Reserved #!/usr/bin/env python import os @@ -11,7 +12,7 @@ os.chdir(path) # Virtualenv support virtualenv_activation = os.path.join(path, "env", "bin", "activate_this.py") if os.path.exists(virtualenv_activation): - execfile(virtualenv_activation, dict(__file__=virtualenv_activation)) + exec(compile(open(virtualenv_activation, "rb").read(), virtualenv_activation, 'exec'), dict(__file__=virtualenv_activation)) else: raise RuntimeError("Could not find the expected virtual python environment.") diff --git a/ietf/wsgi.py b/ietf/wsgi.py index d82a32446..fc92e3e91 100644 --- a/ietf/wsgi.py +++ b/ietf/wsgi.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2013-2019, All Rights Reserved """ WSGI configuration for the datatracker. @@ -50,7 +51,7 @@ syslog.openlog("datatracker", syslog.LOG_PID, syslog.LOG_USER) virtualenv_activation = os.path.join(path, "env", "bin", "activate_this.py") if os.path.exists(virtualenv_activation): syslog.syslog("Starting datatracker wsgi with virtualenv %s" % os.path.dirname(os.path.dirname(virtualenv_activation))) - execfile(virtualenv_activation, dict(__file__=virtualenv_activation)) + exec(compile(open(virtualenv_activation, "rb").read(), virtualenv_activation, 'exec'), dict(__file__=virtualenv_activation)) else: syslog.syslog("Starting datatracker wsgi without virtualenv") diff --git a/tzparse.py b/tzparse.py index 8ba624730..ad264406b 100755 --- a/tzparse.py +++ b/tzparse.py @@ -1,3 +1,4 @@ +# Copyright The IETF Trust 2012-2019, All Rights Reserved #!/usr/bin/env python """ @@ -8,7 +9,7 @@ SYNOPSIS >>> tzparse("2008-09-08 14:40:35 +0200", "%Y-%m-%d %H:%M:%S %Z") datetime.datetime(2008, 9, 8, 14, 40, 35, tzinfo=pytz.FixedOffset(120)) - >>> print tzparse("14:40:35 CEST, 08 Sep 2008", "%H:%M:%S %Z, %d %b %Y") + >>> print(tzparse("14:40:35 CEST, 08 Sep 2008", "%H:%M:%S %Z, %d %b %Y")) 2008-09-08 14:40:35+02:00 DESCRIPTION @@ -94,31 +95,31 @@ def tzparse(string, format): Given a time specification string and a format, tzparse() returns a localized datetime.datetime. - >>> print tzparse("9 Oct 2009 CEST 13:58", "%d %b %Y %Z %H:%M") + >>> print(tzparse("9 Oct 2009 CEST 13:58", "%d %b %Y %Z %H:%M")) 2009-10-09 13:58:00+02:00 - >>> print tzparse("9 Oct 2009 13:58:00 Europe/Stockholm", "%d %b %Y %H:%M:%S %Z") + >>> print(tzparse("9 Oct 2009 13:58:00 Europe/Stockholm", "%d %b %Y %H:%M:%S %Z")) 2009-10-09 13:58:00+02:00 - >>> print tzparse("9 Oct 2009 13:58:00 +0200", "%d %b %Y %H:%M:%S %Z") + >>> print(tzparse("9 Oct 2009 13:58:00 +0200", "%d %b %Y %H:%M:%S %Z")) 2009-10-09 13:58:00+02:00 - >>> print tzparse("Fri, 9 Oct 2009 13:58:00 +0200", "%a, %d %b %Y %H:%M:%S %Z") + >>> print(tzparse("Fri, 9 Oct 2009 13:58:00 +0200", "%a, %d %b %Y %H:%M:%S %Z")) 2009-10-09 13:58:00+02:00 - >>> print tzparse("2009-10-09 13:58:00 EST", '%Y-%m-%d %H:%M:%S %Z') + >>> print(tzparse("2009-10-09 13:58:00 EST", '%Y-%m-%d %H:%M:%S %Z')) 2009-10-09 13:58:00-05:00 - >>> print tzparse("2009-10-09 13:58:00+02:00", "%Y-%m-%d %H:%M:%S%Z") + >>> print(tzparse("2009-10-09 13:58:00+02:00", "%Y-%m-%d %H:%M:%S%Z")) 2009-10-09 13:58:00+02:00 - >>> print tzparse("1985-04-12T23:20:50Z", "%Y-%m-%dT%H:%M:%S%Z") + >>> print(tzparse("1985-04-12T23:20:50Z", "%Y-%m-%dT%H:%M:%S%Z")) 1985-04-12 23:20:50+00:00 - >>> print tzparse("1996-12-19T16:39:57-08:00", "%Y-%m-%dT%H:%M:%S%Z") + >>> print(tzparse("1996-12-19T16:39:57-08:00", "%Y-%m-%dT%H:%M:%S%Z")) 1996-12-19 16:39:57-08:00 - >>> print tzparse("1996-12-19T16:39:57", "%Y-%m-%dT%H:%M:%S") + >>> print(tzparse("1996-12-19T16:39:57", "%Y-%m-%dT%H:%M:%S")) 1996-12-19 16:39:57+01:00 """ @@ -131,8 +132,8 @@ def tzparse(string, format): # from the string, too. def fmt2pat(s): - s = re.sub("%[dHIjmMSUwWyY]", "\d+", s) - s = re.sub("%[aAbBp]", "\w+", s) + s = re.sub("%[dHIjmMSUwWyY]", r"\\d+", s) + s = re.sub("%[aAbBp]", r"\\w+", s) s = re.sub("%[cxX]", ".+", s) s = s.replace("%%", "%") return s @@ -177,9 +178,9 @@ def tzparse(string, format): if __name__ == "__main__": import sys if len(sys.argv[1:]) == 2: - print tzparse(sys.argv[1], sys.argv[2]) + print(tzparse(sys.argv[1], sys.argv[2])) else: - print "Running module tests:\n" + print("Running module tests:\n") import doctest - print doctest.testmod() + print(doctest.testmod()) \ No newline at end of file