mirror of
https://github.com/lucaspalomodevelop/indico-plugins.git
synced 2026-03-12 23:27:22 +00:00
Run modernize, pyupgrade, autoflake and isort
This commit is contained in:
parent
15afb637b6
commit
f2755b4be4
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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})>'
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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}'
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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})
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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': ()
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)):
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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('/') + '/'
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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}}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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'
|
||||
]})
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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 = []
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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_}')
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user