diff options
author | Stephen D. Huston <shuston@apache.org> | 2011-10-21 14:42:12 +0000 |
---|---|---|
committer | Stephen D. Huston <shuston@apache.org> | 2011-10-21 14:42:12 +0000 |
commit | f83677056891e436bf5ba99e79240df2a44528cd (patch) | |
tree | 625bfd644b948e89105630759cf6decb0435354d /cpp/bindings/qpid/python/python.i | |
parent | ebfd9ff053b04ab379acfc0fefedee5a31b6d8a5 (diff) | |
download | qpid-python-QPID-2519.tar.gz |
Merged out from trunkQPID-2519
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-2519@1187375 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/bindings/qpid/python/python.i')
-rw-r--r-- | cpp/bindings/qpid/python/python.i | 338 |
1 files changed, 337 insertions, 1 deletions
diff --git a/cpp/bindings/qpid/python/python.i b/cpp/bindings/qpid/python/python.i index bf61cb10b7..9d45bf54ee 100644 --- a/cpp/bindings/qpid/python/python.i +++ b/cpp/bindings/qpid/python/python.i @@ -21,21 +21,357 @@ %include "std_string.i" %include "../../swig_python_typemaps.i" +/* Needed for get/setPriority methods. Surprising SWIG 1.3.40 doesn't + * convert uint8_t by default. */ +%apply unsigned char { uint8_t }; + + +/* + * Exceptions + * + * The convention below is that exceptions in _cqpid.so have the same + * names as in the C++ library. They get renamed to their Python + * equivalents when brought into the Python wrapping + */ +%{ +static PyObject* pNoMessageAvailable; +static PyObject* pTargetCapacityExceeded; +static PyObject* pNotFound; +static PyObject* pTransportFailure; +%} + +%init %{ + pNoMessageAvailable = PyErr_NewException( + "_cqpid.NoMessageAvailable", NULL, NULL); + Py_INCREF(pNoMessageAvailable); + PyModule_AddObject(m, "NoMessageAvailable", pNoMessageAvailable); + + pTargetCapacityExceeded = PyErr_NewException( + "_cqpid.TargetCapacityExceeded", NULL, NULL); + Py_INCREF(pTargetCapacityExceeded); + PyModule_AddObject(m, "TargetCapacityExceeded", pTargetCapacityExceeded); + + pNotFound = PyErr_NewException( + "_cqpid.NotFound", NULL, NULL); + Py_INCREF(pNotFound); + PyModule_AddObject(m, "NotFound", pNotFound); + + pTransportFailure = PyErr_NewException( + "_cqpid.TransportFailure", NULL, NULL); + Py_INCREF(pTransportFailure); + PyModule_AddObject(m, "TransportFailure", pTransportFailure); +%} + +%pythoncode %{ + Empty = _cqpid.NoMessageAvailable + TargetCapacityExceeded = _cqpid.TargetCapacityExceeded + NotFound = _cqpid.NotFound + ConnectError = _cqpid.TransportFailure +%} + /* Define the general-purpose exception handling */ %exception { + PyObject * pExceptionType = NULL; std::string error; Py_BEGIN_ALLOW_THREADS; try { $action + } catch (qpid::messaging::NoMessageAvailable & ex) { + pExceptionType = pNoMessageAvailable; + error = ex.what(); + } catch (qpid::messaging::TargetCapacityExceeded & ex) { + pExceptionType = pTargetCapacityExceeded; + error = ex.what(); + } catch (qpid::messaging::NotFound & ex) { + pExceptionType = pNotFound; + error = ex.what(); + } catch (qpid::messaging::TransportFailure & ex) { + pExceptionType = pTransportFailure; + error = ex.what(); } catch (qpid::types::Exception& ex) { + pExceptionType = PyExc_RuntimeError; error = ex.what(); } Py_END_ALLOW_THREADS; if (!error.empty()) { - PyErr_SetString(PyExc_RuntimeError, error.c_str()); + PyErr_SetString(pExceptionType, error.c_str()); return NULL; } } + +/* This only renames the non-const version (I believe). Then again, I + * don't even know why there is a non-const version of the method. */ +%rename(opened) qpid::messaging::Connection::isOpen(); +%rename(receiver) qpid::messaging::Session::createReceiver; +%rename(sender) qpid::messaging::Session::createSender; +%rename(_acknowledge_all) qpid::messaging::Session::acknowledge(bool); +%rename(_acknowledge_msg) qpid::messaging::Session::acknowledge( + Message &, bool); + +%rename(_fetch) qpid::messaging::Receiver::fetch; +%rename(unsettled) qpid::messaging::Receiver::getUnsettled; +%rename(available) qpid::messaging::Receiver::getAvailable; + +%rename(unsettled) qpid::messaging::Sender::getUnsettled; +%rename(available) qpid::messaging::Sender::getAvailable; +%rename(_send) qpid::messaging::Sender::send; + +%rename(_getReplyTo) qpid::messaging::Message::getReplyTo; +%rename(_setReplyTo) qpid::messaging::Message::setReplyTo; +%rename(_getTtl) qpid::messaging::Message::getTtl; +%rename(_setTtl) qpid::messaging::Message::setTtl; + + %include "../qpid.i" +%extend qpid::messaging::Connection { + %pythoncode %{ + # Handle the different options by converting underscores to hyphens. + # Also, the sasl_mechanisms option in Python has no direct + # equivalent in C++, so we will translate them to sasl_mechanism + # when possible. + def __init__(self, url=None, **options): + args = [url] if url else [] + if options : + if "sasl_mechanisms" in options : + if ' ' in options.get("sasl_mechanisms",'') : + raise Exception( + "C++ Connection objects are unable to handle " + "multiple sasl-mechanisms") + options["sasl_mechanism"] = options.pop("sasl_mechanisms") + args.append(options) + this = _cqpid.new_Connection(*args) + try: self.this.append(this) + except: self.this = this + %} + + /* Return a pre-existing session with the given name, if one + * exists, otherwise return a new one. (Note that if a + * pre-existing session exists, the transactional argument is + * ignored, and the returned session might not satisfy the desired + * setting. */ + qpid::messaging::Session _session(const std::string & name, + bool transactional) { + if (!name.empty()) { + try { + return self->getSession(name); + } + catch (const qpid::messaging::KeyError &) { + } + } + if (transactional) { + return self->createTransactionalSession(name); + } + else { + return self->createSession(name); + } + } + + %pythoncode %{ + def session(self, name=None, transactional=False) : + if name is None : + name = '' + return self._session(name, transactional) + %} + + %pythoncode %{ + @staticmethod + def establish(url=None, **options) : + conn = Connection(url, **options) + conn.open() + return conn + %} +} + +%extend qpid::messaging::Session { + %pythoncode %{ + def acknowledge(self, message=None, disposition=None, sync=True) : + if disposition : + raise Exception("SWIG does not support dispositions yet. Use " + "Session.reject and Session.release instead") + if message : + self._acknowledge_msg(message, sync) + else : + self._acknowledge_all(sync) + + __swig_getmethods__["connection"] = getConnection + if _newclass: connection = _swig_property(getConnection) + %} +} + + +%extend qpid::messaging::Receiver { + %pythoncode %{ + __swig_getmethods__["capacity"] = getCapacity + __swig_setmethods__["capacity"] = setCapacity + if _newclass: capacity = _swig_property(getCapacity, setCapacity) + + __swig_getmethods__["session"] = getSession + if _newclass: session = _swig_property(getSession) + %} + + %pythoncode %{ + def fetch(self, timeout=None) : + if timeout is None : + return self._fetch() + else : + # Python API uses timeouts in seconds, + # but C++ API uses milliseconds + return self._fetch(Duration(int(1000*timeout))) + %} +} + +%extend qpid::messaging::Sender { + %pythoncode %{ + def send(self, object, sync=True) : + if isinstance(object, Message): + message = object + else: + message = Message(object) + return self._send(message, sync) + + __swig_getmethods__["capacity"] = getCapacity + __swig_setmethods__["capacity"] = setCapacity + if _newclass: capacity = _swig_property(getCapacity, setCapacity) + + __swig_getmethods__["session"] = getSession + if _newclass: session = _swig_property(getSession) + %} +} + + +%extend qpid::messaging::Message { + %pythoncode %{ + # UNSPECIFIED was module level before, but I do not + # know how to insert python code at the top of the module. + # (A bare "%pythoncode" inserts at the end. + UNSPECIFIED=object() + def __init__(self, content=None, content_type=UNSPECIFIED, id=None, + subject=None, user_id=None, reply_to=None, + correlation_id=None, durable=None, priority=None, + ttl=None, properties=None): + this = _cqpid.new_Message('') + try: self.this.append(this) + except: self.this = this + if content : + self.content = content + if content_type != UNSPECIFIED : + self.content_type = content_type + if id is not None : + self.id = id + if subject is not None : + self.subject = subject + if user_id is not None : + self.user_id = user_id + if reply_to is not None : + self.reply_to = reply_to + if correlation_id is not None : + self.correlation_id = correlation_id + if durable is not None : + self.durable = durable + if priority is not None : + self.priority = priority + if ttl is not None : + self.ttl = ttl + if properties is not None : + # Can't set properties via (inst).getProperties, because + # the typemaps make a copy of the underlying properties. + # Instead, set via setProperty for the time-being + for k, v in properties.iteritems() : + self.setProperty(k, v) + + def _get_content(self) : + if self.content_type == "amqp/list" : + return decodeList(self) + if self.content_type == "amqp/map" : + return decodeMap(self) + return self.getContent() + def _set_content(self, content) : + if isinstance(content, basestring) : + self.setContent(content) + elif isinstance(content, list) or isinstance(content, dict) : + encode(content, self) + else : + # Not a type we can handle. Try setting it anyway, + # although this will probably lead to a swig error + self.setContent(content) + __swig_getmethods__["content"] = _get_content + __swig_setmethods__["content"] = _set_content + if _newclass: content = _swig_property(_get_content, _set_content) + + __swig_getmethods__["content_type"] = getContentType + __swig_setmethods__["content_type"] = setContentType + if _newclass: content_type = _swig_property(getContentType, + setContentType) + + __swig_getmethods__["id"] = getMessageId + __swig_setmethods__["id"] = setMessageId + if _newclass: id = _swig_property(getMessageId, setMessageId) + + __swig_getmethods__["subject"] = getSubject + __swig_setmethods__["subject"] = setSubject + if _newclass: subject = _swig_property(getSubject, setSubject) + + __swig_getmethods__["priority"] = getPriority + __swig_setmethods__["priority"] = setPriority + if _newclass: priority = _swig_property(getPriority, setPriority) + + def getTtl(self) : + return self._getTtl().getMilliseconds()/1000.0 + def setTtl(self, duration) : + self._setTtl(Duration(int(1000*duration))) + __swig_getmethods__["ttl"] = getTtl + __swig_setmethods__["ttl"] = setTtl + if _newclass: ttl = _swig_property(getTtl, setTtl) + + __swig_getmethods__["user_id"] = getUserId + __swig_setmethods__["user_id"] = setUserId + if _newclass: user_id = _swig_property(getUserId, setUserId) + + __swig_getmethods__["correlation_id"] = getCorrelationId + __swig_setmethods__["correlation_id"] = setCorrelationId + if _newclass: correlation_id = _swig_property(getCorrelationId, + setCorrelationId) + + __swig_getmethods__["redelivered"] = getRedelivered + __swig_setmethods__["redelivered"] = setRedelivered + if _newclass: redelivered = _swig_property(getRedelivered, + setRedelivered) + + __swig_getmethods__["durable"] = getDurable + __swig_setmethods__["durable"] = setDurable + if _newclass: durable = _swig_property(getDurable, setDurable) + + __swig_getmethods__["properties"] = getProperties + if _newclass: properties = _swig_property(getProperties) + + def getReplyTo(self) : + return self._getReplyTo().str() + def setReplyTo(self, address_str) : + self._setReplyTo(Address(address_str)) + __swig_getmethods__["reply_to"] = getReplyTo + __swig_setmethods__["reply_to"] = setReplyTo + if _newclass: reply_to = _swig_property(getReplyTo, setReplyTo) + + def __repr__(self): + args = [] + for name in ["id", "subject", "user_id", "reply_to", + "correlation_id", "priority", "ttl", + "durable", "redelivered", "properties", + "content_type"] : + value = getattr(self, name) + if value : args.append("%s=%r" % (name, value)) + if self.content is not None: + if args: + args.append("content=%r" % self.content) + else: + args.append(repr(self.content)) + return "Message(%s)" % ", ".join(args) + %} +} + +%pythoncode %{ +# Bring into module scope +UNSPECIFIED = Message.UNSPECIFIED +%} |