summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sleekxmpp/plugins/xep_0009/binding.py12
-rw-r--r--sleekxmpp/plugins/xep_0009/remote.py253
-rw-r--r--sleekxmpp/plugins/xep_0009/rpc.py88
-rw-r--r--sleekxmpp/plugins/xep_0009/stanza/RPC.py24
-rw-r--r--sleekxmpp/plugins/xep_0009/stanza/__init__.py2
5 files changed, 180 insertions, 199 deletions
diff --git a/sleekxmpp/plugins/xep_0009/binding.py b/sleekxmpp/plugins/xep_0009/binding.py
index 700beb2f..30f02d36 100644
--- a/sleekxmpp/plugins/xep_0009/binding.py
+++ b/sleekxmpp/plugins/xep_0009/binding.py
@@ -11,11 +11,9 @@ import base64
import logging
import time
-
-
log = logging.getLogger(__name__)
-_namespace = 'jabber:iq:rpc'
+_namespace = 'jabber:iq:rpc'
def fault2xml(fault):
value = dict()
@@ -25,7 +23,7 @@ def fault2xml(fault):
fault.append(_py2xml((value)))
return fault
-def xml2fault(params):
+def xml2fault(params):
vals = []
for value in params.findall('{%s}value' % _namespace):
vals.append(_xml2py(value))
@@ -101,7 +99,7 @@ def xml2py(params):
def _xml2py(value):
namespace = 'jabber:iq:rpc'
if value.find('{%s}nil' % namespace) is not None:
- return None
+ return None
if value.find('{%s}i4' % namespace) is not None:
return int(value.find('{%s}i4' % namespace).text)
if value.find('{%s}int' % namespace) is not None:
@@ -131,7 +129,7 @@ def _xml2py(value):
class rpcbase64(object):
-
+
def __init__(self, data):
#base 64 encoded string
self.data = data
@@ -148,7 +146,7 @@ class rpcbase64(object):
class rpctime(object):
-
+
def __init__(self,data=None):
#assume string data is in iso format YYYYMMDDTHH:MM:SS
if type(data) is str:
diff --git a/sleekxmpp/plugins/xep_0009/remote.py b/sleekxmpp/plugins/xep_0009/remote.py
index bd931c0c..ea867fd7 100644
--- a/sleekxmpp/plugins/xep_0009/remote.py
+++ b/sleekxmpp/plugins/xep_0009/remote.py
@@ -16,19 +16,15 @@ import sys
import threading
import traceback
-
-
log = logging.getLogger(__name__)
-
-
def _intercept(method, name, public):
def _resolver(instance, *args, **kwargs):
log.debug("Locally calling %s.%s with arguments %s." % (instance.FQN(), method.__name__, args))
- try:
+ try:
value = method(instance, *args, **kwargs)
if value == NotImplemented:
- raise InvocationException("Local handler does not implement %s.%s!" % (instance.FQN(), method.__name__))
+ raise InvocationException("Local handler does not implement %s.%s!" % (instance.FQN(), method.__name__))
return value
except InvocationException:
raise
@@ -43,50 +39,49 @@ def remote(function_argument, public = True):
Decorator for methods which are remotely callable. This decorator
works in conjunction with classes which extend ABC Endpoint.
Example:
-
+
@remote
def remote_method(arg1, arg2)
-
+
Arguments:
function_argument -- a stand-in for either the actual method
OR a new name (string) for the method. In that case the
method is considered mapped:
Example:
-
+
@remote("new_name")
def remote_method(arg1, arg2)
-
+
public -- A flag which indicates if this method should be part
of the known dictionary of remote methods. Defaults to True.
Example:
-
+
@remote(False)
def remote_method(arg1, arg2)
-
+
Note: renaming and revising (public vs. private) can be combined.
Example:
-
+
@remote("new_name", False)
def remote_method(arg1, arg2)
'''
if hasattr(function_argument, '__call__'):
return _intercept(function_argument, None, public)
- else:
+ else:
if not isinstance(function_argument, basestring):
- if not isinstance(function_argument, bool):
+ if not isinstance(function_argument, bool):
raise Exception('Expected an RPC method name or visibility modifier!')
else:
def _wrap_revised(function):
function = _intercept(function, None, function_argument)
return function
- return _wrap_revised
+ return _wrap_revised
def _wrap_remapped(function):
function = _intercept(function, function_argument, public)
return function
return _wrap_remapped
-
-
-
+
+
class ACL:
'''
An Access Control List (ACL) is a list of rules, which are evaluated
@@ -102,7 +97,7 @@ class ACL:
[ (ACL.ALLOW, 'test@xmpp.org/unit', 'test.*'),
(ACL.DENY, '*', '*') ] deny everyone everything, except named
JID, which is allowed access to endpoint 'test' only.
-
+
The use of wildcards is allowed in expressions, as follows:
'*' everyone, or everything (= all endpoints and methods)
'test@xmpp.org/*' every JID regardless of JID resource
@@ -113,7 +108,7 @@ class ACL:
'''
ALLOW = True
DENY = False
-
+
@classmethod
def check(cls, rules, jid, resource):
if rules is None:
@@ -121,9 +116,9 @@ class ACL:
for rule in rules:
policy = cls._check(rule, jid, resource)
if policy is not None:
- return policy
+ return policy
return cls.DENY # By default if not rule matches, deny access.
-
+
@classmethod
def _check(cls, rule, jid, resource):
if cls._match(jid, rule[1]) and cls._match(resource, rule[2]):
@@ -138,13 +133,13 @@ class ACL:
return ''
else:
if new_index == -1:
- return expression[index : ]
+ return expression[index : ]
else:
return expression[index : new_index]
@classmethod
- def _match(cls, value, expression):
- #! print "_match [VALUE] %s [EXPR] %s" % (value, expression)
+ def _match(cls, value, expression):
+ #! print "_match [VALUE] %s [EXPR] %s" % (value, expression)
index = 0
position = 0
while index < len(expression):
@@ -169,24 +164,23 @@ class ACL:
ANY_ALL = [ (ACL.ALLOW, '*', '*') ]
-
class RemoteException(Exception):
'''
Base exception for RPC. This exception is raised when a problem
occurs in the network layer.
'''
-
+
def __init__(self, message="", cause=None):
'''
Initializes a new RemoteException.
-
+
Arguments:
message -- The message accompanying this exception.
cause -- The underlying cause of this exception.
- '''
+ '''
self._message = message
- self._cause = cause
- pass
+ self._cause = cause
+ pass
def __str__(self):
return repr(self._message)
@@ -202,7 +196,7 @@ class RemoteException(Exception):
class InvocationException(RemoteException):
'''
Exception raised when a problem occurs during the remote invocation
- of a method.
+ of a method.
'''
pass
@@ -216,48 +210,45 @@ class AuthorizationException(RemoteException):
pass
-
class TimeoutException(Exception):
'''
Exception raised when the synchronous execution of a method takes
longer than the given threshold because an underlying asynchronous
reply did not arrive in time.
'''
- pass
-
+ pass
class Callback(object):
'''
- A base class for callback handlers.
+ A base class for callback handlers.
'''
__metaclass__ = abc.ABCMeta
-
-
+
+
@abc.abstractproperty
def set_value(self, value):
return NotImplemented
-
+
@abc.abstractproperty
def cancel_with_error(self, exception):
return NotImplemented
-
class Future(Callback):
'''
Represents the result of an asynchronous computation.
'''
-
+
def __init__(self):
'''
Initializes a new Future.
'''
self._value = None
- self._exception = None
+ self._exception = None
self._event = threading.Event()
pass
-
+
def set_value(self, value):
'''
Sets the value of this Future. Once the value is set, a caller
@@ -265,13 +256,13 @@ class Future(Callback):
'''
self._value = value
self._event.set()
-
+
def get_value(self, timeout=None):
'''
Gets the value of this Future. This call will block until
the result is available, or until an optional timeout expires.
- When this Future is cancelled with an error,
-
+ When this Future is cancelled with an error,
+
Arguments:
timeout -- The maximum waiting time to obtain the value.
'''
@@ -281,7 +272,7 @@ class Future(Callback):
if not self._event.is_set():
raise TimeoutException
return self._value
-
+
def is_done(self):
'''
Returns true if a value has been returned.
@@ -290,23 +281,23 @@ class Future(Callback):
def cancel_with_error(self, exception):
'''
- Cancels the Future because of an error. Once cancelled, a
+ Cancels the Future because of an error. Once cancelled, a
caller blocked on get_value will be able to continue.
'''
- self._exception = exception
- self._event.set()
+ self._exception = exception
+ self._event.set()
+
-
class Endpoint(object):
'''
The Endpoint class is an abstract base class for all objects
participating in an RPC-enabled XMPP network.
-
+
A user subclassing this class is required to implement the method:
- FQN(self)
- where FQN stands for Fully Qualified Name, an unambiguous name
- which specifies which object an RPC call refers to. It is the
+ FQN(self)
+ where FQN stands for Fully Qualified Name, an unambiguous name
+ which specifies which object an RPC call refers to. It is the
first part in a RPC method name '<fqn>.<method>'.
'''
__metaclass__ = abc.ABCMeta
@@ -317,38 +308,38 @@ class Endpoint(object):
Initialize a new Endpoint. This constructor should never be
invoked by a user, instead it will be called by the factories
which instantiate the RPC-enabled objects, of which only
- the classes are provided by the user.
-
+ the classes are provided by the user.
+
Arguments:
session -- An RPC session instance.
target_jid -- the identity of the remote XMPP entity.
'''
self.session = session
self.target_jid = target_jid
-
+
@abc.abstractproperty
def FQN(self):
return NotImplemented
-
+
def get_methods(self):
'''
Returns a dictionary of all RPC method names provided by this
class. This method returns the actual method names as found
in the class definition which have been decorated with:
-
+
@remote
def some_rpc_method(arg1, arg2)
-
-
+
+
Unless:
(1) the name has been remapped, in which case the new
name will be returned.
-
+
@remote("new_name")
def some_rpc_method(arg1, arg2)
-
+
(2) the method is set to hidden
-
+
@remote(False)
def some_hidden_method(arg1, arg2)
'''
@@ -360,7 +351,7 @@ class Endpoint(object):
result[test_attr._rpc_name] = test_attr
except Exception:
pass
- return result
+ return result
@@ -374,13 +365,13 @@ class Proxy(Endpoint):
def __init__(self, endpoint, callback = None):
'''
Initializes a new Proxy.
-
+
Arguments:
endpoint -- The endpoint which is proxified.
'''
self._endpoint = endpoint
self._callback = callback
-
+
def __getattribute__(self, name, *args):
if name in ('__dict__', '_endpoint', 'async', '_callback'):
return object.__getattribute__(self, name)
@@ -389,31 +380,30 @@ class Proxy(Endpoint):
if hasattr(attribute, '__call__'):
try:
if attribute._rpc:
- def _remote_call(*args, **kwargs):
+ def _remote_call(*args, **kwargs):
log.debug("Remotely calling '%s.%s' with arguments %s." % (self._endpoint.FQN(), attribute._rpc_name, args))
return self._endpoint.session._call_remote(self._endpoint.target_jid, "%s.%s" % (self._endpoint.FQN(), attribute._rpc_name), self._callback, *args, **kwargs)
return _remote_call
except:
- pass # If the attribute doesn't exist, don't care!
+ pass # If the attribute doesn't exist, don't care!
return attribute
-
- def async(self, callback):
+
+ def async(self, callback):
return Proxy(self._endpoint, callback)
-
+
def get_endpoint(self):
'''
Returns the proxified endpoint.
'''
return self._endpoint
-
+
def FQN(self):
return self._endpoint.FQN()
-
class JabberRPCEntry(object):
-
-
+
+
def __init__(self, endpoint_FQN, call):
self._endpoint_FQN = endpoint_FQN
self._call = call
@@ -424,28 +414,27 @@ class JabberRPCEntry(object):
return return_value
else:
return self._return(return_value)
-
+
def get_endpoint_FQN(self):
return self._endpoint_FQN
def _return(self, *args):
return args
-
-
-
+
+
class RemoteSession(object):
'''
- A context object for a Jabber-RPC session.
+ A context object for a Jabber-RPC session.
'''
-
-
+
+
def __init__(self, client, session_close_callback):
'''
Initializes a new RPC session.
-
+
Arguments:
client -- The SleekXMPP client associated with this session.
- session_close_callback -- A callback called when the
+ session_close_callback -- A callback called when the
session is closed.
'''
self._client = client
@@ -455,16 +444,16 @@ class RemoteSession(object):
self._callbacks = {}
self._acls = {}
self._lock = RLock()
-
+
def _wait(self):
self._event.wait()
-
+
def _notify(self, event):
log.debug("RPC Session as %s started." % self._client.boundjid.full)
self._client.sendPresence()
self._event.set()
pass
-
+
def _register_call(self, endpoint, method, name=None):
'''
Registers a method from an endpoint as remotely callable.
@@ -487,8 +476,8 @@ class RemoteSession(object):
def _register_callback(self, pid, callback):
with self._lock:
self._callbacks[pid] = callback
-
- def forget_callback(self, callback):
+
+ def forget_callback(self, callback):
with self._lock:
pid = self._find_key(self._callbacks, callback)
if pid is not None:
@@ -496,7 +485,7 @@ class RemoteSession(object):
else:
raise ValueError("Unknown callback!")
pass
-
+
def _find_key(self, dict, value):
"""return the key of dictionary dic given the value"""
search = [k for k, v in dict.iteritems() if v == value]
@@ -504,7 +493,7 @@ class RemoteSession(object):
return None
else:
return search[0]
-
+
def _unregister_call(self, key):
#removes the registered call
with self._lock:
@@ -512,18 +501,18 @@ class RemoteSession(object):
del self._entries[key]
else:
raise ValueError()
-
+
def new_proxy(self, target_jid, endpoint_cls):
'''
Instantiates a new proxy object, which proxies to a remote
- endpoint. This method uses a class reference without
+ endpoint. This method uses a class reference without
constructor arguments to instantiate the proxy.
-
+
Arguments:
target_jid -- the XMPP entity ID hosting the endpoint.
endpoint_cls -- The remote (duck) type.
'''
- try:
+ try:
argspec = inspect.getargspec(endpoint_cls.__init__)
args = [None] * (len(argspec[0]) - 1)
result = endpoint_cls(*args)
@@ -531,7 +520,7 @@ class RemoteSession(object):
return Proxy(result)
except:
traceback.print_exc(file=sys.stdout)
-
+
def new_handler(self, acl, handler_cls, *args, **kwargs):
'''
Instantiates a new handler object, which is called remotely
@@ -539,7 +528,7 @@ class RemoteSession(object):
implementing the remote method in the local endpoint class. The
returned reference can be called locally and will behave as a
regular instance.
-
+
Arguments:
acl -- Access control list (see ACL class)
handler_clss -- The local (duck) type.
@@ -556,11 +545,11 @@ class RemoteSession(object):
Endpoint.__init__(result, self, self._client.boundjid.full)
method_dict = result.get_methods()
for method_name, method in method_dict.iteritems():
- #!!! self._client.plugin['xep_0009'].register_call(result.FQN(), method, method_name)
+ #!!! self._client.plugin['xep_0009'].register_call(result.FQN(), method, method_name)
self._register_call(result.FQN(), method, method_name)
self._register_acl(result.FQN(), acl)
return result
-
+
# def is_available(self, targetCls, pto):
# return self._client.is_available(pto)
@@ -571,19 +560,19 @@ class RemoteSession(object):
future = Future()
self._register_callback(pid, future)
iq.send()
- return future.get_value(30)
+ return future.get_value(30)
else:
print "[RemoteSession] _call_remote %s" % callback
self._register_callback(pid, callback)
iq.send()
-
+
def close(self):
'''
Closes this session.
'''
self._client.disconnect(False)
self._session_close_callback()
-
+
def _on_jabber_rpc_method_call(self, iq):
iq.enable('rpc_query')
params = iq['rpc_query']['method_call']['params']
@@ -609,15 +598,15 @@ class RemoteSession(object):
except AuthorizationException as ae:
log.error(ae.get_message())
error = self._client.plugin['xep_0009']._forbidden(iq)
- error.send()
- except Exception as e:
+ error.send()
+ except Exception as e:
if isinstance(e, KeyError):
log.error("No handler available for %s!" % pmethod)
error = self._client.plugin['xep_0009']._item_not_found(iq)
else:
traceback.print_exc(file=sys.stderr)
log.error("An unexpected problem occurred invoking method %s!" % pmethod)
- error = self._client.plugin['xep_0009']._undefined_condition(iq)
+ error = self._client.plugin['xep_0009']._undefined_condition(iq)
#! print "[REMOTE.PY] _handle_remote_procedure_call AN ERROR SHOULD BE SENT NOW %s " % e
error.send()
@@ -632,7 +621,7 @@ class RemoteSession(object):
callback.set_value(args[0])
else:
callback.set_value(None)
- pass
+ pass
def _on_jabber_rpc_method_response2(self, iq):
iq.enable('rpc_query')
@@ -648,41 +637,40 @@ class RemoteSession(object):
callback.set_value(args[0])
else:
callback.set_value(None)
- pass
+ pass
def _on_jabber_rpc_method_fault(self, iq):
iq.enable('rpc_query')
fault = xml2fault(iq['rpc_query']['method_response']['fault'])
- pid = iq['id']
+ pid = iq['id']
with self._lock:
callback = self._callbacks[pid]
del self._callbacks[pid]
e = {
- 500: InvocationException
+ 500: InvocationException
}[fault['code']](fault['string'])
- callback.cancel_with_error(e)
+ callback.cancel_with_error(e)
def _on_jabber_rpc_error(self, iq):
pid = iq['id']
pmethod = self._client.plugin['xep_0009']._extract_method(iq['rpc_query'])
- code = iq['error']['code']
+ code = iq['error']['code']
type = iq['error']['type']
condition = iq['error']['condition']
#! print("['REMOTE.PY']._BINDING_handle_remote_procedure_error -> ERROR! ERROR! ERROR! Condition is '%s'" % condition)
with self._lock:
callback = self._callbacks[pid]
del self._callbacks[pid]
- e = {
+ e = {
'item-not-found': RemoteException("No remote handler available for %s at %s!" % (pmethod, iq['from'])),
'forbidden': AuthorizationException("Forbidden to invoke remote handler for %s at %s!" % (pmethod, iq['from'])),
- 'undefined-condition': RemoteException("An unexpected problem occured trying to invoke %s at %s!" % (pmethod, iq['from'])),
+ 'undefined-condition': RemoteException("An unexpected problem occured trying to invoke %s at %s!" % (pmethod, iq['from'])),
}[condition]
if e is None:
RemoteException("An unexpected exception occurred at %s!" % iq['from'])
callback.cancel_with_error(e)
-
class Remote(object):
'''
Bootstrap class for Jabber-RPC sessions. New sessions are openend
@@ -691,18 +679,18 @@ class Remote(object):
_instance = None
_sessions = dict()
_lock = threading.RLock()
-
+
@classmethod
def new_session_with_client(cls, client, callback=None):
'''
Opens a new session with a given client.
-
+
Arguments:
client -- An XMPP client.
callback -- An optional callback which can be used to track
the starting state of the session.
'''
- with Remote._lock:
+ with Remote._lock:
if(client.boundjid.bare in cls._sessions):
raise RemoteException("There already is a session associated with these credentials!")
else:
@@ -710,21 +698,21 @@ class Remote(object):
def _session_close_callback():
with Remote._lock:
del cls._sessions[client.boundjid.bare]
- result = RemoteSession(client, _session_close_callback)
+ result = RemoteSession(client, _session_close_callback)
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_call', result._on_jabber_rpc_method_call)
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_response', result._on_jabber_rpc_method_response)
- client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_fault', result._on_jabber_rpc_method_fault)
+ client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_fault', result._on_jabber_rpc_method_fault)
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_error', result._on_jabber_rpc_error)
if callback is None:
- start_event_handler = result._notify
+ start_event_handler = result._notify
else:
- start_event_handler = callback
- client.add_event_handler("session_start", start_event_handler)
+ start_event_handler = callback
+ client.add_event_handler("session_start", start_event_handler)
if client.connect():
client.process(threaded=True)
else:
raise RemoteException("Could not connect to XMPP server!")
- pass
+ pass
if callback is None:
result._wait()
return result
@@ -733,20 +721,19 @@ class Remote(object):
def new_session(cls, jid, password, callback=None):
'''
Opens a new session and instantiates a new XMPP client.
-
+
Arguments:
jid -- The XMPP JID for logging in.
password -- The password for logging in.
callback -- An optional callback which can be used to track
- the starting state of the session.
- '''
+ the starting state of the session.
+ '''
client = sleekxmpp.ClientXMPP(jid, password)
- #? Register plug-ins.
+ #? Register plug-ins.
client.registerPlugin('xep_0004') # Data Forms
client.registerPlugin('xep_0009') # Jabber-RPC
client.registerPlugin('xep_0030') # Service Discovery
client.registerPlugin('xep_0060') # PubSub
- client.registerPlugin('xep_0199') # XMPP Ping
- return cls.new_session_with_client(client, callback)
+ client.registerPlugin('xep_0199') # XMPP Ping
+ return cls.new_session_with_client(client, callback)
- \ No newline at end of file
diff --git a/sleekxmpp/plugins/xep_0009/rpc.py b/sleekxmpp/plugins/xep_0009/rpc.py
index 84afeb5f..fc306d31 100644
--- a/sleekxmpp/plugins/xep_0009/rpc.py
+++ b/sleekxmpp/plugins/xep_0009/rpc.py
@@ -6,8 +6,8 @@
See the file LICENSE for copying permission.
"""
-from .. import base
-from stanza.RPC import RPCQuery, MethodCall, MethodResponse
+from sleekxmpp.plugins import base
+from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, MethodResponse
from sleekxmpp.stanza.iq import Iq
from sleekxmpp.xmlstream.handler.callback import Callback
from sleekxmpp.xmlstream.matcher.xpath import MatchXPath
@@ -27,15 +27,15 @@ class xep_0009(base.base_plugin):
self.xep = '0009'
self.description = 'Jabber-RPC'
#self.stanza = sleekxmpp.plugins.xep_0009.stanza
-
+
register_stanza_plugin(Iq, RPCQuery)
- register_stanza_plugin(RPCQuery, MethodCall)
+ register_stanza_plugin(RPCQuery, MethodCall)
register_stanza_plugin(RPCQuery, MethodResponse)
-
+
self.xmpp.registerHandler(
Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodCall' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
self._handle_method_call)
- )
+ )
self.xmpp.registerHandler(
Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodResponse' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
self._handle_method_response)
@@ -46,7 +46,7 @@ class xep_0009(base.base_plugin):
)
self.xmpp.add_event_handler('jabber_rpc_method_call', self._on_jabber_rpc_method_call)
self.xmpp.add_event_handler('jabber_rpc_method_response', self._on_jabber_rpc_method_response)
- self.xmpp.add_event_handler('jabber_rpc_method_fault', self._on_jabber_rpc_method_fault)
+ self.xmpp.add_event_handler('jabber_rpc_method_fault', self._on_jabber_rpc_method_fault)
self.xmpp.add_event_handler('jabber_rpc_error', self._on_jabber_rpc_error)
self.xmpp.add_event_handler('error', self._handle_error)
#self.activeCalls = []
@@ -54,7 +54,7 @@ class xep_0009(base.base_plugin):
def post_init(self):
base.base_plugin.post_init(self)
self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:rpc')
- self.xmpp.plugin['xep_0030'].add_identity('automation','rpc')
+ self.xmpp.plugin['xep_0030'].add_identity('automation','rpc')
def make_iq_method_call(self, pto, pmethod, params):
iq = self.xmpp.makeIqSet()
@@ -64,7 +64,7 @@ class xep_0009(base.base_plugin):
iq['rpc_query']['method_call']['method_name'] = pmethod
iq['rpc_query']['method_call']['params'] = params
return iq;
-
+
def make_iq_method_response(self, pid, pto, params):
iq = self.xmpp.makeIqResult(pid)
iq.attrib['to'] = pto
@@ -78,7 +78,7 @@ class xep_0009(base.base_plugin):
iq.attrib['to'] = pto
iq.attrib['from'] = self.xmpp.boundjid.full
iq.enable('rpc_query')
- iq['rpc_query']['method_response']['params'] = None
+ iq['rpc_query']['method_response']['params'] = None
iq['rpc_query']['method_response']['fault'] = params
return iq
@@ -100,58 +100,58 @@ class xep_0009(base.base_plugin):
iq['error']['type'] = 'cancel'
iq['error']['condition'] = 'item-not-found'
return iq
-
+
def _undefined_condition(self, iq):
- payload = iq.get_payload()
- iq.reply().error().set_payload(payload)
+ payload = iq.get_payload()
+ iq.reply().error().set_payload(payload)
iq['error']['code'] = '500'
iq['error']['type'] = 'cancel'
iq['error']['condition'] = 'undefined-condition'
- return iq
+ return iq
def _forbidden(self, iq):
payload = iq.get_payload()
- iq.reply().error().set_payload(payload)
+ iq.reply().error().set_payload(payload)
iq['error']['code'] = '403'
iq['error']['type'] = 'auth'
iq['error']['condition'] = 'forbidden'
- return iq
+ return iq
def _recipient_unvailable(self, iq):
- payload = iq.get_payload()
- iq.reply().error().set_payload(payload)
+ payload = iq.get_payload()
+ iq.reply().error().set_payload(payload)
iq['error']['code'] = '404'
iq['error']['type'] = 'wait'
iq['error']['condition'] = 'recipient-unavailable'
- return iq
+ return iq
def _handle_method_call(self, iq):
type = iq['type']
if type == 'set':
log.debug("Incoming Jabber-RPC call from %s" % iq['from'])
- self.xmpp.event('jabber_rpc_method_call', iq)
+ self.xmpp.event('jabber_rpc_method_call', iq)
else:
if type == 'error' and ['rpc_query'] is None:
self.handle_error(iq)
else:
- log.debug("Incoming Jabber-RPC error from %s" % iq['from'])
- self.xmpp.event('jabber_rpc_error', iq)
-
+ log.debug("Incoming Jabber-RPC error from %s" % iq['from'])
+ self.xmpp.event('jabber_rpc_error', iq)
+
def _handle_method_response(self, iq):
if iq['rpc_query']['method_response']['fault'] is not None:
- log.debug("Incoming Jabber-RPC fault from %s" % iq['from'])
+ log.debug("Incoming Jabber-RPC fault from %s" % iq['from'])
#self._on_jabber_rpc_method_fault(iq)
self.xmpp.event('jabber_rpc_method_fault', iq)
else:
- log.debug("Incoming Jabber-RPC response from %s" % iq['from'])
- self.xmpp.event('jabber_rpc_method_response', iq)
-
+ log.debug("Incoming Jabber-RPC response from %s" % iq['from'])
+ self.xmpp.event('jabber_rpc_method_response', iq)
+
def _handle_error(self, iq):
print("['XEP-0009']._handle_error -> ERROR! Iq is '%s'" % iq)
print("#######################")
- print("### NOT IMPLEMENTED ###")
+ print("### NOT IMPLEMENTED ###")
print("#######################")
-
+
def _on_jabber_rpc_method_call(self, iq, forwarded=False):
"""
A default handler for Jabber-RPC method call. If another
@@ -161,7 +161,7 @@ class xep_0009(base.base_plugin):
forwarded set to True, then it will run as normal.
"""
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_call') > 1:
- return
+ return
# Reply with error by default
error = self.client.plugin['xep_0009']._item_not_found(iq)
error.send()
@@ -175,7 +175,7 @@ class xep_0009(base.base_plugin):
forwarded set to True, then it will run as normal.
"""
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_response') > 1:
- return
+ return
error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
error.send()
@@ -186,12 +186,12 @@ class xep_0009(base.base_plugin):
If this handler is called by your own custom handler with
forwarded set to True, then it will run as normal.
- """
+ """
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_fault') > 1:
- return
+ return
error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
error.send()
-
+
def _on_jabber_rpc_error(self, iq, forwarded=False):
"""
A default handler for Jabber-RPC error response. If another
@@ -199,23 +199,23 @@ class xep_0009(base.base_plugin):
If this handler is called by your own custom handler with
forwarded set to True, then it will run as normal.
- """
+ """
if not forwarded and self.xmpp.event_handled('jabber_rpc_error') > 1:
- return
+ return
error = self.client.plugin['xep_0009']._recpient_unavailable(iq, iq.get_payload())
error.send()
-
- def _send_fault(self, iq, fault_xml): #
+
+ def _send_fault(self, iq, fault_xml): #
fault = self.make_iq_method_response_fault(iq['id'], iq['from'], fault_xml)
- fault.send()
-
+ fault.send()
+
def _send_error(self, iq):
- print("['XEP-0009']._send_error -> ERROR! Iq is '%s'" % iq)
+ print("['XEP-0009']._send_error -> ERROR! Iq is '%s'" % iq)
print("#######################")
- print("### NOT IMPLEMENTED ###")
+ print("### NOT IMPLEMENTED ###")
print("#######################")
-
+
def _extract_method(self, stanza):
xml = ET.fromstring("%s" % stanza)
return xml.find("./methodCall/methodName").text
- \ No newline at end of file
+
diff --git a/sleekxmpp/plugins/xep_0009/stanza/RPC.py b/sleekxmpp/plugins/xep_0009/stanza/RPC.py
index 24f2efd8..3d1c77a2 100644
--- a/sleekxmpp/plugins/xep_0009/stanza/RPC.py
+++ b/sleekxmpp/plugins/xep_0009/stanza/RPC.py
@@ -14,55 +14,51 @@ class RPCQuery(ElementBase):
name = 'query'
namespace = 'jabber:iq:rpc'
plugin_attrib = 'rpc_query'
- interfaces = set(())
+ interfaces = set(())
subinterfaces = set(())
plugin_attrib_map = {}
plugin_tag_map = {}
-
class MethodCall(ElementBase):
name = 'methodCall'
namespace = 'jabber:iq:rpc'
plugin_attrib = 'method_call'
- interfaces = set(('method_name', 'params'))
+ interfaces = set(('method_name', 'params'))
subinterfaces = set(())
plugin_attrib_map = {}
- plugin_tag_map = {}
-
+ plugin_tag_map = {}
def get_method_name(self):
return self._get_sub_text('methodName')
def set_method_name(self, value):
return self._set_sub_text('methodName', value)
-
+
def get_params(self):
return self.xml.find('{%s}params' % self.namespace)
-
+
def set_params(self, params):
self.append(params)
-
-
+
class MethodResponse(ElementBase):
name = 'methodResponse'
namespace = 'jabber:iq:rpc'
plugin_attrib = 'method_response'
- interfaces = set(('params', 'fault'))
+ interfaces = set(('params', 'fault'))
subinterfaces = set(())
plugin_attrib_map = {}
plugin_tag_map = {}
-
-
+
def get_params(self):
return self.xml.find('{%s}params' % self.namespace)
-
+
def set_params(self, params):
self.append(params)
def get_fault(self):
return self.xml.find('{%s}fault' % self.namespace)
-
+
def set_fault(self, fault):
self.append(fault)
diff --git a/sleekxmpp/plugins/xep_0009/stanza/__init__.py b/sleekxmpp/plugins/xep_0009/stanza/__init__.py
index 0b902238..5dcbf330 100644
--- a/sleekxmpp/plugins/xep_0009/stanza/__init__.py
+++ b/sleekxmpp/plugins/xep_0009/stanza/__init__.py
@@ -6,4 +6,4 @@
See the file LICENSE for copying permission.
"""
-from RPC import RPCQuery, MethodCall, MethodResponse
+from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, MethodResponse