Author: gsim
Date: Tue Jul 12 18:01:50 2011
New Revision: 1145698

URL: http://svn.apache.org/viewvc?rev=1145698&view=rev
Log:
QPID-3333: Patches from Anthony Foglia to close the gap between qpid.messaging 
and swig based python 'binding' (this includes patches 0001 to 0008 as attached 
to JIRA)

Modified:
    qpid/trunk/qpid/cpp/bindings/qpid/python/python.i

Modified: qpid/trunk/qpid/cpp/bindings/qpid/python/python.i
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/bindings/qpid/python/python.i?rev=1145698&r1=1145697&r2=1145698&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/bindings/qpid/python/python.i (original)
+++ qpid/trunk/qpid/cpp/bindings/qpid/python/python.i Tue Jul 12 18:01:50 2011
@@ -21,21 +21,292 @@
 %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 };
+
+%{
+static PyObject* pNoMessageAvailable;    
+%}
+
+%init %{
+    pNoMessageAvailable = PyErr_NewException(
+        "_cqpid.NoMessageAvailable", NULL, NULL);
+    Py_INCREF(pNoMessageAvailable);
+    PyModule_AddObject(m, "NoMessageAvailable", pNoMessageAvailable);
+%}
+
+%pythoncode %{
+    Empty = _cqpid.NoMessageAvailable
+%}
+
 /* 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::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)
+    %}
+}
+
+
+%extend qpid::messaging::Receiver {
+    %pythoncode %{
+         __swig_getmethods__["capacity"] = getCapacity
+         __swig_setmethods__["capacity"] = setCapacity
+         if _newclass: capacity = _swig_property(getCapacity, setCapacity)
+    %}
+
+    %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)
+    %}
+}
+
+
+%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(content if content else '')
+             try: self.this.append(this)
+             except: self.this = this
+             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)
+
+         __swig_getmethods__["content"] = getContent
+         __swig_setmethods__["content"] = setContent
+         if _newclass: content = _swig_property(getContent, setContent)
+
+         __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
+%}



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscr...@qpid.apache.org

Reply via email to