Run modernize, pyupgrade, autoflake and isort

This commit is contained in:
Indico Team 2020-11-10 13:08:04 +01:00 committed by Adrian Moennich
parent 15afb637b6
commit f2755b4be4
87 changed files with 223 additions and 292 deletions

View File

@ -2,9 +2,8 @@
line_length=120
multi_line_output=0
lines_after_imports=2
add_imports=from __future__ import unicode_literals
sections=FUTURE,STDLIB,THIRDPARTY,INDICO,FIRSTPARTY,LOCALFOLDER
known_third_party=flask_multipass,flask_pluginengine
known_first_party=indico_*
known_indico=indico
skip_glob=20??????????_*_*.py
not_skip=__init__.py

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core import signals
from indico.util.i18n import make_bound_gettext

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask_pluginengine import depends, trim_docstring
@ -27,14 +26,14 @@ class LiveSyncPluginBase(IndicoPlugin): # pragma: no cover
category = PluginCategory.synchronization
def init(self):
super(LiveSyncPluginBase, self).init()
for name, backend_class in self.backend_classes.iteritems():
super().init()
for name, backend_class in self.backend_classes.items():
assert backend_class.plugin is None
backend_class.plugin = type(self)
LiveSyncPlugin.instance.register_backend_class(name, backend_class)
class LiveSyncBackendBase(object):
class LiveSyncBackendBase:
"""Base class for livesync backends"""
#: the plugin containing the agent

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core.plugins import IndicoPluginBlueprint

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import click
from flask_pluginengine import current_plugin
@ -27,15 +26,15 @@ def cli():
@cli.command()
def available_backends():
"""Lists the currently available backend types"""
print 'The following LiveSync agents are available:'
for name, backend in current_plugin.backend_classes.iteritems():
print cformat(' - %{white!}{}%{reset}: {} ({})').format(name, backend.title, backend.description)
print('The following LiveSync agents are available:')
for name, backend in current_plugin.backend_classes.items():
print(cformat(' - %{white!}{}%{reset}: {} ({})').format(name, backend.title, backend.description))
@cli.command()
def agents():
"""Lists the currently active agents"""
print 'The following LiveSync agents are active:'
print('The following LiveSync agents are active:')
agent_list = LiveSyncAgent.find().order_by(LiveSyncAgent.backend_name, db.func.lower(LiveSyncAgent.name)).all()
table_data = [['ID', 'Name', 'Backend', 'Initial Export', 'Queue']]
for agent in agent_list:
@ -45,16 +44,16 @@ def agents():
backend_title = cformat('%{red!}invalid backend ({})%{reset}').format(agent.backend_name)
else:
backend_title = agent.backend.title
table_data.append([unicode(agent.id), agent.name, backend_title, initial,
unicode(agent.queue.filter_by(processed=False).count())])
table_data.append([str(agent.id), agent.name, backend_title, initial,
str(agent.queue.filter_by(processed=False).count())])
table = AsciiTable(table_data)
table.justify_columns[4] = 'right'
print table.table
print(table.table)
if not all(a.initial_data_exported for a in agent_list):
print
print "You need to perform the initial data export for some agents."
print cformat("To do so, run "
"%{yellow!}indico livesync initial-export %{reset}%{yellow}<agent_id>%{reset} for those agents.")
print()
print("You need to perform the initial data export for some agents.")
print(cformat("To do so, run "
"%{yellow!}indico livesync initial-export %{reset}%{yellow}<agent_id>%{reset} for those agents."))
@cli.command()
@ -64,15 +63,15 @@ def initial_export(agent_id, force):
"""Performs the initial data export for an agent"""
agent = LiveSyncAgent.find_first(id=agent_id)
if agent is None:
print 'No such agent'
print('No such agent')
return
if agent.backend is None:
print cformat('Cannot run agent %{red!}{}%{reset} (backend not found)').format(agent.name)
print(cformat('Cannot run agent %{red!}{}%{reset} (backend not found)').format(agent.name))
return
print cformat('Selected agent: %{white!}{}%{reset} ({})').format(agent.name, agent.backend.title)
print(cformat('Selected agent: %{white!}{}%{reset} ({})').format(agent.name, agent.backend.title))
if agent.initial_data_exported and not force:
print 'The initial export has already been performed for this agent.'
print cformat('To re-run it, use %{yellow!}--force%{reset}')
print('The initial export has already been performed for this agent.')
print(cformat('To re-run it, use %{yellow!}--force%{reset}'))
return
agent.create_backend().run_initial_export(Event.find(is_deleted=False))
@ -90,18 +89,18 @@ def run(agent_id, force=False):
else:
agent = LiveSyncAgent.find_first(id=agent_id)
if agent is None:
print 'No such agent'
print('No such agent')
return
agent_list = [agent]
for agent in agent_list:
if agent.backend is None:
print cformat('Skipping agent: %{red!}{}%{reset} (backend not found)').format(agent.name)
print(cformat('Skipping agent: %{red!}{}%{reset} (backend not found)').format(agent.name))
continue
if not agent.initial_data_exported and not force:
print cformat('Skipping agent: %{red!}{}%{reset} (initial export not performed)').format(agent.name)
print(cformat('Skipping agent: %{red!}{}%{reset} (initial export not performed)').format(agent.name))
continue
print cformat('Running agent: %{white!}{}%{reset}').format(agent.name)
print(cformat('Running agent: %{white!}{}%{reset}').format(agent.name))
try:
agent.create_backend().run()
db.session.commit()

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask import flash, redirect, request
from flask_pluginengine import current_plugin, render_plugin_template

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from wtforms.fields.core import StringField
from wtforms.validators import DataRequired

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from collections import defaultdict
@ -159,7 +158,7 @@ def _apply_changes(sender, **kwargs):
if not hasattr(g, 'livesync_changes'):
return
excluded_categories = get_excluded_categories()
for ref, changes in g.livesync_changes.iteritems():
for ref, changes in g.livesync_changes.items():
LiveSyncQueueEntry.create(changes, ref, excluded_categories=excluded_categories)

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask_pluginengine import current_plugin
@ -27,7 +26,7 @@ class MARCXMLGenerator:
@classmethod
def records_to_xml(cls, records):
mg = MARCXMLGenerator()
for entry, change in records.iteritems():
for entry, change in records.items():
mg.safe_add_object(entry, bool(change & SimpleChange.deleted))
return mg.get_xml()
@ -79,7 +78,7 @@ class MARCXMLGenerator:
elif isinstance(obj, Category):
pass # we don't send category updates
else:
raise ValueError('unknown object ref: {}'.format(obj))
raise ValueError(f'unknown object ref: {obj}')
return self.xml_generator.getXml()
def get_xml(self):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from sqlalchemy.dialects.postgresql import JSON
@ -73,4 +72,4 @@ class LiveSyncAgent(db.Model):
@return_ascii
def __repr__(self):
return '<LiveSyncAgent({}, {}, {})>'.format(self.id, self.backend_name, self.name)
return f'<LiveSyncAgent({self.id}, {self.backend_name}, {self.name})>'

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask import g
from werkzeug.datastructures import ImmutableDict
@ -47,14 +46,14 @@ _column_for_types = {
def _make_checks():
available_columns = set(_column_for_types.viewvalues())
available_columns = set(_column_for_types.values())
for link_type in EntryType:
required_col = _column_for_types[link_type]
forbidden_cols = available_columns - {required_col}
criteria = ['{} IS NULL'.format(col) for col in sorted(forbidden_cols)]
criteria += ['{} IS NOT NULL'.format(required_col)]
criteria = [f'{col} IS NULL' for col in sorted(forbidden_cols)]
criteria += [f'{required_col} IS NOT NULL']
condition = 'type != {} OR ({})'.format(link_type, ' AND '.join(criteria))
yield db.CheckConstraint(condition, 'valid_{}_entry'.format(link_type.name))
yield db.CheckConstraint(condition, f'valid_{link_type.name}_entry')
class LiveSyncQueueEntry(db.Model):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from wtforms.fields.html5 import IntegerField
from wtforms.validators import NumberRange
@ -48,7 +47,7 @@ class LiveSyncPlugin(IndicoPlugin):
category = PluginCategory.synchronization
def init(self):
super(LiveSyncPlugin, self).init()
super().init()
self.backend_classes = {}
connect_signals(self)
self.connect(signals.plugin.cli, self._extend_indico_cli)
@ -62,7 +61,7 @@ class LiveSyncPlugin(IndicoPlugin):
def register_backend_class(self, name, backend_class):
if name in self.backend_classes:
raise RuntimeError('Duplicate livesync backend: {}'.format(name))
raise RuntimeError(f'Duplicate livesync backend: {name}')
self.backend_classes[name] = backend_class
def _extend_plugin_details(self, plugin, **kwargs):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import itertools
from collections import defaultdict
@ -98,8 +97,7 @@ def _process_cascaded_category_contents(records):
if category_move_records:
changed_events.update(Event.find(Event.category_chain_overlaps(category_move_records)))
for elem in _process_cascaded_event_contents(records, additional_events=changed_events):
yield elem
yield from _process_cascaded_event_contents(records, additional_events=changed_events)
def _process_cascaded_event_contents(records, additional_events=None):
@ -124,8 +122,7 @@ def _process_cascaded_event_contents(records, additional_events=None):
if event_records:
changed_events.update(Event.find(Event.id.in_(event_records)))
for event in changed_events:
yield event
yield from changed_events
# Sessions are added (explicitly changed only, since they don't need to be sent anywhere)
if session_records:
@ -147,5 +144,4 @@ def _process_cascaded_event_contents(records, additional_events=None):
# Same for subcontributions
if subcontribution_records:
changed_subcontributions.update(SubContribution.find(SubContribution.id.in_(subcontribution_records)))
for subcontrib in changed_subcontributions:
yield subcontrib
yield from changed_subcontributions

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from celery.schedules import crontab

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core.db import db
from indico.util.struct.iterables import grouper
@ -13,7 +12,7 @@ from indico.util.struct.iterables import grouper
from indico_livesync import MARCXMLGenerator, process_records
class Uploader(object):
class Uploader:
"""Handles batch data upload to a remote service."""
#: Number of queue entries to process at a time
@ -35,7 +34,7 @@ class Uploader(object):
self.logger.info('%s processing batch %d', self_name, i)
try:
for j, proc_batch in enumerate(grouper(
process_records(batch).iteritems(), self.BATCH_SIZE, skip_missing=True), 1):
process_records(batch).items(), self.BATCH_SIZE, skip_missing=True), 1):
self.logger.info('%s uploading chunk #%d (batch %d)', self_name, j, i)
self.upload_records({k: v for k, v in proc_batch}, from_queue=True)
except Exception:

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from datetime import timedelta
@ -34,7 +33,7 @@ def obj_ref(obj):
elif isinstance(obj, SubContribution):
ref = {'type': EntryType.subcontribution, 'subcontrib_id': obj.id}
else:
raise ValueError('Unexpected object: {}'.format(obj.__class__.__name__))
raise ValueError(f'Unexpected object: {obj.__class__.__name__}')
return ImmutableDict(ref)
@ -58,8 +57,8 @@ def obj_deref(ref):
def clean_old_entries():
"""Deletes obsolete entries from the queues"""
from indico_livesync.plugin import LiveSyncPlugin
from indico_livesync.models.queue import LiveSyncQueueEntry
from indico_livesync.plugin import LiveSyncPlugin
queue_entry_ttl = LiveSyncPlugin.settings.get('queue_entry_ttl')
if not queue_entry_ttl:
@ -81,8 +80,8 @@ def compound_id(obj):
if isinstance(obj, (Category, Session)):
raise TypeError('Compound IDs are not supported for this entry type')
elif isinstance(obj, Event):
return unicode(obj.id)
return str(obj.id)
elif isinstance(obj, Contribution):
return '{}.{}'.format(obj.event_id, obj.id)
return f'{obj.event_id}.{obj.id}'
elif isinstance(obj, SubContribution):
return '{}.{}.{}'.format(obj.contribution.event_id, obj.contribution_id, obj.id)
return f'{obj.contribution.event_id}.{obj.contribution_id}.{obj.id}'

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,7 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from mock import MagicMock
from unittest.mock import MagicMock
from indico_livesync.base import LiveSyncBackendBase
from indico_livesync.models.queue import ChangeType, EntryType, LiveSyncQueueEntry

View File

@ -31,7 +31,7 @@ def test_excluded_categories(mocker, monkeypatch, db, create_category):
categories = {}
with db.session.no_autoflush:
for cat_id in xrange(6):
for cat_id in range(6):
category = (create_category(cat_id, title=str(cat_id), protection_mode=0,
parent=categories[CATEGORY_PARENTS[cat_id]])
if cat_id else Category.get_root())
@ -41,7 +41,7 @@ def test_excluded_categories(mocker, monkeypatch, db, create_category):
db.session.flush()
for cat in categories.viewvalues():
for cat in categories.values():
db = mocker.patch('indico_livesync.models.queue.db')
LiveSyncQueueEntry.create({ChangeType.created}, obj_ref(cat), excluded_categories=get_excluded_categories())
assert db.session.add.called == (cat.id not in {2, 3, 4, 5})

View File

@ -13,7 +13,7 @@ from indico_livesync import SimpleChange, process_records
from indico_livesync.models.queue import ChangeType, EntryType, LiveSyncQueueEntry
class Dummy(object):
class Dummy:
pass
@ -41,7 +41,7 @@ def test_process_records_category_ignored(mocker, change, invalid):
else:
result = process_records(records)
assert len(result) == 1
assert result.values()[0] == SimpleChange.updated
assert list(result.values())[0] == SimpleChange.updated
@pytest.mark.parametrize(('change', 'cascade'), (
@ -96,7 +96,7 @@ def test_process_records_simplify(changes, mocker, db, create_event, dummy_agent
assert result == process_records(reversed(queue)) # queue order shouldn't matter
assert len(result) == sum(1 for x in expected if x)
result_refs = {obj.id: change for obj, change in result.viewitems()}
result_refs = {obj.id: change for obj, change in result.items()}
for i, ref in enumerate(refs):
assert (ref['event_id'] in list(result_refs)) == bool(expected[i])
assert result_refs.get(ref['event_id'], 0) == expected[i]

View File

@ -5,7 +5,7 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from mock import MagicMock, Mock
from unittest.mock import MagicMock, Mock
from indico.modules.events import Event
@ -17,13 +17,13 @@ from indico_livesync.uploader import MARCXMLUploader, Uploader
class RecordingUploader(Uploader):
"""An uploader which logs each 'upload'"""
def __init__(self, *args, **kwargs):
super(RecordingUploader, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self._uploaded = []
self.logger = MagicMock()
def upload_records(self, records, from_queue):
if from_queue:
recs = set(records.viewitems())
recs = set(records.items())
self._uploaded.append((recs, from_queue))
else:
self._uploaded.append((set(records), from_queue))
@ -36,11 +36,11 @@ class RecordingUploader(Uploader):
class FailingUploader(RecordingUploader):
"""An uploader where the second batch fails"""
def __init__(self, *args, **kwargs):
super(FailingUploader, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self._n = 0
def upload_records(self, records, from_queue):
super(FailingUploader, self).upload_records(records, from_queue)
super().upload_records(records, from_queue)
self._n += 1
if self._n == 2:
raise Exception('All your data are belong to us!')
@ -51,7 +51,7 @@ def test_run_initial(mocker):
mocker.patch.object(Uploader, 'processed_records', autospec=True)
uploader = RecordingUploader(MagicMock())
uploader.INITIAL_BATCH_SIZE = 3
records = tuple(Mock(spec=Event, id=evt_id) for evt_id in xrange(4))
records = tuple(Mock(spec=Event, id=evt_id) for evt_id in range(4))
uploader.run_initial(records)
# We expect two batches, with the second one being smaller (i.e. no None padding, just the events)
batches = set(records[:3]), set(records[3:])
@ -65,7 +65,7 @@ def test_run(mocker, db, create_event, dummy_agent):
uploader = RecordingUploader(MagicMock())
uploader.BATCH_SIZE = 3
events = tuple(create_event(id_=evt_id) for evt_id in xrange(4))
events = tuple(create_event(id_=evt_id) for evt_id in range(4))
records = tuple(LiveSyncQueueEntry(change=ChangeType.created, type=EntryType.event, event_id=evt.id,
agent=dummy_agent)
for evt in events)
@ -91,7 +91,7 @@ def test_run_failing(mocker, db, create_event, dummy_agent):
uploader = FailingUploader(MagicMock())
uploader.BATCH_SIZE = 3
events = tuple(create_event(id_=evt_id) for evt_id in xrange(10))
events = tuple(create_event(id_=evt_id) for evt_id in range(10))
records = tuple(LiveSyncQueueEntry(change=ChangeType.created, type=EntryType.event, event_id=evt.id,
agent=dummy_agent)
for evt in events)

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.util.console import cformat
from indico.util.struct.iterables import grouper
@ -24,7 +23,7 @@ class LiveSyncDebugBackend(LiveSyncBackendBase):
"""
def _print(self, msg=''):
print msg
print(msg)
def run(self):
records = self.fetch_records()
@ -38,7 +37,7 @@ class LiveSyncDebugBackend(LiveSyncBackendBase):
self._print()
self._print(cformat('%{white!}Simplified/cascaded changes:%{reset}'))
for obj, change in process_records(records).iteritems():
for obj, change in process_records(records).items():
self._print(cformat('%{white!}{}%{reset}: {}').format(_change_str(change), obj))
self._print()
@ -51,17 +50,17 @@ class LiveSyncDebugBackend(LiveSyncBackendBase):
uploader = DebugUploader(self)
uploader.run_initial(events)
for i, batch in enumerate(grouper(events, 10, skip_missing=True), 1):
print
print cformat('%{white!}Batch {}:%{reset}').format(i)
print MARCXMLGenerator.objects_to_xml(event for event in batch if event is not None)
print
print()
print(cformat('%{white!}Batch {}:%{reset}').format(i))
print(MARCXMLGenerator.objects_to_xml(event for event in batch if event is not None))
print()
class DebugUploader(Uploader):
BATCH_SIZE = 5
def __init__(self, *args, **kwargs):
super(DebugUploader, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.n = 0
def upload_records(self, records, from_queue):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico_livesync import LiveSyncPluginBase
from indico_livesync_debug.backend import LiveSyncDebugBackend

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.util.i18n import make_bound_gettext

View File

@ -5,10 +5,10 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from decimal import Decimal
from urllib import quote_plus
from six.moves.urllib.parse import quote_plus
from indico.modules.events.registration.placeholders.registrations import IDPlaceholder
from indico.util.placeholders import ParametrizedPlaceholder, Placeholder
@ -74,11 +74,11 @@ class PricePlaceholder(ParametrizedPlaceholder):
@classmethod
def render(cls, param, regform, registration):
if param == 'int':
return unicode(int(registration.price * 100))
return str(int(registration.price * 100))
elif param == 'short' and int(registration.price) == registration.price:
return unicode(int(registration.price))
return str(int(registration.price))
else:
return unicode(registration.price.quantize(Decimal('.01')))
return str(registration.price.quantize(Decimal('.01')))
@classmethod
def iter_param_info(cls, regform, registration):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from wtforms.fields.simple import TextAreaField
from wtforms.validators import DataRequired
@ -29,7 +28,7 @@ class PluginSettingsForm(PaymentPluginSettingsFormBase):
details = TextAreaField(_('Payment details'), [])
def __init__(self, *args, **kwargs):
super(PluginSettingsForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.details.description = DETAILS_DESC + '\n' + render_placeholder_info('manual-payment-details',
regform=None, registration=None)
@ -38,7 +37,7 @@ class EventSettingsForm(PaymentEventSettingsFormBase):
details = TextAreaField(_('Payment details'), [UsedIf(lambda form, _: form.enabled.data), DataRequired()])
def __init__(self, *args, **kwargs):
super(EventSettingsForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.details.description = DETAILS_DESC + '\n' + render_placeholder_info('manual-payment-details',
regform=None, registration=None)
@ -60,13 +59,13 @@ class ManualPaymentPlugin(PaymentPluginMixin, IndicoPlugin):
'details': ''}
def init(self):
super(ManualPaymentPlugin, self).init()
super().init()
self.connect(signals.get_placeholders, self._get_details_placeholders, sender='manual-payment-details')
def _get_details_placeholders(self, sender, regform, registration, **kwargs):
from indico_payment_manual.placeholders import (FirstNamePlaceholder, LastNamePlaceholder, EmailPlaceholder,
RegistrationIDPlaceholder, EventIDPlaceholder, PricePlaceholder,
CurrencyPlaceholder)
from indico_payment_manual.placeholders import (CurrencyPlaceholder, EmailPlaceholder, EventIDPlaceholder,
FirstNamePlaceholder, LastNamePlaceholder, PricePlaceholder,
RegistrationIDPlaceholder)
yield FirstNamePlaceholder
yield LastNamePlaceholder
yield EmailPlaceholder

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.util.i18n import make_bound_gettext

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core.plugins import IndicoPluginBlueprint

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from itertools import chain
@ -45,7 +44,7 @@ class RHPaypalIPN(RH):
def _process(self):
self._verify_business()
verify_params = list(chain(IPN_VERIFY_EXTRA_PARAMS, request.form.iteritems()))
verify_params = list(chain(IPN_VERIFY_EXTRA_PARAMS, request.form.items()))
result = requests.post(current_plugin.settings.get('url'), data=verify_params).text
if result != 'VERIFIED':
current_plugin.logger.warning("Paypal IPN string %s did not validate (%s)", verify_params, result)

View File

@ -5,10 +5,8 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask_pluginengine import render_plugin_template
from wtforms.fields.core import StringField
from wtforms.fields.html5 import URLField
from wtforms.validators import DataRequired, Optional
@ -53,7 +51,7 @@ class PaypalPaymentPlugin(PaymentPluginMixin, IndicoPlugin):
'business': None}
def init(self):
super(PaypalPaymentPlugin, self).init()
super().init()
self.template_hook('event-manage-payment-plugin-before-form', self._get_encoding_warning)
@property

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import re

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,9 +5,10 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from unittest.mock import MagicMock
import pytest
from flask import request
from mock import MagicMock
from indico.modules.events.payment.models.transactions import PaymentTransaction

View File

@ -5,8 +5,9 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from unittest.mock import MagicMock
import pytest
from mock import MagicMock
from wtforms import ValidationError
from indico_payment_paypal.util import validate_business

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.util.i18n import make_bound_gettext

View File

@ -20,8 +20,7 @@ class WPPiwikStatistics(WPStatistics):
@property
def additional_bundles(self):
return {
'screen': map(lambda x: current_plugin.manifest[x],
('main.js', 'main.css')),
'screen': [current_plugin.manifest[x] for x in ('main.js', 'main.css')],
'print': ()
}

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from wtforms import BooleanField, IntegerField, StringField
from wtforms.validators import ValidationError

View File

@ -6,13 +6,13 @@
# see the LICENSE file for more details.
import socket
from urllib2 import urlparse
import requests
from flask_pluginengine import current_plugin
from urllib2 import urlparse
class PiwikRequest(object):
class PiwikRequest:
"""Wrapper for Piwik API requests"""
def __init__(self, server_url, query_script, site_id, api_token=None):
@ -31,7 +31,7 @@ class PiwikRequest(object):
def api_url(self):
url = urlparse.urlparse(self.server_url)
scheme = url.scheme if url.scheme else 'https'
return '{}://{}{}{}'.format(scheme, url.netloc, url.path, self.query_script)
return f'{scheme}://{url.netloc}{url.path}{self.query_script}'
def call(self, default_response=None, **query_params):
"""Perform a query to the Piwik server and return the response.
@ -50,7 +50,7 @@ class PiwikRequest(object):
query_params['idSite'] = self.site_id
if self.api_token is not None:
query_params['token_auth'] = self.api_token
for key, value in query_params.iteritems():
for key, value in query_params.items():
if isinstance(value, list):
value = ','.join(value)
query += '{}={}&'.format(str(key), str(value))

View File

@ -5,10 +5,9 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from urllib2 import urlparse
from flask import request, session
from flask_pluginengine import render_plugin_template
from urllib2 import urlparse
from indico.core import signals
from indico.core.plugins import IndicoPlugin, IndicoPluginBlueprint, plugin_url_rule_to_js, url_for_plugin
@ -38,9 +37,9 @@ class PiwikPlugin(IndicoPlugin):
'enabled_for_events': True,
'enabled_for_downloads': True,
'cache_enabled': True,
'server_url': u'//127.0.0.1/piwik/',
'server_api_url': u'//127.0.0.1/piwik/',
'server_token': u'',
'server_url': '//127.0.0.1/piwik/',
'server_api_url': '//127.0.0.1/piwik/',
'server_token': '',
'site_id_general': 1,
'site_id_events': 2,
'cache_ttl': 3600,
@ -48,7 +47,7 @@ class PiwikPlugin(IndicoPlugin):
}
def init(self):
super(PiwikPlugin, self).init()
super().init()
self.connect(signals.menu.items, self.add_sidemenu_item, sender='event-management-sidemenu')
self.connect(signals.attachments.attachment_accessed, self.track_download)
self.template_hook('html-head', self.inject_tracking)
@ -67,7 +66,7 @@ class PiwikPlugin(IndicoPlugin):
def add_sidemenu_item(self, sender, event, **kwargs):
if not event.can_manage(session.user) or not PiwikPlugin.settings.get('site_id_events'):
return
return SideMenuItem(u'statistics', _(u"Statistics"), url_for_plugin(u'piwik.view', event), section=u'reports')
return SideMenuItem('statistics', _("Statistics"), url_for_plugin('piwik.view', event), section='reports')
def get_blueprints(self):
return blueprint
@ -84,10 +83,10 @@ class PiwikPlugin(IndicoPlugin):
return
if attachment.type == AttachmentType.link:
resource_url = attachment.link_url
resource_title = u'Link - {0.title}'.format(attachment)
resource_title = f'Link - {attachment.title}'
else:
resource_url = request.base_url
resource_title = u'Download - {0.title}'.format(attachment)
resource_title = f'Download - {attachment.title}'
track_download_request.delay(resource_url, resource_title)
def _get_event_tracking_params(self):
@ -96,16 +95,16 @@ class PiwikPlugin(IndicoPlugin):
return {}
params = {'site_id_events': site_id_events}
if request.blueprint in ('event', 'events', 'contributions') and 'confId' in request.view_args:
if not unicode(request.view_args['confId']).isdigit():
if not str(request.view_args['confId']).isdigit():
return {}
params['event_id'] = request.view_args['confId']
contrib_id = request.view_args.get('contrib_id')
if contrib_id is not None and unicode(contrib_id).isdigit():
if contrib_id is not None and str(contrib_id).isdigit():
contribution = Contribution.find_first(event_id=params['event_id'], id=contrib_id)
if contribution:
cid = (contribution.legacy_mapping.legacy_contribution_id if contribution.legacy_mapping
else contribution.id)
params['contrib_id'] = '{}t{}'.format(contribution.event_id, cid)
params['contrib_id'] = f'{contribution.event_id}t{cid}'
return params
def _get_tracking_url(self):

View File

@ -8,7 +8,7 @@
from indico_piwik.piwik import PiwikRequest
class PiwikQueryBase(object):
class PiwikQueryBase:
"""Base Piwik query"""
def __init__(self, query_script):
@ -27,18 +27,18 @@ class PiwikQueryReportBase(PiwikQueryBase):
def __init__(self):
from indico_piwik.plugin import PiwikPlugin
super(PiwikQueryReportBase, self).__init__(query_script=PiwikPlugin.report_script)
super().__init__(query_script=PiwikPlugin.report_script)
def call(self, date=('last7',), period='day', **query_params):
date = ','.join(map(unicode, date))
return super(PiwikQueryReportBase, self).call(date=date, period=period, **query_params)
date = ','.join(map(str, date))
return super().call(date=date, period=period, **query_params)
class PiwikQueryReportEventBase(PiwikQueryReportBase):
"""Base Piwik query to request reports of events and contributions"""
def __init__(self, event_id, start_date, end_date, contrib_id=None):
super(PiwikQueryReportEventBase, self).__init__()
super().__init__()
self.event_id = event_id
self.contrib_id = contrib_id
self.start_date = start_date
@ -47,7 +47,7 @@ class PiwikQueryReportEventBase(PiwikQueryReportBase):
def call(self, segmentation_enabled=True, **query_params):
if segmentation_enabled:
query_params['segment'] = self.get_segmentation()
return super(PiwikQueryReportEventBase, self).call(module='API', date=[self.start_date, self.end_date],
return super().call(module='API', date=[self.start_date, self.end_date],
**query_params)
def get_segmentation(self):
@ -59,8 +59,8 @@ class PiwikQueryReportEventBase(PiwikQueryReportBase):
segmentation['customVariablePageValue2'] = ('==', self.contrib_id)
segments = set()
for name, (equality, value) in segmentation.iteritems():
segment = '{}{}{}'.format(name, equality, value)
for name, (equality, value) in segmentation.items():
segment = f'{name}{equality}{value}'
segments.add(segment)
return ';'.join(segments)

View File

@ -20,7 +20,7 @@ class PiwikQueryReportEventGraphBase(PiwikQueryReportEventBase):
query_params['height'] = height
if width is not None:
query_params['width'] = width
return super(PiwikQueryReportEventGraphBase, self).call(method='ImageGraph.get',
return super().call(method='ImageGraph.get',
apiModule=apiModule, apiAction=apiAction,
aliasedGraph='1', graphType=graphType, **query_params)
@ -41,13 +41,13 @@ class PiwikQueryReportEventGraphBase(PiwikQueryReportEventBase):
class PiwikQueryReportEventGraphCountries(PiwikQueryReportEventGraphBase):
def call(self, **query_params):
return super(PiwikQueryReportEventGraphCountries, self).call(apiModule='UserCountry', apiAction='getCountry',
return super().call(apiModule='UserCountry', apiAction='getCountry',
period='range', width=490, height=260,
graphType='horizontalBar', **query_params)
class PiwikQueryReportEventGraphDevices(PiwikQueryReportEventGraphBase):
def call(self, **query_params):
return super(PiwikQueryReportEventGraphDevices, self).call(apiModule='UserSettings', apiAction='getOS',
return super().call(apiModule='UserSettings', apiAction='getOS',
period='range', width=320, height=260,
graphType='horizontalBar', **query_params)

View File

@ -5,10 +5,10 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import division
from operator import itemgetter
from urllib2 import quote
from six.moves.urllib.parse import quote
from indico_piwik.queries.base import PiwikQueryReportEventBase
from indico_piwik.queries.utils import get_json_from_remote_server, reduce_json, stringify_seconds
@ -18,11 +18,10 @@ class PiwikQueryReportEventMetricBase(PiwikQueryReportEventBase):
"""Base Piwik query for retrieving metrics in JSON format"""
def call(self, method, **query_params):
return super(PiwikQueryReportEventMetricBase, self).call(method=method, format='JSON', **query_params)
return super().call(method=method, format='JSON', **query_params)
def get_result(self):
"""Perform the call and return the sum of all unique values"""
pass
class PiwikQueryReportEventMetricVisitsBase(PiwikQueryReportEventMetricBase):
@ -35,7 +34,7 @@ class PiwikQueryReportEventMetricVisitsBase(PiwikQueryReportEventMetricBase):
class PiwikQueryReportEventMetricDownloads(PiwikQueryReportEventMetricBase):
def call(self, download_url, **query_params):
return super(PiwikQueryReportEventMetricDownloads, self).call(method='Actions.getDownload',
return super().call(method='Actions.getDownload',
downloadUrl=quote(download_url),
**query_params)
@ -47,7 +46,7 @@ class PiwikQueryReportEventMetricDownloads(PiwikQueryReportEventMetricBase):
def _get_per_day_results(self, results):
hits_calendar = {}
for date, hits in results.iteritems():
for date, hits in results.items():
day_hits = {'total': 0, 'unique': 0}
if hits:
for metrics in hits:
@ -74,7 +73,7 @@ class PiwikQueryReportEventMetricDownloads(PiwikQueryReportEventMetricBase):
class PiwikQueryReportEventMetricReferrers(PiwikQueryReportEventMetricBase):
def call(self, **query_params):
return super(PiwikQueryReportEventMetricReferrers, self).call(method='Referrers.getReferrerType',
return super().call(method='Referrers.getReferrerType',
period='range', **query_params)
def get_result(self):
@ -88,18 +87,18 @@ class PiwikQueryReportEventMetricReferrers(PiwikQueryReportEventMetricBase):
class PiwikQueryReportEventMetricUniqueVisits(PiwikQueryReportEventMetricVisitsBase):
def call(self, **query_params):
return super(PiwikQueryReportEventMetricUniqueVisits, self).call(method='VisitsSummary.getUniqueVisitors',
return super().call(method='VisitsSummary.getUniqueVisitors',
**query_params)
class PiwikQueryReportEventMetricVisits(PiwikQueryReportEventMetricVisitsBase):
def call(self, **query_params):
return super(PiwikQueryReportEventMetricVisits, self).call(method='VisitsSummary.getVisits', **query_params)
return super().call(method='VisitsSummary.getVisits', **query_params)
class PiwikQueryReportEventMetricVisitDuration(PiwikQueryReportEventMetricBase):
def call(self, **query_params):
return super(PiwikQueryReportEventMetricVisitDuration, self).call(method='VisitsSummary.get', **query_params)
return super().call(method='VisitsSummary.get', **query_params)
def get_result(self):
"""Perform the call and return a string with the time in hh:mm:ss"""
@ -109,7 +108,7 @@ class PiwikQueryReportEventMetricVisitDuration(PiwikQueryReportEventMetricBase):
def _get_average_duration(self, result):
seconds = 0
data = result.values()
data = list(result.values())
if not data:
return seconds
for day in data:
@ -120,14 +119,14 @@ class PiwikQueryReportEventMetricVisitDuration(PiwikQueryReportEventMetricBase):
class PiwikQueryReportEventMetricPeakDateAndVisitors(PiwikQueryReportEventMetricBase):
def call(self, **query_params):
return super(PiwikQueryReportEventMetricPeakDateAndVisitors, self).call(method='VisitsSummary.getVisits',
return super().call(method='VisitsSummary.getVisits',
**query_params)
def get_result(self):
"""Perform the call and return the peak date and how many users"""
result = get_json_from_remote_server(self.call)
if result:
date, value = max(result.iteritems(), key=itemgetter(1))
date, value = max(result.items(), key=itemgetter(1))
return {'date': date, 'users': value}
else:
return {'date': "No Data", 'users': 0}

View File

@ -6,7 +6,8 @@
# see the LICENSE file for more details.
from datetime import datetime
from urllib2 import quote
from six.moves.urllib.parse import quote
from indico.core.celery import celery

View File

@ -6,6 +6,7 @@
# see the LICENSE file for more details.
import json
from functools import reduce
from flask_pluginengine import current_plugin
@ -33,7 +34,7 @@ def get_json_from_remote_server(func, **kwargs):
def reduce_json(data):
"""Reduce a JSON object"""
return reduce(lambda x, y: int(x) + int(y), data.values())
return reduce(lambda x, y: int(x) + int(y), list(data.values()))
def stringify_seconds(seconds=0):

View File

@ -55,7 +55,7 @@ class ReportBase(Serializer):
return cls(*args, **kwargs).to_serializable()
cache = GenericCache('Piwik.Report')
key = u'{}-{}-{}'.format(cls.__name__, args, kwargs)
key = f'{cls.__name__}-{args}-{kwargs}'
report = cache.get(key)
if not report:
@ -65,7 +65,6 @@ class ReportBase(Serializer):
def _build_report(self):
"""To be overriden"""
pass
def _init_date_range(self, start_date=None, end_date=None):
"""Set date range defaults if no dates are passed"""
@ -112,7 +111,7 @@ class ReportGeneral(ReportBase):
'referrers': PiwikQueryReportEventMetricReferrers(**self.params),
'peak': PiwikQueryReportEventMetricPeakDateAndVisitors(**self.params)}
for query_name, query in queries.iteritems():
for query_name, query in queries.items():
self.metrics[query_name] = query.get_result()
self._fetch_contribution_info()
@ -129,8 +128,8 @@ class ReportGeneral(ReportBase):
continue
cid = (contribution.legacy_mapping.legacy_contribution_id if contribution.legacy_mapping
else contribution.id)
key = '{}t{}'.format(contribution.event_id, cid)
self.contributions[key] = u'{} ({})'.format(contribution.title, format_time(contribution.start_dt))
key = f'{contribution.event_id}t{cid}'
self.contributions[key] = '{} ({})'.format(contribution.title, format_time(contribution.start_dt))
class ReportMaterial(ReportBase):
@ -172,8 +171,8 @@ class ReportVisitsPerDay(ReportBase):
def _reduce_metrics(self):
reduced_metrics = defaultdict(dict)
for metric_type, records in self.metrics.iteritems():
for date, hits in records.iteritems():
for metric_type, records in self.metrics.items():
for date, hits in records.items():
reduced_metrics[date][metric_type] = int(hits)
self.metrics = reduced_metrics

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import mimetypes
@ -67,7 +66,7 @@ class CodePreviewerPlugin(IndicoPlugin):
configurable = False
def init(self):
super(CodePreviewerPlugin, self).init()
super().init()
self.connect(signals.attachments.get_file_previewers, self._get_file_previewers)
def _get_file_previewers(self, sender, **kwargs):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -45,7 +45,7 @@ class RHEventPreviewIPyNB(RH):
response = current_app.response_class(html)
# Use CSP to restrict access to possibly malicious scripts or inline JS
csp_header = "script-src cdn.mathjax.org 'nonce-{}';".format(nonce)
csp_header = f"script-src cdn.mathjax.org 'nonce-{nonce}';"
response.headers['Content-Security-Policy'] = csp_header
response.headers['X-Webkit-CSP'] = csp_header
# IE10 doesn't have proper CSP support, so we need to be more strict

View File

@ -30,12 +30,12 @@ class CppHighlighter(Preprocessor):
python = 'python'
def __init__(self, config=None, **kw):
super(CppHighlighter, self).__init__(config=config, **kw)
super().__init__(config=config, **kw)
# Build regular expressions to catch language extensions or switches and choose
# an adequate pygments lexer
any_magic = "|".join(self.magics)
self.re_magic_language = re.compile(r"^\s*({0}).*".format(any_magic), re.DOTALL)
self.re_magic_language = re.compile(fr"^\s*({any_magic}).*", re.DOTALL)
def matches(self, source, reg_expr):
return bool(reg_expr.match(source))
@ -62,4 +62,4 @@ class CppHighlighter(Preprocessor):
except:
# if no language metadata, keep python as default
pass
return super(CppHighlighter, self).preprocess(nb, resources)
return super().preprocess(nb, resources)

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import mimetypes
import re
@ -42,7 +41,7 @@ class JupyterPreviewerPlugin(IndicoPlugin):
configurable = False
def init(self):
super(JupyterPreviewerPlugin, self).init()
super().init()
self.connect(signals.attachments.get_file_previewers, self._get_file_previewers)
def get_blueprints(self):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core import signals
from indico.util.i18n import make_bound_gettext

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core.plugins import IndicoPluginBlueprint

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask import current_app, jsonify, request
from werkzeug.exceptions import NotFound, Unauthorized

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import errno
import json
@ -88,11 +87,11 @@ def rmlinktree(path):
elif stat.S_ISLNK(mode):
os.remove(fullname)
else:
raise Exception('Tried to delete {} (not a directory/symlink)'.format(fullname))
raise Exception(f'Tried to delete {fullname} (not a directory/symlink)')
os.rmdir(path)
class S3Importer(object):
class S3Importer:
def __init__(self, get_bucket_name, static_bucket_name, output_file, source_backend_names, rclone_remote,
s3_endpoint, s3_profile, s3_bucket_policy):
self.get_bucket_name = get_bucket_name
@ -133,12 +132,12 @@ class S3Importer(object):
def run(self):
models = {model: self.make_query(model).count() for model in StoredFileMixin.__subclasses__()}
models = {model: total for model, total in models.iteritems() if total}
models = {model: total for model, total in models.items() if total}
labels = {model: cformat('Processing %{blue!}{}%{reset} (%{cyan}{}%{reset} rows)').format(model.__name__, total)
for model, total in models.iteritems()}
max_length = max(len(x) for x in labels.itervalues())
labels = {model: label.ljust(max_length) for model, label in labels.iteritems()}
for model, total in sorted(models.items(), key=itemgetter(1)):
for model, total in models.items()}
max_length = max(len(x) for x in labels.values())
labels = {model: label.ljust(max_length) for model, label in labels.items()}
for model, total in sorted(list(models.items()), key=itemgetter(1)):
with click.progressbar(self.query_chunked(model, 1000), length=total, label=labels[model],
show_percent=True, show_pos=True) as objects:
for obj in self.flush_rclone_iterator(objects, 1000):
@ -149,14 +148,14 @@ class S3Importer(object):
.format(obj, exc))
click.secho('All done!', fg='green')
click.echo('Add the following entries to your STORAGE_BACKENDS:')
for bucket, data in sorted(self.buckets.viewitems(), key=itemgetter(0)):
for bucket, data in sorted(self.buckets.items(), key=itemgetter(0)):
click.echo("'{}': 's3-readonly:host={},bucket={}',".format(
data['backend'], self.s3_endpoint.replace('https://', ''), bucket))
def process_obj(self, obj):
new_storage_path, new_filename = self.build_storage_path(obj)
if new_storage_path in self.used_storage_paths:
raise Exception('Non-unique storage path: {}'.format(new_storage_path))
raise Exception(f'Non-unique storage path: {new_storage_path}')
self.used_storage_paths.add(new_storage_path)
bucket_name, backend = self.get_bucket_name(self.get_object_dt(obj))
bucket_info = self.get_bucket_info(bucket_name, backend, create=(not self.rclone_remote))
@ -202,7 +201,7 @@ class S3Importer(object):
with obj.get_local_path() as file_path:
pass
while not os.path.exists(file_path):
raw_input(cformat('\n%{red}File not found on disk: %{yellow}{}').format(file_path))
input(cformat('\n%{red}File not found on disk: %{yellow}{}').format(file_path))
try:
queue_entry = self.rclone_queue[bucket]
except KeyError:
@ -235,18 +234,18 @@ class S3Importer(object):
if not self.rclone_remote or not self.rclone_queue:
return
click.echo()
for name, data in self.buckets.viewitems():
for name, data in self.buckets.items():
if not data['exists']:
self.create_bucket(name)
data['exists'] = True
for bucket, data in self.rclone_queue.viewitems():
for bucket, data in self.rclone_queue.items():
click.echo(cformat('Copying %{cyan}{}%{reset} files (%{cyan}{}%{reset}) to %{cyan}{}%{reset} via rclone')
.format(data['files'], do_filesizeformat(data['bytes']), bucket))
start = datetime.now()
try:
subprocess.check_call([
'rclone', 'copy', '--copy-links',
data['path'], '{}:{}'.format(self.rclone_remote, bucket)
data['path'], f'{self.rclone_remote}:{bucket}'
])
except subprocess.CalledProcessError:
click.secho('\nError while running rclone', fg='red')
@ -335,17 +334,17 @@ def apply_changes(data_file, revert=False):
data = defaultdict(list)
for line in data_file:
line_data = json.loads(line)
converted = {mapping[k]: v for k, v in line_data.viewitems() if k in mapping}
converted = {mapping[k]: v for k, v in line_data.items() if k in mapping}
data[line_data['m']].append(converted)
models = {model: len(data[model.__name__])
for model in StoredFileMixin.__subclasses__()
if model.__name__ in data and len(data[model.__name__])}
labels = {model: cformat('Processing %{blue!}{}%{reset} (%{cyan}{}%{reset} rows)').format(model.__name__, total)
for model, total in models.iteritems()}
max_length = max(len(x) for x in labels.itervalues())
labels = {model: label.ljust(max_length) for model, label in labels.iteritems()}
for model, total in sorted(models.items(), key=itemgetter(1)):
for model, total in models.items()}
max_length = max(len(x) for x in labels.values())
labels = {model: label.ljust(max_length) for model, label in labels.items()}
for model, total in sorted(list(models.items()), key=itemgetter(1)):
pks = inspect(model).primary_key
with click.progressbar(data[model.__name__], length=total, label=labels[model],
show_percent=True, show_pos=True) as entries:
@ -368,7 +367,7 @@ def monkeypatch_registration_file_time():
# here we want reliable filenames
from indico.modules.events.registration.models import registrations
class FakeTime(object):
class FakeTime:
def time(self):
return 0
@ -472,7 +471,7 @@ def copy(source_backend_names, bucket_names, static_bucket_name, s3_endpoint, s3
code.append(' backend = backend.replace("<week>", dt.strftime("%W"))')
code.append(' return bucket, backend')
d = {}
exec '\n'.join(code) in d
exec('\n'.join(code), d)
if not source_backend_names:
source_backend_names = [x for x in config.STORAGE_BACKENDS if not isinstance(get_storage(x), S3StorageBase)]
if rclone:

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import sys
@ -41,7 +40,7 @@ class SettingsForm(IndicoForm):
description=_("The password to access the S3 bucket info endpoint"))
def __init__(self, *args, **kwargs):
super(SettingsForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
url = Markup('<strong><code>{}</code></strong>').format(url_for_plugin('storage_s3.buckets'))
self.bucket_info_enabled.description = _("Enables an API on {url} that returns information on all S3 buckets "
"currently in use, including dynamically-named ones.").format(url=url)
@ -62,7 +61,7 @@ class S3StoragePlugin(IndicoPlugin):
}
def init(self):
super(S3StoragePlugin, self).init()
super().init()
self.connect(signals.get_storage_backends, self._get_storage_backends)
self.connect(signals.plugin.cli, self._extend_indico_cli)
@ -90,25 +89,25 @@ class S3StoragePlugin(IndicoPlugin):
storage_instance = get_storage(key)
except RuntimeError:
if storage:
click.echo('Storage {} does not exist'.format(key))
click.echo(f'Storage {key} does not exist')
sys.exit(1)
continue
if isinstance(storage_instance, ReadOnlyStorageMixin):
if storage:
click.echo('Storage {} is read-only'.format(key))
click.echo(f'Storage {key} is read-only')
sys.exit(1)
continue
if isinstance(storage_instance, S3StorageBase):
bucket_name = storage_instance._get_current_bucket_name()
if storage_instance._bucket_exists(bucket_name):
click.echo('Storage {}: bucket {} already exists'.format(key, bucket_name))
click.echo(f'Storage {key}: bucket {bucket_name} already exists')
continue
storage_instance._create_bucket(bucket_name)
click.echo('Storage {}: bucket {} created'.format(key, bucket_name))
click.echo(f'Storage {key}: bucket {bucket_name} created')
elif storage:
click.echo('Storage {} is not an s3 storage'.format(key))
click.echo(f'Storage {key} is not an s3 storage')
sys.exit(1)
s3.add_command(migrate_cli, name='migrate')

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import hashlib
import hmac
@ -71,7 +70,7 @@ class S3StorageBase(Storage):
@cached_property
def session(self):
key = '__'.join('{}_{}'.format(k, v) for k, v in sorted(self.session_kwargs.viewitems()))
key = '__'.join(f'{k}_{v}' for k, v in sorted(self.session_kwargs.items()))
try:
return getattr(s3_session_cache, key)
except AttributeError:
@ -95,7 +94,7 @@ class S3StorageBase(Storage):
s3_object = self.client.get_object(Bucket=bucket, Key=id_)['Body']
return BytesIO(s3_object.read())
except Exception as e:
raise StorageError('Could not open "{}": {}'.format(file_id, e)), None, sys.exc_info()[2]
raise None.with_traceback(sys.exc_info()[2])
@contextmanager
def get_local_path(self, file_id):
@ -128,14 +127,14 @@ class S3StorageBase(Storage):
try:
self.client.delete_object(Bucket=bucket, Key=id_)
except Exception as e:
raise StorageError('Could not delete "{}": {}'.format(file_id, e)), None, sys.exc_info()[2]
raise None.with_traceback(sys.exc_info()[2])
def getsize(self, file_id):
bucket, id_ = self._parse_file_id(file_id)
try:
return self.client.head_object(Bucket=bucket, Key=id_)['ContentLength']
except Exception as e:
raise StorageError('Could not get size of "{}": {}'.format(file_id, e)), None, sys.exc_info()[2]
raise None.with_traceback(sys.exc_info()[2])
def send_file(self, file_id, content_type, filename, inline=True):
if self.proxy_downloads == ProxyDownloadsMode.local:
@ -159,7 +158,7 @@ class S3StorageBase(Storage):
response.headers['X-Accel-Redirect'] = '/.xsf/s3/' + url.replace('://', '/', 1)
return response
except Exception as e:
raise StorageError('Could not send file "{}": {}'.format(file_id, e)), None, sys.exc_info()[2]
raise None.with_traceback(sys.exc_info()[2])
def _create_bucket(self, name):
from indico_storage_s3.plugin import S3StoragePlugin
@ -190,7 +189,7 @@ class S3Storage(S3StorageBase):
name = 's3'
def __init__(self, data):
super(S3Storage, self).__init__(data)
super().__init__(data)
self.bucket_name = self.parsed_data['bucket']
if len(self.bucket_name) > 63:
raise StorageError('Bucket name cannot be longer than 63 chars')
@ -211,14 +210,14 @@ class S3Storage(S3StorageBase):
checksum = self._save(bucket, name, content_type, fileobj)
return name, checksum
except Exception as e:
raise StorageError('Could not save "{}": {}'.format(name, e)), None, sys.exc_info()[2]
raise None.with_traceback(sys.exc_info()[2])
class DynamicS3Storage(S3StorageBase):
name = 's3-dynamic'
def __init__(self, data):
super(DynamicS3Storage, self).__init__(data)
super().__init__(data)
self.bucket_name_template = self.parsed_data['bucket_template']
self.bucket_secret = (self.parsed_data.get('bucket_secret', '') or
self.session._session.get_scoped_config().get('indico_bucket_secret', ''))
@ -245,7 +244,7 @@ class DynamicS3Storage(S3StorageBase):
def _get_bucket_name(self, date):
name = self._replace_bucket_placeholders(self.bucket_name_template, date)
token = hmac.new(self.bucket_secret.encode('utf-8'), name, hashlib.md5).hexdigest()
return '{}-{}'.format(name, token)[:63]
return f'{name}-{token}'[:63]
def _replace_bucket_placeholders(self, name, date):
name = name.replace('<year>', date.strftime('%Y'))
@ -257,10 +256,10 @@ class DynamicS3Storage(S3StorageBase):
try:
bucket = self._get_current_bucket_name()
checksum = self._save(bucket, name, content_type, fileobj)
file_id = '{}//{}'.format(bucket, name)
file_id = f'{bucket}//{name}'
return file_id, checksum
except Exception as e:
raise StorageError('Could not save "{}": {}'.format(name, e)), None, sys.exc_info()[2]
raise None.with_traceback(sys.exc_info()[2])
class ReadOnlyS3Storage(ReadOnlyStorageMixin, S3Storage):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import re
from datetime import date

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import hashlib
import hmac
@ -39,13 +38,13 @@ def test_resolve_bucket_name_static():
))
def test_resolve_bucket_name_dynamic(freeze_time, date, name_template, expected_name):
freeze_time(date)
storage = plugin.DynamicS3Storage('bucket_template={},bucket_secret=secret'.format(name_template))
storage = plugin.DynamicS3Storage(f'bucket_template={name_template},bucket_secret=secret')
name, token = storage._get_current_bucket_name().rsplit('-', 1)
assert name == expected_name
assert token == hmac.new(b'secret', expected_name, hashlib.md5).hexdigest()
class MockConfig(object):
class MockConfig:
def __init__(self):
self.STORAGE_BACKENDS = {'s3': None}
@ -68,9 +67,9 @@ def test_dynamic_bucket_creation_task(freeze_time, mocker, date, name_template,
expected_error):
freeze_time(date)
if '<' in name_template:
storage = plugin.DynamicS3Storage('bucket_template={},bucket_secret=secret'.format(name_template))
storage = plugin.DynamicS3Storage(f'bucket_template={name_template},bucket_secret=secret')
else:
storage = plugin.S3Storage('bucket={}'.format(name_template))
storage = plugin.S3Storage(f'bucket={name_template}')
mocker.patch('indico_storage_s3.task.config', MockConfig())
mocker.patch('indico_storage_s3.task.get_storage', return_value=storage)
create_bucket_call = mocker.patch.object(plugin.DynamicS3Storage, '_create_bucket')
@ -81,7 +80,7 @@ def test_dynamic_bucket_creation_task(freeze_time, mocker, date, name_template,
create_bucket()
if bucket_created:
token = hmac.new(b'secret', expected_name, hashlib.md5).hexdigest()
create_bucket_call.assert_called_with('{}-{}'.format(expected_name, token))
create_bucket_call.assert_called_with(f'{expected_name}-{token}')
else:
assert not create_bucket_call.called

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import errno
import os
@ -24,8 +23,8 @@ END_MARKER = '# END GENERATED REQUIREMENTS'
def _find_plugins():
subdirs = sorted((x for x in os.walk('.').next()[1]
if x[0] != '.' and x != '_meta' and os.path.exists(os.path.join(x, 'setup.py'))))
subdirs = sorted(x for x in os.walk('.').next()[1]
if x[0] != '.' and x != '_meta' and os.path.exists(os.path.join(x, 'setup.py')))
for subdir in subdirs:
path = os.path.join(subdir, 'setup.py')
with open(path) as f:
@ -34,7 +33,7 @@ def _find_plugins():
name = re.search(r'''name=(['"])(.+)\1''', setup_py)
version = re.search(r'''version=(['"])(.+)\1''', setup_py)
if name is None or version is None:
click.secho('Could not extract name/version from {}'.format(path), fg='red', bold=True)
click.secho(f'Could not extract name/version from {path}', fg='red', bold=True)
continue
minver = str(Version(version.group(2)))
yield name.group(2), minver
@ -44,7 +43,7 @@ def _get_config():
rv = {'extras': {}, 'skip': []}
try:
f = open('_meta/meta.yaml')
except IOError as exc:
except OSError as exc:
if exc.errno != errno.ENOENT:
raise
else:
@ -83,7 +82,7 @@ def cli(nextver):
for name, minver in sorted(_find_plugins()):
if name in config['skip']:
continue
pkgspec = '{}>={},<{}'.format(name, minver, nextver)
pkgspec = f'{name}>={minver},<{nextver}'
if name in config['extras']:
extras_require[config['extras'][name]].append(pkgspec)
else:
@ -101,8 +100,8 @@ def cli(nextver):
output.append('extras_require = {}')
else:
output.append('extras_require = {')
for extra, pkgspecs in sorted(extras_require.iteritems()):
output.append(' {!r}: {!r},'.format(extra, map(str, sorted(pkgspecs))))
for extra, pkgspecs in sorted(extras_require.items()):
output.append(' {!r}: {!r},'.format(extra, list(map(str, sorted(pkgspecs)))))
output.append('}')
if _update_meta('\n'.join(output)):

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.util.i18n import make_bound_gettext

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core.plugins import IndicoPluginBlueprint

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import posixpath
@ -74,7 +73,7 @@ class RHCustomShortURLPage(RHManageEventBase):
def _process_args(self):
from indico_ursh.plugin import UrshPlugin
super(RHCustomShortURLPage, self)._process_args()
super()._process_args()
api_host = url_parse(UrshPlugin.settings.get('api_host'))
self.ursh_host = strip_end(api_host.to_url(), api_host.path[1:]).rstrip('/') + '/'

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask_pluginengine import render_plugin_template
from wtforms.fields.core import StringField
@ -42,7 +41,7 @@ class UrshPlugin(IndicoPlugin):
}
def init(self):
super(UrshPlugin, self).init()
super().init()
self.template_hook('url-shortener', self._inject_ursh_link)
self.template_hook('page-footer', self._inject_ursh_footer)
self.inject_bundle('main.js', WPBase)

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import json
import posixpath
@ -36,7 +35,7 @@ def is_configured():
def request_short_url(original_url):
from indico_ursh.plugin import UrshPlugin
api_key, api_host = _get_settings()
headers = {'Authorization': 'Bearer {api_key}'.format(api_key=api_key), 'Content-Type': 'application/json'}
headers = {'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'}
url = posixpath.join(api_host, 'api/urls/')
response = requests.post(url, data=json.dumps({'url': original_url, 'allow_reuse': True}), headers=headers)
@ -49,7 +48,7 @@ def request_short_url(original_url):
def register_shortcut(original_url, shortcut, user):
from indico_ursh.plugin import UrshPlugin
api_key, api_host = _get_settings()
headers = {'Authorization': 'Bearer {api_key}'.format(api_key=api_key), 'Content-Type': 'application/json'}
headers = {'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'}
url = posixpath.join(api_host, 'api/urls', shortcut)
data = {'url': original_url, 'allow_reuse': True, 'meta': {'indico.user': user.id}}

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core.plugins import WPJinjaMixinPlugin
from indico.web.views import WPDecorated

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from sqlalchemy.orm.attributes import flag_modified
from wtforms.fields.core import BooleanField
@ -62,7 +61,7 @@ class DummyPlugin(VCPluginMixin, IndicoPlugin):
pass
def update_data_association(self, event, vc_room, event_vc_room, data):
super(DummyPlugin, self).update_data_association(event, vc_room, event_vc_room, data)
super().update_data_association(event, vc_room, event_vc_room, data)
event_vc_room.data.update({key: data.pop(key) for key in [
'show_phone_numbers'
]})

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core import signals
from indico.util.i18n import make_bound_gettext

View File

@ -39,7 +39,7 @@ def raises_api_error(wrapped):
return _wrapper
class ClientBase(object):
class ClientBase:
def __init__(self, wsdl, settings):
session = Session()
transport = Transport(session=session, cache=ZeepCache())
@ -54,12 +54,12 @@ class ClientBase(object):
class UserClient(ClientBase):
def __init__(self, settings):
super(UserClient, self).__init__(settings.get('user_api_wsdl'), settings)
super().__init__(settings.get('user_api_wsdl'), settings)
class AdminClient(ClientBase):
def __init__(self, settings):
super(AdminClient, self).__init__(settings.get('admin_api_wsdl'), settings)
super().__init__(settings.get('admin_api_wsdl'), settings)
def create_room_object(self, **kwargs):
return self.factory.Room(**kwargs)

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from indico.core.plugins import IndicoPluginBlueprint

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import click
from terminaltables import AsciiTable
@ -31,10 +30,10 @@ def rooms(status=None):
room_query = room_query.filter(VCRoom.status == VCRoomStatus.get(status))
for room in room_query:
table_data.append([unicode(room.id), room.name, room.status.name,
unicode(room.data['vidyo_id']), unicode(room.vidyo_extension.extension)])
table_data.append([str(room.id), room.name, room.status.name,
str(room.data['vidyo_id']), str(room.vidyo_extension.extension)])
table = AsciiTable(table_data)
for col in (0, 3, 4):
table.justify_columns[col] = 'right'
print table.table
print(table.table)

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask import flash, jsonify, session
@ -26,6 +25,6 @@ class RHVidyoRoomOwner(RHVCSystemEventBase):
result['success'] = False
db.session.rollback()
else:
flash(_("You are now the owner of the room '{room.name}'".format(room=self.vc_room)), 'success')
flash(_(f"You are now the owner of the room '{self.vc_room.name}'"), 'success')
result['success'] = True
return jsonify(result)

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from wtforms.fields.core import BooleanField
from wtforms.fields.simple import TextAreaField
@ -23,7 +22,7 @@ from indico_vc_vidyo.util import iter_user_identities, retrieve_principal
PIN_VALIDATORS = [Optional(), Length(min=3, max=10), Regexp(r'^\d+$', message=_("The PIN must be a number"))]
class VidyoAdvancedFormMixin(object):
class VidyoAdvancedFormMixin:
# Advanced options (per event)
show_pin = BooleanField(_('Show PIN'),
widget=SwitchWidget(),
@ -62,7 +61,7 @@ class VCRoomForm(VCRoomFormBase, VidyoAdvancedFormMixin):
defaults = kwargs['obj']
if defaults.owner_user is None and defaults.owner is not None:
defaults.owner_user = retrieve_principal(defaults.owner)
super(VCRoomForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
@generated_data
def owner(self):

View File

@ -25,12 +25,12 @@ class DeleteVCRoomAPI(HTTPAPIHook):
return user in VidyoPlugin.settings.acls.get('managers')
def _getParams(self):
super(DeleteVCRoomAPI, self)._getParams()
self._room_ids = map(int, request.form.getlist('rid'))
super()._getParams()
self._room_ids = list(map(int, request.form.getlist('rid')))
def api_deletevcroom(self, user):
from indico_vc_vidyo.plugin import VidyoPlugin
from indico_vc_vidyo.api import APIException
from indico_vc_vidyo.plugin import VidyoPlugin
success = []
failed = []

View File

@ -5,10 +5,10 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import urllib
import six.moves.urllib.error
import six.moves.urllib.parse
import six.moves.urllib.request
from sqlalchemy.event import listens_for
from sqlalchemy.orm.attributes import flag_modified
@ -63,12 +63,12 @@ class VidyoExtension(db.Model):
url = self.vc_room.data['url']
custom_url_tpl = VidyoPlugin.settings.get('client_chooser_url')
if custom_url_tpl:
return custom_url_tpl + '?' + urllib.urlencode({'url': url})
return custom_url_tpl + '?' + six.moves.urllib.parse.urlencode({'url': url})
return url
@return_ascii
def __repr__(self):
return '<VidyoExtension({}, {}, {})>'.format(self.vc_room, self.extension, self.owned_by_user)
return f'<VidyoExtension({self.vc_room}, {self.extension}, {self.owned_by_user})>'
@listens_for(VidyoExtension.owned_by_user, 'set')

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from flask import session
from sqlalchemy.orm.attributes import flag_modified
@ -75,7 +74,7 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
friendly_name = 'Vidyo'
def init(self):
super(VidyoPlugin, self).init()
super().init()
self.connect(signals.plugin.cli, self._extend_indico_cli)
self.inject_bundle('main.js', WPSimpleEventDisplay)
self.inject_bundle('main.js', WPVCEventPage)
@ -95,7 +94,7 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
# we skip identity providers in the default list if they don't support get_identity.
# these providers (local accounts, oauth) are unlikely be the correct ones to integrate
# with the vidyo infrastructure.
'authenticators': ', '.join(p.name for p in multipass.identity_providers.itervalues() if p.supports_get),
'authenticators': ', '.join(p.name for p in multipass.identity_providers.values() if p.supports_get),
'num_days_old': 365,
'max_rooms_warning': 5000,
'vidyo_phone_link': None,
@ -115,7 +114,7 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
return cli
def update_data_association(self, event, vc_room, event_vc_room, data):
super(VidyoPlugin, self).update_data_association(event, vc_room, event_vc_room, data)
super().update_data_association(event, vc_room, event_vc_room, data)
event_vc_room.data.update({key: data.pop(key) for key in [
'show_pin',
@ -126,7 +125,7 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
flag_modified(event_vc_room, 'data')
def update_data_vc_room(self, vc_room, data, is_new=False):
super(VidyoPlugin, self).update_data_vc_room(vc_room, data)
super().update_data_vc_room(vc_room, data, is_new=is_new)
for key in ['description', 'owner', 'room_pin', 'moderation_pin', 'auto_mute']:
if key in data:
@ -203,7 +202,7 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
if not created_room:
raise VCRoomNotFoundError(_("Could not find newly created room in Vidyo"))
vc_room.data.update({
'vidyo_id': unicode(created_room.roomID),
'vidyo_id': str(created_room.roomID),
'url': created_room.RoomMode.roomURL,
'owner_identity': created_room.ownerName
})
@ -299,7 +298,7 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
return blueprint
def get_vc_room_form_defaults(self, event):
defaults = super(VidyoPlugin, self).get_vc_room_form_defaults(event)
defaults = super().get_vc_room_form_defaults(event)
defaults.update({
'auto_mute': True,
'show_pin': False,
@ -311,7 +310,7 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
return defaults
def get_vc_room_attach_form_defaults(self, event):
defaults = super(VidyoPlugin, self).get_vc_room_attach_form_defaults(event)
defaults = super().get_vc_room_attach_form_defaults(event)
defaults.update({
'show_pin': False,
'show_autojoin': True,
@ -320,10 +319,10 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
return defaults
def can_manage_vc_room(self, user, room):
return user == room.vidyo_extension.owned_by_user or super(VidyoPlugin, self).can_manage_vc_room(user, room)
return user == room.vidyo_extension.owned_by_user or super().can_manage_vc_room(user, room)
def _merge_users(self, target, source, **kwargs):
super(VidyoPlugin, self)._merge_users(target, source, **kwargs)
super()._merge_users(target, source, **kwargs)
for ext in VidyoExtension.find(owned_by_user=source):
ext.owned_by_user = target
flag_modified(ext.vc_room, 'data')

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from datetime import timedelta

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
import re
@ -60,11 +59,11 @@ def iter_extensions(prefix, event_id):
"""Return extension (prefix + event_id) with an optional suffix which is
incremented step by step in case of collision
"""
extension = '{prefix}{event_id}'.format(prefix=prefix, event_id=event_id)
extension = f'{prefix}{event_id}'
yield extension
suffix = 1
while True:
yield '{extension}{suffix}'.format(extension=extension, suffix=suffix)
yield f'{extension}{suffix}'
suffix += 1
@ -77,7 +76,7 @@ def update_room_from_obj(settings, vc_room, room_obj):
vc_room.data.update({
'description': room_obj.description,
'vidyo_id': unicode(room_obj.roomID),
'vidyo_id': str(room_obj.roomID),
'url': room_obj.RoomMode.roomURL,
'owner_identity': room_obj.ownerName,
'room_pin': room_obj.RoomMode.roomPIN if room_obj.RoomMode.hasPIN else "",
@ -92,4 +91,4 @@ def retrieve_principal(principal):
if type_ in {'Avatar', 'User'}:
return User.get(int(id_))
else:
raise ValueError('Unexpected type: {}'.format(type_))
raise ValueError(f'Unexpected type: {type_}')

View File

@ -5,7 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import unicode_literals
from setuptools import find_packages, setup

View File

@ -56,7 +56,7 @@ def test_room_cleanup(create_event, create_dummy_room, freeze_time, db):
(1235, 5679, (2,)),
(1236, 5670, (4,)),
(1237, 5671, ())), start=1):
room = create_dummy_room('test_room_{}'.format(id_), extension, {
room = create_dummy_room(f'test_room_{id_}', extension, {
'vidyo_id': vidyo_id
})
for evt_id in evt_ids: