VC/Zoom: Switch to Python 3

This commit is contained in:
Adrian Moennich 2021-01-05 14:34:19 +01:00
parent 490f86b498
commit a23e362d18
11 changed files with 41 additions and 60 deletions

View File

@ -5,8 +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,8 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import absolute_import, unicode_literals
import time
import jwt
@ -28,7 +26,7 @@ def _handle_response(resp, expected_code=200, expects_json=True):
try:
resp.raise_for_status()
if resp.status_code != expected_code:
raise HTTPError('Unexpected status code {}'.format(resp.status_code), response=resp)
raise HTTPError(f'Unexpected status code {resp.status_code}', response=resp)
except HTTPError:
from indico_vc_zoom.plugin import ZoomPlugin
ZoomPlugin.logger.error('Error in API call to %s: %s', resp.url, resp.content)
@ -40,7 +38,7 @@ class APIException(Exception):
pass
class BaseComponent(object):
class BaseComponent:
def __init__(self, base_uri, config, timeout):
self.base_uri = base_uri
self.config = config
@ -58,7 +56,7 @@ class BaseComponent(object):
session = Session()
session.headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {}'.format(self.token)
'Authorization': f'Bearer {self.token}'
}
return session
@ -66,60 +64,60 @@ class BaseComponent(object):
class MeetingComponent(BaseComponent):
def list(self, user_id, **kwargs):
return self.get(
'{}/users/{}/meetings'.format(self.base_uri, user_id), params=kwargs
f'{self.base_uri}/users/{user_id}/meetings', params=kwargs
)
def create(self, user_id, **kwargs):
if kwargs.get('start_time'):
kwargs['start_time'] = format_iso_dt(kwargs['start_time'])
return self.session.post(
'{}/users/{}/meetings'.format(self.base_uri, user_id),
f'{self.base_uri}/users/{user_id}/meetings',
json=kwargs
)
def get(self, meeting_id, **kwargs):
return self.session.get('{}/meetings/{}'.format(self.base_uri, meeting_id), json=kwargs)
return self.session.get(f'{self.base_uri}/meetings/{meeting_id}', json=kwargs)
def update(self, meeting_id, **kwargs):
if kwargs.get('start_time'):
kwargs['start_time'] = format_iso_dt(kwargs['start_time'])
return self.session.patch(
'{}/meetings/{}'.format(self.base_uri, meeting_id), json=kwargs
f'{self.base_uri}/meetings/{meeting_id}', json=kwargs
)
def delete(self, meeting_id, **kwargs):
return self.session.delete(
'{}/meetings/{}'.format(self.base_uri, meeting_id), json=kwargs
f'{self.base_uri}/meetings/{meeting_id}', json=kwargs
)
class WebinarComponent(BaseComponent):
def list(self, user_id, **kwargs):
return self.get(
'{}/users/{}/webinars'.format(self.base_uri, user_id), params=kwargs
f'{self.base_uri}/users/{user_id}/webinars', params=kwargs
)
def create(self, user_id, **kwargs):
if kwargs.get('start_time'):
kwargs['start_time'] = format_iso_dt(kwargs['start_time'])
return self.session.post(
'{}/users/{}/webinars'.format(self.base_uri, user_id),
f'{self.base_uri}/users/{user_id}/webinars',
json=kwargs
)
def get(self, meeting_id, **kwargs):
return self.session.get('{}/webinars/{}'.format(self.base_uri, meeting_id), json=kwargs)
return self.session.get(f'{self.base_uri}/webinars/{meeting_id}', json=kwargs)
def update(self, meeting_id, **kwargs):
if kwargs.get('start_time'):
kwargs['start_time'] = format_iso_dt(kwargs['start_time'])
return self.session.patch(
'{}/webinars/{}'.format(self.base_uri, meeting_id), json=kwargs
f'{self.base_uri}/webinars/{meeting_id}', json=kwargs
)
def delete(self, meeting_id, **kwargs):
return self.session.delete(
'{}/webinars/{}'.format(self.base_uri, meeting_id), json=kwargs
f'{self.base_uri}/webinars/{meeting_id}', json=kwargs
)
@ -128,22 +126,22 @@ class UserComponent(BaseComponent):
return self.get('me')
def list(self, **kwargs):
return self.session.get('{}/users'.format(self.base_uri), params=kwargs)
return self.session.get(f'{self.base_uri}/users', params=kwargs)
def create(self, **kwargs):
return self.session.post('{}/users'.format(self.base_uri), params=kwargs)
return self.session.post(f'{self.base_uri}/users', params=kwargs)
def update(self, user_id, **kwargs):
return self.session.patch('{}/users/{}'.format(self.base_uri, user_id), params=kwargs)
return self.session.patch(f'{self.base_uri}/users/{user_id}', params=kwargs)
def delete(self, user_id, **kwargs):
return self.session.delete('{}/users/{}'.format(self.base_uri, user_id), params=kwargs)
return self.session.delete(f'{self.base_uri}/users/{user_id}', params=kwargs)
def get(self, user_id, **kwargs):
return self.session.get('{}/users/{}'.format(self.base_uri, user_id), params=kwargs)
return self.session.get(f'{self.base_uri}/users/{user_id}', params=kwargs)
class ZoomClient(object):
class ZoomClient:
"""Zoom REST API Python Client."""
BASE_URI = 'https://api.zoom.us/v2'
@ -170,7 +168,7 @@ class ZoomClient(object):
# Instantiate the components
self.components = {
key: component(base_uri=self.BASE_URI, config=config, timeout=timeout)
for key, component in self._components.viewitems()
for key, component in self._components.items()
}
@property
@ -189,7 +187,7 @@ class ZoomClient(object):
return self.components['webinar']
class ZoomIndicoClient(object):
class ZoomIndicoClient:
def __init__(self):
from indico_vc_zoom.plugin import ZoomPlugin
self.client = ZoomClient(

View File

@ -5,8 +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
from indico_vc_zoom.controllers import RHRoomAlternativeHost, RHWebhook

View File

@ -5,8 +5,6 @@
# them and/or modify them under the terms of the MIT License;
# see the LICENSE file for more details.
from __future__ import print_function, unicode_literals
import click
from terminaltables import AsciiTable
@ -31,7 +29,7 @@ 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['zoom_id'])])
table_data.append([str(room.id), room.name, room.status.name, str(room.data['zoom_id'])])
table = AsciiTable(table_data)
for col in (0, 3, 4):

View File

@ -5,8 +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, request, session
from flask_pluginengine import current_plugin
from sqlalchemy.orm.attributes import flag_modified

View File

@ -5,8 +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 flask_pluginengine import current_plugin
from wtforms.fields.core import BooleanField, StringField
@ -100,7 +98,7 @@ class VCRoomForm(VCRoomFormBase):
for field_name in {'mute_audio', 'mute_participant_video', 'waiting_room'}:
inject_validators(self, field_name, [HiddenUnless('meeting_type', 'regular')])
super(VCRoomForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
if not allow_webinars:
del self.meeting_type

View File

@ -5,8 +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.notifications import make_email, send_email
from indico.util.user import principal_from_identifier
from indico.web.flask.templating import get_template_module

View File

@ -5,8 +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, session
from markupsafe import escape
from requests.exceptions import HTTPError
@ -147,7 +145,7 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
})
def init(self):
super(ZoomPlugin, self).init()
super().init()
self.connect(signals.plugin.cli, self._extend_indico_cli)
self.connect(signals.event.times_changed, self._times_changed)
self.template_hook('event-vc-room-list-item-labels', self._render_vc_room_labels)
@ -165,7 +163,7 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
def create_form(self, event, existing_vc_room=None, existing_event_vc_room=None):
"""Override the default room form creation mechanism."""
form = super(ZoomPlugin, self).create_form(
form = super().create_form(
event,
existing_vc_room=existing_vc_room,
existing_event_vc_room=existing_event_vc_room
@ -203,7 +201,7 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
# in a new room, `meeting_type` comes in `data`, otherwise it's already in the VCRoom
is_webinar = data.get('meeting_type', vc_room.data and vc_room.data.get('meeting_type')) == 'webinar'
super(ZoomPlugin, self).update_data_association(event, vc_room, room_assoc, data)
super().update_data_association(event, vc_room, room_assoc, data)
if vc_room.data:
# this is not a new room
@ -232,7 +230,7 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
flag_modified(room_assoc, 'data')
def update_data_vc_room(self, vc_room, data, is_new=False):
super(ZoomPlugin, self).update_data_vc_room(vc_room, data)
super().update_data_vc_room(vc_room, data)
fields = {'description', 'password'}
# we may end up not getting a meeting_type from the form
@ -319,7 +317,7 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
raise VCRoomError(_('Could not create the room in Zoom. Please contact support if the error persists'))
vc_room.data.update({
'zoom_id': unicode(meeting_obj['id']),
'zoom_id': str(meeting_obj['id']),
'start_url': meeting_obj['start_url'],
'host': host.identifier,
'alternative_hosts': process_alternative_hosts(meeting_obj['settings'].get('alternative_hosts', ''))
@ -412,7 +410,7 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
vc_room = old_event_vc_room.vc_room
is_webinar = vc_room.data.get('meeting_type', 'regular') == 'webinar'
has_only_one_association = len({assoc.event_id for assoc in vc_room.events}) == 1
new_assoc = super(ZoomPlugin, self).clone_room(old_event_vc_room, link_object)
new_assoc = super().clone_room(old_event_vc_room, link_object)
if has_only_one_association:
update_zoom_meeting(vc_room.data['zoom_id'], {
@ -431,7 +429,7 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
return blueprint
def get_vc_room_form_defaults(self, event):
defaults = super(ZoomPlugin, self).get_vc_room_form_defaults(event)
defaults = super().get_vc_room_form_defaults(event)
defaults.update({
'meeting_type': 'regular' if self.settings.get('allow_webinars') else None,
'mute_audio': self.settings.get('mute_audio'),
@ -445,18 +443,18 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
return defaults
def get_vc_room_attach_form_defaults(self, event):
defaults = super(ZoomPlugin, self).get_vc_room_attach_form_defaults(event)
defaults = super().get_vc_room_attach_form_defaults(event)
defaults['password_visibility'] = 'logged_in'
return defaults
def can_manage_vc_room(self, user, room):
return (
user == principal_from_identifier(room.data['host']) or
super(ZoomPlugin, self).can_manage_vc_room(user, room)
super().can_manage_vc_room(user, room)
)
def _merge_users(self, target, source, **kwargs):
super(ZoomPlugin, self)._merge_users(target, source, **kwargs)
super()._merge_users(target, source, **kwargs)
for room in VCRoom.query.filter(
VCRoom.type == self.service_name, VCRoom.data.contains({'host': source.identifier})
):
@ -478,8 +476,8 @@ class ZoomPlugin(VCPluginMixin, IndicoPlugin):
return render_plugin_template('room_labels.html', vc_room=vc_room)
def _times_changed(self, sender, obj, **kwargs):
from indico.modules.events.models.events import Event
from indico.modules.events.contributions.models.contributions import Contribution
from indico.modules.events.models.events import Event
from indico.modules.events.sessions.models.blocks import SessionBlock
if not hasattr(obj, 'vc_room_associations'):

View File

@ -5,8 +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 random
import re
import string
@ -38,7 +36,7 @@ class ZoomMeetingType(int, IndicoEnum):
recurring_webinar_fixed_time = 9
class UserLookupMode(unicode, RichEnum):
class UserLookupMode(str, RichEnum):
__titles__ = {
'all_emails': _('All emails'),
'email_domains': _('Email domains'),
@ -79,7 +77,7 @@ def iter_user_emails(user):
domains = ZoomPlugin.settings.get('email_domains')
if not domains:
return
email_criterion = db.or_(UserEmail.email.endswith('@{}'.format(domain)) for domain in domains)
email_criterion = db.or_(UserEmail.email.endswith(f'@{domain}') for domain in domains)
# get all matching e-mails, primary first
query = UserEmail.query.filter(
UserEmail.user == user,
@ -92,7 +90,7 @@ def iter_user_emails(user):
elif mode == UserLookupMode.authenticators:
domain = ZoomPlugin.settings.get('enterprise_domain')
for username in _iter_user_identifiers(user):
yield '{}@{}'.format(username, domain)
yield f'{username}@{domain}'
@memoize_request

View File

@ -11,13 +11,13 @@ classifiers =
Environment :: Plugins
Environment :: Web Environment
License :: OSI Approved :: MIT License
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3.9
[options]
packages = find:
zip_safe = false
include_package_data = true
python_requires = ~=2.7
python_requires = ~=3.9
[options.entry_points]
indico.plugins =

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
@ -15,9 +14,9 @@ from setuptools import setup
# is in setup.cfg now
setup(
name='indico-plugin-vc-zoom',
version='2.3b1',
version='3.0-dev',
install_requires=[
'indico>=2.3.2.dev0',
'indico>=3.0.dev0',
'PyJWT>=1.7.1,<2'
],
)