Module proton
[frames] | no frames]

Source Code for Module proton

   1  # 
   2   # Licensed to the Apache Software Foundation (ASF) under one 
   3  # or more contributor license agreements.  See the NOTICE file 
   4  # distributed with this work for additional information 
   5  # regarding copyright ownership.  The ASF licenses this file 
   6  # to you under the Apache License, Version 2.0 (the 
   7  # "License"); you may not use this file except in compliance 
   8  # with the License.  You may obtain a copy of the License at 
   9  #  
  10  #   http://www.apache.org/licenses/LICENSE-2.0 
  11  #  
  12  # Unless required by applicable law or agreed to in writing, 
  13  # software distributed under the License is distributed on an 
  14  # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
  15  # KIND, either express or implied.  See the License for the 
  16  # specific language governing permissions and limitations 
  17  # under the License. 
  18  # 
  19   
  20  """ 
  21  The proton module defines a suite of APIs that implement the AMQP 1.0 
  22  protocol. 
  23   
  24  The proton APIs consist of the following classes: 
  25   
  26   - L{Messenger} -- A messaging endpoint. 
  27   - L{Message}   -- A class for creating and/or accessing AMQP message content. 
  28   - L{Data}      -- A class for creating and/or accessing arbitrary AMQP encoded 
  29                    data. 
  30   
  31  """ 
  32   
  33  from cproton import * 
34 35 -class ProtonException(Exception):
36 """ 37 The root of the proton exception hierarchy. All proton exception 38 classes derive from this exception. 39 """ 40 pass
41
42 -class Timeout(ProtonException):
43 """ 44 A timeout exception indicates that a blocking operation has timed 45 out. 46 """ 47 pass
48
49 -class MessengerException(ProtonException):
50 """ 51 The root of the messenger exception hierarchy. All exceptions 52 generated by the messenger class derive from this exception. 53 """ 54 pass
55
56 -class MessageException(ProtonException):
57 """ 58 The MessageException class is the root of the message exception 59 hierarhcy. All exceptions generated by the Message class derive from 60 this exception. 61 """ 62 pass
63 64 EXCEPTIONS = { 65 PN_TIMEOUT: Timeout 66 }
67 68 -class Messenger(object):
69 """ 70 The L{Messenger} class defines a high level interface for sending 71 and receiving L{Messages<Message>}. Every L{Messenger} contains a 72 single logical queue of incoming messages and a single logical queue 73 of outgoing messages. These messages in these queues may be destined 74 for, or originate from, a variety of addresses. 75 76 Address Syntax 77 ============== 78 79 An address has the following form:: 80 81 [ amqp[s]:// ] [user[:password]@] domain [/[name]] 82 83 Where domain can be one of:: 84 85 host | host:port | ip | ip:port | name 86 87 The following are valid examples of addresses: 88 89 - example.org 90 - example.org:1234 91 - amqp://example.org 92 - amqps://example.org 93 - example.org/incoming 94 - amqps://example.org/outgoing 95 - amqps://fred:trustno1@example.org 96 - 127.0.0.1:1234 97 - amqps://127.0.0.1:1234 98 99 Sending & Receiving Messages 100 ============================ 101 102 The L{Messenger} class works in conjuction with the L{Message} 103 class. The L{Message} class is a mutable holder of message content. 104 The L{put} method will encode the content in a given L{Message} 105 object into the outgoing message queue leaving that L{Message} 106 object free to be modified or discarded without having any impact on 107 the content in the outgoing queue. 108 109 >>> message = Message() 110 >>> for i in range(3): 111 ... message.address = "amqp://host/queue" 112 ... message.subject = "Hello World %i" % i 113 ... messenger.put(message) 114 >>> messenger.send() 115 116 Similarly, the L{get} method will decode the content in the incoming 117 message queue into the supplied L{Message} object. 118 119 >>> message = Message() 120 >>> messenger.recv(10): 121 >>> while messenger.incoming > 0: 122 ... messenger.get(message) 123 ... print message.subject 124 Hello World 0 125 Hello World 1 126 Hello World 2 127 """ 128
129 - def __init__(self, name=None):
130 """ 131 Construct a new L{Messenger} with the given name. The name has 132 global scope. If a NULL name is supplied, a L{uuid.UUID} based 133 name will be chosen. 134 135 @type name: string 136 @param name: the name of the messenger or None 137 """ 138 self._mng = pn_messenger(name)
139
140 - def __del__(self):
141 if hasattr(self, "_mng"): 142 pn_messenger_free(self._mng) 143 del self._mng
144
145 - def _check(self, err):
146 if err < 0: 147 exc = EXCEPTIONS.get(err, MessengerException) 148 raise exc("[%s]: %s" % (err, pn_messenger_error(self._mng))) 149 else: 150 return err
151 152 @property
153 - def name(self):
154 """ 155 The name of the L{Messenger}. 156 """ 157 return pn_messenger_name(self._mng)
158
159 - def _get_certificate(self):
160 return pn_messenger_get_certificate(self._mng)
161
162 - def _set_certificate(self, value):
163 self._check(pn_messenger_set_certificate(self._mng, value))
164 165 certificate = property(_get_certificate, _set_certificate, 166 doc=""" 167 Path to a certificate file for the L{Messenger}. This certificate is 168 used when the L{Messenger} accepts or establishes SSL/TLS connections. 169 This property must be specified for the L{Messenger} to accept 170 incoming SSL/TLS connections and to establish client authenticated 171 outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS 172 connections do not require this property. 173 """) 174
175 - def _get_private_key(self):
176 return pn_messenger_get_private_key(self._mng)
177
178 - def _set_private_key(self, value):
179 self._check(pn_messenger_set_private_key(self._mng, value))
180 181 private_key = property(_get_private_key, _set_private_key, 182 doc=""" 183 Path to a private key file for the L{Messenger's<Messenger>} 184 certificate. This property must be specified for the L{Messenger} to 185 accept incoming SSL/TLS connections and to establish client 186 authenticated outgoing SSL/TLS connection. Non client authenticated 187 SSL/TLS connections do not require this property. 188 """) 189
190 - def _get_password(self):
191 return pn_messenger_get_password(self._mng)
192
193 - def _set_password(self, value):
194 self._check(pn_messenger_set_password(self._mng, value))
195 196 password = property(_get_password, _set_password, 197 doc=""" 198 This property contains the password for the L{Messenger.private_key} 199 file, or None if the file is not encrypted. 200 """) 201
202 - def _get_trusted_certificates(self):
203 return pn_messenger_get_trusted_certificates(self._mng)
204
205 - def _set_trusted_certificates(self, value):
206 self._check(pn_messenger_set_trusted_certificates(self._mng, value))
207 208 trusted_certificates = property(_get_trusted_certificates, 209 _set_trusted_certificates, 210 doc=""" 211 A path do a database of trusted certificates for use in verifying the 212 peer on an SSL/TLS connection. If this property is None, then the peer 213 will not be verified. 214 """) 215
216 - def _get_timeout(self):
217 return pn_messenger_get_timeout(self._mng)
218
219 - def _set_timeout(self, value):
220 self._check(pn_messenger_set_timeout(self._mng, value))
221 222 timeout = property(_get_timeout, _set_timeout, 223 doc=""" 224 The timeout property contains the default timeout for blocking 225 operations performed by the L{Messenger}. 226 """) 227
228 - def start(self):
229 """ 230 Transitions the L{Messenger} to an active state. A L{Messenger} is 231 initially created in an inactive state. When inactive a 232 L{Messenger} will not send or receive messages from its internal 233 queues. A L{Messenger} must be started before calling L{send} or 234 L{recv}. 235 """ 236 self._check(pn_messenger_start(self._mng))
237
238 - def stop(self):
239 """ 240 Transitions the L{Messenger} to an inactive state. An inactive 241 L{Messenger} will not send or receive messages from its internal 242 queues. A L{Messenger} should be stopped before being discarded to 243 ensure a clean shutdown handshake occurs on any internally managed 244 connections. 245 """ 246 self._check(pn_messenger_stop(self._mng))
247
248 - def subscribe(self, source):
249 """ 250 Subscribes the L{Messenger} to messages originating from the 251 specified source. The source is an address as specified in the 252 L{Messenger} introduction with the following addition. If the 253 domain portion of the address begins with the '~' character, the 254 L{Messenger} will interpret the domain as host/port, bind to it, 255 and listen for incoming messages. For example "~0.0.0.0", 256 "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any 257 local interface and listen for incoming messages with the last 258 variant only permitting incoming SSL connections. 259 260 @type source: string 261 @param source: the source of messages to subscribe to 262 """ 263 self._check(pn_messenger_subscribe(self._mng, source))
264
265 - def put(self, message):
266 """ 267 Places the content contained in the message onto the outgoing 268 queue of the L{Messenger}. This method will never block, however 269 it will send any unblocked L{Messages<Message>} in the outgoing 270 queue immediately and leave any blocked L{Messages<Message>} 271 remaining in the outgoing queue. The L{send} call may be used to 272 block until the outgoing queue is empty. The L{outgoing} property 273 may be used to check the depth of the outgoing queue. 274 275 @type message: Message 276 @param message: the message to place in the outgoing queue 277 """ 278 self._check(pn_messenger_put(self._mng, message._msg))
279
280 - def send(self):
281 """ 282 Blocks until the outgoing queue is empty or the operation times 283 out. The L{timeout} property controls how long a L{Messenger} will 284 block before timing out. 285 """ 286 self._check(pn_messenger_send(self._mng))
287
288 - def recv(self, n):
289 """ 290 Receives up to I{n} messages into the incoming queue of the 291 L{Messenger}. This method will block until at least one message is 292 available or the operation times out. 293 """ 294 self._check(pn_messenger_recv(self._mng, n))
295
296 - def get(self, message):
297 """ 298 Moves the message from the head of the incoming message queue into 299 the supplied message object. Any content in the message will be 300 overwritten. 301 302 @type message: Message 303 @param message: the destination message object 304 """ 305 self._check(pn_messenger_get(self._mng, message._msg))
306 307 @property
308 - def outgoing(self):
309 """ 310 The outgoing queue depth. 311 """ 312 return pn_messenger_outgoing(self._mng)
313 314 @property
315 - def incoming(self):
316 """ 317 The incoming queue depth. 318 """ 319 return pn_messenger_incoming(self._mng)
320
321 -class Message(object):
322 """ 323 The L{Message} class is a mutable holder of message content. 324 """ 325 326 DATA = PN_DATA 327 TEXT = PN_TEXT 328 AMQP = PN_AMQP 329 JSON = PN_JSON 330 331 DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY 332
333 - def __init__(self):
334 self._msg = pn_message()
335
336 - def __del__(self):
337 if hasattr(self, "_msg"): 338 pn_message_free(self._msg) 339 del self._msg
340
341 - def _check(self, err):
342 if err < 0: 343 exc = EXCEPTIONS.get(err, MessageException) 344 raise exc("[%s]: %s" % (err, pn_message_error(self._msg))) 345 else: 346 return err
347
348 - def clear(self):
349 """ 350 Clears the contents of the L{Message}. All fields will be reset to 351 their default values. 352 """ 353 pn_message_clear(self._msg)
354
355 - def _is_durable(self):
356 return pn_message_is_durable(self._msg)
357
358 - def _set_durable(self, value):
359 self._check(pn_message_set_durable(self._msg, bool(value)))
360 361 durable = property(_is_durable, _set_durable, 362 doc=""" 363 The durable property indicates that the message should be held durably 364 by any intermediaries taking responsibility for the message. 365 """) 366
367 - def _get_priority(self):
368 return pn_message_get_priority(self._msg)
369
370 - def _set_priority(self, value):
371 self._check(pn_message_set_priority(self._msg, value))
372 373 priority = property(_get_priority, _set_priority, 374 doc=""" 375 The priority of the message. 376 """) 377
378 - def _get_ttl(self):
379 return pn_message_get_ttl(self._msg)
380
381 - def _set_ttl(self, value):
382 self._check(pn_message_set_ttl(self._msg, value))
383 384 ttl = property(_get_ttl, _set_ttl, 385 doc=""" 386 The time to live of the message measured in milliseconds. Expired 387 messages may be dropped. 388 """) 389
390 - def _is_first_acquirer(self):
391 return pn_message_is_first_acquirer(self._msg)
392
393 - def _set_first_acquirer(self, value):
394 self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
395 396 first_acquirer = property(_is_first_acquirer, _set_first_acquirer, 397 doc=""" 398 True iff the recipient is the first to acquire the message. 399 """) 400
401 - def _get_delivery_count(self):
402 return pn_message_get_delivery_count(self._msg)
403
404 - def _set_delivery_count(self, value):
405 self._check(pn_message_set_delivery_count(self._msg, value))
406 407 delivery_count = property(_get_delivery_count, _set_delivery_count, 408 doc=""" 409 The number of delivery attempts made for this message. 410 """) 411 412 # XXX
413 - def _get_id(self):
414 return pn_message_get_id(self._msg)
415
416 - def _set_id(self, value):
417 self._check(pn_message_set_id(self._msg, value))
418 419 id = property(_get_id, _set_id, 420 doc=""" 421 The id of the message. 422 """) 423
424 - def _get_user_id(self):
425 return pn_message_get_user_id(self._msg)
426
427 - def _set_user_id(self, value):
428 self._check(pn_message_set_user_id(self._msg, value))
429 430 user_id = property(_get_user_id, _set_user_id, 431 doc=""" 432 The user id of the message creator. 433 """) 434
435 - def _get_address(self):
436 return pn_message_get_address(self._msg)
437
438 - def _set_address(self, value):
439 self._check(pn_message_set_address(self._msg, value))
440 441 address = property(_get_address, _set_address, 442 doc=""" 443 The address of the message. 444 """) 445
446 - def _get_subject(self):
447 return pn_message_get_subject(self._msg)
448
449 - def _set_subject(self, value):
450 self._check(pn_message_set_subject(self._msg, value))
451 452 subject = property(_get_subject, _set_subject, 453 doc=""" 454 The subject of the message. 455 """) 456
457 - def _get_reply_to(self):
458 return pn_message_get_reply_to(self._msg)
459
460 - def _set_reply_to(self, value):
461 self._check(pn_message_set_reply_to(self._msg, value))
462 463 reply_to = property(_get_reply_to, _set_reply_to, 464 doc=""" 465 The reply-to address for the message. 466 """) 467 468 # XXX
469 - def _get_correlation_id(self):
470 return pn_message_get_correlation_id(self._msg)
471
472 - def _set_correlation_id(self, value):
473 self._check(pn_message_set_correlation_id(self._msg, value))
474 475 correlation_id = property(_get_correlation_id, _set_correlation_id, 476 doc=""" 477 The correlation-id for the message. 478 """) 479
480 - def _get_content_type(self):
481 return pn_message_get_content_type(self._msg)
482
483 - def _set_content_type(self, value):
484 self._check(pn_message_set_content_type(self._msg, value))
485 486 content_type = property(_get_content_type, _set_content_type, 487 doc=""" 488 The content-type of the message. 489 """) 490
491 - def _get_content_encoding(self):
492 return pn_message_get_content_encoding(self._msg)
493
494 - def _set_content_encoding(self, value):
495 self._check(pn_message_set_content_encoding(self._msg, value))
496 497 content_encoding = property(_get_content_encoding, _set_content_encoding, 498 doc=""" 499 The content-encoding of the message. 500 """) 501
502 - def _get_expiry_time(self):
503 return pn_message_get_expiry_time(self._msg)
504
505 - def _set_expiry_time(self, value):
506 self._check(pn_message_set_expiry_time(self._msg, value))
507 508 expiry_time = property(_get_expiry_time, _set_expiry_time, 509 doc=""" 510 The expiry time of the message. 511 """) 512
513 - def _get_creation_time(self):
514 return pn_message_get_creation_time(self._msg)
515
516 - def _set_creation_time(self, value):
517 self._check(pn_message_set_creation_time(self._msg, value))
518 519 creation_time = property(_get_creation_time, _set_creation_time, 520 doc=""" 521 The creation time of the message. 522 """) 523
524 - def _get_group_id(self):
525 return pn_message_get_group_id(self._msg)
526
527 - def _set_group_id(self, value):
528 self._check(pn_message_set_group_id(self._msg, value))
529 530 group_id = property(_get_group_id, _set_group_id, 531 doc=""" 532 The group id of the message. 533 """) 534
535 - def _get_group_sequence(self):
536 return pn_message_get_group_sequence(self._msg)
537
538 - def _set_group_sequence(self, value):
539 self._check(pn_message_set_group_sequence(self._msg, value))
540 541 group_sequence = property(_get_group_sequence, _set_group_sequence, 542 doc=""" 543 The sequence of the message within its group. 544 """) 545
546 - def _get_reply_to_group_id(self):
547 return pn_message_get_reply_to_group_id(self._msg)
548
549 - def _set_reply_to_group_id(self, value):
550 self._check(pn_message_set_reply_to_group_id(self._msg, value))
551 552 reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id, 553 doc=""" 554 The group-id for any replies. 555 """) 556 557 # XXX
558 - def _get_format(self):
559 return pn_message_get_format(self._msg)
560
561 - def _set_format(self, value):
562 self._check(pn_message_set_format(self._msg, value))
563 564 format = property(_get_format, _set_format, 565 doc=""" 566 The format of the message. 567 """) 568
569 - def encode(self):
570 sz = 16 571 while True: 572 err, data = pn_message_encode(self._msg, sz) 573 if err == PN_OVERFLOW: 574 sz *= 2 575 continue 576 else: 577 self._check(err) 578 return data
579
580 - def decode(self, data):
581 return self._check(pn_message_decode(self._msg, data, len(data)))
582
583 - def load(self, data):
584 self._check(pn_message_load(self._msg, data))
585
586 - def save(self):
587 sz = 16 588 while True: 589 err, data = pn_message_save(self._msg, sz) 590 if err == PN_OVERFLOW: 591 sz *= 2 592 continue 593 else: 594 self._check(err) 595 return data
596
597 -class DataException(ProtonException):
598 """ 599 The DataException class is the root of the Data exception hierarchy. 600 All exceptions raised by the Data class extend this exception. 601 """ 602 pass
603
604 -class Data:
605 """ 606 The L{Data} class provides an interface for decoding, extracting, 607 creating, and encoding arbitrary AMQP data. A L{Data} object 608 contains a tree of AMQP values. Leaf nodes in this tree correspond 609 to scalars in the AMQP type system such as L{ints<INT>} or 610 L{strings<STRING>}. Non-leaf nodes in this tree correspond to 611 compound values in the AMQP type system such as L{lists<LIST>}, 612 L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}. 613 The root node of the tree is the L{Data} object itself and can have 614 an arbitrary number of children. 615 616 A L{Data} object maintains the notion of the current sibling node 617 and a current parent node. Siblings are ordered within their parent. 618 Values are accessed and/or added by using the L{next}, L{prev}, 619 L{enter}, and L{exit} methods to navigate to the desired location in 620 the tree and using the supplied variety of put_*/get_* methods to 621 access or add a value of the desired type. 622 623 The put_* methods will always add a value I{after} the current node 624 in the tree. If the current node has a next sibling the put_* method 625 will overwrite the value on this node. If there is no current node 626 or the current node has no next sibling then one will be added. The 627 put_* methods always set the added/modified node to the current 628 node. The get_* methods read the value of the current node and do 629 not change which node is current. 630 631 The following types of scalar values are supported: 632 633 - L{NULL} 634 - L{BOOL} 635 - L{UBYTE} 636 - L{USHORT} 637 - L{SHORT} 638 - L{UINT} 639 - L{INT} 640 - L{ULONG} 641 - L{LONG} 642 - L{FLOAT} 643 - L{DOUBLE} 644 - L{BINARY} 645 - L{STRING} 646 - L{SYMBOL} 647 648 The following types of compound values are supported: 649 650 - L{DESCRIBED} 651 - L{ARRAY} 652 - L{LIST} 653 - L{MAP} 654 """ 655 656 NULL = PN_NULL; "A null value." 657 BOOL = PN_BOOL; "A boolean value." 658 UBYTE = PN_UBYTE; "An unsigned byte value." 659 BYTE = PN_BYTE; "A signed byte value." 660 USHORT = PN_USHORT; "An unsigned short value." 661 SHORT = PN_SHORT; "A short value." 662 UINT = PN_UINT; "An unsigned int value." 663 INT = PN_INT; "A signed int value." 664 CHAR = PN_CHAR; "A character value." 665 ULONG = PN_ULONG; "An unsigned long value." 666 LONG = PN_LONG; "A signed long value." 667 TIMESTAMP = PN_TIMESTAMP; "A timestamp value." 668 FLOAT = PN_FLOAT; "A float value." 669 DOUBLE = PN_DOUBLE; "A double value." 670 BINARY = PN_BINARY; "A binary string." 671 STRING = PN_STRING; "A unicode string." 672 SYMBOL = PN_SYMBOL; "A symbolic string." 673 DESCRIBED = PN_DESCRIPTOR; "A described value." 674 ARRAY = PN_ARRAY; "An array value." 675 LIST = PN_LIST; "A list value." 676 MAP = PN_MAP; "A map value." 677
678 - def __init__(self, capacity=16):
679 self._data = pn_data(capacity)
680
681 - def __del__(self):
682 if hasattr(self, "_data"): 683 pn_data_free(self._data) 684 del self._data
685
686 - def _check(self, err):
687 if err < 0: 688 exc = EXCEPTIONS.get(err, DataException) 689 raise exc("[%s]: %s" % (err, "xxx")) 690 else: 691 return err
692
693 - def rewind(self):
694 """ 695 Clears current node and sets the parent to the root node. 696 """ 697 pn_data_rewind(self._data)
698
699 - def next(self):
700 """ 701 Advances the current node to its next sibling and returns its 702 type. If there is no next sibling the current node remains 703 unchanged and None is returned. 704 """ 705 found, dtype = pn_data_next(self._data) 706 if found: 707 return dtype 708 else: 709 return None
710
711 - def prev(self):
712 """ 713 Advances the current node to its previous sibling and returns its 714 type. If there is no previous sibling the current node remains 715 unchanged and None is returned. 716 """ 717 found, dtype = pn_data_prev(self._data) 718 if found: 719 return dtype 720 else: 721 return None
722
723 - def enter(self):
724 """ 725 Sets the parent node to the current node and clears the current node. 726 """ 727 return pn_data_enter(self._data)
728
729 - def exit(self):
730 """ 731 Sets the current node to the parent node and the parent node to 732 its own parent. 733 """ 734 return pn_data_exit(self._data)
735
736 - def encode(self):
737 """ 738 Returns a representation of the data encoded in AMQP format. 739 """ 740 size = 1024 741 while True: 742 cd, enc = pn_data_encode(self._data, size) 743 if cd == PN_OVERFLOW: 744 size *= 2 745 elif cd >= 0: 746 return enc 747 else: 748 self._check(cd)
749
750 - def decode(self, encoded):
751 """ 752 Decodes the first value from supplied AMQP data and returns the 753 number of bytes consumed. 754 755 @type encoded: binary 756 @param encoded: AMQP encoded binary data 757 """ 758 return self._check(pn_data_decode(self._data, encoded))
759
760 - def put_list(self):
761 """ 762 Puts a list value. Elements may be filled by entering the list 763 node and putting element values. 764 765 >>> data = Data() 766 >>> data.put_list() 767 >>> data.enter() 768 >>> data.put_int(1) 769 >>> data.put_int(2) 770 >>> data.put_int(3) 771 >>> data.exit() 772 """ 773 self._check(pn_data_put_list(self._data))
774
775 - def put_map(self):
776 """ 777 Puts a map value. Elements may be filled by entering the map node 778 and putting alternating key value pairs. 779 780 >>> data = Data() 781 >>> data.put_map() 782 >>> data.enter() 783 >>> data.put_string("key") 784 >>> data.put_string("value") 785 >>> data.exit() 786 """ 787 self._check(pn_data_put_map(self._data))
788
789 - def put_array(self, described, element_type):
790 """ 791 Puts an array value. Elements may be filled by entering the array 792 node and putting the element values. The values must all be of the 793 specified array element type. If an array is described then the 794 first child value of the array is the descriptor and may be of any 795 type. 796 797 >>> data = Data() 798 >>> 799 >>> data.put_array(False, Data.INT) 800 >>> data.enter() 801 >>> data.put_int(1) 802 >>> data.put_int(2) 803 >>> data.put_int(3) 804 >>> data.exit() 805 >>> 806 >>> data.put_array(True, Data.DOUBLE) 807 >>> data.enter() 808 >>> data.put_symbol("array-descriptor") 809 >>> data.enter() 810 >>> data.put_double(1.1) 811 >>> data.put_double(1.2) 812 >>> data.put_double(1.3) 813 >>> data.exit() 814 815 @type described: bool 816 @param described: specifies whether the array is described 817 @type element_type: int 818 @param element_type: the type of the array elements 819 """ 820 self._check(pn_data_put_array(self._data, described, element_type))
821
822 - def put_described(self):
823 """ 824 Puts a described value. A described node has two children, the 825 descriptor and the value. These are specified by entering the node 826 and putting the desired values. 827 828 >>> data = Data() 829 >>> data.put_described() 830 >>> data.enter() 831 >>> data.put_symbol("value-descriptor") 832 >>> data.put_string("the value") 833 >>> data.exit() 834 """ 835 self._check(pn_data_put_described(self._data))
836
837 - def put_null(self):
838 """ 839 Puts a null value. 840 """ 841 self._check(pn_data_put_null(self._data))
842
843 - def put_bool(self, b):
844 """ 845 Puts a boolean value. 846 847 @param b: a boolean value 848 """ 849 self._check(pn_data_put_bool(self._data, b))
850
851 - def put_ubyte(self, ub):
852 """ 853 Puts an unsigned byte value. 854 855 @param ub: an integral value 856 """ 857 self._check(pn_data_put_ubyte(self._data, ub))
858
859 - def put_byte(self, b):
860 """ 861 Puts a signed byte value. 862 863 @param b: an integral value 864 """ 865 self._check(pn_data_put_byte(self._data, b))
866
867 - def put_ushort(self, us):
868 """ 869 Puts an unsigned short value. 870 871 @param us: an integral value. 872 """ 873 self._check(pn_data_put_ushort(self._data, us))
874
875 - def put_short(self, s):
876 """ 877 Puts a signed short value. 878 879 @param s: an integral value 880 """ 881 self._check(pn_data_put_short(self._data, s))
882
883 - def put_uint(self, ui):
884 """ 885 Puts an unsigned int value. 886 887 @param ui: an integral value 888 """ 889 self._check(pn_data_put_uint(self._data, ui))
890
891 - def put_int(self, i):
892 """ 893 Puts a signed int value. 894 895 @param i: an integral value 896 """ 897 self._check(pn_data_put_int(self._data, i))
898
899 - def put_char(self, c):
900 """ 901 Puts a char value. 902 903 @param c: a single character 904 """ 905 self._check(pn_data_put_char(self._data, ord(c)))
906
907 - def put_ulong(self, ul):
908 """ 909 Puts an unsigned long value. 910 911 @param ul: an integral value 912 """ 913 self._check(pn_data_put_ulong(self._data, ul))
914
915 - def put_long(self, l):
916 """ 917 Puts a signed long value. 918 919 @param l: an integral value 920 """ 921 self._check(pn_data_put_long(self._data, l))
922
923 - def put_timestamp(self, t):
924 """ 925 Puts a timestamp value. 926 927 @param t: an integral value 928 """ 929 self._check(pn_data_put_timestamp(self._data, t))
930
931 - def put_float(self, f):
932 """ 933 Puts a float value. 934 935 @param f: a floating point value 936 """ 937 self._check(pn_data_put_float(self._data, f))
938
939 - def put_double(self, d):
940 """ 941 Puts a double value. 942 943 @param d: a floating point value. 944 """ 945 self._check(pn_data_put_double(self._data, d))
946
947 - def put_binary(self, b):
948 """ 949 Puts a binary value. 950 951 @type b: binary 952 @param b: a binary value 953 """ 954 self._check(pn_data_put_binary(self._data, b))
955
956 - def put_string(self, s):
957 """ 958 Puts a unicode value. 959 960 @type s: unicode 961 @param s: a unicode value 962 """ 963 self._check(pn_data_put_string(self._data, s))
964
965 - def put_symbol(self, s):
966 """ 967 Puts a symbolic value. 968 969 @type s: string 970 @param s: the symbol name 971 """ 972 self._check(pn_data_put_symbol(self._data, s))
973
974 - def get_list(self):
975 """ 976 If the current node is a list, return the number of elements, 977 otherwise raise an error. List elements can be accessed by 978 entering the list. 979 980 >>> count = data.get_list() 981 >>> data.enter() 982 >>> for i in range(count): 983 ... type = data.next() 984 ... if type == Data.STRING: 985 ... print data.get_string() 986 ... elif type == ...: 987 ... ... 988 >>> data.exit() 989 """ 990 err, count = pn_data_get_list(self._data) 991 self._check(err) 992 return count
993
994 - def get_map(self):
995 """ 996 If the current node is a map, return the number of child elements, 997 otherwise raise an error. Key value pairs can be accessed by 998 entering the map. 999 1000 >>> count = data.get_map() 1001 >>> data.enter() 1002 >>> for i in range(count/2): 1003 ... type = data.next() 1004 ... if type == Data.STRING: 1005 ... print data.get_string() 1006 ... elif type == ...: 1007 ... ... 1008 >>> data.exit() 1009 """ 1010 err, count = pn_data_get_map(self._data) 1011 self._check(err) 1012 return count
1013
1014 - def get_array(self):
1015 """ 1016 If the current node is an array, return a tuple of the element 1017 count, a boolean indicating whether the array is described, and 1018 the type of each element. Array data can be accessed by entering 1019 the array. 1020 1021 >>> # read an array of strings with a symbolic descriptor 1022 >>> count, described, type = data.get_array() 1023 >>> data.enter() 1024 >>> data.next() 1025 >>> print "Descriptor:", data.get_symbol() 1026 >>> for i in range(count): 1027 ... data.next() 1028 ... print "Element:", data.get_string() 1029 >>> data.exit() 1030 """ 1031 err, count, described, type = pn_data_get_array(self._data) 1032 self._check(err) 1033 return count, described, type
1034
1035 - def get_described(self):
1036 """ 1037 Checks if the current node is a described value, raises an 1038 exception otherwise. The descriptor and value may be accessed by 1039 entering the described value. 1040 1041 >>> # read a symbolically described string 1042 >>> data.get_described() # will error if the current node is not described 1043 >>> data.enter() 1044 >>> print data.get_symbol() 1045 >>> print data.get_string() 1046 >>> data.exit() 1047 """ 1048 self._check(pn_data_get_described(self._data))
1049
1050 - def get_null(self):
1051 """ 1052 Checks if the current node is a null, raises an exception 1053 otherwise. 1054 """ 1055 self._check(pn_data_get_null(self._data))
1056
1057 - def get_bool(self):
1058 """ 1059 If the current node is a boolean, returns its value, raises an 1060 exception otherwise. 1061 """ 1062 err, b = pn_data_get_bool(self._data) 1063 self._check(err) 1064 return b
1065
1066 - def get_ubyte(self):
1067 """ 1068 If the current node is an unsigned byte, returns its value, raises 1069 an exception otherwise. 1070 """ 1071 err, value = pn_data_get_ubyte(self._data) 1072 self._check(err) 1073 return value
1074
1075 - def get_byte(self):
1076 """ 1077 If the current node is a signed byte, returns its value, raises an 1078 exception otherwise. 1079 """ 1080 err, value = pn_data_get_byte(self._data) 1081 self._check(err) 1082 return value
1083
1084 - def get_ushort(self):
1085 """ 1086 If the current node is an unsigned short, returns its value, 1087 raises an exception otherwise. 1088 """ 1089 err, value = pn_data_get_ushort(self._data) 1090 self._check(err) 1091 return value
1092
1093 - def get_short(self):
1094 """ 1095 If the current node is a signed short, returns its value, raises 1096 an exception otherwise. 1097 """ 1098 err, value = pn_data_get_short(self._data) 1099 self._check(err) 1100 return value
1101
1102 - def get_uint(self):
1103 """ 1104 If the current node is an unsigned int, returns its value, raises 1105 an exception otherwise. 1106 """ 1107 err, value = pn_data_get_uint(self._data) 1108 self._check(err) 1109 return value
1110
1111 - def get_int(self):
1112 """ 1113 If the current node is a signed int, returns its value, raises an 1114 exception otherwise. 1115 """ 1116 err, value = pn_data_get_int(self._data) 1117 self._check(err) 1118 return value
1119
1120 - def get_char(self):
1121 """ 1122 If the current node is a char, returns its value, raises an 1123 exception otherwise. 1124 """ 1125 err, value = pn_data_get_char(self._data) 1126 self._check(err) 1127 return unichr(value)
1128
1129 - def get_ulong(self):
1130 """ 1131 If the current node is an unsigned long, returns its value, raises 1132 an exception otherwise. 1133 """ 1134 err, value = pn_data_get_ulong(self._data) 1135 self._check(err) 1136 return value
1137
1138 - def get_long(self):
1139 """ 1140 If the current node is an signed long, returns its value, raises 1141 an exception otherwise. 1142 """ 1143 err, value = pn_data_get_long(self._data) 1144 self._check(err) 1145 return value
1146
1147 - def get_timestamp(self):
1148 """ 1149 If the current node is a timestamp, returns its value, raises 1150 an exception otherwise. 1151 """ 1152 err, value = pn_data_get_timestamp(self._data) 1153 self._check(err) 1154 return value
1155
1156 - def get_float(self):
1157 """ 1158 If the current node is a float, returns its value, raises an 1159 exception otherwise. 1160 """ 1161 err, value = pn_data_get_float(self._data) 1162 self._check(err) 1163 return value
1164
1165 - def get_double(self):
1166 """ 1167 If the current node is a double, returns its value, raises an 1168 exception otherwise. 1169 """ 1170 err, value = pn_data_get_double(self._data) 1171 self._check(err) 1172 return value
1173
1174 - def get_binary(self):
1175 """ 1176 If the current node is binary, returns its value, raises an 1177 exception otherwise. 1178 """ 1179 err, value = pn_data_get_binary(self._data) 1180 self._check(err) 1181 return value
1182
1183 - def get_string(self):
1184 """ 1185 If the current node is a string, returns its value, raises an 1186 exception otherwise. 1187 """ 1188 err, value = pn_data_get_string(self._data) 1189 self._check(err) 1190 return value
1191
1192 - def get_symbol(self):
1193 """ 1194 If the current node is a symbol, returns its value, raises an 1195 exception otherwise. 1196 """ 1197 err, value = pn_data_get_symbol(self._data) 1198 self._check(err) 1199 return value
1200
1201 - def dump(self):
1202 pn_data_dump(self._data)
1203
1204 -class ConnectionException(ProtonException):
1205 pass
1206
1207 -class Endpoint(object):
1208 1209 LOCAL_UNINIT = PN_LOCAL_UNINIT 1210 REMOTE_UNINIT = PN_REMOTE_UNINIT 1211 LOCAL_ACTIVE = PN_LOCAL_ACTIVE 1212 REMOTE_ACTIVE = PN_REMOTE_ACTIVE 1213 LOCAL_CLOSED = PN_LOCAL_CLOSED 1214 REMOTE_CLOSED = PN_REMOTE_CLOSED
1215
1216 -def wrap_connection(conn):
1217 if not conn: return None 1218 ctx = pn_connection_get_context(conn) 1219 if ctx: return ctx 1220 wrapper = Connection(_conn=conn) 1221 return wrapper
1222
1223 -class Connection(Endpoint):
1224
1225 - def __init__(self, _conn=None):
1226 if _conn: 1227 self._conn = _conn 1228 else: 1229 self._conn = pn_connection() 1230 pn_connection_set_context(self._conn, self)
1231
1232 - def __del__(self):
1233 if hasattr(self, "_conn"): 1234 pn_connection_free(self._conn) 1235 del self._conn
1236
1237 - def _check(self, err):
1238 if err < 0: 1239 exc = EXCEPTIONS.get(err, ConnectionException) 1240 raise exc("[%s]: %s" % (err, pn_connection_error(self._conn))) 1241 else: 1242 return err
1243
1244 - def _get_container(self):
1245 return pn_connection_get_container(self._conn)
1246 - def _set_container(self, name):
1247 return pn_connection_set_container(self._conn, name)
1248 1249 container = property(_get_container, _set_container) 1250
1251 - def _get_hostname(self):
1252 return pn_connection_get_hostname(self._conn)
1253 - def _set_hostname(self, name):
1254 return pn_connection_set_hostname(self._conn, name)
1255 1256 hostname = property(_get_hostname, _set_hostname) 1257 1258 @property
1259 - def remote_container(self):
1260 return pn_connection_remote_container(self._conn)
1261 1262 @property
1263 - def remote_hostname(self):
1264 return pn_connection_remote_hostname(self._conn)
1265
1266 - def open(self):
1267 pn_connection_open(self._conn)
1268
1269 - def close(self):
1270 pn_connection_close(self._conn)
1271 1272 @property
1273 - def state(self):
1274 return pn_connection_state(self._conn)
1275 1276 @property
1277 - def writable(self):
1278 return pn_connection_writable(self._conn)
1279
1280 - def session(self):
1281 return wrap_session(pn_session(self._conn))
1282
1283 - def session_head(self, mask):
1284 return wrap_session(pn_session_head(self._conn, mask))
1285 1288 1289 @property
1290 - def work_head(self):
1291 return wrap_delivery(pn_work_head(self._conn))
1292
1293 -class SessionException(ProtonException):
1294 pass
1295
1296 -def wrap_session(ssn):
1297 if ssn is None: return None 1298 ctx = pn_session_get_context(ssn) 1299 if ctx: 1300 return ctx 1301 else: 1302 wrapper = Session(ssn) 1303 pn_session_set_context(ssn, wrapper) 1304 return wrapper
1305
1306 -class Session(Endpoint):
1307
1308 - def __init__(self, ssn):
1309 self._ssn = ssn
1310
1311 - def __del__(self):
1312 if hasattr(self, "_ssn"): 1313 pn_session_free(self._ssn) 1314 del self._ssn
1315
1316 - def open(self):
1317 pn_session_open(self._ssn)
1318
1319 - def close(self):
1320 pn_session_close(self._ssn)
1321 1322 @property
1323 - def state(self):
1324 return pn_session_state(self._ssn)
1325 1326 @property
1327 - def connection(self):
1328 return wrap_connection(pn_session_connection(self._ssn))
1329
1330 - def sender(self, name):
1331 return wrap_link(pn_sender(self._ssn, name))
1332
1333 - def receiver(self, name):
1334 return wrap_link(pn_receiver(self._ssn, name))
1335
1336 -class LinkException(ProtonException):
1337 pass
1338 1351 1430
1431 -class Sender(Link):
1432
1433 - def offered(self, n):
1434 pn_link_offered(self._link, n)
1435
1436 - def send(self, bytes):
1437 return self._check(pn_link_send(self._link, bytes))
1438
1439 - def drained(self):
1440 pn_link_drained(self._link)
1441
1442 -class Receiver(Link):
1443
1444 - def flow(self, n):
1445 pn_link_flow(self._link, n)
1446
1447 - def recv(self, limit):
1448 n, bytes = pn_link_recv(self._link, limit) 1449 if n == PN_EOS: 1450 return None 1451 else: 1452 self._check(n) 1453 return bytes
1454
1455 - def drain(self, n):
1456 pn_link_drain(self._link, n)
1457
1458 -def wrap_delivery(dlv):
1459 if not dlv: return None 1460 ctx = pn_delivery_get_context(dlv) 1461 if ctx: return ctx 1462 wrapper = Delivery(dlv) 1463 pn_delivery_set_context(dlv, wrapper) 1464 return wrapper
1465
1466 -class Delivery(object):
1467 1468 ACCEPTED = PN_ACCEPTED 1469
1470 - def __init__(self, dlv):
1471 self._dlv = dlv
1472 1473 @property
1474 - def tag(self):
1475 return pn_delivery_tag(self._dlv)
1476 1477 @property
1478 - def writable(self):
1479 return pn_delivery_writable(self._dlv)
1480 1481 @property
1482 - def readable(self):
1483 return pn_delivery_readable(self._dlv)
1484 1485 @property
1486 - def updated(self):
1487 return pn_delivery_updated(self._dlv)
1488
1489 - def update(self, state):
1490 pn_delivery_update(self._dlv, state)
1491 1492 @property
1493 - def local_state(self):
1494 return pn_delivery_local_state(self._dlv)
1495 1496 @property
1497 - def remote_state(self):
1498 return pn_delivery_remote_state(self._dlv)
1499 1500 @property
1501 - def settled(self):
1502 return pn_delivery_settled(self._dlv)
1503
1504 - def settle(self):
1505 pn_delivery_settle(self._dlv)
1506 1507 @property
1508 - def work_next(self):
1509 return wrap_delivery(pn_work_next(self._dlv))
1510
1511 -class TransportException(ProtonException):
1512 pass
1513
1514 -class Transport(object):
1515 1516 TRACE_DRV = PN_TRACE_DRV 1517 TRACE_FRM = PN_TRACE_FRM 1518 TRACE_RAW = PN_TRACE_RAW 1519
1520 - def __init__(self):
1521 self._trans = pn_transport()
1522
1523 - def __del__(self):
1524 if hasattr(self, "_trans"): 1525 pn_transport_free(self._trans) 1526 del self._trans
1527
1528 - def _check(self, err):
1529 if err < 0: 1530 exc = EXCEPTIONS.get(err, TransportException) 1531 raise exc("[%s]: %s" % (err, pn_error_text(pn_transport_error(self._trans)))) 1532 else: 1533 return err
1534
1535 - def bind(self, connection):
1536 self._check(pn_transport_bind(self._trans, connection._conn))
1537
1538 - def trace(self, n):
1539 pn_transport_trace(self._trans, n)
1540
1541 - def tick(self, now):
1542 return pn_transport_tick(self._trans, now)
1543
1544 - def output(self, n):
1545 cd, out = pn_transport_output(self._trans, n) 1546 if cd == PN_EOS: 1547 return None 1548 else: 1549 self._check(cd) 1550 return out
1551
1552 - def input(self, binary):
1553 n = pn_transport_input(self._trans, binary) 1554 if n == PN_EOS: 1555 return None 1556 else: 1557 return self._check(n)
1558
1559 -class SASLException(TransportException):
1560 pass
1561
1562 -class SASL(object):
1563 1564 OK = PN_SASL_OK 1565 AUTH = PN_SASL_AUTH 1566
1567 - def __init__(self, transport):
1568 self._sasl = pn_sasl(transport._trans)
1569
1570 - def _check(self, err):
1571 if err < 0: 1572 exc = EXCEPTIONS.get(err, SASLException) 1573 raise exc("[%s]" % (err)) 1574 else: 1575 return err
1576
1577 - def mechanisms(self, mechs):
1578 pn_sasl_mechanisms(self._sasl, mechs)
1579
1580 - def client(self):
1581 pn_sasl_client(self._sasl)
1582
1583 - def server(self):
1584 pn_sasl_server(self._sasl)
1585
1586 - def plain(self, user, password):
1587 pn_sasl_plain(self._sasl, user, password)
1588
1589 - def send(self, data):
1590 self._check(pn_sasl_send(self._sasl, data, len(data)))
1591
1592 - def recv(self):
1593 sz = 16 1594 while True: 1595 n, data = pn_sasl_recv(self._sasl, sz) 1596 if n == PN_OVERFLOW: 1597 sz *= 2 1598 continue 1599 elif n == PN_EOS: 1600 return None 1601 else: 1602 self._check(n) 1603 return data
1604 1605 @property
1606 - def outcome(self):
1607 outcome = pn_sasl_outcome(self._sasl) 1608 if outcome == PN_SASL_NONE: 1609 return None 1610 else: 1611 return outcome
1612
1613 - def done(self, outcome):
1614 pn_sasl_done(self._sasl, outcome)
1615
1616 -class SSL(object):
1617
1618 - def __init__(self, transport):
1619 self._ssl = pn_ssl(transport._trans)
1620 1621 __all__ = ["Messenger", "Message", "ProtonException", "MessengerException", 1622 "MessageException", "Timeout", "Data", "Endpoint", "Connection", 1623 "Session", "Link", "Sender", "Receiver", "Delivery", "Transport", 1624 "TransportException", "SASL", "SSL", "PN_SESSION_WINDOW"] 1625