XEP-0050 Make handle_command_xxx async
This commit is contained in:
parent
e97f5ccb9c
commit
eac5ad50a8
2 changed files with 471 additions and 19 deletions
|
@ -3,6 +3,7 @@
|
||||||
# Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
|
# Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
|
||||||
# This file is part of Slixmpp.
|
# This file is part of Slixmpp.
|
||||||
# See the file LICENSE for copying permission.
|
# See the file LICENSE for copying permission.
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -164,25 +165,25 @@ class XEP_0050(BasePlugin):
|
||||||
self.xmpp.event('command', iq)
|
self.xmpp.event('command', iq)
|
||||||
self.xmpp.event('command_%s' % iq['command']['action'], iq)
|
self.xmpp.event('command_%s' % iq['command']['action'], iq)
|
||||||
|
|
||||||
def _handle_command_all(self, iq: Iq) -> None:
|
async def _handle_command_all(self, iq: Iq) -> None:
|
||||||
action = iq['command']['action']
|
action = iq['command']['action']
|
||||||
sessionid = iq['command']['sessionid']
|
sessionid = iq['command']['sessionid']
|
||||||
session = self.sessions.get(sessionid)
|
session = self.sessions.get(sessionid)
|
||||||
|
|
||||||
if session is None:
|
if session is None:
|
||||||
return self._handle_command_start(iq)
|
return await self._handle_command_start(iq)
|
||||||
|
|
||||||
if action in ('next', 'execute'):
|
if action in ('next', 'execute'):
|
||||||
return self._handle_command_next(iq)
|
return await self._handle_command_next(iq)
|
||||||
if action == 'prev':
|
if action == 'prev':
|
||||||
return self._handle_command_prev(iq)
|
return await self._handle_command_prev(iq)
|
||||||
if action == 'complete':
|
if action == 'complete':
|
||||||
return self._handle_command_complete(iq)
|
return await self._handle_command_complete(iq)
|
||||||
if action == 'cancel':
|
if action == 'cancel':
|
||||||
return self._handle_command_cancel(iq)
|
return await self._handle_command_cancel(iq)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _handle_command_start(self, iq):
|
async def _handle_command_start(self, iq):
|
||||||
"""
|
"""
|
||||||
Process an initial request to execute a command.
|
Process an initial request to execute a command.
|
||||||
|
|
||||||
|
@ -222,11 +223,11 @@ class XEP_0050(BasePlugin):
|
||||||
'prev': None,
|
'prev': None,
|
||||||
'cancel': None}
|
'cancel': None}
|
||||||
|
|
||||||
session = handler(iq, initial_session)
|
session = await _await_if_needed(handler, iq, initial_session)
|
||||||
|
|
||||||
self._process_command_response(iq, session)
|
self._process_command_response(iq, session)
|
||||||
|
|
||||||
def _handle_command_next(self, iq):
|
async def _handle_command_next(self, iq):
|
||||||
"""
|
"""
|
||||||
Process a request for the next step in the workflow
|
Process a request for the next step in the workflow
|
||||||
for a command with multiple steps.
|
for a command with multiple steps.
|
||||||
|
@ -246,13 +247,13 @@ class XEP_0050(BasePlugin):
|
||||||
if len(results) == 1:
|
if len(results) == 1:
|
||||||
results = results[0]
|
results = results[0]
|
||||||
|
|
||||||
session = handler(results, session)
|
session = await _await_if_needed(handler, results, session)
|
||||||
|
|
||||||
self._process_command_response(iq, session)
|
self._process_command_response(iq, session)
|
||||||
else:
|
else:
|
||||||
raise XMPPError('item-not-found')
|
raise XMPPError('item-not-found')
|
||||||
|
|
||||||
def _handle_command_prev(self, iq):
|
async def _handle_command_prev(self, iq):
|
||||||
"""
|
"""
|
||||||
Process a request for the prev step in the workflow
|
Process a request for the prev step in the workflow
|
||||||
for a command with multiple steps.
|
for a command with multiple steps.
|
||||||
|
@ -272,7 +273,7 @@ class XEP_0050(BasePlugin):
|
||||||
if len(results) == 1:
|
if len(results) == 1:
|
||||||
results = results[0]
|
results = results[0]
|
||||||
|
|
||||||
session = handler(results, session)
|
session = await _await_if_needed(handler, results, session)
|
||||||
|
|
||||||
self._process_command_response(iq, session)
|
self._process_command_response(iq, session)
|
||||||
else:
|
else:
|
||||||
|
@ -334,7 +335,7 @@ class XEP_0050(BasePlugin):
|
||||||
|
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def _handle_command_cancel(self, iq):
|
async def _handle_command_cancel(self, iq):
|
||||||
"""
|
"""
|
||||||
Process a request to cancel a command's execution.
|
Process a request to cancel a command's execution.
|
||||||
|
|
||||||
|
@ -348,7 +349,7 @@ class XEP_0050(BasePlugin):
|
||||||
if session:
|
if session:
|
||||||
handler = session['cancel']
|
handler = session['cancel']
|
||||||
if handler:
|
if handler:
|
||||||
handler(iq, session)
|
await _await_if_needed(handler, iq, session)
|
||||||
del self.sessions[sessionid]
|
del self.sessions[sessionid]
|
||||||
iq = iq.reply()
|
iq = iq.reply()
|
||||||
iq['command']['node'] = node
|
iq['command']['node'] = node
|
||||||
|
@ -360,7 +361,7 @@ class XEP_0050(BasePlugin):
|
||||||
raise XMPPError('item-not-found')
|
raise XMPPError('item-not-found')
|
||||||
|
|
||||||
|
|
||||||
def _handle_command_complete(self, iq):
|
async def _handle_command_complete(self, iq):
|
||||||
"""
|
"""
|
||||||
Process a request to finish the execution of command
|
Process a request to finish the execution of command
|
||||||
and terminate the workflow.
|
and terminate the workflow.
|
||||||
|
@ -385,7 +386,7 @@ class XEP_0050(BasePlugin):
|
||||||
results = results[0]
|
results = results[0]
|
||||||
|
|
||||||
if handler:
|
if handler:
|
||||||
handler(results, session)
|
await _await_if_needed(handler, results, session)
|
||||||
|
|
||||||
del self.sessions[sessionid]
|
del self.sessions[sessionid]
|
||||||
|
|
||||||
|
@ -616,3 +617,12 @@ class XEP_0050(BasePlugin):
|
||||||
|
|
||||||
if iq['command']['status'] == 'completed':
|
if iq['command']['status'] == 'completed':
|
||||||
self.terminate_command(session)
|
self.terminate_command(session)
|
||||||
|
|
||||||
|
|
||||||
|
async def _await_if_needed(handler, *args):
|
||||||
|
if asyncio.iscoroutinefunction(handler):
|
||||||
|
log.debug(f"%s is async", handler)
|
||||||
|
return await handler(*args)
|
||||||
|
else:
|
||||||
|
log.debug(f"%s is sync", handler)
|
||||||
|
return handler(*args)
|
||||||
|
|
|
@ -47,7 +47,6 @@ class TestAdHocCommands(SlixTest):
|
||||||
session['has_next'] = False
|
session['has_next'] = False
|
||||||
|
|
||||||
return session
|
return session
|
||||||
|
|
||||||
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
||||||
'Do Foo', handle_command)
|
'Do Foo', handle_command)
|
||||||
|
|
||||||
|
@ -418,8 +417,6 @@ class TestAdHocCommands(SlixTest):
|
||||||
</iq>
|
</iq>
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def testMultiPayloads(self):
|
def testMultiPayloads(self):
|
||||||
"""Test using commands with multiple payloads."""
|
"""Test using commands with multiple payloads."""
|
||||||
results = []
|
results = []
|
||||||
|
@ -519,6 +516,451 @@ class TestAdHocCommands(SlixTest):
|
||||||
self.assertEqual(results, [['form_1'], ['form_2']],
|
self.assertEqual(results, [['form_1'], ['form_2']],
|
||||||
"Command handler was not executed: %s" % results)
|
"Command handler was not executed: %s" % results)
|
||||||
|
|
||||||
|
def testZeroStepCommandAsync(self):
|
||||||
|
"""Test running a command with no steps."""
|
||||||
|
|
||||||
|
async def handle_command(iq, session):
|
||||||
|
form = self.xmpp['xep_0004'].make_form(ftype='result')
|
||||||
|
form.addField(var='foo', ftype='text-single',
|
||||||
|
label='Foo', value='bar')
|
||||||
|
|
||||||
|
session['payload'] = form
|
||||||
|
session['next'] = None
|
||||||
|
session['has_next'] = False
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
||||||
|
'Do Foo', handle_command)
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="11" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="execute" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="11" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="completed"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<x xmlns="jabber:x:data" type="result">
|
||||||
|
<field var="foo" label="Foo" type="text-single">
|
||||||
|
<value>bar</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
def testOneStepCommandAsync(self):
|
||||||
|
"""Test running a single step command."""
|
||||||
|
results = []
|
||||||
|
|
||||||
|
async def handle_command(iq, session):
|
||||||
|
|
||||||
|
async def handle_form(form, session):
|
||||||
|
results.append(form.get_values()['foo'])
|
||||||
|
session['payload'] = None
|
||||||
|
|
||||||
|
form = self.xmpp['xep_0004'].make_form('form')
|
||||||
|
form.addField(var='foo', ftype='text-single', label='Foo')
|
||||||
|
|
||||||
|
session['payload'] = form
|
||||||
|
session['next'] = handle_form
|
||||||
|
session['has_next'] = False
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
||||||
|
'Do Foo', handle_command)
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="11" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="execute" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="11" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="executing"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<actions>
|
||||||
|
<complete />
|
||||||
|
</actions>
|
||||||
|
<x xmlns="jabber:x:data" type="form">
|
||||||
|
<field var="foo" label="Foo" type="text-single" />
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="12" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="complete"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<x xmlns="jabber:x:data" type="submit">
|
||||||
|
<field var="foo" label="Foo" type="text-single">
|
||||||
|
<value>blah</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="12" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="completed"
|
||||||
|
sessionid="_sessionid_" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.assertEqual(results, ['blah'],
|
||||||
|
"Command handler was not executed: %s" % results)
|
||||||
|
|
||||||
|
def testTwoStepCommandAsync(self):
|
||||||
|
"""Test using a two-stage command."""
|
||||||
|
results = []
|
||||||
|
|
||||||
|
async def handle_command(iq, session):
|
||||||
|
|
||||||
|
async def handle_step2(form, session):
|
||||||
|
results.append(form.get_values()['bar'])
|
||||||
|
session['payload'] = None
|
||||||
|
|
||||||
|
async def handle_step1(form, session):
|
||||||
|
results.append(form.get_values()['foo'])
|
||||||
|
|
||||||
|
form = self.xmpp['xep_0004'].make_form('form')
|
||||||
|
form.addField(var='bar', ftype='text-single', label='Bar')
|
||||||
|
|
||||||
|
session['payload'] = form
|
||||||
|
session['next'] = handle_step2
|
||||||
|
session['has_next'] = False
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
form = self.xmpp['xep_0004'].make_form('form')
|
||||||
|
form.addField(var='foo', ftype='text-single', label='Foo')
|
||||||
|
|
||||||
|
session['payload'] = form
|
||||||
|
session['next'] = handle_step1
|
||||||
|
session['has_next'] = True
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
||||||
|
'Do Foo', handle_command)
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="11" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="execute" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="11" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="executing"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<actions>
|
||||||
|
<next />
|
||||||
|
</actions>
|
||||||
|
<x xmlns="jabber:x:data" type="form">
|
||||||
|
<field var="foo" label="Foo" type="text-single" />
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="12" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="next"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<x xmlns="jabber:x:data" type="submit">
|
||||||
|
<field var="foo" label="Foo" type="text-single">
|
||||||
|
<value>blah</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="12" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="executing"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<actions>
|
||||||
|
<complete />
|
||||||
|
</actions>
|
||||||
|
<x xmlns="jabber:x:data" type="form">
|
||||||
|
<field var="bar" label="Bar" type="text-single" />
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="13" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="complete"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<x xmlns="jabber:x:data" type="submit">
|
||||||
|
<field var="bar" label="Bar" type="text-single">
|
||||||
|
<value>meh</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
self.send("""
|
||||||
|
<iq id="13" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="completed"
|
||||||
|
sessionid="_sessionid_" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.assertEqual(results, ['blah', 'meh'],
|
||||||
|
"Command handler was not executed: %s" % results)
|
||||||
|
|
||||||
|
def testCancelCommandAsync(self):
|
||||||
|
"""Test canceling command."""
|
||||||
|
results = []
|
||||||
|
|
||||||
|
async def handle_command(iq, session):
|
||||||
|
|
||||||
|
async def handle_form(form, session):
|
||||||
|
results.append(form['values']['foo'])
|
||||||
|
|
||||||
|
async def handle_cancel(iq, session):
|
||||||
|
results.append('canceled')
|
||||||
|
|
||||||
|
form = self.xmpp['xep_0004'].make_form('form')
|
||||||
|
form.addField(var='foo', ftype='text-single', label='Foo')
|
||||||
|
|
||||||
|
session['payload'] = form
|
||||||
|
session['next'] = handle_form
|
||||||
|
session['cancel'] = handle_cancel
|
||||||
|
session['has_next'] = False
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
||||||
|
'Do Foo', handle_command)
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="11" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="execute" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="11" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="executing"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<actions>
|
||||||
|
<complete />
|
||||||
|
</actions>
|
||||||
|
<x xmlns="jabber:x:data" type="form">
|
||||||
|
<field var="foo" label="Foo" type="text-single" />
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="12" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="cancel"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<x xmlns="jabber:x:data" type="submit">
|
||||||
|
<field var="foo" label="Foo" type="text-single">
|
||||||
|
<value>blah</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="12" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="canceled"
|
||||||
|
sessionid="_sessionid_" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.assertEqual(results, ['canceled'],
|
||||||
|
"Cancelation handler not executed: %s" % results)
|
||||||
|
|
||||||
|
def testCommandNoteAsync(self):
|
||||||
|
"""Test adding notes to commands."""
|
||||||
|
|
||||||
|
async def handle_command(iq, session):
|
||||||
|
form = self.xmpp['xep_0004'].make_form(ftype='result')
|
||||||
|
form.addField(var='foo', ftype='text-single',
|
||||||
|
label='Foo', value='bar')
|
||||||
|
|
||||||
|
session['payload'] = form
|
||||||
|
session['next'] = None
|
||||||
|
session['has_next'] = False
|
||||||
|
session['notes'] = [('info', 'testing notes')]
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
||||||
|
'Do Foo', handle_command)
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="11" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="execute" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="11" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="completed"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<note type="info">testing notes</note>
|
||||||
|
<x xmlns="jabber:x:data" type="result">
|
||||||
|
<field var="foo" label="Foo" type="text-single">
|
||||||
|
<value>bar</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
def testMultiPayloadsAsync(self):
|
||||||
|
"""Test using commands with multiple payloads."""
|
||||||
|
results = []
|
||||||
|
|
||||||
|
async def handle_command(iq, session):
|
||||||
|
|
||||||
|
async def handle_form(forms, session):
|
||||||
|
for form in forms:
|
||||||
|
results.append(form.get_values()['FORM_TYPE'])
|
||||||
|
session['payload'] = None
|
||||||
|
|
||||||
|
form1 = self.xmpp['xep_0004'].make_form('form')
|
||||||
|
form1.addField(var='FORM_TYPE', ftype='hidden', value='form_1')
|
||||||
|
form1.addField(var='foo', ftype='text-single', label='Foo')
|
||||||
|
|
||||||
|
form2 = self.xmpp['xep_0004'].make_form('form')
|
||||||
|
form2.addField(var='FORM_TYPE', ftype='hidden', value='form_2')
|
||||||
|
form2.addField(var='foo', ftype='text-single', label='Foo')
|
||||||
|
|
||||||
|
session['payload'] = [form1, form2]
|
||||||
|
session['next'] = handle_form
|
||||||
|
session['has_next'] = False
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
|
||||||
|
'Do Foo', handle_command)
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="11" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="execute" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="11" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="executing"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<actions>
|
||||||
|
<complete />
|
||||||
|
</actions>
|
||||||
|
<x xmlns="jabber:x:data" type="form">
|
||||||
|
<field var="FORM_TYPE" type="hidden">
|
||||||
|
<value>form_1</value>
|
||||||
|
</field>
|
||||||
|
<field var="foo" label="Foo" type="text-single" />
|
||||||
|
</x>
|
||||||
|
<x xmlns="jabber:x:data" type="form">
|
||||||
|
<field var="FORM_TYPE" type="hidden">
|
||||||
|
<value>form_2</value>
|
||||||
|
</field>
|
||||||
|
<field var="foo" label="Foo" type="text-single" />
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.recv("""
|
||||||
|
<iq id="12" type="set" to="tester@localhost" from="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
action="complete"
|
||||||
|
sessionid="_sessionid_">
|
||||||
|
<x xmlns="jabber:x:data" type="submit">
|
||||||
|
<field var="FORM_TYPE" type="hidden">
|
||||||
|
<value>form_1</value>
|
||||||
|
</field>
|
||||||
|
<field var="foo" type="text-single">
|
||||||
|
<value>bar</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
<x xmlns="jabber:x:data" type="submit">
|
||||||
|
<field var="FORM_TYPE" type="hidden">
|
||||||
|
<value>form_2</value>
|
||||||
|
</field>
|
||||||
|
<field var="foo" type="text-single">
|
||||||
|
<value>bar</value>
|
||||||
|
</field>
|
||||||
|
</x>
|
||||||
|
</command>
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.send("""
|
||||||
|
<iq id="12" type="result" to="foo@bar">
|
||||||
|
<command xmlns="http://jabber.org/protocol/commands"
|
||||||
|
node="foo"
|
||||||
|
status="completed"
|
||||||
|
sessionid="_sessionid_" />
|
||||||
|
</iq>
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.assertEqual(results, [['form_1'], ['form_2']],
|
||||||
|
"Command handler was not executed: %s" % results)
|
||||||
|
|
||||||
def testClientAPI(self):
|
def testClientAPI(self):
|
||||||
"""Test using client-side API for commands."""
|
"""Test using client-side API for commands."""
|
||||||
results = []
|
results = []
|
||||||
|
|
Loading…
Reference in a new issue