Merge branch 'async-adhoc' into 'master'
XEP-0050 Make handle_command_xxx async See merge request poezio/slixmpp!144
This commit is contained in:
		@@ -3,6 +3,7 @@
 | 
			
		||||
# Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
# This file is part of Slixmpp.
 | 
			
		||||
# See the file LICENSE for copying permission.
 | 
			
		||||
import asyncio
 | 
			
		||||
import logging
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
@@ -164,25 +165,25 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
        self.xmpp.event('command', 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']
 | 
			
		||||
        sessionid = iq['command']['sessionid']
 | 
			
		||||
        session = self.sessions.get(sessionid)
 | 
			
		||||
 | 
			
		||||
        if session is None:
 | 
			
		||||
            return self._handle_command_start(iq)
 | 
			
		||||
            return await self._handle_command_start(iq)
 | 
			
		||||
 | 
			
		||||
        if action in ('next', 'execute'):
 | 
			
		||||
            return self._handle_command_next(iq)
 | 
			
		||||
            return await self._handle_command_next(iq)
 | 
			
		||||
        if action == 'prev':
 | 
			
		||||
            return self._handle_command_prev(iq)
 | 
			
		||||
            return await self._handle_command_prev(iq)
 | 
			
		||||
        if action == 'complete':
 | 
			
		||||
            return self._handle_command_complete(iq)
 | 
			
		||||
            return await self._handle_command_complete(iq)
 | 
			
		||||
        if action == 'cancel':
 | 
			
		||||
            return self._handle_command_cancel(iq)
 | 
			
		||||
            return await self._handle_command_cancel(iq)
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def _handle_command_start(self, iq):
 | 
			
		||||
    async def _handle_command_start(self, iq):
 | 
			
		||||
        """
 | 
			
		||||
        Process an initial request to execute a command.
 | 
			
		||||
 | 
			
		||||
@@ -222,11 +223,11 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
                           'prev': None,
 | 
			
		||||
                           'cancel': None}
 | 
			
		||||
 | 
			
		||||
        session = handler(iq, initial_session)
 | 
			
		||||
        session = await _await_if_needed(handler, iq, initial_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
 | 
			
		||||
        for a command with multiple steps.
 | 
			
		||||
@@ -246,13 +247,13 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
            if len(results) == 1:
 | 
			
		||||
                results = results[0]
 | 
			
		||||
 | 
			
		||||
            session = handler(results, session)
 | 
			
		||||
            session = await _await_if_needed(handler, results, session)
 | 
			
		||||
 | 
			
		||||
            self._process_command_response(iq, session)
 | 
			
		||||
        else:
 | 
			
		||||
            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
 | 
			
		||||
        for a command with multiple steps.
 | 
			
		||||
@@ -272,7 +273,7 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
            if len(results) == 1:
 | 
			
		||||
                results = results[0]
 | 
			
		||||
 | 
			
		||||
            session = handler(results, session)
 | 
			
		||||
            session = await _await_if_needed(handler, results, session)
 | 
			
		||||
 | 
			
		||||
            self._process_command_response(iq, session)
 | 
			
		||||
        else:
 | 
			
		||||
@@ -334,7 +335,7 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
 | 
			
		||||
        iq.send()
 | 
			
		||||
 | 
			
		||||
    def _handle_command_cancel(self, iq):
 | 
			
		||||
    async def _handle_command_cancel(self, iq):
 | 
			
		||||
        """
 | 
			
		||||
        Process a request to cancel a command's execution.
 | 
			
		||||
 | 
			
		||||
@@ -348,7 +349,7 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
        if session:
 | 
			
		||||
            handler = session['cancel']
 | 
			
		||||
            if handler:
 | 
			
		||||
                handler(iq, session)
 | 
			
		||||
                await _await_if_needed(handler, iq, session)
 | 
			
		||||
            del self.sessions[sessionid]
 | 
			
		||||
            iq = iq.reply()
 | 
			
		||||
            iq['command']['node'] = node
 | 
			
		||||
@@ -360,7 +361,7 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
            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
 | 
			
		||||
        and terminate the workflow.
 | 
			
		||||
@@ -385,7 +386,7 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
                results = results[0]
 | 
			
		||||
 | 
			
		||||
            if handler:
 | 
			
		||||
                handler(results, session)
 | 
			
		||||
                await _await_if_needed(handler, results, session)
 | 
			
		||||
 | 
			
		||||
            del self.sessions[sessionid]
 | 
			
		||||
 | 
			
		||||
@@ -616,3 +617,12 @@ class XEP_0050(BasePlugin):
 | 
			
		||||
 | 
			
		||||
        if iq['command']['status'] == 'completed':
 | 
			
		||||
            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
 | 
			
		||||
 | 
			
		||||
            return session
 | 
			
		||||
 | 
			
		||||
        self.xmpp['xep_0050'].add_command('tester@localhost', 'foo',
 | 
			
		||||
                                          'Do Foo', handle_command)
 | 
			
		||||
 | 
			
		||||
@@ -418,8 +417,6 @@ class TestAdHocCommands(SlixTest):
 | 
			
		||||
          </iq>
 | 
			
		||||
        """)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def testMultiPayloads(self):
 | 
			
		||||
        """Test using commands with multiple payloads."""
 | 
			
		||||
        results = []
 | 
			
		||||
@@ -519,6 +516,451 @@ class TestAdHocCommands(SlixTest):
 | 
			
		||||
        self.assertEqual(results, [['form_1'], ['form_2']],
 | 
			
		||||
                "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):
 | 
			
		||||
        """Test using client-side API for commands."""
 | 
			
		||||
        results = []
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user