LiveSync: Rename agents to backends

This commit is contained in:
Adrian Moennich 2014-11-20 11:21:52 +01:00
parent 5c0e092133
commit e4e7c5bd1f
15 changed files with 76 additions and 77 deletions

View File

@ -16,10 +16,10 @@
from __future__ import unicode_literals
__all__ = ('LiveSyncPluginBase', 'LiveSyncAgentBase', 'AgentForm', 'SimpleChange', 'process_records',
__all__ = ('LiveSyncPluginBase', 'LiveSyncBackendBase', 'AgentForm', 'SimpleChange', 'process_records',
'MARCXMLGenerator', 'Uploader', 'MARCXMLUploader')
from .base import LiveSyncPluginBase, LiveSyncAgentBase
from .base import LiveSyncPluginBase, LiveSyncBackendBase
from .forms import AgentForm
from .simplify import SimpleChange, process_records
from .marcxml import MARCXMLGenerator

View File

@ -32,19 +32,19 @@ from indico_livesync.plugin import LiveSyncPlugin
class LiveSyncPluginBase(IndicoPlugin): # pragma: no cover
"""Base class for livesync plugins"""
#: dict containing the agent(s) provided by the plugin; the keys are unique identifiers
agent_classes = None
#: dict containing the backend(s) provided by the plugin; the keys are unique identifiers
backend_classes = None
def init(self):
super(LiveSyncPluginBase, self).init()
for name, agent_class in self.agent_classes.iteritems():
assert agent_class.plugin is None
agent_class.plugin = type(self)
LiveSyncPlugin.instance.register_agent_class(name, agent_class)
for name, backend_class in self.backend_classes.iteritems():
assert backend_class.plugin is None
backend_class.plugin = type(self)
LiveSyncPlugin.instance.register_backend_class(name, backend_class)
class LiveSyncAgentBase(object):
"""Base class for livesync agents"""
class LiveSyncBackendBase(object):
"""Base class for livesync backends"""
#: the plugin containing the agent
plugin = None # set automatically when the agent is registered

View File

@ -38,11 +38,11 @@ cli_manager = Manager(usage="Manages LiveSync")
@cli_manager.command
def available_agents():
"""Lists the currently available agent types"""
def available_backends():
"""Lists the currently available backend types"""
print 'The following LiveSync agents are available:'
for name, agent_class in current_plugin.agent_classes.iteritems():
print cformat(' - %{white!}{}%{reset}: {} ({})').format(name, agent_class.title, agent_class.description)
for name, backend in current_plugin.backend_classes.iteritems():
print cformat(' - %{white!}{}%{reset}: {} ({})').format(name, backend.title, backend.description)
@cli_manager.command

View File

@ -31,7 +31,7 @@ from indico_livesync.views import WPLiveSync
def extend_plugin_details():
agents = LiveSyncAgent.find().order_by(LiveSyncAgent.name, LiveSyncAgent.id).all()
return render_plugin_template('plugin_details_extra.html', agents=agents, backends=current_plugin.agent_classes)
return render_plugin_template('plugin_details_extra.html', agents=agents, backends=current_plugin.backend_classes)
class RHDeleteAgent(RHAdminBase):
@ -51,7 +51,7 @@ class RHAddAgent(RHAdminBase):
def _checkParams(self):
self.backend_name = request.view_args['backend']
self.backend = current_plugin.agent_classes[self.backend_name]
self.backend = current_plugin.backend_classes[self.backend_name]
def _process(self):
form = self.backend.form(obj=FormDefaults(name=self.backend.title))

View File

@ -74,7 +74,7 @@ class LiveSyncAgent(db.Model):
def backend(self):
"""Returns the backend class"""
from indico_livesync.plugin import LiveSyncPlugin
return LiveSyncPlugin.instance.agent_classes.get(self.backend_name)
return LiveSyncPlugin.instance.backend_classes.get(self.backend_name)
def create_backend(self, task=None):
"""Creates a new backend instance"""

View File

@ -58,7 +58,7 @@ class LiveSyncPlugin(IndicoPlugin):
def init(self):
super(LiveSyncPlugin, self).init()
self.agent_classes = {}
self.backend_classes = {}
connect_signals(self)
self.template_hook('plugin-details', self._extend_plugin_details)
self.inject_js('livesync_admin_js', WPPlugins, subclasses=False,
@ -73,10 +73,10 @@ class LiveSyncPlugin(IndicoPlugin):
def add_cli_command(self, manager):
manager.add_command('livesync', wrap_cli_manager(cli_manager, self))
def register_agent_class(self, name, agent_class):
if name in self.agent_classes:
raise RuntimeError('Duplicate livesync agent: {}'.format(name))
self.agent_classes[name] = agent_class
def register_backend_class(self, name, backend_class):
if name in self.backend_classes:
raise RuntimeError('Duplicate livesync backend: {}'.format(name))
self.backend_classes[name] = backend_class
def _extend_plugin_details(self, plugin, **kwargs):
if plugin == self:

View File

@ -6,7 +6,7 @@
{%- if agent -%}
{% trans %}Edit Agent{% endtrans %}
{%- else -%}
{% trans %}Add{% endtrans %} {{ backend.title }}
{% trans backend=backend.title %}Add {{ backend }} Agent{% endtrans %}
{%- endif -%}
</h2>
</div>

View File

@ -53,7 +53,7 @@
</table>
{% for name, backend in backends.items() | sort(attribute='1.title') %}
<a class="i-button icon-plus i-form-button" href="{{ url_for_plugin('livesync.add_agent', backend=name) }}">{% trans %}Add{% endtrans %} {{ backend.title }}</a>
<a class="i-button icon-plus i-form-button" href="{{ url_for_plugin('livesync.add_agent', backend=name) }}">{% trans backend=backend.title %}Add {{ backend }} agent{% endtrans %}</a>
{% endfor %}
{% set missing_initial_export = agents|rejectattr('initial_data_exported')|list %}

View File

@ -32,10 +32,10 @@ class Uploader(object):
#: Number of events to process at a time during initial export
INITIAL_BATCH_SIZE = 100
def __init__(self, agent):
self.agent = agent
self.task = agent.task
self.logger = agent.task.logger if agent.task else agent.plugin.logger
def __init__(self, backend):
self.backend = backend
self.task = backend.task
self.logger = backend.task.logger if backend.task else backend.plugin.logger
def run(self, records):
"""Runs the batch upload

View File

@ -16,12 +16,12 @@
from mock import MagicMock
from indico_livesync.base import LiveSyncAgentBase
from indico_livesync.base import LiveSyncBackendBase
from indico_livesync.models.agents import LiveSyncAgent
from indico_livesync.models.queue import LiveSyncQueueEntry, ChangeType
class DummyAgent(LiveSyncAgentBase):
class DummyBackend(LiveSyncBackendBase):
"""Dummy agent
A dummy agent for testing
@ -31,7 +31,7 @@ class DummyAgent(LiveSyncAgentBase):
return set()
class NonDescriptiveAgent(LiveSyncAgentBase):
class NonDescriptiveAgent(LiveSyncBackendBase):
"""Nondescriptive agent"""
@ -67,46 +67,46 @@ class MockCategoryManager(object):
def test_title_description():
"""Test if title/description are extracted from docstring"""
assert DummyAgent.title == 'Dummy agent'
assert DummyAgent.description == 'A dummy agent for testing'
assert DummyBackend.title == 'Dummy agent'
assert DummyBackend.description == 'A dummy agent for testing'
assert NonDescriptiveAgent.title == 'Nondescriptive agent'
assert NonDescriptiveAgent.description == 'no description available'
def test_run_initial():
"""Test if run_initial_export calls the uploader properly"""
agent = DummyAgent(MagicMock())
backend = DummyBackend(MagicMock())
mock_uploader = MagicMock()
agent.uploader = lambda x: mock_uploader
backend.uploader = lambda x: mock_uploader
events = object()
agent.run_initial_export(events)
backend.run_initial_export(events)
mock_uploader.run_initial.assert_called_with(events)
def test_run(mocker):
"""Test if run calls the fetcher/uploader properly"""
mocker.patch.object(DummyAgent, 'fetch_records')
agent = DummyAgent(MagicMock())
mocker.patch.object(DummyBackend, 'fetch_records')
backend = DummyBackend(MagicMock())
mock_uploader = MagicMock()
agent.uploader = lambda x: mock_uploader
agent.run()
assert agent.fetch_records.called
backend.uploader = lambda x: mock_uploader
backend.run()
assert backend.fetch_records.called
assert mock_uploader.run.called
def test_fetch_records(db, mocker):
"""Test if the correct records are fetched"""
mocker.patch.object(DummyAgent, '_is_entry_excluded', return_value=False)
db_agent = LiveSyncAgent(backend_name='dummy', name='dummy')
agent = DummyAgent(db_agent)
db.session.add(db_agent)
mocker.patch.object(DummyBackend, '_is_entry_excluded', return_value=False)
agent = LiveSyncAgent(backend_name='dummy', name='dummy')
backend = DummyBackend(agent)
db.session.add(agent)
queue = [LiveSyncQueueEntry(change=ChangeType.created, type='dummy', processed=True),
LiveSyncQueueEntry(change=ChangeType.created, type='dummy')]
db_agent.queue = queue
agent.queue = queue
db.session.flush()
assert agent.fetch_records() == [queue[1]]
assert agent._is_entry_excluded.call_count == 1
agent._is_entry_excluded.assert_called_with(queue[1])
assert backend.fetch_records() == [queue[1]]
assert backend._is_entry_excluded.call_count == 1
backend._is_entry_excluded.assert_called_with(queue[1])
def test_excluded_categories(mocker, monkeypatch):
@ -114,5 +114,5 @@ def test_excluded_categories(mocker, monkeypatch):
monkeypatch.setattr('indico_livesync.base.CategoryManager', MockCategoryManager)
plugin = mocker.patch('indico_livesync.base.LiveSyncPlugin')
plugin.settings.get.return_value = [{'id': 'invalid'}, {'id': 'c'}, {'id': 'd'}]
agent = LiveSyncAgentBase(MagicMock())
assert agent.excluded_categories == {'c', 'd', 'e', 'f'}
backend = LiveSyncBackendBase(MagicMock())
assert backend.excluded_categories == {'c', 'd', 'e', 'f'}

View File

@ -44,7 +44,7 @@ class FailingUploader(RecordingUploader):
raise Exception('All your data are belong to us!')
def create_mock_agent(has_task=False):
def create_mock_backend(has_task=False):
agent = MagicMock()
if not has_task:
agent.task = None
@ -55,7 +55,7 @@ def create_mock_agent(has_task=False):
def test_run_initial(mocker):
"""Test the initial upload"""
mocker.patch.object(Uploader, 'processed_records', autospec=True)
uploader = RecordingUploader(create_mock_agent())
uploader = RecordingUploader(create_mock_backend())
uploader.INITIAL_BATCH_SIZE = 3
events = tuple(range(4))
uploader.run_initial(events)
@ -70,7 +70,7 @@ def test_run_initial(mocker):
def test_run(mocker):
"""Test uploading queued data"""
db = mocker.patch('indico_livesync.uploader.db')
uploader = RecordingUploader(create_mock_agent())
uploader = RecordingUploader(create_mock_backend())
uploader.BATCH_SIZE = 3
records = tuple(LiveSyncQueueEntry(change=ChangeType.created) for _ in xrange(4))
uploader.run(records)
@ -85,17 +85,17 @@ def test_run(mocker):
def test_run_extend_task(mocker):
"""Test if the task is extended"""
mocker.patch('indico_livesync.uploader.db')
uploader = RecordingUploader(create_mock_agent(has_task=True))
uploader = RecordingUploader(create_mock_backend(has_task=True))
uploader.BATCH_SIZE = 3
records = tuple(LiveSyncQueueEntry(change=ChangeType.created) for _ in xrange(4))
uploader.run(records)
assert uploader.agent.task.extend_runtime.call_count == 2
assert uploader.backend.task.extend_runtime.call_count == 2
def test_run_failing(mocker):
"""Test a failing queue run"""
db = mocker.patch('indico_livesync.uploader.db')
uploader = FailingUploader(create_mock_agent())
uploader = FailingUploader(create_mock_backend())
uploader.BATCH_SIZE = 3
records = tuple(LiveSyncQueueEntry(change=ChangeType.created) for _ in xrange(10))
uploader.run(records)
@ -114,7 +114,7 @@ def test_marcxml_run(mocker):
mocker.patch('indico_livesync.uploader.db')
mocker.patch.object(MARCXMLUploader, 'upload_xml', autospec=True)
mxg = mocker.patch('indico_livesync.uploader.MARCXMLGenerator')
uploader = MARCXMLUploader(create_mock_agent())
uploader = MARCXMLUploader(create_mock_backend())
uploader.run([LiveSyncQueueEntry(change=ChangeType.created)])
assert mxg.records_to_xml.called
assert not mxg.objects_to_xml.called
@ -130,6 +130,6 @@ def test_marcxml_empty_result(mocker):
"""Test if the MARCXML uploader doesn't upload empty records"""
mocker.patch('indico_livesync.uploader.MARCXMLGenerator.objects_to_xml', return_value=None)
mocker.patch.object(MARCXMLUploader, 'upload_xml', autospec=True)
uploader = MARCXMLUploader(create_mock_agent())
uploader = MARCXMLUploader(create_mock_backend())
uploader.run_initial([1])
assert not uploader.upload_xml.called

View File

@ -19,7 +19,7 @@ from __future__ import unicode_literals
from indico.util.console import cformat, strip_ansi
from indico.util.struct.iterables import grouper
from indico_livesync import LiveSyncAgentBase, SimpleChange, MARCXMLGenerator, process_records, Uploader
from indico_livesync import LiveSyncBackendBase, SimpleChange, MARCXMLGenerator, process_records, Uploader
from indico_livesync.util import obj_deref
@ -27,10 +27,10 @@ def _change_str(change):
return ','.join(flag.name for flag in SimpleChange if change & flag)
class LiveSyncDebugAgent(LiveSyncAgentBase):
"""Debug Agent
class LiveSyncDebugBackend(LiveSyncBackendBase):
"""Debug
This agent simply dumps all changes to stdout.
This backend simply dumps all changes to stdout or the logger.
"""
def _print(self, msg=''):
@ -82,6 +82,6 @@ class DebugUploader(Uploader):
def upload_records(self, records, from_queue):
self.n += 1
self.agent._print(cformat('%{white!}Batch {}:%{reset}').format(self.n))
self.backend._print(cformat('%{white!}Batch {}:%{reset}').format(self.n))
xml = MARCXMLGenerator.records_to_xml(records) if from_queue else MARCXMLGenerator.objects_to_xml(records)
self.agent._print(xml if xml else '(no changes)')
self.backend._print(xml if xml else '(no changes)')

View File

@ -18,13 +18,13 @@ from __future__ import unicode_literals
from indico_livesync import LiveSyncPluginBase
from indico_livesync_debug.agent import LiveSyncDebugAgent
from indico_livesync_debug.agent import LiveSyncDebugBackend
class LiveSyncDebugPlugin(LiveSyncPluginBase):
"""LiveSync Debug
Provides a debug agent for LiveSync which just prints changes
Provides the debug backend for LiveSync which just prints/logs changes
"""
agent_classes = {'debug': LiveSyncDebugAgent}
backend_classes = {'debug': LiveSyncDebugBackend}

View File

@ -22,7 +22,7 @@ from wtforms.validators import DataRequired, URL
from indico.util.i18n import _
from indico.util.string import strip_whitespace
from indico_livesync import LiveSyncAgentBase, MARCXMLUploader, AgentForm
from indico_livesync import LiveSyncBackendBase, MARCXMLUploader, AgentForm
from indico_livesync_invenio.connector import InvenioConnector
@ -36,10 +36,9 @@ class InvenioUploaderError(Exception):
class InvenioUploader(MARCXMLUploader):
def __init__(self, *args, **kwargs):
super(InvenioUploader, self).__init__(*args, **kwargs)
url = self.agent.agent.settings.get('server_url')
url = self.backend.agent.settings.get('server_url')
self.connector = InvenioConnector(url)
def upload_xml(self, xml):
@ -48,10 +47,10 @@ class InvenioUploader(MARCXMLUploader):
raise InvenioUploaderError(result.strip())
class InvenioLiveSyncAgent(LiveSyncAgentBase):
"""Invenio Agent
class InvenioLiveSyncBackend(LiveSyncBackendBase):
"""Invenio
This agent uploads data to Invenio.
This backend uploads data to Invenio.
"""
uploader = InvenioUploader

View File

@ -18,13 +18,13 @@ from __future__ import unicode_literals
from indico_livesync import LiveSyncPluginBase
from indico_livesync_invenio.agent import InvenioLiveSyncAgent
from indico_livesync_invenio.agent import InvenioLiveSyncBackend
class InvenioLiveSyncPlugin(LiveSyncPluginBase):
"""LiveSync Invenio
Provides an Invenio agent for LiveSync
Provides the Invenio backend for LiveSync
"""
agent_classes = {'invenio': InvenioLiveSyncAgent}
backend_classes = {'invenio': InvenioLiveSyncBackend}