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  try: 
  35    import uuid 
  36  except ImportError: 
  37    """ 
  38    No 'native' UUID support.  Provide a very basic UUID type that is a compatible subset of the uuid type provided by more modern python releases. 
  39    """ 
  40    import struct 
41 - class uuid:
42 - class UUID:
43 - def __init__(self, hex=None, bytes=None):
44 if [hex, bytes].count(None) != 1: 45 raise TypeErrror("need one of hex or bytes") 46 if bytes is not None: 47 self.bytes = bytes 48 elif hex is not None: 49 fields=hex.split("-") 50 fields[4:5] = [fields[4][:4], fields[4][4:]] 51 self.bytes = struct.pack("!LHHHHL", *[int(x,16) for x in fields])
52
53 - def __cmp__(self, other):
54 if isinstance(other, uuid.UUID): 55 return cmp(self.bytes, other.bytes) 56 else: 57 return -1
58
59 - def __str__(self):
60 return "%08x-%04x-%04x-%04x-%04x%08x" % struct.unpack("!LHHHHL", self.bytes)
61
62 - def __repr__(self):
63 return "UUID(%r)" % str(self)
64
65 - def __hash__(self):
66 return self.bytes.__hash__()
67 68 import os, random, socket, time 69 rand = random.Random() 70 rand.seed((os.getpid(), time.time(), socket.gethostname()))
71 - def random_uuid():
72 bytes = [rand.randint(0, 255) for i in xrange(16)] 73 74 # From RFC4122, the version bits are set to 0100 75 bytes[7] &= 0x0F 76 bytes[7] |= 0x40 77 78 # From RFC4122, the top two bits of byte 8 get set to 01 79 bytes[8] &= 0x3F 80 bytes[8] |= 0x80 81 return "".join(map(chr, bytes))
82
83 - def uuid4():
84 return uuid.UUID(bytes=random_uuid())
85 86 try: 87 bytes() 88 except NameError: 89 bytes = str 90 91 LANGUAGE = "C"
92 93 -class Constant(object):
94
95 - def __init__(self, name):
96 self.name = name
97
98 - def __repr__(self):
99 return self.name
100
101 -class ProtonException(Exception):
102 """ 103 The root of the proton exception hierarchy. All proton exception 104 classes derive from this exception. 105 """ 106 pass
107
108 -class Timeout(ProtonException):
109 """ 110 A timeout exception indicates that a blocking operation has timed 111 out. 112 """ 113 pass
114
115 -class MessengerException(ProtonException):
116 """ 117 The root of the messenger exception hierarchy. All exceptions 118 generated by the messenger class derive from this exception. 119 """ 120 pass
121
122 -class MessageException(ProtonException):
123 """ 124 The MessageException class is the root of the message exception 125 hierarhcy. All exceptions generated by the Message class derive from 126 this exception. 127 """ 128 pass
129 130 EXCEPTIONS = { 131 PN_TIMEOUT: Timeout 132 } 133 134 PENDING = Constant("PENDING") 135 ACCEPTED = Constant("ACCEPTED") 136 REJECTED = Constant("REJECTED") 137 138 STATUSES = { 139 PN_STATUS_ACCEPTED: ACCEPTED, 140 PN_STATUS_REJECTED: REJECTED, 141 PN_STATUS_PENDING: PENDING, 142 PN_STATUS_UNKNOWN: None 143 } 144 145 AUTOMATIC = Constant("AUTOMATIC") 146 MANUAL = Constant("MANUAL")
147 148 -class Messenger(object):
149 """ 150 The L{Messenger} class defines a high level interface for sending 151 and receiving L{Messages<Message>}. Every L{Messenger} contains a 152 single logical queue of incoming messages and a single logical queue 153 of outgoing messages. These messages in these queues may be destined 154 for, or originate from, a variety of addresses. 155 156 Address Syntax 157 ============== 158 159 An address has the following form:: 160 161 [ amqp[s]:// ] [user[:password]@] domain [/[name]] 162 163 Where domain can be one of:: 164 165 host | host:port | ip | ip:port | name 166 167 The following are valid examples of addresses: 168 169 - example.org 170 - example.org:1234 171 - amqp://example.org 172 - amqps://example.org 173 - example.org/incoming 174 - amqps://example.org/outgoing 175 - amqps://fred:trustno1@example.org 176 - 127.0.0.1:1234 177 - amqps://127.0.0.1:1234 178 179 Sending & Receiving Messages 180 ============================ 181 182 The L{Messenger} class works in conjuction with the L{Message} 183 class. The L{Message} class is a mutable holder of message content. 184 The L{put} method will encode the content in a given L{Message} 185 object into the outgoing message queue leaving that L{Message} 186 object free to be modified or discarded without having any impact on 187 the content in the outgoing queue. 188 189 >>> message = Message() 190 >>> for i in range(3): 191 ... message.address = "amqp://host/queue" 192 ... message.subject = "Hello World %i" % i 193 ... messenger.put(message) 194 >>> messenger.send() 195 196 Similarly, the L{get} method will decode the content in the incoming 197 message queue into the supplied L{Message} object. 198 199 >>> message = Message() 200 >>> messenger.recv(10): 201 >>> while messenger.incoming > 0: 202 ... messenger.get(message) 203 ... print message.subject 204 Hello World 0 205 Hello World 1 206 Hello World 2 207 """ 208
209 - def __init__(self, name=None):
210 """ 211 Construct a new L{Messenger} with the given name. The name has 212 global scope. If a NULL name is supplied, a L{uuid.UUID} based 213 name will be chosen. 214 215 @type name: string 216 @param name: the name of the messenger or None 217 """ 218 self._mng = pn_messenger(name)
219
220 - def __del__(self):
221 if hasattr(self, "_mng"): 222 pn_messenger_free(self._mng) 223 del self._mng
224
225 - def _check(self, err):
226 if err < 0: 227 exc = EXCEPTIONS.get(err, MessengerException) 228 raise exc("[%s]: %s" % (err, pn_messenger_error(self._mng))) 229 else: 230 return err
231 232 @property
233 - def name(self):
234 """ 235 The name of the L{Messenger}. 236 """ 237 return pn_messenger_name(self._mng)
238
239 - def _get_certificate(self):
240 return pn_messenger_get_certificate(self._mng)
241
242 - def _set_certificate(self, value):
243 self._check(pn_messenger_set_certificate(self._mng, value))
244 245 certificate = property(_get_certificate, _set_certificate, 246 doc=""" 247 Path to a certificate file for the L{Messenger}. This certificate is 248 used when the L{Messenger} accepts or establishes SSL/TLS connections. 249 This property must be specified for the L{Messenger} to accept 250 incoming SSL/TLS connections and to establish client authenticated 251 outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS 252 connections do not require this property. 253 """) 254
255 - def _get_private_key(self):
256 return pn_messenger_get_private_key(self._mng)
257
258 - def _set_private_key(self, value):
259 self._check(pn_messenger_set_private_key(self._mng, value))
260 261 private_key = property(_get_private_key, _set_private_key, 262 doc=""" 263 Path to a private key file for the L{Messenger's<Messenger>} 264 certificate. This property must be specified for the L{Messenger} to 265 accept incoming SSL/TLS connections and to establish client 266 authenticated outgoing SSL/TLS connection. Non client authenticated 267 SSL/TLS connections do not require this property. 268 """) 269
270 - def _get_password(self):
271 return pn_messenger_get_password(self._mng)
272
273 - def _set_password(self, value):
274 self._check(pn_messenger_set_password(self._mng, value))
275 276 password = property(_get_password, _set_password, 277 doc=""" 278 This property contains the password for the L{Messenger.private_key} 279 file, or None if the file is not encrypted. 280 """) 281
282 - def _get_trusted_certificates(self):
283 return pn_messenger_get_trusted_certificates(self._mng)
284
285 - def _set_trusted_certificates(self, value):
286 self._check(pn_messenger_set_trusted_certificates(self._mng, value))
287 288 trusted_certificates = property(_get_trusted_certificates, 289 _set_trusted_certificates, 290 doc=""" 291 A path do a database of trusted certificates for use in verifying the 292 peer on an SSL/TLS connection. If this property is None, then the peer 293 will not be verified. 294 """) 295
296 - def _get_timeout(self):
297 return pn_messenger_get_timeout(self._mng)
298
299 - def _set_timeout(self, value):
300 self._check(pn_messenger_set_timeout(self._mng, value))
301 302 timeout = property(_get_timeout, _set_timeout, 303 doc=""" 304 The timeout property contains the default timeout for blocking 305 operations performed by the L{Messenger}. 306 """) 307
308 - def _get_incoming_window(self):
309 return pn_messenger_get_incoming_window(self._mng)
310
311 - def _set_incoming_window(self, window):
312 self._check(pn_messenger_set_incoming_window(self._mng, window))
313 314 incoming_window = property(_get_incoming_window, _set_incoming_window, 315 doc=""" 316 The incoming tracking window for the messenger. The messenger will 317 track the remote status of this many incoming deliveries after they 318 have been accepted or rejected. Defaults to zero. 319 """) 320
321 - def _get_outgoing_window(self):
322 return pn_messenger_get_outgoing_window(self._mng)
323
324 - def _set_outgoing_window(self, window):
325 self._check(pn_messenger_set_outgoing_window(self._mng, window))
326 327 outgoing_window = property(_get_outgoing_window, _set_outgoing_window, 328 doc=""" 329 The outgoing tracking window for the messenger. The messenger will 330 track the remote status of this many outgoing deliveries after calling 331 send. Defaults to zero. 332 """) 333
334 - def start(self):
335 """ 336 Transitions the L{Messenger} to an active state. A L{Messenger} is 337 initially created in an inactive state. When inactive a 338 L{Messenger} will not send or receive messages from its internal 339 queues. A L{Messenger} must be started before calling L{send} or 340 L{recv}. 341 """ 342 self._check(pn_messenger_start(self._mng))
343
344 - def stop(self):
345 """ 346 Transitions the L{Messenger} to an inactive state. An inactive 347 L{Messenger} will not send or receive messages from its internal 348 queues. A L{Messenger} should be stopped before being discarded to 349 ensure a clean shutdown handshake occurs on any internally managed 350 connections. 351 """ 352 self._check(pn_messenger_stop(self._mng))
353
354 - def subscribe(self, source):
355 """ 356 Subscribes the L{Messenger} to messages originating from the 357 specified source. The source is an address as specified in the 358 L{Messenger} introduction with the following addition. If the 359 domain portion of the address begins with the '~' character, the 360 L{Messenger} will interpret the domain as host/port, bind to it, 361 and listen for incoming messages. For example "~0.0.0.0", 362 "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any 363 local interface and listen for incoming messages with the last 364 variant only permitting incoming SSL connections. 365 366 @type source: string 367 @param source: the source of messages to subscribe to 368 """ 369 sub_impl = pn_messenger_subscribe(self._mng, source) 370 if not sub_impl: 371 self._check(PN_ERR)
372
373 - def put(self, message):
374 """ 375 Places the content contained in the message onto the outgoing 376 queue of the L{Messenger}. This method will never block, however 377 it will send any unblocked L{Messages<Message>} in the outgoing 378 queue immediately and leave any blocked L{Messages<Message>} 379 remaining in the outgoing queue. The L{send} call may be used to 380 block until the outgoing queue is empty. The L{outgoing} property 381 may be used to check the depth of the outgoing queue. 382 383 @type message: Message 384 @param message: the message to place in the outgoing queue 385 @return: a tracker 386 """ 387 message._pre_encode() 388 self._check(pn_messenger_put(self._mng, message._msg)) 389 return pn_messenger_outgoing_tracker(self._mng)
390
391 - def status(self, tracker):
392 """ 393 Gets the last known remote state of the delivery associated with 394 the given tracker. 395 396 @type tracker: tracker 397 @param tracker: the tracker whose status is to be retrieved 398 399 @return: one of None, PENDING, REJECTED, or ACCEPTED 400 """ 401 disp = pn_messenger_status(self._mng, tracker); 402 return STATUSES.get(disp, disp)
403
404 - def settle(self, tracker=None):
405 if tracker is None: 406 tracker = pn_messenger_outgoing_tracker(self._mng) 407 flags = PN_CUMULATIVE 408 else: 409 flags = 0 410 self._check(pn_messenger_settle(self._mng, tracker, flags))
411
412 - def send(self):
413 """ 414 Blocks until the outgoing queue is empty or the operation times 415 out. The L{timeout} property controls how long a L{Messenger} will 416 block before timing out. 417 """ 418 self._check(pn_messenger_send(self._mng))
419
420 - def recv(self, n=None):
421 """ 422 Receives up to I{n} messages into the incoming queue of the 423 L{Messenger}. If I{n} is not specified, L{Messenger} will receive as many 424 messages as it can buffer internally. This method will block until at least 425 one message is available or the operation times out. 426 """ 427 if n is None: 428 n = -1 429 self._check(pn_messenger_recv(self._mng, n))
430
431 - def get(self, message=None):
432 """ 433 Moves the message from the head of the incoming message queue into 434 the supplied message object. Any content in the message will be 435 overwritten. 436 437 @type message: Message 438 @param message: the destination message object 439 @return: a tracker 440 """ 441 if message is None: 442 impl = None 443 else: 444 impl = message._msg 445 self._check(pn_messenger_get(self._mng, impl)) 446 if message is not None: 447 message._post_decode() 448 return pn_messenger_incoming_tracker(self._mng)
449
450 - def accept(self, tracker=None):
451 """ 452 Accepts messages retreived from the incoming message queue. 453 454 @type tracker: tracker 455 @param tracker: a tracker as returned by get 456 """ 457 if tracker is None: 458 tracker = pn_messenger_incoming_tracker(self._mng) 459 flags = PN_CUMULATIVE 460 else: 461 flags = 0 462 self._check(pn_messenger_accept(self._mng, tracker, flags))
463
464 - def reject(self, tracker=None):
465 """ 466 Rejects messages retreived from the incoming message queue. 467 468 @type tracker: tracker 469 @param tracker: a tracker as returned by get 470 """ 471 if tracker is None: 472 tracker = pn_messenger_incoming_tracker(self._mng) 473 flags = PN_CUMULATIVE 474 else: 475 flags = 0 476 self._check(pn_messenger_reject(self._mng, tracker, flags))
477 478 @property
479 - def outgoing(self):
480 """ 481 The outgoing queue depth. 482 """ 483 return pn_messenger_outgoing(self._mng)
484 485 @property
486 - def incoming(self):
487 """ 488 The incoming queue depth. 489 """ 490 return pn_messenger_incoming(self._mng)
491
492 -class Message(object):
493 """ 494 The L{Message} class is a mutable holder of message content. 495 496 @ivar instructions: delivery instructions for the message 497 @type instructions: dict 498 @ivar annotations: infrastructure defined message annotations 499 @type annotations: dict 500 @ivar properties: application defined message properties 501 @type properties: dict 502 @ivar body: message body 503 @type body: bytes | unicode | dict | list | int | long | float | UUID 504 """ 505 506 DATA = PN_DATA 507 TEXT = PN_TEXT 508 AMQP = PN_AMQP 509 JSON = PN_JSON 510 511 DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY 512
513 - def __init__(self):
514 self._msg = pn_message() 515 self._id = Data(pn_message_id(self._msg)) 516 self._correlation_id = Data(pn_message_correlation_id(self._msg)) 517 self.instructions = None 518 self.annotations = None 519 self.properties = None 520 self.body = None
521
522 - def __del__(self):
523 if hasattr(self, "_msg"): 524 pn_message_free(self._msg) 525 del self._msg
526
527 - def _check(self, err):
528 if err < 0: 529 exc = EXCEPTIONS.get(err, MessageException) 530 raise exc("[%s]: %s" % (err, pn_message_error(self._msg))) 531 else: 532 return err
533
534 - def _pre_encode(self):
535 inst = Data(pn_message_instructions(self._msg)) 536 ann = Data(pn_message_annotations(self._msg)) 537 props = Data(pn_message_properties(self._msg)) 538 body = Data(pn_message_body(self._msg)) 539 540 inst.clear() 541 if self.instructions is not None: 542 inst.put_object(self.instructions) 543 ann.clear() 544 if self.annotations is not None: 545 ann.put_object(self.annotations) 546 props.clear() 547 if self.properties is not None: 548 props.put_object(self.properties) 549 if self.body is not None: 550 # XXX: move this out when load/save are gone 551 body.clear() 552 body.put_object(self.body)
553
554 - def _post_decode(self):
555 inst = Data(pn_message_instructions(self._msg)) 556 ann = Data(pn_message_annotations(self._msg)) 557 props = Data(pn_message_properties(self._msg)) 558 body = Data(pn_message_body(self._msg)) 559 560 if inst.next(): 561 self.instructions = inst.get_object() 562 else: 563 self.instructions = None 564 if ann.next(): 565 self.annotations = ann.get_object() 566 else: 567 self.annotations = None 568 if props.next(): 569 self.properties = props.get_object() 570 else: 571 self.properties = None 572 if body.next(): 573 self.body = body.get_object() 574 else: 575 self.body = None
576
577 - def clear(self):
578 """ 579 Clears the contents of the L{Message}. All fields will be reset to 580 their default values. 581 """ 582 pn_message_clear(self._msg) 583 self.instructions = None 584 self.annotations = None 585 self.properties = None 586 self.body = None
587
588 - def _is_inferred(self):
589 return pn_message_is_inferred(self._msg)
590
591 - def _set_inferred(self, value):
592 self._check(pn_message_set_inferred(self._msg, bool(value)))
593 594 inferred = property(_is_inferred, _set_inferred) 595
596 - def _is_durable(self):
597 return pn_message_is_durable(self._msg)
598
599 - def _set_durable(self, value):
600 self._check(pn_message_set_durable(self._msg, bool(value)))
601 602 durable = property(_is_durable, _set_durable, 603 doc=""" 604 The durable property indicates that the message should be held durably 605 by any intermediaries taking responsibility for the message. 606 """) 607
608 - def _get_priority(self):
609 return pn_message_get_priority(self._msg)
610
611 - def _set_priority(self, value):
612 self._check(pn_message_set_priority(self._msg, value))
613 614 priority = property(_get_priority, _set_priority, 615 doc=""" 616 The priority of the message. 617 """) 618
619 - def _get_ttl(self):
620 return pn_message_get_ttl(self._msg)
621
622 - def _set_ttl(self, value):
623 self._check(pn_message_set_ttl(self._msg, value))
624 625 ttl = property(_get_ttl, _set_ttl, 626 doc=""" 627 The time to live of the message measured in milliseconds. Expired 628 messages may be dropped. 629 """) 630
631 - def _is_first_acquirer(self):
632 return pn_message_is_first_acquirer(self._msg)
633
634 - def _set_first_acquirer(self, value):
635 self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
636 637 first_acquirer = property(_is_first_acquirer, _set_first_acquirer, 638 doc=""" 639 True iff the recipient is the first to acquire the message. 640 """) 641
642 - def _get_delivery_count(self):
643 return pn_message_get_delivery_count(self._msg)
644
645 - def _set_delivery_count(self, value):
646 self._check(pn_message_set_delivery_count(self._msg, value))
647 648 delivery_count = property(_get_delivery_count, _set_delivery_count, 649 doc=""" 650 The number of delivery attempts made for this message. 651 """) 652 653
654 - def _get_id(self):
655 return self._id.get_object()
656 - def _set_id(self, value):
657 if type(value) in (int, long): 658 value = ulong(value) 659 self._id.rewind() 660 self._id.put_object(value)
661 id = property(_get_id, _set_id, 662 doc=""" 663 The id of the message. 664 """) 665
666 - def _get_user_id(self):
667 return pn_message_get_user_id(self._msg)
668
669 - def _set_user_id(self, value):
670 self._check(pn_message_set_user_id(self._msg, value))
671 672 user_id = property(_get_user_id, _set_user_id, 673 doc=""" 674 The user id of the message creator. 675 """) 676
677 - def _get_address(self):
678 return pn_message_get_address(self._msg)
679
680 - def _set_address(self, value):
681 self._check(pn_message_set_address(self._msg, value))
682 683 address = property(_get_address, _set_address, 684 doc=""" 685 The address of the message. 686 """) 687
688 - def _get_subject(self):
689 return pn_message_get_subject(self._msg)
690
691 - def _set_subject(self, value):
692 self._check(pn_message_set_subject(self._msg, value))
693 694 subject = property(_get_subject, _set_subject, 695 doc=""" 696 The subject of the message. 697 """) 698
699 - def _get_reply_to(self):
700 return pn_message_get_reply_to(self._msg)
701
702 - def _set_reply_to(self, value):
703 self._check(pn_message_set_reply_to(self._msg, value))
704 705 reply_to = property(_get_reply_to, _set_reply_to, 706 doc=""" 707 The reply-to address for the message. 708 """) 709
710 - def _get_correlation_id(self):
711 return self._correlation_id.get_object()
712 - def _set_correlation_id(self, value):
713 if type(value) in (int, long): 714 value = ulong(value) 715 self._correlation_id.rewind() 716 self._correlation_id.put_object(value)
717 718 correlation_id = property(_get_correlation_id, _set_correlation_id, 719 doc=""" 720 The correlation-id for the message. 721 """) 722
723 - def _get_content_type(self):
724 return pn_message_get_content_type(self._msg)
725
726 - def _set_content_type(self, value):
727 self._check(pn_message_set_content_type(self._msg, value))
728 729 content_type = property(_get_content_type, _set_content_type, 730 doc=""" 731 The content-type of the message. 732 """) 733
734 - def _get_content_encoding(self):
735 return pn_message_get_content_encoding(self._msg)
736
737 - def _set_content_encoding(self, value):
738 self._check(pn_message_set_content_encoding(self._msg, value))
739 740 content_encoding = property(_get_content_encoding, _set_content_encoding, 741 doc=""" 742 The content-encoding of the message. 743 """) 744
745 - def _get_expiry_time(self):
746 return pn_message_get_expiry_time(self._msg)
747
748 - def _set_expiry_time(self, value):
749 self._check(pn_message_set_expiry_time(self._msg, value))
750 751 expiry_time = property(_get_expiry_time, _set_expiry_time, 752 doc=""" 753 The expiry time of the message. 754 """) 755
756 - def _get_creation_time(self):
757 return pn_message_get_creation_time(self._msg)
758
759 - def _set_creation_time(self, value):
760 self._check(pn_message_set_creation_time(self._msg, value))
761 762 creation_time = property(_get_creation_time, _set_creation_time, 763 doc=""" 764 The creation time of the message. 765 """) 766
767 - def _get_group_id(self):
768 return pn_message_get_group_id(self._msg)
769
770 - def _set_group_id(self, value):
771 self._check(pn_message_set_group_id(self._msg, value))
772 773 group_id = property(_get_group_id, _set_group_id, 774 doc=""" 775 The group id of the message. 776 """) 777
778 - def _get_group_sequence(self):
779 return pn_message_get_group_sequence(self._msg)
780
781 - def _set_group_sequence(self, value):
782 self._check(pn_message_set_group_sequence(self._msg, value))
783 784 group_sequence = property(_get_group_sequence, _set_group_sequence, 785 doc=""" 786 The sequence of the message within its group. 787 """) 788
789 - def _get_reply_to_group_id(self):
790 return pn_message_get_reply_to_group_id(self._msg)
791
792 - def _set_reply_to_group_id(self, value):
793 self._check(pn_message_set_reply_to_group_id(self._msg, value))
794 795 reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id, 796 doc=""" 797 The group-id for any replies. 798 """) 799 800 # XXX
801 - def _get_format(self):
802 return pn_message_get_format(self._msg)
803
804 - def _set_format(self, value):
805 self._check(pn_message_set_format(self._msg, value))
806 807 format = property(_get_format, _set_format, 808 doc=""" 809 The format of the message. 810 """) 811
812 - def encode(self):
813 self._pre_encode() 814 sz = 16 815 while True: 816 err, data = pn_message_encode(self._msg, sz) 817 if err == PN_OVERFLOW: 818 sz *= 2 819 continue 820 else: 821 self._check(err) 822 return data
823
824 - def decode(self, data):
825 self._check(pn_message_decode(self._msg, data, len(data))) 826 self._post_decode()
827
828 - def load(self, data):
829 self._check(pn_message_load(self._msg, data))
830
831 - def save(self):
832 sz = 16 833 while True: 834 err, data = pn_message_save(self._msg, sz) 835 if err == PN_OVERFLOW: 836 sz *= 2 837 continue 838 else: 839 self._check(err) 840 return data
841
842 -class DataException(ProtonException):
843 """ 844 The DataException class is the root of the Data exception hierarchy. 845 All exceptions raised by the Data class extend this exception. 846 """ 847 pass
848
849 -class UnmappedType:
850
851 - def __init__(self, msg):
852 self.msg = msg
853
854 - def __repr__(self):
855 return "UnmappedType(%s)" % self.msg
856
857 -class ulong(long):
858
859 - def __repr__(self):
860 return "ulong(%s)" % long.__repr__(self)
861
862 -class timestamp(long):
863
864 - def __repr__(self):
865 return "timestamp(%s)" % long.__repr__(self)
866
867 -class symbol(unicode):
868
869 - def __repr__(self):
870 return "symbol(%s)" % unicode.__repr__(self)
871
872 -class char(unicode):
873
874 - def __repr__(self):
875 return "char(%s)" % unicode.__repr__(self)
876
877 -class Described(object):
878
879 - def __init__(self, descriptor, value):
880 self.descriptor = descriptor 881 self.value = value
882
883 - def __repr__(self):
884 return "Described(%r, %r)" % (self.descriptor, self.value)
885
886 - def __eq__(self, o):
887 if isinstance(o, Described): 888 return self.descriptor == o.descriptor and self.value == o.value 889 else: 890 return False
891 892 UNDESCRIBED = Constant("UNDESCRIBED")
893 894 -class Array(object):
895
896 - def __init__(self, descriptor, type, *elements):
897 self.descriptor = descriptor 898 self.type = type 899 self.elements = elements
900
901 - def __repr__(self):
902 if self.elements: 903 els = ", %s" % (", ".join(map(repr, self.elements))) 904 else: 905 els = "" 906 return "Array(%r, %r%s)" % (self.descriptor, self.type, els)
907
908 - def __eq__(self, o):
909 if isinstance(o, Array): 910 return self.descriptor == o.descriptor and \ 911 self.type == o.type and self.elements == o.elements 912 else: 913 return False
914
915 -class Data:
916 """ 917 The L{Data} class provides an interface for decoding, extracting, 918 creating, and encoding arbitrary AMQP data. A L{Data} object 919 contains a tree of AMQP values. Leaf nodes in this tree correspond 920 to scalars in the AMQP type system such as L{ints<INT>} or 921 L{strings<STRING>}. Non-leaf nodes in this tree correspond to 922 compound values in the AMQP type system such as L{lists<LIST>}, 923 L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}. 924 The root node of the tree is the L{Data} object itself and can have 925 an arbitrary number of children. 926 927 A L{Data} object maintains the notion of the current sibling node 928 and a current parent node. Siblings are ordered within their parent. 929 Values are accessed and/or added by using the L{next}, L{prev}, 930 L{enter}, and L{exit} methods to navigate to the desired location in 931 the tree and using the supplied variety of put_*/get_* methods to 932 access or add a value of the desired type. 933 934 The put_* methods will always add a value I{after} the current node 935 in the tree. If the current node has a next sibling the put_* method 936 will overwrite the value on this node. If there is no current node 937 or the current node has no next sibling then one will be added. The 938 put_* methods always set the added/modified node to the current 939 node. The get_* methods read the value of the current node and do 940 not change which node is current. 941 942 The following types of scalar values are supported: 943 944 - L{NULL} 945 - L{BOOL} 946 - L{UBYTE} 947 - L{USHORT} 948 - L{SHORT} 949 - L{UINT} 950 - L{INT} 951 - L{ULONG} 952 - L{LONG} 953 - L{FLOAT} 954 - L{DOUBLE} 955 - L{BINARY} 956 - L{STRING} 957 - L{SYMBOL} 958 959 The following types of compound values are supported: 960 961 - L{DESCRIBED} 962 - L{ARRAY} 963 - L{LIST} 964 - L{MAP} 965 """ 966 967 NULL = PN_NULL; "A null value." 968 BOOL = PN_BOOL; "A boolean value." 969 UBYTE = PN_UBYTE; "An unsigned byte value." 970 BYTE = PN_BYTE; "A signed byte value." 971 USHORT = PN_USHORT; "An unsigned short value." 972 SHORT = PN_SHORT; "A short value." 973 UINT = PN_UINT; "An unsigned int value." 974 INT = PN_INT; "A signed int value." 975 CHAR = PN_CHAR; "A character value." 976 ULONG = PN_ULONG; "An unsigned long value." 977 LONG = PN_LONG; "A signed long value." 978 TIMESTAMP = PN_TIMESTAMP; "A timestamp value." 979 FLOAT = PN_FLOAT; "A float value." 980 DOUBLE = PN_DOUBLE; "A double value." 981 DECIMAL32 = PN_DECIMAL32; "A DECIMAL32 value." 982 DECIMAL64 = PN_DECIMAL64; "A DECIMAL64 value." 983 DECIMAL128 = PN_DECIMAL128; "A DECIMAL128 value." 984 UUID = PN_UUID; "A UUID value." 985 BINARY = PN_BINARY; "A binary string." 986 STRING = PN_STRING; "A unicode string." 987 SYMBOL = PN_SYMBOL; "A symbolic string." 988 DESCRIBED = PN_DESCRIBED; "A described value." 989 ARRAY = PN_ARRAY; "An array value." 990 LIST = PN_LIST; "A list value." 991 MAP = PN_MAP; "A map value." 992 993 type_names = { 994 NULL: "null", 995 BOOL: "bool", 996 BYTE: "byte", 997 UBYTE: "ubyte", 998 SHORT: "short", 999 USHORT: "ushort", 1000 INT: "int", 1001 UINT: "uint", 1002 CHAR: "char", 1003 LONG: "long", 1004 ULONG: "ulong", 1005 TIMESTAMP: "timestamp", 1006 FLOAT: "float", 1007 DOUBLE: "double", 1008 DECIMAL32: "decimal32", 1009 DECIMAL64: "decimal64", 1010 DECIMAL128: "decimal128", 1011 UUID: "uuid", 1012 BINARY: "binary", 1013 STRING: "string", 1014 SYMBOL: "symbol", 1015 DESCRIBED: "described", 1016 ARRAY: "array", 1017 LIST: "list", 1018 MAP: "map" 1019 } 1020 1021 @classmethod
1022 - def type_name(type): return Data.type_names[type]
1023
1024 - def __init__(self, capacity=16):
1025 if type(capacity) in (int, long): 1026 self._data = pn_data(capacity) 1027 self._free = True 1028 else: 1029 self._data = capacity 1030 self._free = False
1031
1032 - def __del__(self):
1033 if self._free and hasattr(self, "_data"): 1034 pn_data_free(self._data) 1035 del self._data
1036
1037 - def _check(self, err):
1038 if err < 0: 1039 exc = EXCEPTIONS.get(err, DataException) 1040 raise exc("[%s]: %s" % (err, pn_data_error(self._data))) 1041 else: 1042 return err
1043
1044 - def clear(self):
1045 """ 1046 Clears the data object. 1047 """ 1048 pn_data_clear(self._data)
1049
1050 - def rewind(self):
1051 """ 1052 Clears current node and sets the parent to the root node. Clearing the 1053 current node sets it _before_ the first node, calling next() will advance to 1054 the first node. 1055 """ 1056 pn_data_rewind(self._data)
1057
1058 - def next(self):
1059 """ 1060 Advances the current node to its next sibling and returns its 1061 type. If there is no next sibling the current node remains 1062 unchanged and None is returned. 1063 """ 1064 found = pn_data_next(self._data) 1065 if found: 1066 return self.type() 1067 else: 1068 return None
1069
1070 - def prev(self):
1071 """ 1072 Advances the current node to its previous sibling and returns its 1073 type. If there is no previous sibling the current node remains 1074 unchanged and None is returned. 1075 """ 1076 found = pn_data_prev(self._data) 1077 if found: 1078 return self.type() 1079 else: 1080 return None
1081
1082 - def enter(self):
1083 """ 1084 Sets the parent node to the current node and clears the current node. 1085 Clearing the current node sets it _before_ the first child, 1086 call next() advances to the first child. 1087 """ 1088 return pn_data_enter(self._data)
1089
1090 - def exit(self):
1091 """ 1092 Sets the current node to the parent node and the parent node to 1093 its own parent. 1094 """ 1095 return pn_data_exit(self._data)
1096
1097 - def type(self):
1098 """ 1099 Returns the type of the current node. 1100 """ 1101 dtype = pn_data_type(self._data) 1102 if dtype == -1: 1103 return None 1104 else: 1105 return dtype
1106
1107 - def encode(self):
1108 """ 1109 Returns a representation of the data encoded in AMQP format. 1110 """ 1111 size = 1024 1112 while True: 1113 cd, enc = pn_data_encode(self._data, size) 1114 if cd == PN_OVERFLOW: 1115 size *= 2 1116 elif cd >= 0: 1117 return enc 1118 else: 1119 self._check(cd)
1120
1121 - def decode(self, encoded):
1122 """ 1123 Decodes the first value from supplied AMQP data and returns the 1124 number of bytes consumed. 1125 1126 @type encoded: binary 1127 @param encoded: AMQP encoded binary data 1128 """ 1129 return self._check(pn_data_decode(self._data, encoded))
1130
1131 - def put_list(self):
1132 """ 1133 Puts a list value. Elements may be filled by entering the list 1134 node and putting element values. 1135 1136 >>> data = Data() 1137 >>> data.put_list() 1138 >>> data.enter() 1139 >>> data.put_int(1) 1140 >>> data.put_int(2) 1141 >>> data.put_int(3) 1142 >>> data.exit() 1143 """ 1144 self._check(pn_data_put_list(self._data))
1145
1146 - def put_map(self):
1147 """ 1148 Puts a map value. Elements may be filled by entering the map node 1149 and putting alternating key value pairs. 1150 1151 >>> data = Data() 1152 >>> data.put_map() 1153 >>> data.enter() 1154 >>> data.put_string("key") 1155 >>> data.put_string("value") 1156 >>> data.exit() 1157 """ 1158 self._check(pn_data_put_map(self._data))
1159
1160 - def put_array(self, described, element_type):
1161 """ 1162 Puts an array value. Elements may be filled by entering the array 1163 node and putting the element values. The values must all be of the 1164 specified array element type. If an array is described then the 1165 first child value of the array is the descriptor and may be of any 1166 type. 1167 1168 >>> data = Data() 1169 >>> 1170 >>> data.put_array(False, Data.INT) 1171 >>> data.enter() 1172 >>> data.put_int(1) 1173 >>> data.put_int(2) 1174 >>> data.put_int(3) 1175 >>> data.exit() 1176 >>> 1177 >>> data.put_array(True, Data.DOUBLE) 1178 >>> data.enter() 1179 >>> data.put_symbol("array-descriptor") 1180 >>> data.put_double(1.1) 1181 >>> data.put_double(1.2) 1182 >>> data.put_double(1.3) 1183 >>> data.exit() 1184 1185 @type described: bool 1186 @param described: specifies whether the array is described 1187 @type element_type: int 1188 @param element_type: the type of the array elements 1189 """ 1190 self._check(pn_data_put_array(self._data, described, element_type))
1191
1192 - def put_described(self):
1193 """ 1194 Puts a described value. A described node has two children, the 1195 descriptor and the value. These are specified by entering the node 1196 and putting the desired values. 1197 1198 >>> data = Data() 1199 >>> data.put_described() 1200 >>> data.enter() 1201 >>> data.put_symbol("value-descriptor") 1202 >>> data.put_string("the value") 1203 >>> data.exit() 1204 """ 1205 self._check(pn_data_put_described(self._data))
1206
1207 - def put_null(self):
1208 """ 1209 Puts a null value. 1210 """ 1211 self._check(pn_data_put_null(self._data))
1212
1213 - def put_bool(self, b):
1214 """ 1215 Puts a boolean value. 1216 1217 @param b: a boolean value 1218 """ 1219 self._check(pn_data_put_bool(self._data, b))
1220
1221 - def put_ubyte(self, ub):
1222 """ 1223 Puts an unsigned byte value. 1224 1225 @param ub: an integral value 1226 """ 1227 self._check(pn_data_put_ubyte(self._data, ub))
1228
1229 - def put_byte(self, b):
1230 """ 1231 Puts a signed byte value. 1232 1233 @param b: an integral value 1234 """ 1235 self._check(pn_data_put_byte(self._data, b))
1236
1237 - def put_ushort(self, us):
1238 """ 1239 Puts an unsigned short value. 1240 1241 @param us: an integral value. 1242 """ 1243 self._check(pn_data_put_ushort(self._data, us))
1244
1245 - def put_short(self, s):
1246 """ 1247 Puts a signed short value. 1248 1249 @param s: an integral value 1250 """ 1251 self._check(pn_data_put_short(self._data, s))
1252
1253 - def put_uint(self, ui):
1254 """ 1255 Puts an unsigned int value. 1256 1257 @param ui: an integral value 1258 """ 1259 self._check(pn_data_put_uint(self._data, ui))
1260
1261 - def put_int(self, i):
1262 """ 1263 Puts a signed int value. 1264 1265 @param i: an integral value 1266 """ 1267 self._check(pn_data_put_int(self._data, i))
1268
1269 - def put_char(self, c):
1270 """ 1271 Puts a char value. 1272 1273 @param c: a single character 1274 """ 1275 self._check(pn_data_put_char(self._data, ord(c)))
1276
1277 - def put_ulong(self, ul):
1278 """ 1279 Puts an unsigned long value. 1280 1281 @param ul: an integral value 1282 """ 1283 self._check(pn_data_put_ulong(self._data, ul))
1284
1285 - def put_long(self, l):
1286 """ 1287 Puts a signed long value. 1288 1289 @param l: an integral value 1290 """ 1291 self._check(pn_data_put_long(self._data, l))
1292
1293 - def put_timestamp(self, t):
1294 """ 1295 Puts a timestamp value. 1296 1297 @param t: an integral value 1298 """ 1299 self._check(pn_data_put_timestamp(self._data, t))
1300
1301 - def put_float(self, f):
1302 """ 1303 Puts a float value. 1304 1305 @param f: a floating point value 1306 """ 1307 self._check(pn_data_put_float(self._data, f))
1308
1309 - def put_double(self, d):
1310 """ 1311 Puts a double value. 1312 1313 @param d: a floating point value. 1314 """ 1315 self._check(pn_data_put_double(self._data, d))
1316
1317 - def put_decimal32(self, d):
1318 """ 1319 Puts a decimal32 value. 1320 1321 @param d: a decimal32 value 1322 """ 1323 self._check(pn_data_put_decimal32(self._data, d))
1324
1325 - def put_decimal64(self, d):
1326 """ 1327 Puts a decimal64 value. 1328 1329 @param d: a decimal64 value 1330 """ 1331 self._check(pn_data_put_decimal64(self._data, d))
1332
1333 - def put_decimal128(self, d):
1334 """ 1335 Puts a decimal128 value. 1336 1337 @param d: a decimal128 value 1338 """ 1339 self._check(pn_data_put_decimal128(self._data, d))
1340
1341 - def put_uuid(self, u):
1342 """ 1343 Puts a UUID value. 1344 1345 @param u: a uuid value 1346 """ 1347 self._check(pn_data_put_uuid(self._data, u.bytes))
1348
1349 - def put_binary(self, b):
1350 """ 1351 Puts a binary value. 1352 1353 @type b: binary 1354 @param b: a binary value 1355 """ 1356 self._check(pn_data_put_binary(self._data, b))
1357
1358 - def put_string(self, s):
1359 """ 1360 Puts a unicode value. 1361 1362 @type s: unicode 1363 @param s: a unicode value 1364 """ 1365 self._check(pn_data_put_string(self._data, s.encode("utf8")))
1366
1367 - def put_symbol(self, s):
1368 """ 1369 Puts a symbolic value. 1370 1371 @type s: string 1372 @param s: the symbol name 1373 """ 1374 self._check(pn_data_put_symbol(self._data, s))
1375
1376 - def get_list(self):
1377 """ 1378 If the current node is a list, return the number of elements, 1379 otherwise return zero. List elements can be accessed by entering 1380 the list. 1381 1382 >>> count = data.get_list() 1383 >>> data.enter() 1384 >>> for i in range(count): 1385 ... type = data.next() 1386 ... if type == Data.STRING: 1387 ... print data.get_string() 1388 ... elif type == ...: 1389 ... ... 1390 >>> data.exit() 1391 """ 1392 return pn_data_get_list(self._data)
1393
1394 - def get_map(self):
1395 """ 1396 If the current node is a map, return the number of child elements, 1397 otherwise return zero. Key value pairs can be accessed by entering 1398 the map. 1399 1400 >>> count = data.get_map() 1401 >>> data.enter() 1402 >>> for i in range(count/2): 1403 ... type = data.next() 1404 ... if type == Data.STRING: 1405 ... print data.get_string() 1406 ... elif type == ...: 1407 ... ... 1408 >>> data.exit() 1409 """ 1410 return pn_data_get_map(self._data)
1411
1412 - def get_array(self):
1413 """ 1414 If the current node is an array, return a tuple of the element 1415 count, a boolean indicating whether the array is described, and 1416 the type of each element, otherwise return (0, False, None). Array 1417 data can be accessed by entering the array. 1418 1419 >>> # read an array of strings with a symbolic descriptor 1420 >>> count, described, type = data.get_array() 1421 >>> data.enter() 1422 >>> data.next() 1423 >>> print "Descriptor:", data.get_symbol() 1424 >>> for i in range(count): 1425 ... data.next() 1426 ... print "Element:", data.get_string() 1427 >>> data.exit() 1428 """ 1429 count = pn_data_get_array(self._data) 1430 described = pn_data_is_array_described(self._data) 1431 type = pn_data_get_array_type(self._data) 1432 if type == -1: 1433 type = None 1434 return count, described, type
1435
1436 - def is_described(self):
1437 """ 1438 Checks if the current node is a described value. The descriptor 1439 and value may be accessed by entering the described value. 1440 1441 >>> # read a symbolically described string 1442 >>> assert data.is_described() # will error if the current node is not described 1443 >>> data.enter() 1444 >>> print data.get_symbol() 1445 >>> print data.get_string() 1446 >>> data.exit() 1447 """ 1448 return pn_data_is_described(self._data)
1449
1450 - def is_null(self):
1451 """ 1452 Checks if the current node is a null. 1453 """ 1454 self._check(pn_data_get_null(self._data))
1455
1456 - def get_bool(self):
1457 """ 1458 If the current node is a boolean, returns its value, returns False 1459 otherwise. 1460 """ 1461 return pn_data_get_bool(self._data)
1462
1463 - def get_ubyte(self):
1464 """ 1465 If the current node is an unsigned byte, returns its value, 1466 returns 0 otherwise. 1467 """ 1468 return pn_data_get_ubyte(self._data)
1469
1470 - def get_byte(self):
1471 """ 1472 If the current node is a signed byte, returns its value, returns 0 1473 otherwise. 1474 """ 1475 return pn_data_get_byte(self._data)
1476
1477 - def get_ushort(self):
1478 """ 1479 If the current node is an unsigned short, returns its value, 1480 returns 0 otherwise. 1481 """ 1482 return pn_data_get_ushort(self._data)
1483
1484 - def get_short(self):
1485 """ 1486 If the current node is a signed short, returns its value, returns 1487 0 otherwise. 1488 """ 1489 return pn_data_get_short(self._data)
1490
1491 - def get_uint(self):
1492 """ 1493 If the current node is an unsigned int, returns its value, returns 1494 0 otherwise. 1495 """ 1496 return pn_data_get_uint(self._data)
1497
1498 - def get_int(self):
1499 """ 1500 If the current node is a signed int, returns its value, returns 0 1501 otherwise. 1502 """ 1503 return pn_data_get_int(self._data)
1504
1505 - def get_char(self):
1506 """ 1507 If the current node is a char, returns its value, returns 0 1508 otherwise. 1509 """ 1510 return char(unichr(pn_data_get_char(self._data)))
1511
1512 - def get_ulong(self):
1513 """ 1514 If the current node is an unsigned long, returns its value, 1515 returns 0 otherwise. 1516 """ 1517 return ulong(pn_data_get_ulong(self._data))
1518
1519 - def get_long(self):
1520 """ 1521 If the current node is an signed long, returns its value, returns 1522 0 otherwise. 1523 """ 1524 return pn_data_get_long(self._data)
1525
1526 - def get_timestamp(self):
1527 """ 1528 If the current node is a timestamp, returns its value, returns 0 1529 otherwise. 1530 """ 1531 return timestamp(pn_data_get_timestamp(self._data))
1532
1533 - def get_float(self):
1534 """ 1535 If the current node is a float, returns its value, raises 0 1536 otherwise. 1537 """ 1538 return pn_data_get_float(self._data)
1539
1540 - def get_double(self):
1541 """ 1542 If the current node is a double, returns its value, returns 0 1543 otherwise. 1544 """ 1545 return pn_data_get_double(self._data)
1546 1547 # XXX: need to convert
1548 - def get_decimal32(self):
1549 """ 1550 If the current node is a decimal32, returns its value, returns 0 1551 otherwise. 1552 """ 1553 return pn_data_get_decimal32(self._data)
1554 1555 # XXX: need to convert
1556 - def get_decimal64(self):
1557 """ 1558 If the current node is a decimal64, returns its value, returns 0 1559 otherwise. 1560 """ 1561 return pn_data_get_decimal64(self._data)
1562 1563 # XXX: need to convert
1564 - def get_decimal128(self):
1565 """ 1566 If the current node is a decimal128, returns its value, returns 0 1567 otherwise. 1568 """ 1569 return pn_data_get_decimal128(self._data)
1570
1571 - def get_uuid(self):
1572 """ 1573 If the current node is a UUID, returns its value, returns None 1574 otherwise. 1575 """ 1576 if pn_data_type(self._data) == Data.UUID: 1577 return uuid.UUID(bytes=pn_data_get_uuid(self._data)) 1578 else: 1579 return None
1580
1581 - def get_binary(self):
1582 """ 1583 If the current node is binary, returns its value, returns "" 1584 otherwise. 1585 """ 1586 return pn_data_get_binary(self._data)
1587
1588 - def get_string(self):
1589 """ 1590 If the current node is a string, returns its value, returns "" 1591 otherwise. 1592 """ 1593 return pn_data_get_string(self._data).decode("utf8")
1594
1595 - def get_symbol(self):
1596 """ 1597 If the current node is a symbol, returns its value, returns "" 1598 otherwise. 1599 """ 1600 return symbol(pn_data_get_symbol(self._data))
1601
1602 - def copy(self, src):
1603 self._check(pn_data_copy(self._data, src._data))
1604
1605 - def format(self):
1606 sz = 16 1607 while True: 1608 err, result = pn_data_format(self._data, sz) 1609 if err == PN_OVERFLOW: 1610 sz *= 2 1611 continue 1612 else: 1613 self._check(err) 1614 return result
1615
1616 - def dump(self):
1617 pn_data_dump(self._data)
1618
1619 - def put_dict(self, d):
1620 self.put_map() 1621 self.enter() 1622 try: 1623 for k, v in d.items(): 1624 self.put_object(k) 1625 self.put_object(v) 1626 finally: 1627 self.exit()
1628
1629 - def get_dict(self):
1630 if self.enter(): 1631 try: 1632 result = {} 1633 while self.next(): 1634 k = self.get_object() 1635 if self.next(): 1636 v = self.get_object() 1637 else: 1638 v = None 1639 result[k] = v 1640 finally: 1641 self.exit() 1642 return result
1643
1644 - def put_sequence(self, s):
1645 self.put_list() 1646 self.enter() 1647 try: 1648 for o in s: 1649 self.put_object(o) 1650 finally: 1651 self.exit()
1652
1653 - def get_sequence(self):
1654 if self.enter(): 1655 try: 1656 result = [] 1657 while self.next(): 1658 result.append(self.get_object()) 1659 finally: 1660 self.exit() 1661 return result
1662
1663 - def get_py_described(self):
1664 if self.enter(): 1665 try: 1666 self.next() 1667 descriptor = self.get_object() 1668 self.next() 1669 value = self.get_object() 1670 finally: 1671 self.exit() 1672 return Described(descriptor, value)
1673
1674 - def put_py_described(self, d):
1675 self.put_described() 1676 self.enter() 1677 try: 1678 self.put_object(d.descriptor) 1679 self.put_object(d.value) 1680 finally: 1681 self.exit()
1682
1683 - def get_py_array(self):
1684 """ 1685 If the current node is an array, return an Array object 1686 representing the array and its contents. Otherwise return None. 1687 This is a convenience wrapper around get_array, enter, etc. 1688 """ 1689 1690 count, described, type = self.get_array() 1691 if type is None: return None 1692 if self.enter(): 1693 try: 1694 if described: 1695 self.next() 1696 descriptor = self.get_object() 1697 else: 1698 descriptor = UNDESCRIBED 1699 elements = [] 1700 while self.next(): 1701 elements.append(self.get_object()) 1702 finally: 1703 self.exit() 1704 return Array(descriptor, type, *elements)
1705
1706 - def put_py_array(self, a):
1707 described = a.descriptor != UNDESCRIBED 1708 self.put_array(described, a.type) 1709 self.enter() 1710 try: 1711 if described: 1712 self.put_object(a.descriptor) 1713 for e in a.elements: 1714 self.put_object(e) 1715 finally: 1716 self.exit()
1717 1718 put_mappings = { 1719 None.__class__: lambda s, _: s.put_null(), 1720 bool: put_bool, 1721 dict: put_dict, 1722 list: put_sequence, 1723 tuple: put_sequence, 1724 unicode: put_string, 1725 bytes: put_binary, 1726 symbol: put_symbol, 1727 int: put_long, 1728 char: put_char, 1729 long: put_long, 1730 ulong: put_ulong, 1731 timestamp: put_timestamp, 1732 float: put_double, 1733 uuid.UUID: put_uuid, 1734 Described: put_py_described, 1735 Array: put_py_array 1736 } 1737 get_mappings = { 1738 NULL: lambda s: None, 1739 BOOL: get_bool, 1740 BYTE: get_byte, 1741 UBYTE: get_ubyte, 1742 SHORT: get_short, 1743 USHORT: get_ushort, 1744 INT: get_int, 1745 UINT: get_uint, 1746 CHAR: get_char, 1747 LONG: get_long, 1748 ULONG: get_ulong, 1749 TIMESTAMP: get_timestamp, 1750 FLOAT: get_float, 1751 DOUBLE: get_double, 1752 DECIMAL32: get_decimal32, 1753 DECIMAL64: get_decimal64, 1754 DECIMAL128: get_decimal128, 1755 UUID: get_uuid, 1756 BINARY: get_binary, 1757 STRING: get_string, 1758 SYMBOL: get_symbol, 1759 DESCRIBED: get_py_described, 1760 ARRAY: get_py_array, 1761 LIST: get_sequence, 1762 MAP: get_dict 1763 } 1764 1765
1766 - def put_object(self, obj):
1767 putter = self.put_mappings[obj.__class__] 1768 putter(self, obj)
1769
1770 - def get_object(self):
1771 type = self.type() 1772 if type is None: return None 1773 getter = self.get_mappings.get(type) 1774 if getter: 1775 return getter(self) 1776 else: 1777 return UnmappedType(str(type))
1778
1779 -class ConnectionException(ProtonException):
1780 pass
1781
1782 -class Endpoint(object):
1783 1784 LOCAL_UNINIT = PN_LOCAL_UNINIT 1785 REMOTE_UNINIT = PN_REMOTE_UNINIT 1786 LOCAL_ACTIVE = PN_LOCAL_ACTIVE 1787 REMOTE_ACTIVE = PN_REMOTE_ACTIVE 1788 LOCAL_CLOSED = PN_LOCAL_CLOSED 1789 REMOTE_CLOSED = PN_REMOTE_CLOSED 1790
1791 - def __init__(self):
1792 self.condition = None
1793
1794 - def _update_cond(self):
1795 impl = self._get_cond_impl() 1796 pn_condition_clear(impl) 1797 if self.condition: 1798 pn_condition_set_name(impl, self.condition.name) 1799 pn_condition_set_description(impl, self.condition.description) 1800 info = Data(pn_condition_info(impl)) 1801 if self.condition.info: 1802 info.put_object(self.condition.info)
1803 1804 @property
1805 - def remote_condition(self):
1806 impl = self._get_remote_cond_impl() 1807 if pn_condition_is_set(impl): 1808 info_impl = Data(pn_condition_info(impl)) 1809 info_impl.rewind() 1810 info_impl.next() 1811 info = info_impl.get_object() 1812 info_impl.rewind() 1813 return Condition(pn_condition_get_name(impl), 1814 pn_condition_get_description(impl), 1815 info)
1816
1817 -class Condition:
1818
1819 - def __init__(self, name, description=None, info=None):
1820 self.name = name 1821 self.description = description 1822 self.info = info
1823
1824 - def __repr__(self):
1825 return "Condition(%s)" % ", ".join([repr(x) for x in 1826 (self.name, self.description, self.info) 1827 if x])
1828
1829 - def __eq__(self, o):
1830 if not isinstance(o, Condition): return False 1831 return self.name == o.name and \ 1832 self.description == o.description and \ 1833 self.info == o.info
1834
1835 -def wrap_connection(conn):
1836 if not conn: return None 1837 ctx = pn_connection_get_context(conn) 1838 if ctx: return ctx 1839 wrapper = Connection(_conn=conn) 1840 return wrapper
1841
1842 -class Connection(Endpoint):
1843
1844 - def __init__(self, _conn=None):
1845 Endpoint.__init__(self) 1846 if _conn: 1847 self._conn = _conn 1848 else: 1849 self._conn = pn_connection() 1850 pn_connection_set_context(self._conn, self) 1851 self.offered_capabilities = None 1852 self.desired_capabilities = None
1853
1854 - def __del__(self):
1855 if hasattr(self, "_conn"): 1856 pn_connection_free(self._conn) 1857 del self._conn
1858
1859 - def _check(self, err):
1860 if err < 0: 1861 exc = EXCEPTIONS.get(err, ConnectionException) 1862 raise exc("[%s]: %s" % (err, pn_connection_error(self._conn))) 1863 else: 1864 return err
1865
1866 - def _get_cond_impl(self):
1867 return pn_connection_condition(self._conn)
1868
1869 - def _get_remote_cond_impl(self):
1870 return pn_connection_remote_condition(self._conn)
1871
1872 - def _get_container(self):
1873 return pn_connection_get_container(self._conn)
1874 - def _set_container(self, name):
1875 return pn_connection_set_container(self._conn, name)
1876 1877 container = property(_get_container, _set_container) 1878
1879 - def _get_hostname(self):
1880 return pn_connection_get_hostname(self._conn)
1881 - def _set_hostname(self, name):
1882 return pn_connection_set_hostname(self._conn, name)
1883 1884 hostname = property(_get_hostname, _set_hostname) 1885 1886 @property
1887 - def remote_container(self):
1888 return pn_connection_remote_container(self._conn)
1889 1890 @property
1891 - def remote_hostname(self):
1892 return pn_connection_remote_hostname(self._conn)
1893
1894 - def _dat2cap(self, dimpl):
1895 d = Data(dimpl) 1896 d.rewind() 1897 d.next() 1898 obj = d.get_object() 1899 d.rewind() 1900 return obj
1901 1902 @property
1904 return self._dat2cap(pn_connection_remote_offered_capabilities(self._conn))
1905 1906 @property
1908 return self._dat2cap(pn_connection_remote_desired_capabilities(self._conn))
1909
1910 - def _cap2data(self, obj, dimpl):
1911 if obj is not None: 1912 d = Data(dimpl) 1913 d.put_object(obj)
1914
1915 - def open(self):
1916 self._cap2data(self.offered_capabilities, 1917 pn_connection_offered_capabilities(self._conn)) 1918 self._cap2data(self.desired_capabilities, 1919 pn_connection_desired_capabilities(self._conn)) 1920 pn_connection_open(self._conn)
1921
1922 - def close(self):
1923 self._update_cond() 1924 pn_connection_close(self._conn)
1925 1926 @property
1927 - def state(self):
1928 return pn_connection_state(self._conn)
1929 1930 @property
1931 - def writable(self):
1932 return pn_connection_writable(self._conn)
1933
1934 - def session(self):
1935 return wrap_session(pn_session(self._conn))
1936
1937 - def session_head(self, mask):
1938 return wrap_session(pn_session_head(self._conn, mask))
1939 1942 1943 @property
1944 - def work_head(self):
1945 return wrap_delivery(pn_work_head(self._conn))
1946 1947 @property
1948 - def error(self):
1949 return pn_error_code(pn_connection_error(self._conn))
1950
1951 -class SessionException(ProtonException):
1952 pass
1953
1954 -def wrap_session(ssn):
1955 if ssn is None: return None 1956 ctx = pn_session_get_context(ssn) 1957 if ctx: 1958 return ctx 1959 else: 1960 wrapper = Session(ssn) 1961 pn_session_set_context(ssn, wrapper) 1962 return wrapper
1963
1964 -class Session(Endpoint):
1965
1966 - def __init__(self, ssn):
1967 Endpoint.__init__(self) 1968 self._ssn = ssn
1969
1970 - def __del__(self):
1971 if hasattr(self, "_ssn"): 1972 pn_session_free(self._ssn) 1973 del self._ssn
1974
1975 - def _get_cond_impl(self):
1976 return pn_session_condition(self._ssn)
1977
1978 - def _get_remote_cond_impl(self):
1979 return pn_session_remote_condition(self._ssn)
1980
1981 - def open(self):
1982 pn_session_open(self._ssn)
1983
1984 - def close(self):
1985 self._update_cond() 1986 pn_session_close(self._ssn)
1987
1988 - def next(self, mask):
1989 return wrap_session(pn_session_next(self._ssn, mask))
1990 1991 @property
1992 - def state(self):
1993 return pn_session_state(self._ssn)
1994 1995 @property
1996 - def connection(self):
1997 return wrap_connection(pn_session_connection(self._ssn))
1998
1999 - def sender(self, name):
2000 return wrap_link(pn_sender(self._ssn, name))
2001
2002 - def receiver(self, name):
2003 return wrap_link(pn_receiver(self._ssn, name))
2004
2005 -class LinkException(ProtonException):
2006 pass
2007 2020 2111
2112 2113 -class Terminus(object):
2114 2115 UNSPECIFIED = PN_UNSPECIFIED 2116 SOURCE = PN_SOURCE 2117 TARGET = PN_TARGET 2118 COORDINATOR = PN_COORDINATOR 2119 2120 NONDURABLE = PN_NONDURABLE 2121 CONFIGURATION = PN_CONFIGURATION 2122 DELIVERIES = PN_DELIVERIES 2123
2124 - def __init__(self, impl):
2125 self._impl = impl
2126
2127 - def _check(self, err):
2128 if err < 0: 2129 exc = EXCEPTIONS.get(err, LinkException) 2130 raise exc("[%s]" % err) 2131 else: 2132 return err
2133
2134 - def _get_type(self):
2135 return pn_terminus_get_type(self._impl)
2136 - def _set_type(self, type):
2137 self._check(pn_terminus_set_type(self._impl, type))
2138 type = property(_get_type, _set_type) 2139
2140 - def _get_address(self):
2141 return pn_terminus_get_address(self._impl)
2142 - def _set_address(self, address):
2143 self._check(pn_terminus_set_address(self._impl, address))
2144 address = property(_get_address, _set_address) 2145
2146 - def _get_durability(self):
2147 return pn_terminus_get_durability(self._impl)
2148 - def _set_durability(self, seconds):
2149 self._check(pn_terminus_set_durability(self._impl, seconds))
2150 durability = property(_get_durability, _set_durability) 2151
2152 - def _get_expiry_policy(self):
2153 return pn_terminus_get_expiry_policy(self._impl)
2154 - def _set_expiry_policy(self, seconds):
2155 self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
2156 expiry_policy = property(_get_expiry_policy, _set_expiry_policy) 2157
2158 - def _get_timeout(self):
2159 return pn_terminus_get_timeout(self._impl)
2160 - def _set_timeout(self, seconds):
2161 self._check(pn_terminus_set_timeout(self._impl, seconds))
2162 timeout = property(_get_timeout, _set_timeout) 2163
2164 - def _is_dynamic(self):
2165 return pn_terminus_is_dynamic(self._impl)
2166 - def _set_dynamic(self, dynamic):
2167 self._check(pn_terminus_set_dynamic(self._impl, dynamic))
2168 dynamic = property(_is_dynamic, _set_dynamic) 2169 2170 @property
2171 - def properties(self):
2172 return Data(pn_terminus_properties(self._impl))
2173 2174 @property
2175 - def capabilities(self):
2176 return Data(pn_terminus_capabilities(self._impl))
2177 2178 @property
2179 - def outcomes(self):
2180 return Data(pn_terminus_outcomes(self._impl))
2181 2182 @property
2183 - def filter(self):
2184 return Data(pn_terminus_filter(self._impl))
2185
2186 - def copy(self, src):
2187 self._check(pn_terminus_copy(self._impl, src._impl))
2188
2189 2190 -class Sender(Link):
2191
2192 - def offered(self, n):
2193 pn_link_offered(self._link, n)
2194
2195 - def send(self, bytes):
2196 return self._check(pn_link_send(self._link, bytes))
2197
2198 - def drained(self):
2199 pn_link_drained(self._link)
2200
2201 -class Receiver(Link):
2202
2203 - def flow(self, n):
2204 pn_link_flow(self._link, n)
2205
2206 - def recv(self, limit):
2207 n, bytes = pn_link_recv(self._link, limit) 2208 if n == PN_EOS: 2209 return None 2210 else: 2211 self._check(n) 2212 return bytes
2213
2214 - def drain(self, n):
2215 pn_link_drain(self._link, n)
2216
2217 -def wrap_delivery(dlv):
2218 if not dlv: return None 2219 ctx = pn_delivery_get_context(dlv) 2220 if ctx: return ctx 2221 wrapper = Delivery(dlv) 2222 pn_delivery_set_context(dlv, wrapper) 2223 return wrapper
2224
2225 -class Delivery(object):
2226 2227 ACCEPTED = PN_ACCEPTED 2228
2229 - def __init__(self, dlv):
2230 self._dlv = dlv
2231 2232 @property
2233 - def tag(self):
2234 return pn_delivery_tag(self._dlv)
2235 2236 @property
2237 - def writable(self):
2238 return pn_delivery_writable(self._dlv)
2239 2240 @property
2241 - def readable(self):
2242 return pn_delivery_readable(self._dlv)
2243 2244 @property
2245 - def updated(self):
2246 return pn_delivery_updated(self._dlv)
2247
2248 - def update(self, state):
2249 pn_delivery_update(self._dlv, state)
2250 2251 @property
2252 - def local_state(self):
2253 return pn_delivery_local_state(self._dlv)
2254 2255 @property
2256 - def remote_state(self):
2257 return pn_delivery_remote_state(self._dlv)
2258 2259 @property
2260 - def settled(self):
2261 return pn_delivery_settled(self._dlv)
2262
2263 - def settle(self):
2264 pn_delivery_settle(self._dlv)
2265 2266 @property
2267 - def work_next(self):
2268 return wrap_delivery(pn_work_next(self._dlv))
2269 2270 @property
2273
2274 2275 -class TransportException(ProtonException):
2276 pass
2277
2278 -class Transport(object):
2279 2280 TRACE_DRV = PN_TRACE_DRV 2281 TRACE_FRM = PN_TRACE_FRM 2282 TRACE_RAW = PN_TRACE_RAW 2283
2284 - def __init__(self, _trans=None):
2285 if not _trans: 2286 self._trans = pn_transport() 2287 else: 2288 self._shared_trans = True 2289 self._trans = _trans
2290
2291 - def __del__(self):
2292 if hasattr(self, "_trans"): 2293 if not hasattr(self, "_shared_trans"): 2294 pn_transport_free(self._trans) 2295 del self._trans
2296
2297 - def _check(self, err):
2298 if err < 0: 2299 exc = EXCEPTIONS.get(err, TransportException) 2300 raise exc("[%s]: %s" % (err, pn_error_text(pn_transport_error(self._trans)))) 2301 else: 2302 return err
2303
2304 - def bind(self, connection):
2305 self._check(pn_transport_bind(self._trans, connection._conn))
2306
2307 - def trace(self, n):
2308 pn_transport_trace(self._trans, n)
2309
2310 - def tick(self, now):
2311 return pn_transport_tick(self._trans, now)
2312
2313 - def output(self, n):
2314 cd, out = pn_transport_output(self._trans, n) 2315 if cd == PN_EOS: 2316 return None 2317 else: 2318 self._check(cd) 2319 return out
2320
2321 - def input(self, binary):
2322 n = pn_transport_input(self._trans, binary) 2323 if n == PN_EOS: 2324 return None 2325 else: 2326 return self._check(n)
2327 2328 # AMQP 1.0 max-frame-size
2329 - def _get_max_frame_size(self):
2330 return pn_transport_get_max_frame(self._trans)
2331
2332 - def _set_max_frame_size(self, value):
2333 pn_transport_set_max_frame(self._trans, value)
2334 2335 max_frame_size = property(_get_max_frame_size, _set_max_frame_size, 2336 doc=""" 2337 Sets the maximum size for received frames (in bytes). 2338 """) 2339 2340 @property
2341 - def remote_max_frame_size(self):
2342 return pn_transport_get_remote_max_frame(self._trans)
2343 2344 # AMQP 1.0 idle-time-out
2345 - def _get_idle_timeout(self):
2346 return pn_transport_get_idle_timeout(self._trans)
2347
2348 - def _set_idle_timeout(self, value):
2349 pn_transport_set_idle_timeout(self._trans, value)
2350 2351 idle_timeout = property(_get_idle_timeout, _set_idle_timeout, 2352 doc=""" 2353 The idle timeout of the connection (in milliseconds). 2354 """) 2355 2356 @property
2357 - def remote_idle_timeout(self):
2358 return pn_transport_get_remote_idle_timeout(self._trans)
2359 2360 @property
2361 - def frames_output(self):
2362 return pn_transport_get_frames_output(self._trans)
2363 2364 @property
2365 - def frames_input(self):
2366 return pn_transport_get_frames_input(self._trans)
2367
2368 -class SASLException(TransportException):
2369 pass
2370
2371 -class SASL(object):
2372 2373 OK = PN_SASL_OK 2374 AUTH = PN_SASL_AUTH 2375
2376 - def __init__(self, transport):
2377 self._sasl = pn_sasl(transport._trans)
2378
2379 - def _check(self, err):
2380 if err < 0: 2381 exc = EXCEPTIONS.get(err, SASLException) 2382 raise exc("[%s]" % (err)) 2383 else: 2384 return err
2385
2386 - def mechanisms(self, mechs):
2387 pn_sasl_mechanisms(self._sasl, mechs)
2388
2389 - def client(self):
2390 pn_sasl_client(self._sasl)
2391
2392 - def server(self):
2393 pn_sasl_server(self._sasl)
2394
2395 - def plain(self, user, password):
2396 pn_sasl_plain(self._sasl, user, password)
2397
2398 - def send(self, data):
2399 self._check(pn_sasl_send(self._sasl, data, len(data)))
2400
2401 - def recv(self):
2402 sz = 16 2403 while True: 2404 n, data = pn_sasl_recv(self._sasl, sz) 2405 if n == PN_OVERFLOW: 2406 sz *= 2 2407 continue 2408 elif n == PN_EOS: 2409 return None 2410 else: 2411 self._check(n) 2412 return data
2413 2414 @property
2415 - def outcome(self):
2416 outcome = pn_sasl_outcome(self._sasl) 2417 if outcome == PN_SASL_NONE: 2418 return None 2419 else: 2420 return outcome
2421
2422 - def done(self, outcome):
2423 pn_sasl_done(self._sasl, outcome)
2424 2425 STATE_CONF = PN_SASL_CONF 2426 STATE_IDLE = PN_SASL_IDLE 2427 STATE_STEP = PN_SASL_STEP 2428 STATE_PASS = PN_SASL_PASS 2429 STATE_FAIL = PN_SASL_FAIL 2430 2431 @property
2432 - def state(self):
2433 return pn_sasl_state(self._sasl)
2434
2435 2436 -class SSLException(TransportException):
2437 pass
2438
2439 -class SSLUnavailable(SSLException):
2440 pass
2441
2442 -class SSLDomain(object):
2443 2444 MODE_CLIENT = PN_SSL_MODE_CLIENT 2445 MODE_SERVER = PN_SSL_MODE_SERVER 2446 VERIFY_PEER = PN_SSL_VERIFY_PEER 2447 VERIFY_PEER_NAME = PN_SSL_VERIFY_PEER_NAME 2448 ANONYMOUS_PEER = PN_SSL_ANONYMOUS_PEER 2449
2450 - def __init__(self, mode):
2451 self._domain = pn_ssl_domain(mode) 2452 if self._domain is None: 2453 raise SSLUnavailable()
2454
2455 - def _check(self, err):
2456 if err < 0: 2457 exc = EXCEPTIONS.get(err, SSLException) 2458 raise exc("SSL failure.") 2459 else: 2460 return err
2461
2462 - def set_credentials(self, cert_file, key_file, password):
2463 return self._check( pn_ssl_domain_set_credentials(self._domain, 2464 cert_file, key_file, 2465 password) )
2466 - def set_trusted_ca_db(self, certificate_db):
2467 return self._check( pn_ssl_domain_set_trusted_ca_db(self._domain, 2468 certificate_db) )
2469 - def set_peer_authentication(self, verify_mode, trusted_CAs=None):
2470 return self._check( pn_ssl_domain_set_peer_authentication(self._domain, 2471 verify_mode, 2472 trusted_CAs) )
2473
2474 - def allow_unsecured_client(self):
2475 return self._check( pn_ssl_domain_allow_unsecured_client(self._domain) )
2476
2477 -class SSL(object):
2478
2479 - def _check(self, err):
2480 if err < 0: 2481 exc = EXCEPTIONS.get(err, SSLException) 2482 raise exc("SSL failure.") 2483 else: 2484 return err
2485
2486 - def __init__(self, transport, domain, session_details=None):
2487 session_id = None 2488 if session_details: 2489 session_id = session_details.get_session_id() 2490 self._ssl = pn_ssl( transport._trans ) 2491 if self._ssl is None: 2492 raise SSLUnavailable() 2493 pn_ssl_init( self._ssl, domain._domain, session_id )
2494
2495 - def cipher_name(self):
2496 rc, name = pn_ssl_get_cipher_name( self._ssl, 128 ) 2497 if rc: 2498 return name 2499 return None
2500
2501 - def protocol_name(self):
2502 rc, name = pn_ssl_get_protocol_name( self._ssl, 128 ) 2503 if rc: 2504 return name 2505 return None
2506 2507 RESUME_UNKNOWN = PN_SSL_RESUME_UNKNOWN 2508 RESUME_NEW = PN_SSL_RESUME_NEW 2509 RESUME_REUSED = PN_SSL_RESUME_REUSED 2510
2511 - def resume_status(self):
2512 return pn_ssl_resume_status( self._ssl )
2513
2514 - def _set_peer_hostname(self, hostname):
2515 self._check(pn_ssl_set_peer_hostname( self._ssl, hostname ))
2516 - def _get_peer_hostname(self):
2517 err, name = pn_ssl_get_peer_hostname( self._ssl, 1024 ) 2518 self._check(err) 2519 return name
2520 peer_hostname = property(_get_peer_hostname, _set_peer_hostname, 2521 doc=""" 2522 Manage the expected name of the remote peer. Used to authenticate the remote. 2523 """)
2524
2525 2526 -class SSLSessionDetails(object):
2527 """ Unique identifier for the SSL session. Used to resume previous session on a new 2528 SSL connection. 2529 """ 2530
2531 - def __init__(self, session_id):
2532 self._session_id = session_id
2533
2534 - def get_session_id(self):
2535 return self._session_id
2536
2537 2538 ### 2539 # Driver 2540 ### 2541 2542 -class DriverException(ProtonException):
2543 """ 2544 The DriverException class is the root of the driver exception hierarchy. 2545 """ 2546 pass
2547
2548 2549 -def wrap_connector(cxtr):
2550 if not cxtr: return None 2551 ctx = pn_connector_context(cxtr) 2552 if ctx: return ctx 2553 wrapper = Connector(_cxtr=cxtr) 2554 pn_connector_set_context(cxtr, wrapper) 2555 return wrapper
2556
2557 -class Connector(object):
2558 - def __init__(self, _cxtr):
2559 self._cxtr = _cxtr
2560
2561 - def next(self):
2562 return wrap_connector(pn_connector_next(self._cxtr))
2563
2564 - def process(self):
2565 pn_connector_process(self._cxtr)
2566
2567 - def listener(self):
2568 return wrap_listener(pn_connector_listener(self._cxtr))
2569
2570 - def sasl(self):
2571 ## seems easier just to grab the SASL associated with the transport: 2572 trans = self.transport 2573 if trans: 2574 return SASL(self.transport) 2575 return None
2576 2577 @property
2578 - def transport(self):
2579 trans = pn_connector_transport(self._cxtr) 2580 if trans: 2581 return Transport(trans) 2582 return None
2583
2584 - def close(self):
2585 return pn_connector_close(self._cxtr)
2586 2587 @property
2588 - def closed(self):
2589 return pn_connector_closed(self._cxtr)
2590
2591 - def _get_connection(self):
2592 return wrap_connection(pn_connector_connection(self._cxtr))
2593
2594 - def _set_connection(self, conn):
2595 pn_connector_set_connection(self._cxtr, conn._conn)
2596 2597 connection = property(_get_connection, _set_connection, 2598 doc=""" 2599 Associate a Connection with this Connector. 2600 """)
2601
2602 -def wrap_listener(lsnr):
2603 if not lsnr: return None 2604 ctx = pn_listener_context(lsnr) 2605 if ctx: return ctx 2606 wrapper = Listener(_lsnr=lsnr) 2607 pn_listener_set_context(lsnr, wrapper) 2608 return wrapper
2609
2610 -class Listener(object):
2611 - def __init__(self, _lsnr=None):
2612 self._lsnr = _lsnr
2613
2614 - def next(self):
2615 return wrap_listener(pn_listener_next(self._lsnr))
2616
2617 - def accept(self):
2618 cxtr = pn_listener_accept(self._lsnr) 2619 return wrap_connector(cxtr)
2620
2621 - def close(self):
2622 pn_listener_close(self._lsnr)
2623
2624 -class Driver(object):
2625 - def __init__(self):
2626 self._driver = pn_driver()
2627
2628 - def __del__(self):
2629 if hasattr(self, "_driver"): 2630 pn_driver_free(self._driver) 2631 del self._driver
2632
2633 - def wait(self, timeout):
2634 return pn_driver_wait(self._driver, timeout)
2635
2636 - def wakeup(self):
2637 return pn_driver_wakeup(self._driver)
2638
2639 - def listener(self, host, port):
2640 return wrap_listener(pn_listener(self._driver, host, port, None))
2641
2642 - def pending_listener(self):
2643 return wrap_listener(pn_driver_listener(self._driver))
2644
2645 - def head_listener(self):
2646 return wrap_listener(pn_listener_head(self._driver))
2647
2648 - def connector(self, host, port):
2649 return wrap_connector(pn_connector(self._driver, host, port, None))
2650
2651 - def head_connector(self):
2652 return wrap_connector(pn_connector_head(self._driver))
2653
2654 - def pending_connector(self):
2655 return wrap_connector(pn_driver_connector(self._driver))
2656 2657 __all__ = [ 2658 "LANGUAGE", 2659 "PN_SESSION_WINDOW", 2660 "ACCEPTED", 2661 "AUTOMATIC", 2662 "PENDING", 2663 "MANUAL", 2664 "REJECTED", 2665 "UNDESCRIBED", 2666 "Array", 2667 "Condition", 2668 "Connection", 2669 "Connector", 2670 "Data", 2671 "Delivery", 2672 "Described", 2673 "Driver", 2674 "DriverException", 2675 "Endpoint", 2676 "Link", 2677 "Listener", 2678 "Message", 2679 "MessageException", 2680 "Messenger", 2681 "MessengerException", 2682 "ProtonException", 2683 "Receiver", 2684 "SASL", 2685 "Sender", 2686 "Session", 2687 "SSL", 2688 "SSLDomain", 2689 "SSLSessionDetails", 2690 "SSLUnavailable", 2691 "Terminus", 2692 "Timeout", 2693 "Transport", 2694 "TransportException", 2695 "char", 2696 "symbol", 2697 "timestamp", 2698 "ulong" 2699 ] 2700