qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Gordon Sim (Confluence)" <conflue...@apache.org>
Subject [CONF] Apache Qpid > C++ vs. Python API Discrepancies
Date Tue, 16 Jul 2013 08:01:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/en/2176/1/21/_/styles/combined.css?spaceKey=qpid&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><s>C++ vs. Python API Discrepancies</s></h2>
     <h4>Page <b>removed</b> by             <a href="https://cwiki.apache.org/confluence/display/~gsim@redhat.com">Gordon
Sim</a>
    </h4>
     <br/>
     <div class="notificationGreySide">
         <p>This page compares C++ and Python code samples from our examples, looking
for arbitrary discrepancies in the API. I suggest that we add proposals to fix these discrepancies
inline for each example.</p>

<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Openingandclosingconnectionsandsessions"></a>Opening
and closing connections and sessions</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-C"></a>C++</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
Connection connection;
try {
    connection.open(host, port);
    Session session =  connection.newSession();
    ...
    connection.close();
    return 0;
} catch(const std::exception&amp; error) {
    std::cout &lt;&lt; error.what() &lt;&lt; std::endl;
}
return 1;
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Python"></a>Python</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
host="127.0.0.1"
port=5672
user="guest"
password="guest"

socket = connect(host, port)
connection = Connection (sock=socket, username=user, password=password)
connection.start()
session = connection.session(str(uuid4()))
...
session.close(timeout=10)
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>Python uses a socket object, not needed in the C++ API. I suggest that Python follow
C++ here.</li>
	<li>Python requires the user to provide a UUID instead of creating one for him. I suggest
that Python provide the UUID automagically, as does C++.</li>
	<li>Our Python examples end by closing the session, our C++ examples end by closing
the connection. If both APIs allow both approaches, we should fix the examples; if not, we
should make the APIs consistent.</li>
</ul>


<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-SubscribingtoaQueue"></a>Subscribing
to a Queue</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-C"></a>C++</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>LocalQueue local_queue;
SubscriptionManager subscriptions(session);
subscriptions.subscribe(local_queue, string("message_queue"));
subscriptions.run();
</pre>
</div></div>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Python"></a>Python</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>local_queue_name = "local_queue"
queue = session.incoming(local_queue_name)
session.message_subscribe(queue="message_queue", destination=local_queue_name)
queue.start()
</pre>
</div></div>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>C++ local queues are created as standalone objects, then subscribed. Python retrieves
a local queue from the server using the session.incoming() method.</li>
	<li>Python starts delivery using the local queue's start() method. C++ begins delivery
using the SubscriptionManger.run() or Session.run() method.</li>
	<li>Naming: Python calls the method "message_subscribe", which corresponds to the AMQP
name, but it's odd naming: it does not subscribe to a message, nor does it subscribe a message
to anything else.</li>
</ul>


<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-SettingDeliveryProperties%2CMessageProperties"></a>Setting
Delivery Properties, Message Properties</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-C"></a>C++</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
message.getDeliveryProperties().setRoutingKey("routing_key");
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Python"></a>Python</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
delivery_props = session.delivery_properties(routing_key="routing_key")
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>Python requires the programmer to create the delivery property object for a new
message using a session object. That seems strange - it would be better to create it using
the message, since it pertains to a message's delivery properties.</li>
	<li>This same discrepancy affects message properties</li>
</ul>


<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-SubscriptionManager"></a>SubscriptionManager</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>Python does not have a SubscriptionManager. This would be very useful once Python
supports async mode.</li>
</ul>


<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-MessageListeners"></a>Message
Listeners</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-C"></a>C++</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
// A message listener:

class Listener : public MessageListener{
  private:
    SubscriptionManager&amp; subscriptions;
  public:
    Listener(SubscriptionManager&amp; subscriptions);
    virtual void received(Message&amp; message);
};

void Listener::received(Message&amp; message) {
    std::cout &lt;&lt; "Message: " &lt;&lt; message.getData() &lt;&lt;
std::endl;
    if (endCondition(message)) {
       subscriptions.cancel(message.getDestination());
    }
}

// Using a message listener with a subscription manager:

SubscriptionManager subscriptions(session);

Listener listener(subscriptions);
subscriptions.subscribe(listener, "message_queue");
subscriptions.run();
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Python"></a>Python</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
#----- Message Receive Handler -----------------------------
class Receiver:
  def __init__ (self):
    self.finalReceived = False

  def isFinal (self):
    return self.finalReceived

  def Handler (self, message):
    content = message.body
    session.message_accept(RangedSet(message.id))
    print content
    if content == "That's all, folks!":
      self.finalReceived = True

# Call message_subscribe() to tell the broker to deliver messages
# from the AMQP queue to this local client queue. The broker will
# start delivering messages as soon as message_subscribe() is called.

session.message_subscribe(queue="message_queue", destination=local_queue_name)
queue.start()

# Register a message listener with the queue

receiver = Receiver()
queue.listen (receiver.Handler)

while not receiver.isFinal() :
  sleep (1)
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>In Python, a message handler is registered with a local queue, and the local queue
is subscribed to the remote queue. In C+<ins>, a message listener is subscribed to using
a Session or a Subscription Manager. I prefer the C</ins>+ approach here.</li>
</ul>



<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Synchronous%2FAsynchronousModes"></a>Synchronous
/ Asynchronous Modes</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>C++ supports both synchronous and asynchronous modes. Python supports only synchronous
mode. Python should support both.</li>
</ul>



<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-GettingandSettingMessageContents"></a>Getting
and Setting Message Contents</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-C"></a>C++</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
// getData()

std::cout &lt;&lt; "Response: " &lt;&lt; message.getData() &lt;&lt;
std::endl;

// setData()

message.setData("That's all, folks!");

// appendData()

message.appendData(" ... let's add a bit more ...");
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Python"></a>Python</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
message = queue.get(timeout=10)
content = message.body
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>C++ calls this "message data" and accesses it via methods, Python calls it the
message body and provides direct access. They are completely different</li>
</ul>


<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Otherissues"></a>Other issues</h3>

<ul>
	<li>Both languages should support streaming data into and out of messages</li>
	<li>The C++ interface has consistently confused people who work with binary data</li>
</ul>


<h2><a name="C%2B%2Bvs.PythonAPIDiscrepancies-GettingandSettingApplicationHeaders"></a>Getting
and Setting Application Headers</h2>

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-C"></a>C++</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
message.getHeaders().getString("control");

message.getHeaders().setString("control","continue");
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Python"></a>Python</h3>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre> 
message_properties = message.get("message_properties")
message_properties.application_headers["control"] = "continue"
</pre>
</div></div> 

<h3><a name="C%2B%2Bvs.PythonAPIDiscrepancies-Discrepancies"></a>Discrepancies</h3>

<ul>
	<li>Different data model. C++ has a message, which has headers. Python has a message,
which has message properties, including application headers.</li>
</ul>


<ul>
	<li>Python supports via a dictionary, which is very nice. Can I do this in C++?</li>
</ul>

     </div>
</div>
</div>
</div>
</div>
</body>
</html>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


Mime
View raw message