1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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
54 if isinstance(other, uuid.UUID):
55 return cmp(self.bytes, other.bytes)
56 else:
57 return -1
58
60 return "%08x-%04x-%04x-%04x-%04x%08x" % struct.unpack("!LHHHHL", self.bytes)
61
63 return "UUID(%r)" % str(self)
64
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()))
72 bytes = [rand.randint(0, 255) for i in xrange(16)]
73
74
75 bytes[7] &= 0x0F
76 bytes[7] |= 0x40
77
78
79 bytes[8] &= 0x3F
80 bytes[8] |= 0x80
81 return "".join(map(chr, bytes))
82
84 return uuid.UUID(bytes=random_uuid())
85
86 try:
87 bytes()
88 except NameError:
89 bytes = str
90
91 API_LANGUAGE = "C"
92 IMPLEMENTATION_LANGUAGE = "C"
101
103 """
104 The root of the proton exception hierarchy. All proton exception
105 classes derive from this exception.
106 """
107 pass
108
110 """
111 A timeout exception indicates that a blocking operation has timed
112 out.
113 """
114 pass
115
117 """
118 An interrupt exception indicaes that a blocking operation was interrupted.
119 """
120 pass
121
123 """
124 The root of the messenger exception hierarchy. All exceptions
125 generated by the messenger class derive from this exception.
126 """
127 pass
128
130 """
131 The MessageException class is the root of the message exception
132 hierarhcy. All exceptions generated by the Message class derive from
133 this exception.
134 """
135 pass
136
137 EXCEPTIONS = {
138 PN_TIMEOUT: Timeout,
139 PN_INTR: Interrupt
140 }
141
142 PENDING = Constant("PENDING")
143 ACCEPTED = Constant("ACCEPTED")
144 REJECTED = Constant("REJECTED")
145
146 STATUSES = {
147 PN_STATUS_ACCEPTED: ACCEPTED,
148 PN_STATUS_REJECTED: REJECTED,
149 PN_STATUS_PENDING: PENDING,
150 PN_STATUS_UNKNOWN: None
151 }
152
153 AUTOMATIC = Constant("AUTOMATIC")
154 MANUAL = Constant("MANUAL")
157 """
158 The L{Messenger} class defines a high level interface for sending
159 and receiving L{Messages<Message>}. Every L{Messenger} contains a
160 single logical queue of incoming messages and a single logical queue
161 of outgoing messages. These messages in these queues may be destined
162 for, or originate from, a variety of addresses.
163
164 Address Syntax
165 ==============
166
167 An address has the following form::
168
169 [ amqp[s]:// ] [user[:password]@] domain [/[name]]
170
171 Where domain can be one of::
172
173 host | host:port | ip | ip:port | name
174
175 The following are valid examples of addresses:
176
177 - example.org
178 - example.org:1234
179 - amqp://example.org
180 - amqps://example.org
181 - example.org/incoming
182 - amqps://example.org/outgoing
183 - amqps://fred:trustno1@example.org
184 - 127.0.0.1:1234
185 - amqps://127.0.0.1:1234
186
187 Sending & Receiving Messages
188 ============================
189
190 The L{Messenger} class works in conjuction with the L{Message}
191 class. The L{Message} class is a mutable holder of message content.
192 The L{put} method will encode the content in a given L{Message}
193 object into the outgoing message queue leaving that L{Message}
194 object free to be modified or discarded without having any impact on
195 the content in the outgoing queue.
196
197 >>> message = Message()
198 >>> for i in range(3):
199 ... message.address = "amqp://host/queue"
200 ... message.subject = "Hello World %i" % i
201 ... messenger.put(message)
202 >>> messenger.send()
203
204 Similarly, the L{get} method will decode the content in the incoming
205 message queue into the supplied L{Message} object.
206
207 >>> message = Message()
208 >>> messenger.recv(10):
209 >>> while messenger.incoming > 0:
210 ... messenger.get(message)
211 ... print message.subject
212 Hello World 0
213 Hello World 1
214 Hello World 2
215 """
216
218 """
219 Construct a new L{Messenger} with the given name. The name has
220 global scope. If a NULL name is supplied, a L{uuid.UUID} based
221 name will be chosen.
222
223 @type name: string
224 @param name: the name of the messenger or None
225 """
226 self._mng = pn_messenger(name)
227
229 if hasattr(self, "_mng"):
230 pn_messenger_free(self._mng)
231 del self._mng
232
234 if err < 0:
235 if (err == PN_INPROGRESS):
236 return
237 exc = EXCEPTIONS.get(err, MessengerException)
238 raise exc("[%s]: %s" % (err, pn_error_text(pn_messenger_error(self._mng))))
239 else:
240 return err
241
242 @property
244 """
245 The name of the L{Messenger}.
246 """
247 return pn_messenger_name(self._mng)
248
250 return pn_messenger_get_certificate(self._mng)
251
253 self._check(pn_messenger_set_certificate(self._mng, value))
254
255 certificate = property(_get_certificate, _set_certificate,
256 doc="""
257 Path to a certificate file for the L{Messenger}. This certificate is
258 used when the L{Messenger} accepts or establishes SSL/TLS connections.
259 This property must be specified for the L{Messenger} to accept
260 incoming SSL/TLS connections and to establish client authenticated
261 outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS
262 connections do not require this property.
263 """)
264
266 return pn_messenger_get_private_key(self._mng)
267
269 self._check(pn_messenger_set_private_key(self._mng, value))
270
271 private_key = property(_get_private_key, _set_private_key,
272 doc="""
273 Path to a private key file for the L{Messenger's<Messenger>}
274 certificate. This property must be specified for the L{Messenger} to
275 accept incoming SSL/TLS connections and to establish client
276 authenticated outgoing SSL/TLS connection. Non client authenticated
277 SSL/TLS connections do not require this property.
278 """)
279
281 return pn_messenger_get_password(self._mng)
282
284 self._check(pn_messenger_set_password(self._mng, value))
285
286 password = property(_get_password, _set_password,
287 doc="""
288 This property contains the password for the L{Messenger.private_key}
289 file, or None if the file is not encrypted.
290 """)
291
293 return pn_messenger_get_trusted_certificates(self._mng)
294
296 self._check(pn_messenger_set_trusted_certificates(self._mng, value))
297
298 trusted_certificates = property(_get_trusted_certificates,
299 _set_trusted_certificates,
300 doc="""
301 A path do a database of trusted certificates for use in verifying the
302 peer on an SSL/TLS connection. If this property is None, then the peer
303 will not be verified.
304 """)
305
307 t = pn_messenger_get_timeout(self._mng)
308 if t == -1:
309 return None
310 else:
311 return float(t)/1000
312
314 if value is None:
315 t = -1
316 else:
317 t = long(1000*value)
318 self._check(pn_messenger_set_timeout(self._mng, t))
319
320 timeout = property(_get_timeout, _set_timeout,
321 doc="""
322 The timeout property contains the default timeout for blocking
323 operations performed by the L{Messenger}.
324 """)
325
327 return pn_messenger_is_blocking(self._mng)
328
330 self._check(pn_messenger_set_blocking(self._mng, b))
331
332 blocking = property(_is_blocking, _set_blocking)
333
335 return pn_messenger_get_incoming_window(self._mng)
336
338 self._check(pn_messenger_set_incoming_window(self._mng, window))
339
340 incoming_window = property(_get_incoming_window, _set_incoming_window,
341 doc="""
342 The incoming tracking window for the messenger. The messenger will
343 track the remote status of this many incoming deliveries after they
344 have been accepted or rejected. Defaults to zero.
345 """)
346
348 return pn_messenger_get_outgoing_window(self._mng)
349
351 self._check(pn_messenger_set_outgoing_window(self._mng, window))
352
353 outgoing_window = property(_get_outgoing_window, _set_outgoing_window,
354 doc="""
355 The outgoing tracking window for the messenger. The messenger will
356 track the remote status of this many outgoing deliveries after calling
357 send. Defaults to zero.
358 """)
359
361 """
362 Transitions the L{Messenger} to an active state. A L{Messenger} is
363 initially created in an inactive state. When inactive a
364 L{Messenger} will not send or receive messages from its internal
365 queues. A L{Messenger} must be started before calling L{send} or
366 L{recv}.
367 """
368 self._check(pn_messenger_start(self._mng))
369
371 """
372 Transitions the L{Messenger} to an inactive state. An inactive
373 L{Messenger} will not send or receive messages from its internal
374 queues. A L{Messenger} should be stopped before being discarded to
375 ensure a clean shutdown handshake occurs on any internally managed
376 connections.
377 """
378 self._check(pn_messenger_stop(self._mng))
379
380 @property
382 return pn_messenger_stopped(self._mng)
383
385 """
386 Subscribes the L{Messenger} to messages originating from the
387 specified source. The source is an address as specified in the
388 L{Messenger} introduction with the following addition. If the
389 domain portion of the address begins with the '~' character, the
390 L{Messenger} will interpret the domain as host/port, bind to it,
391 and listen for incoming messages. For example "~0.0.0.0",
392 "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any
393 local interface and listen for incoming messages with the last
394 variant only permitting incoming SSL connections.
395
396 @type source: string
397 @param source: the source of messages to subscribe to
398 """
399 sub_impl = pn_messenger_subscribe(self._mng, source)
400 if not sub_impl:
401 self._check(PN_ERR)
402
403 - def put(self, message):
404 """
405 Places the content contained in the message onto the outgoing
406 queue of the L{Messenger}. This method will never block, however
407 it will send any unblocked L{Messages<Message>} in the outgoing
408 queue immediately and leave any blocked L{Messages<Message>}
409 remaining in the outgoing queue. The L{send} call may be used to
410 block until the outgoing queue is empty. The L{outgoing} property
411 may be used to check the depth of the outgoing queue.
412
413 @type message: Message
414 @param message: the message to place in the outgoing queue
415 @return: a tracker
416 """
417 message._pre_encode()
418 self._check(pn_messenger_put(self._mng, message._msg))
419 return pn_messenger_outgoing_tracker(self._mng)
420
422 """
423 Gets the last known remote state of the delivery associated with
424 the given tracker.
425
426 @type tracker: tracker
427 @param tracker: the tracker whose status is to be retrieved
428
429 @return: one of None, PENDING, REJECTED, or ACCEPTED
430 """
431 disp = pn_messenger_status(self._mng, tracker);
432 return STATUSES.get(disp, disp)
433
434 - def settle(self, tracker=None):
435 if tracker is None:
436 tracker = pn_messenger_outgoing_tracker(self._mng)
437 flags = PN_CUMULATIVE
438 else:
439 flags = 0
440 self._check(pn_messenger_settle(self._mng, tracker, flags))
441
442 - def send(self, n=-1):
443 """
444 Blocks until the outgoing queue is empty or the operation times
445 out. The L{timeout} property controls how long a L{Messenger} will
446 block before timing out.
447 """
448 self._check(pn_messenger_send(self._mng, n))
449
450 - def recv(self, n=None):
451 """
452 Receives up to I{n} messages into the incoming queue of the
453 L{Messenger}. If I{n} is not specified, L{Messenger} will receive as many
454 messages as it can buffer internally. This method will block until at least
455 one message is available or the operation times out.
456 """
457 if n is None:
458 n = -1
459 self._check(pn_messenger_recv(self._mng, n))
460
461 - def work(self, timeout=None):
462 if timeout is None:
463 t = -1
464 else:
465 t = long(1000*timeout)
466 err = pn_messenger_work(self._mng, t)
467 if (err == PN_TIMEOUT):
468 return False
469 else:
470 self._check(err)
471 return True
472
474 self._check(pn_messenger_interrupt(self._mng))
475
476 - def get(self, message=None):
477 """
478 Moves the message from the head of the incoming message queue into
479 the supplied message object. Any content in the message will be
480 overwritten.
481
482 @type message: Message
483 @param message: the destination message object
484 @return: a tracker
485 """
486 if message is None:
487 impl = None
488 else:
489 impl = message._msg
490 self._check(pn_messenger_get(self._mng, impl))
491 if message is not None:
492 message._post_decode()
493 return pn_messenger_incoming_tracker(self._mng)
494
495 - def accept(self, tracker=None):
496 """
497 Accepts messages retreived from the incoming message queue.
498
499 @type tracker: tracker
500 @param tracker: a tracker as returned by get
501 """
502 if tracker is None:
503 tracker = pn_messenger_incoming_tracker(self._mng)
504 flags = PN_CUMULATIVE
505 else:
506 flags = 0
507 self._check(pn_messenger_accept(self._mng, tracker, flags))
508
509 - def reject(self, tracker=None):
510 """
511 Rejects messages retreived from the incoming message queue.
512
513 @type tracker: tracker
514 @param tracker: a tracker as returned by get
515 """
516 if tracker is None:
517 tracker = pn_messenger_incoming_tracker(self._mng)
518 flags = PN_CUMULATIVE
519 else:
520 flags = 0
521 self._check(pn_messenger_reject(self._mng, tracker, flags))
522
523 @property
525 """
526 The outgoing queue depth.
527 """
528 return pn_messenger_outgoing(self._mng)
529
530 @property
532 """
533 The incoming queue depth.
534 """
535 return pn_messenger_incoming(self._mng)
536
537 - def route(self, pattern, address):
538 self._check(pn_messenger_route(self._mng, pattern, address))
539
540 - def rewrite(self, pattern, address):
541 self._check(pn_messenger_rewrite(self._mng, pattern, address))
542
544 """
545 The L{Message} class is a mutable holder of message content.
546
547 @ivar instructions: delivery instructions for the message
548 @type instructions: dict
549 @ivar annotations: infrastructure defined message annotations
550 @type annotations: dict
551 @ivar properties: application defined message properties
552 @type properties: dict
553 @ivar body: message body
554 @type body: bytes | unicode | dict | list | int | long | float | UUID
555 """
556
557 DATA = PN_DATA
558 TEXT = PN_TEXT
559 AMQP = PN_AMQP
560 JSON = PN_JSON
561
562 DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY
563
565 self._msg = pn_message()
566 self._id = Data(pn_message_id(self._msg))
567 self._correlation_id = Data(pn_message_correlation_id(self._msg))
568 self.instructions = None
569 self.annotations = None
570 self.properties = None
571 self.body = None
572
574 if hasattr(self, "_msg"):
575 pn_message_free(self._msg)
576 del self._msg
577
579 if err < 0:
580 exc = EXCEPTIONS.get(err, MessageException)
581 raise exc("[%s]: %s" % (err, pn_message_error(self._msg)))
582 else:
583 return err
584
603
604 - def _post_decode(self):
605 inst = Data(pn_message_instructions(self._msg))
606 ann = Data(pn_message_annotations(self._msg))
607 props = Data(pn_message_properties(self._msg))
608 body = Data(pn_message_body(self._msg))
609
610 if inst.next():
611 self.instructions = inst.get_object()
612 else:
613 self.instructions = None
614 if ann.next():
615 self.annotations = ann.get_object()
616 else:
617 self.annotations = None
618 if props.next():
619 self.properties = props.get_object()
620 else:
621 self.properties = None
622 if body.next():
623 self.body = body.get_object()
624 else:
625 self.body = None
626
628 """
629 Clears the contents of the L{Message}. All fields will be reset to
630 their default values.
631 """
632 pn_message_clear(self._msg)
633 self.instructions = None
634 self.annotations = None
635 self.properties = None
636 self.body = None
637
639 return pn_message_is_inferred(self._msg)
640
642 self._check(pn_message_set_inferred(self._msg, bool(value)))
643
644 inferred = property(_is_inferred, _set_inferred)
645
647 return pn_message_is_durable(self._msg)
648
650 self._check(pn_message_set_durable(self._msg, bool(value)))
651
652 durable = property(_is_durable, _set_durable,
653 doc="""
654 The durable property indicates that the message should be held durably
655 by any intermediaries taking responsibility for the message.
656 """)
657
659 return pn_message_get_priority(self._msg)
660
662 self._check(pn_message_set_priority(self._msg, value))
663
664 priority = property(_get_priority, _set_priority,
665 doc="""
666 The priority of the message.
667 """)
668
670 return pn_message_get_ttl(self._msg)
671
673 self._check(pn_message_set_ttl(self._msg, value))
674
675 ttl = property(_get_ttl, _set_ttl,
676 doc="""
677 The time to live of the message measured in milliseconds. Expired
678 messages may be dropped.
679 """)
680
682 return pn_message_is_first_acquirer(self._msg)
683
685 self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
686
687 first_acquirer = property(_is_first_acquirer, _set_first_acquirer,
688 doc="""
689 True iff the recipient is the first to acquire the message.
690 """)
691
693 return pn_message_get_delivery_count(self._msg)
694
696 self._check(pn_message_set_delivery_count(self._msg, value))
697
698 delivery_count = property(_get_delivery_count, _set_delivery_count,
699 doc="""
700 The number of delivery attempts made for this message.
701 """)
702
703
711 id = property(_get_id, _set_id,
712 doc="""
713 The id of the message.
714 """)
715
717 return pn_message_get_user_id(self._msg)
718
720 self._check(pn_message_set_user_id(self._msg, value))
721
722 user_id = property(_get_user_id, _set_user_id,
723 doc="""
724 The user id of the message creator.
725 """)
726
728 return pn_message_get_address(self._msg)
729
731 self._check(pn_message_set_address(self._msg, value))
732
733 address = property(_get_address, _set_address,
734 doc="""
735 The address of the message.
736 """)
737
739 return pn_message_get_subject(self._msg)
740
742 self._check(pn_message_set_subject(self._msg, value))
743
744 subject = property(_get_subject, _set_subject,
745 doc="""
746 The subject of the message.
747 """)
748
750 return pn_message_get_reply_to(self._msg)
751
753 self._check(pn_message_set_reply_to(self._msg, value))
754
755 reply_to = property(_get_reply_to, _set_reply_to,
756 doc="""
757 The reply-to address for the message.
758 """)
759
763 if type(value) in (int, long):
764 value = ulong(value)
765 self._correlation_id.rewind()
766 self._correlation_id.put_object(value)
767
768 correlation_id = property(_get_correlation_id, _set_correlation_id,
769 doc="""
770 The correlation-id for the message.
771 """)
772
774 return pn_message_get_content_type(self._msg)
775
776 - def _set_content_type(self, value):
777 self._check(pn_message_set_content_type(self._msg, value))
778
779 content_type = property(_get_content_type, _set_content_type,
780 doc="""
781 The content-type of the message.
782 """)
783
785 return pn_message_get_content_encoding(self._msg)
786
787 - def _set_content_encoding(self, value):
788 self._check(pn_message_set_content_encoding(self._msg, value))
789
790 content_encoding = property(_get_content_encoding, _set_content_encoding,
791 doc="""
792 The content-encoding of the message.
793 """)
794
796 return pn_message_get_expiry_time(self._msg)
797
799 self._check(pn_message_set_expiry_time(self._msg, value))
800
801 expiry_time = property(_get_expiry_time, _set_expiry_time,
802 doc="""
803 The expiry time of the message.
804 """)
805
807 return pn_message_get_creation_time(self._msg)
808
810 self._check(pn_message_set_creation_time(self._msg, value))
811
812 creation_time = property(_get_creation_time, _set_creation_time,
813 doc="""
814 The creation time of the message.
815 """)
816
818 return pn_message_get_group_id(self._msg)
819
821 self._check(pn_message_set_group_id(self._msg, value))
822
823 group_id = property(_get_group_id, _set_group_id,
824 doc="""
825 The group id of the message.
826 """)
827
829 return pn_message_get_group_sequence(self._msg)
830
832 self._check(pn_message_set_group_sequence(self._msg, value))
833
834 group_sequence = property(_get_group_sequence, _set_group_sequence,
835 doc="""
836 The sequence of the message within its group.
837 """)
838
840 return pn_message_get_reply_to_group_id(self._msg)
841
843 self._check(pn_message_set_reply_to_group_id(self._msg, value))
844
845 reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id,
846 doc="""
847 The group-id for any replies.
848 """)
849
850
853
856
857 format = property(_get_format, _set_format,
858 doc="""
859 The format of the message.
860 """)
861
863 self._pre_encode()
864 sz = 16
865 while True:
866 err, data = pn_message_encode(self._msg, sz)
867 if err == PN_OVERFLOW:
868 sz *= 2
869 continue
870 else:
871 self._check(err)
872 return data
873
875 self._check(pn_message_decode(self._msg, data, len(data)))
876 self._post_decode()
877
878 - def load(self, data):
879 self._check(pn_message_load(self._msg, data))
880
882 sz = 16
883 while True:
884 err, data = pn_message_save(self._msg, sz)
885 if err == PN_OVERFLOW:
886 sz *= 2
887 continue
888 else:
889 self._check(err)
890 return data
891
893 props = []
894 for attr in ("inferred", "address", "reply_to", "durable", "ttl",
895 "priority", "first_acquirer", "delivery_count", "id",
896 "correlation_id", "user_id", "group_id", "group_sequence",
897 "reply_to_group_id", "instructions", "annotations",
898 "properties", "body"):
899 value = getattr(self, attr)
900 if value: props.append("%s=%r" % (attr, value))
901 return "Message(%s)" % ", ".join(props)
902
904 tmp = pn_string(None)
905 err = pn_inspect(self._msg, tmp)
906 result = pn_string_get(tmp)
907 pn_free(tmp)
908 self._check(err)
909 return result
910
912 """
913 The DataException class is the root of the Data exception hierarchy.
914 All exceptions raised by the Data class extend this exception.
915 """
916 pass
917
919
922
924 return "UnmappedType(%s)" % self.msg
925
927
929 return "ulong(%s)" % long.__repr__(self)
930
932
934 return "timestamp(%s)" % long.__repr__(self)
935
937
939 return "symbol(%s)" % unicode.__repr__(self)
940
941 -class char(unicode):
942
944 return "char(%s)" % unicode.__repr__(self)
945
947
949 self.descriptor = descriptor
950 self.value = value
951
953 return "Described(%r, %r)" % (self.descriptor, self.value)
954
956 if isinstance(o, Described):
957 return self.descriptor == o.descriptor and self.value == o.value
958 else:
959 return False
960
961 UNDESCRIBED = Constant("UNDESCRIBED")
964
965 - def __init__(self, descriptor, type, *elements):
966 self.descriptor = descriptor
967 self.type = type
968 self.elements = elements
969
971 if self.elements:
972 els = ", %s" % (", ".join(map(repr, self.elements)))
973 else:
974 els = ""
975 return "Array(%r, %r%s)" % (self.descriptor, self.type, els)
976
978 if isinstance(o, Array):
979 return self.descriptor == o.descriptor and \
980 self.type == o.type and self.elements == o.elements
981 else:
982 return False
983
985 """
986 The L{Data} class provides an interface for decoding, extracting,
987 creating, and encoding arbitrary AMQP data. A L{Data} object
988 contains a tree of AMQP values. Leaf nodes in this tree correspond
989 to scalars in the AMQP type system such as L{ints<INT>} or
990 L{strings<STRING>}. Non-leaf nodes in this tree correspond to
991 compound values in the AMQP type system such as L{lists<LIST>},
992 L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}.
993 The root node of the tree is the L{Data} object itself and can have
994 an arbitrary number of children.
995
996 A L{Data} object maintains the notion of the current sibling node
997 and a current parent node. Siblings are ordered within their parent.
998 Values are accessed and/or added by using the L{next}, L{prev},
999 L{enter}, and L{exit} methods to navigate to the desired location in
1000 the tree and using the supplied variety of put_*/get_* methods to
1001 access or add a value of the desired type.
1002
1003 The put_* methods will always add a value I{after} the current node
1004 in the tree. If the current node has a next sibling the put_* method
1005 will overwrite the value on this node. If there is no current node
1006 or the current node has no next sibling then one will be added. The
1007 put_* methods always set the added/modified node to the current
1008 node. The get_* methods read the value of the current node and do
1009 not change which node is current.
1010
1011 The following types of scalar values are supported:
1012
1013 - L{NULL}
1014 - L{BOOL}
1015 - L{UBYTE}
1016 - L{USHORT}
1017 - L{SHORT}
1018 - L{UINT}
1019 - L{INT}
1020 - L{ULONG}
1021 - L{LONG}
1022 - L{FLOAT}
1023 - L{DOUBLE}
1024 - L{BINARY}
1025 - L{STRING}
1026 - L{SYMBOL}
1027
1028 The following types of compound values are supported:
1029
1030 - L{DESCRIBED}
1031 - L{ARRAY}
1032 - L{LIST}
1033 - L{MAP}
1034 """
1035
1036 NULL = PN_NULL; "A null value."
1037 BOOL = PN_BOOL; "A boolean value."
1038 UBYTE = PN_UBYTE; "An unsigned byte value."
1039 BYTE = PN_BYTE; "A signed byte value."
1040 USHORT = PN_USHORT; "An unsigned short value."
1041 SHORT = PN_SHORT; "A short value."
1042 UINT = PN_UINT; "An unsigned int value."
1043 INT = PN_INT; "A signed int value."
1044 CHAR = PN_CHAR; "A character value."
1045 ULONG = PN_ULONG; "An unsigned long value."
1046 LONG = PN_LONG; "A signed long value."
1047 TIMESTAMP = PN_TIMESTAMP; "A timestamp value."
1048 FLOAT = PN_FLOAT; "A float value."
1049 DOUBLE = PN_DOUBLE; "A double value."
1050 DECIMAL32 = PN_DECIMAL32; "A DECIMAL32 value."
1051 DECIMAL64 = PN_DECIMAL64; "A DECIMAL64 value."
1052 DECIMAL128 = PN_DECIMAL128; "A DECIMAL128 value."
1053 UUID = PN_UUID; "A UUID value."
1054 BINARY = PN_BINARY; "A binary string."
1055 STRING = PN_STRING; "A unicode string."
1056 SYMBOL = PN_SYMBOL; "A symbolic string."
1057 DESCRIBED = PN_DESCRIBED; "A described value."
1058 ARRAY = PN_ARRAY; "An array value."
1059 LIST = PN_LIST; "A list value."
1060 MAP = PN_MAP; "A map value."
1061
1062 type_names = {
1063 NULL: "null",
1064 BOOL: "bool",
1065 BYTE: "byte",
1066 UBYTE: "ubyte",
1067 SHORT: "short",
1068 USHORT: "ushort",
1069 INT: "int",
1070 UINT: "uint",
1071 CHAR: "char",
1072 LONG: "long",
1073 ULONG: "ulong",
1074 TIMESTAMP: "timestamp",
1075 FLOAT: "float",
1076 DOUBLE: "double",
1077 DECIMAL32: "decimal32",
1078 DECIMAL64: "decimal64",
1079 DECIMAL128: "decimal128",
1080 UUID: "uuid",
1081 BINARY: "binary",
1082 STRING: "string",
1083 SYMBOL: "symbol",
1084 DESCRIBED: "described",
1085 ARRAY: "array",
1086 LIST: "list",
1087 MAP: "map"
1088 }
1089
1090 @classmethod
1092
1094 if type(capacity) in (int, long):
1095 self._data = pn_data(capacity)
1096 self._free = True
1097 else:
1098 self._data = capacity
1099 self._free = False
1100
1102 if self._free and hasattr(self, "_data"):
1103 pn_data_free(self._data)
1104 del self._data
1105
1107 if err < 0:
1108 exc = EXCEPTIONS.get(err, DataException)
1109 raise exc("[%s]: %s" % (err, pn_data_error(self._data)))
1110 else:
1111 return err
1112
1114 """
1115 Clears the data object.
1116 """
1117 pn_data_clear(self._data)
1118
1120 """
1121 Clears current node and sets the parent to the root node. Clearing the
1122 current node sets it _before_ the first node, calling next() will advance to
1123 the first node.
1124 """
1125 pn_data_rewind(self._data)
1126
1128 """
1129 Advances the current node to its next sibling and returns its
1130 type. If there is no next sibling the current node remains
1131 unchanged and None is returned.
1132 """
1133 found = pn_data_next(self._data)
1134 if found:
1135 return self.type()
1136 else:
1137 return None
1138
1140 """
1141 Advances the current node to its previous sibling and returns its
1142 type. If there is no previous sibling the current node remains
1143 unchanged and None is returned.
1144 """
1145 found = pn_data_prev(self._data)
1146 if found:
1147 return self.type()
1148 else:
1149 return None
1150
1152 """
1153 Sets the parent node to the current node and clears the current node.
1154 Clearing the current node sets it _before_ the first child,
1155 call next() advances to the first child.
1156 """
1157 return pn_data_enter(self._data)
1158
1160 """
1161 Sets the current node to the parent node and the parent node to
1162 its own parent.
1163 """
1164 return pn_data_exit(self._data)
1165
1167 return pn_data_lookup(self._data, name)
1168
1170 pn_data_narrow(self._data)
1171
1173 pn_data_widen(self._data)
1174
1176 """
1177 Returns the type of the current node.
1178 """
1179 dtype = pn_data_type(self._data)
1180 if dtype == -1:
1181 return None
1182 else:
1183 return dtype
1184
1186 """
1187 Returns a representation of the data encoded in AMQP format.
1188 """
1189 size = 1024
1190 while True:
1191 cd, enc = pn_data_encode(self._data, size)
1192 if cd == PN_OVERFLOW:
1193 size *= 2
1194 elif cd >= 0:
1195 return enc
1196 else:
1197 self._check(cd)
1198
1200 """
1201 Decodes the first value from supplied AMQP data and returns the
1202 number of bytes consumed.
1203
1204 @type encoded: binary
1205 @param encoded: AMQP encoded binary data
1206 """
1207 return self._check(pn_data_decode(self._data, encoded))
1208
1210 """
1211 Puts a list value. Elements may be filled by entering the list
1212 node and putting element values.
1213
1214 >>> data = Data()
1215 >>> data.put_list()
1216 >>> data.enter()
1217 >>> data.put_int(1)
1218 >>> data.put_int(2)
1219 >>> data.put_int(3)
1220 >>> data.exit()
1221 """
1222 self._check(pn_data_put_list(self._data))
1223
1225 """
1226 Puts a map value. Elements may be filled by entering the map node
1227 and putting alternating key value pairs.
1228
1229 >>> data = Data()
1230 >>> data.put_map()
1231 >>> data.enter()
1232 >>> data.put_string("key")
1233 >>> data.put_string("value")
1234 >>> data.exit()
1235 """
1236 self._check(pn_data_put_map(self._data))
1237
1238 - def put_array(self, described, element_type):
1239 """
1240 Puts an array value. Elements may be filled by entering the array
1241 node and putting the element values. The values must all be of the
1242 specified array element type. If an array is described then the
1243 first child value of the array is the descriptor and may be of any
1244 type.
1245
1246 >>> data = Data()
1247 >>>
1248 >>> data.put_array(False, Data.INT)
1249 >>> data.enter()
1250 >>> data.put_int(1)
1251 >>> data.put_int(2)
1252 >>> data.put_int(3)
1253 >>> data.exit()
1254 >>>
1255 >>> data.put_array(True, Data.DOUBLE)
1256 >>> data.enter()
1257 >>> data.put_symbol("array-descriptor")
1258 >>> data.put_double(1.1)
1259 >>> data.put_double(1.2)
1260 >>> data.put_double(1.3)
1261 >>> data.exit()
1262
1263 @type described: bool
1264 @param described: specifies whether the array is described
1265 @type element_type: int
1266 @param element_type: the type of the array elements
1267 """
1268 self._check(pn_data_put_array(self._data, described, element_type))
1269
1271 """
1272 Puts a described value. A described node has two children, the
1273 descriptor and the value. These are specified by entering the node
1274 and putting the desired values.
1275
1276 >>> data = Data()
1277 >>> data.put_described()
1278 >>> data.enter()
1279 >>> data.put_symbol("value-descriptor")
1280 >>> data.put_string("the value")
1281 >>> data.exit()
1282 """
1283 self._check(pn_data_put_described(self._data))
1284
1286 """
1287 Puts a null value.
1288 """
1289 self._check(pn_data_put_null(self._data))
1290
1292 """
1293 Puts a boolean value.
1294
1295 @param b: a boolean value
1296 """
1297 self._check(pn_data_put_bool(self._data, b))
1298
1300 """
1301 Puts an unsigned byte value.
1302
1303 @param ub: an integral value
1304 """
1305 self._check(pn_data_put_ubyte(self._data, ub))
1306
1308 """
1309 Puts a signed byte value.
1310
1311 @param b: an integral value
1312 """
1313 self._check(pn_data_put_byte(self._data, b))
1314
1316 """
1317 Puts an unsigned short value.
1318
1319 @param us: an integral value.
1320 """
1321 self._check(pn_data_put_ushort(self._data, us))
1322
1324 """
1325 Puts a signed short value.
1326
1327 @param s: an integral value
1328 """
1329 self._check(pn_data_put_short(self._data, s))
1330
1332 """
1333 Puts an unsigned int value.
1334
1335 @param ui: an integral value
1336 """
1337 self._check(pn_data_put_uint(self._data, ui))
1338
1340 """
1341 Puts a signed int value.
1342
1343 @param i: an integral value
1344 """
1345 self._check(pn_data_put_int(self._data, i))
1346
1348 """
1349 Puts a char value.
1350
1351 @param c: a single character
1352 """
1353 self._check(pn_data_put_char(self._data, ord(c)))
1354
1356 """
1357 Puts an unsigned long value.
1358
1359 @param ul: an integral value
1360 """
1361 self._check(pn_data_put_ulong(self._data, ul))
1362
1364 """
1365 Puts a signed long value.
1366
1367 @param l: an integral value
1368 """
1369 self._check(pn_data_put_long(self._data, l))
1370
1372 """
1373 Puts a timestamp value.
1374
1375 @param t: an integral value
1376 """
1377 self._check(pn_data_put_timestamp(self._data, t))
1378
1380 """
1381 Puts a float value.
1382
1383 @param f: a floating point value
1384 """
1385 self._check(pn_data_put_float(self._data, f))
1386
1388 """
1389 Puts a double value.
1390
1391 @param d: a floating point value.
1392 """
1393 self._check(pn_data_put_double(self._data, d))
1394
1396 """
1397 Puts a decimal32 value.
1398
1399 @param d: a decimal32 value
1400 """
1401 self._check(pn_data_put_decimal32(self._data, d))
1402
1404 """
1405 Puts a decimal64 value.
1406
1407 @param d: a decimal64 value
1408 """
1409 self._check(pn_data_put_decimal64(self._data, d))
1410
1412 """
1413 Puts a decimal128 value.
1414
1415 @param d: a decimal128 value
1416 """
1417 self._check(pn_data_put_decimal128(self._data, d))
1418
1420 """
1421 Puts a UUID value.
1422
1423 @param u: a uuid value
1424 """
1425 self._check(pn_data_put_uuid(self._data, u.bytes))
1426
1428 """
1429 Puts a binary value.
1430
1431 @type b: binary
1432 @param b: a binary value
1433 """
1434 self._check(pn_data_put_binary(self._data, b))
1435
1437 """
1438 Puts a unicode value.
1439
1440 @type s: unicode
1441 @param s: a unicode value
1442 """
1443 self._check(pn_data_put_string(self._data, s.encode("utf8")))
1444
1446 """
1447 Puts a symbolic value.
1448
1449 @type s: string
1450 @param s: the symbol name
1451 """
1452 self._check(pn_data_put_symbol(self._data, s))
1453
1455 """
1456 If the current node is a list, return the number of elements,
1457 otherwise return zero. List elements can be accessed by entering
1458 the list.
1459
1460 >>> count = data.get_list()
1461 >>> data.enter()
1462 >>> for i in range(count):
1463 ... type = data.next()
1464 ... if type == Data.STRING:
1465 ... print data.get_string()
1466 ... elif type == ...:
1467 ... ...
1468 >>> data.exit()
1469 """
1470 return pn_data_get_list(self._data)
1471
1473 """
1474 If the current node is a map, return the number of child elements,
1475 otherwise return zero. Key value pairs can be accessed by entering
1476 the map.
1477
1478 >>> count = data.get_map()
1479 >>> data.enter()
1480 >>> for i in range(count/2):
1481 ... type = data.next()
1482 ... if type == Data.STRING:
1483 ... print data.get_string()
1484 ... elif type == ...:
1485 ... ...
1486 >>> data.exit()
1487 """
1488 return pn_data_get_map(self._data)
1489
1491 """
1492 If the current node is an array, return a tuple of the element
1493 count, a boolean indicating whether the array is described, and
1494 the type of each element, otherwise return (0, False, None). Array
1495 data can be accessed by entering the array.
1496
1497 >>> # read an array of strings with a symbolic descriptor
1498 >>> count, described, type = data.get_array()
1499 >>> data.enter()
1500 >>> data.next()
1501 >>> print "Descriptor:", data.get_symbol()
1502 >>> for i in range(count):
1503 ... data.next()
1504 ... print "Element:", data.get_string()
1505 >>> data.exit()
1506 """
1507 count = pn_data_get_array(self._data)
1508 described = pn_data_is_array_described(self._data)
1509 type = pn_data_get_array_type(self._data)
1510 if type == -1:
1511 type = None
1512 return count, described, type
1513
1515 """
1516 Checks if the current node is a described value. The descriptor
1517 and value may be accessed by entering the described value.
1518
1519 >>> # read a symbolically described string
1520 >>> assert data.is_described() # will error if the current node is not described
1521 >>> data.enter()
1522 >>> print data.get_symbol()
1523 >>> print data.get_string()
1524 >>> data.exit()
1525 """
1526 return pn_data_is_described(self._data)
1527
1529 """
1530 Checks if the current node is a null.
1531 """
1532 self._check(pn_data_get_null(self._data))
1533
1535 """
1536 If the current node is a boolean, returns its value, returns False
1537 otherwise.
1538 """
1539 return pn_data_get_bool(self._data)
1540
1542 """
1543 If the current node is an unsigned byte, returns its value,
1544 returns 0 otherwise.
1545 """
1546 return pn_data_get_ubyte(self._data)
1547
1549 """
1550 If the current node is a signed byte, returns its value, returns 0
1551 otherwise.
1552 """
1553 return pn_data_get_byte(self._data)
1554
1556 """
1557 If the current node is an unsigned short, returns its value,
1558 returns 0 otherwise.
1559 """
1560 return pn_data_get_ushort(self._data)
1561
1563 """
1564 If the current node is a signed short, returns its value, returns
1565 0 otherwise.
1566 """
1567 return pn_data_get_short(self._data)
1568
1570 """
1571 If the current node is an unsigned int, returns its value, returns
1572 0 otherwise.
1573 """
1574 return pn_data_get_uint(self._data)
1575
1577 """
1578 If the current node is a signed int, returns its value, returns 0
1579 otherwise.
1580 """
1581 return pn_data_get_int(self._data)
1582
1584 """
1585 If the current node is a char, returns its value, returns 0
1586 otherwise.
1587 """
1588 return char(unichr(pn_data_get_char(self._data)))
1589
1591 """
1592 If the current node is an unsigned long, returns its value,
1593 returns 0 otherwise.
1594 """
1595 return ulong(pn_data_get_ulong(self._data))
1596
1598 """
1599 If the current node is an signed long, returns its value, returns
1600 0 otherwise.
1601 """
1602 return pn_data_get_long(self._data)
1603
1605 """
1606 If the current node is a timestamp, returns its value, returns 0
1607 otherwise.
1608 """
1609 return timestamp(pn_data_get_timestamp(self._data))
1610
1612 """
1613 If the current node is a float, returns its value, raises 0
1614 otherwise.
1615 """
1616 return pn_data_get_float(self._data)
1617
1619 """
1620 If the current node is a double, returns its value, returns 0
1621 otherwise.
1622 """
1623 return pn_data_get_double(self._data)
1624
1625
1627 """
1628 If the current node is a decimal32, returns its value, returns 0
1629 otherwise.
1630 """
1631 return pn_data_get_decimal32(self._data)
1632
1633
1635 """
1636 If the current node is a decimal64, returns its value, returns 0
1637 otherwise.
1638 """
1639 return pn_data_get_decimal64(self._data)
1640
1641
1643 """
1644 If the current node is a decimal128, returns its value, returns 0
1645 otherwise.
1646 """
1647 return pn_data_get_decimal128(self._data)
1648
1650 """
1651 If the current node is a UUID, returns its value, returns None
1652 otherwise.
1653 """
1654 if pn_data_type(self._data) == Data.UUID:
1655 return uuid.UUID(bytes=pn_data_get_uuid(self._data))
1656 else:
1657 return None
1658
1660 """
1661 If the current node is binary, returns its value, returns ""
1662 otherwise.
1663 """
1664 return pn_data_get_binary(self._data)
1665
1667 """
1668 If the current node is a string, returns its value, returns ""
1669 otherwise.
1670 """
1671 return pn_data_get_string(self._data).decode("utf8")
1672
1674 """
1675 If the current node is a symbol, returns its value, returns ""
1676 otherwise.
1677 """
1678 return symbol(pn_data_get_symbol(self._data))
1679
1680 - def copy(self, src):
1681 self._check(pn_data_copy(self._data, src._data))
1682
1693
1695 pn_data_dump(self._data)
1696
1706
1708 if self.enter():
1709 try:
1710 result = {}
1711 while self.next():
1712 k = self.get_object()
1713 if self.next():
1714 v = self.get_object()
1715 else:
1716 v = None
1717 result[k] = v
1718 finally:
1719 self.exit()
1720 return result
1721
1730
1732 if self.enter():
1733 try:
1734 result = []
1735 while self.next():
1736 result.append(self.get_object())
1737 finally:
1738 self.exit()
1739 return result
1740
1751
1760
1762 """
1763 If the current node is an array, return an Array object
1764 representing the array and its contents. Otherwise return None.
1765 This is a convenience wrapper around get_array, enter, etc.
1766 """
1767
1768 count, described, type = self.get_array()
1769 if type is None: return None
1770 if self.enter():
1771 try:
1772 if described:
1773 self.next()
1774 descriptor = self.get_object()
1775 else:
1776 descriptor = UNDESCRIBED
1777 elements = []
1778 while self.next():
1779 elements.append(self.get_object())
1780 finally:
1781 self.exit()
1782 return Array(descriptor, type, *elements)
1783
1795
1796 put_mappings = {
1797 None.__class__: lambda s, _: s.put_null(),
1798 bool: put_bool,
1799 dict: put_dict,
1800 list: put_sequence,
1801 tuple: put_sequence,
1802 unicode: put_string,
1803 bytes: put_binary,
1804 symbol: put_symbol,
1805 int: put_long,
1806 char: put_char,
1807 long: put_long,
1808 ulong: put_ulong,
1809 timestamp: put_timestamp,
1810 float: put_double,
1811 uuid.UUID: put_uuid,
1812 Described: put_py_described,
1813 Array: put_py_array
1814 }
1815 get_mappings = {
1816 NULL: lambda s: None,
1817 BOOL: get_bool,
1818 BYTE: get_byte,
1819 UBYTE: get_ubyte,
1820 SHORT: get_short,
1821 USHORT: get_ushort,
1822 INT: get_int,
1823 UINT: get_uint,
1824 CHAR: get_char,
1825 LONG: get_long,
1826 ULONG: get_ulong,
1827 TIMESTAMP: get_timestamp,
1828 FLOAT: get_float,
1829 DOUBLE: get_double,
1830 DECIMAL32: get_decimal32,
1831 DECIMAL64: get_decimal64,
1832 DECIMAL128: get_decimal128,
1833 UUID: get_uuid,
1834 BINARY: get_binary,
1835 STRING: get_string,
1836 SYMBOL: get_symbol,
1837 DESCRIBED: get_py_described,
1838 ARRAY: get_py_array,
1839 LIST: get_sequence,
1840 MAP: get_dict
1841 }
1842
1843
1845 putter = self.put_mappings[obj.__class__]
1846 putter(self, obj)
1847
1849 type = self.type()
1850 if type is None: return None
1851 getter = self.get_mappings.get(type)
1852 if getter:
1853 return getter(self)
1854 else:
1855 return UnmappedType(str(type))
1856
1859
1878
1880
1881 - def __init__(self, name, description=None, info=None):
1882 self.name = name
1883 self.description = description
1884 self.info = info
1885
1887 return "Condition(%s)" % ", ".join([repr(x) for x in
1888 (self.name, self.description, self.info)
1889 if x])
1890
1892 if not isinstance(o, Condition): return False
1893 return self.name == o.name and \
1894 self.description == o.description and \
1895 self.info == o.info
1896
1898 pn_condition_clear(cond)
1899 if obj:
1900 pn_condition_set_name(cond, str(obj.name))
1901 pn_condition_set_description(cond, obj.description)
1902 info = Data(pn_condition_info(cond))
1903 if obj.info:
1904 info.put_object(obj.info)
1905
1907 if pn_condition_is_set(cond):
1908 return Condition(pn_condition_get_name(cond),
1909 pn_condition_get_description(cond),
1910 dat2obj(pn_condition_info(cond)))
1911 else:
1912 return None
1913
1921
1926
1928 if not conn: return None
1929 ctx = pn_connection_get_context(conn)
1930 if ctx: return ctx
1931 wrapper = Connection(_conn=conn)
1932 return wrapper
1933
1935
1937 Endpoint.__init__(self)
1938 if _conn:
1939 self._conn = _conn
1940 else:
1941 self._conn = pn_connection()
1942 pn_connection_set_context(self._conn, self)
1943 self.offered_capabilities = None
1944 self.desired_capabilities = None
1945 self.properties = None
1946
1948 if hasattr(self, "_conn"):
1949 pn_connection_free(self._conn)
1950 del self._conn
1951
1953 if err < 0:
1954 exc = EXCEPTIONS.get(err, ConnectionException)
1955 raise exc("[%s]: %s" % (err, pn_connection_error(self._conn)))
1956 else:
1957 return err
1958
1960 return pn_connection_condition(self._conn)
1961
1963 return pn_connection_remote_condition(self._conn)
1964
1966 return pn_connection_get_container(self._conn)
1968 return pn_connection_set_container(self._conn, name)
1969
1970 container = property(_get_container, _set_container)
1971
1973 return pn_connection_get_hostname(self._conn)
1975 return pn_connection_set_hostname(self._conn, name)
1976
1977 hostname = property(_get_hostname, _set_hostname)
1978
1979 @property
1981 return pn_connection_remote_container(self._conn)
1982
1983 @property
1985 return pn_connection_remote_hostname(self._conn)
1986
1987 @property
1989 return dat2obj(pn_connection_remote_offered_capabilities(self._conn))
1990
1991 @property
1993 return dat2obj(pn_connection_remote_desired_capabilities(self._conn))
1994
1995 @property
1997 return dat2obj(pn_connection_remote_properties(self._conn))
1998
2000 obj2dat(self.offered_capabilities,
2001 pn_connection_offered_capabilities(self._conn))
2002 obj2dat(self.desired_capabilities,
2003 pn_connection_desired_capabilities(self._conn))
2004 obj2dat(self.properties, pn_connection_properties(self._conn))
2005 pn_connection_open(self._conn)
2006
2008 self._update_cond()
2009 pn_connection_close(self._conn)
2010
2011 @property
2013 return pn_connection_state(self._conn)
2014
2015 @property
2017 return pn_connection_writable(self._conn)
2018
2020 return wrap_session(pn_session(self._conn))
2021
2023 return wrap_session(pn_session_head(self._conn, mask))
2024
2026 return wrap_link(pn_link_head(self._conn, mask))
2027
2028 @property
2030 return wrap_delivery(pn_work_head(self._conn))
2031
2032 @property
2034 return pn_error_code(pn_connection_error(self._conn))
2035
2038
2040 if ssn is None: return None
2041 ctx = pn_session_get_context(ssn)
2042 if ctx:
2043 return ctx
2044 else:
2045 wrapper = Session(ssn)
2046 pn_session_set_context(ssn, wrapper)
2047 return wrapper
2048
2050
2054
2056 if hasattr(self, "_ssn"):
2057 pn_session_free(self._ssn)
2058 del self._ssn
2059
2061 return pn_session_condition(self._ssn)
2062
2064 return pn_session_remote_condition(self._ssn)
2065
2067 return pn_session_get_incoming_capacity(self._ssn)
2068
2070 pn_session_set_incoming_capacity(self._ssn, capacity)
2071
2072 incoming_capacity = property(_get_incoming_capacity, _set_incoming_capacity)
2073
2074 @property
2076 return pn_session_outgoing_bytes(self._ssn)
2077
2078 @property
2080 return pn_session_incoming_bytes(self._ssn)
2081
2083 pn_session_open(self._ssn)
2084
2086 self._update_cond()
2087 pn_session_close(self._ssn)
2088
2089 - def next(self, mask):
2090 return wrap_session(pn_session_next(self._ssn, mask))
2091
2092 @property
2094 return pn_session_state(self._ssn)
2095
2096 @property
2098 return wrap_connection(pn_session_connection(self._ssn))
2099
2101 return wrap_link(pn_sender(self._ssn, name))
2102
2104 return wrap_link(pn_receiver(self._ssn, name))
2105
2108
2110 if link is None: return None
2111 ctx = pn_link_get_context(link)
2112 if ctx:
2113 return ctx
2114 else:
2115 if pn_link_is_sender(link):
2116 wrapper = Sender(link)
2117 else:
2118 wrapper = Receiver(link)
2119 pn_link_set_context(link, wrapper)
2120 return wrapper
2121
2122 -class Link(Endpoint):
2123
2124 SND_UNSETTLED = PN_SND_UNSETTLED
2125 SND_SETTLED = PN_SND_SETTLED
2126 SND_MIXED = PN_SND_MIXED
2127
2128 RCV_FIRST = PN_RCV_FIRST
2129 RCV_SECOND = PN_RCV_SECOND
2130
2134
2136 if hasattr(self, "_link"):
2137 pn_link_free(self._link)
2138 del self._link
2139
2141 if err < 0:
2142 exc = EXCEPTIONS.get(err, LinkException)
2143 raise exc("[%s]: %s" % (err, pn_link_error(self._link)))
2144 else:
2145 return err
2146
2148 return pn_link_condition(self._link)
2149
2151 return pn_link_remote_condition(self._link)
2152
2154 pn_link_open(self._link)
2155
2157 self._update_cond()
2158 pn_link_close(self._link)
2159
2160 @property
2162 return pn_link_state(self._link)
2163
2164 @property
2166 return Terminus(pn_link_source(self._link))
2167
2168 @property
2170 return Terminus(pn_link_target(self._link))
2171
2172 @property
2174 return Terminus(pn_link_remote_source(self._link))
2175 @property
2177 return Terminus(pn_link_remote_target(self._link))
2178
2179 @property
2181 return wrap_session(pn_link_session(self._link))
2182
2184 return wrap_delivery(pn_delivery(self._link, tag))
2185
2186 @property
2188 return wrap_delivery(pn_link_current(self._link))
2189
2191 return pn_link_advance(self._link)
2192
2193 @property
2195 return pn_link_unsettled(self._link)
2196
2197 @property
2199 return pn_link_credit(self._link)
2200
2201 @property
2203 return pn_link_available(self._link)
2204
2205 @property
2207 return pn_link_queued(self._link)
2208
2209 - def next(self, mask):
2210 return wrap_link(pn_link_next(self._link, mask))
2211
2212 @property
2214 return pn_link_is_sender(self._link)
2215
2216 @property
2218 return pn_link_is_receiver(self._link)
2219
2220 @property
2222 return pn_link_remote_snd_settle_mode(self._link)
2223
2224 @property
2226 return pn_link_remote_rcv_settle_mode(self._link)
2227
2229 return pn_link_snd_settle_mode(self._link)
2231 pn_link_set_snd_settle_mode(self._link, mode)
2232 snd_settle_mode = property(_get_snd_settle_mode, _set_snd_settle_mode)
2233
2235 return pn_link_rcv_settle_mode(self._link)
2237 pn_link_set_rcv_settle_mode(self._link, mode)
2238 rcv_settle_mode = property(_get_rcv_settle_mode, _set_rcv_settle_mode)
2239
2242
2243 UNSPECIFIED = PN_UNSPECIFIED
2244 SOURCE = PN_SOURCE
2245 TARGET = PN_TARGET
2246 COORDINATOR = PN_COORDINATOR
2247
2248 NONDURABLE = PN_NONDURABLE
2249 CONFIGURATION = PN_CONFIGURATION
2250 DELIVERIES = PN_DELIVERIES
2251
2252 DIST_MODE_UNSPECIFIED = PN_DIST_MODE_UNSPECIFIED
2253 DIST_MODE_COPY = PN_DIST_MODE_COPY
2254 DIST_MODE_MOVE = PN_DIST_MODE_MOVE
2255
2258
2260 if err < 0:
2261 exc = EXCEPTIONS.get(err, LinkException)
2262 raise exc("[%s]" % err)
2263 else:
2264 return err
2265
2267 return pn_terminus_get_type(self._impl)
2269 self._check(pn_terminus_set_type(self._impl, type))
2270 type = property(_get_type, _set_type)
2271
2273 return pn_terminus_get_address(self._impl)
2275 self._check(pn_terminus_set_address(self._impl, address))
2276 address = property(_get_address, _set_address)
2277
2279 return pn_terminus_get_durability(self._impl)
2281 self._check(pn_terminus_set_durability(self._impl, seconds))
2282 durability = property(_get_durability, _set_durability)
2283
2285 return pn_terminus_get_expiry_policy(self._impl)
2287 self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
2288 expiry_policy = property(_get_expiry_policy, _set_expiry_policy)
2289
2291 return pn_terminus_get_timeout(self._impl)
2293 self._check(pn_terminus_set_timeout(self._impl, seconds))
2294 timeout = property(_get_timeout, _set_timeout)
2295
2297 return pn_terminus_is_dynamic(self._impl)
2299 self._check(pn_terminus_set_dynamic(self._impl, dynamic))
2300 dynamic = property(_is_dynamic, _set_dynamic)
2301
2303 return pn_terminus_get_distribution_mode(self._impl)
2305 self._check(pn_terminus_set_distribution_mode(self._impl, mode))
2306 distribution_mode = property(_get_distribution_mode, _set_distribution_mode)
2307
2308 @property
2310 return Data(pn_terminus_properties(self._impl))
2311
2312 @property
2314 return Data(pn_terminus_capabilities(self._impl))
2315
2316 @property
2318 return Data(pn_terminus_outcomes(self._impl))
2319
2320 @property
2322 return Data(pn_terminus_filter(self._impl))
2323
2324 - def copy(self, src):
2325 self._check(pn_terminus_copy(self._impl, src._impl))
2326
2329
2331 pn_link_offered(self._link, n)
2332
2333 - def send(self, bytes):
2334 return self._check(pn_link_send(self._link, bytes))
2335
2337 pn_link_drained(self._link)
2338
2340
2341 - def flow(self, n):
2342 pn_link_flow(self._link, n)
2343
2344 - def recv(self, limit):
2345 n, bytes = pn_link_recv(self._link, limit)
2346 if n == PN_EOS:
2347 return None
2348 else:
2349 self._check(n)
2350 return bytes
2351
2353 pn_link_drain(self._link, n)
2354
2356 if not dlv: return None
2357 ctx = pn_delivery_get_context(dlv)
2358 if ctx: return ctx
2359 wrapper = Delivery(dlv)
2360 pn_delivery_set_context(dlv, wrapper)
2361 return wrapper
2362
2364
2365 RECEIVED = PN_RECEIVED
2366 ACCEPTED = PN_ACCEPTED
2367 REJECTED = PN_REJECTED
2368 RELEASED = PN_RELEASED
2369 MODIFIED = PN_MODIFIED
2370
2372 self._impl = impl
2373 self.local = local
2374 self._data = None
2375 self._condition = None
2376 self._annotations = None
2377
2378 @property
2380 return pn_disposition_type(self._impl)
2381
2383 return pn_disposition_get_section_number(self._impl)
2385 pn_disposition_set_section_number(self._impl, n)
2386 section_number = property(_get_section_number, _set_section_number)
2387
2389 return pn_disposition_get_section_offset(self._impl)
2391 pn_disposition_set_section_offset(self._impl, n)
2392 section_offset = property(_get_section_offset, _set_section_offset)
2393
2395 return pn_disposition_is_failed(self._impl)
2397 pn_disposition_set_failed(self._impl, b)
2398 failed = property(_get_failed, _set_failed)
2399
2401 return pn_disposition_is_undeliverable(self._impl)
2403 pn_disposition_set_undeliverable(self._impl, b)
2404 undeliverable = property(_get_undeliverable, _set_undeliverable)
2405
2407 if self.local:
2408 return self._data
2409 else:
2410 return dat2obj(pn_disposition_data(self._impl))
2412 if self.local:
2413 self._data = obj
2414 else:
2415 raise AttributeError("data attribute is read-only")
2416 data = property(_get_data, _set_data)
2417
2419 if self.local:
2420 return self._annotations
2421 else:
2422 return dat2obj(pn_disposition_annotations(self._impl))
2424 if self.local:
2425 self._annotations = obj
2426 else:
2427 raise AttributeError("annotations attribute is read-only")
2428 annotations = property(_get_annotations, _set_annotations)
2429
2431 if self.local:
2432 return self._condition
2433 else:
2434 return cond2obj(pn_disposition_condition(self._impl))
2436 if self.local:
2437 self._condition = obj
2438 else:
2439 raise AttributeError("condition attribute is read-only")
2440 condition = property(_get_condition, _set_condition)
2441
2443
2444 RECEIVED = Disposition.RECEIVED
2445 ACCEPTED = Disposition.ACCEPTED
2446 REJECTED = Disposition.REJECTED
2447 RELEASED = Disposition.RELEASED
2448 MODIFIED = Disposition.MODIFIED
2449
2451 self._dlv = dlv
2452 self.local = Disposition(pn_delivery_local(self._dlv), True)
2453 self.remote = Disposition(pn_delivery_remote(self._dlv), False)
2454
2455 @property
2457 return pn_delivery_tag(self._dlv)
2458
2459 @property
2461 return pn_delivery_writable(self._dlv)
2462
2463 @property
2465 return pn_delivery_readable(self._dlv)
2466
2467 @property
2469 return pn_delivery_updated(self._dlv)
2470
2472 obj2dat(self.local._data, pn_disposition_data(self.local._impl))
2473 obj2dat(self.local._annotations, pn_disposition_annotations(self.local._impl))
2474 obj2cond(self.local._condition, pn_disposition_condition(self.local._impl))
2475 pn_delivery_update(self._dlv, state)
2476
2477 @property
2479 return pn_delivery_pending(self._dlv)
2480
2481 @property
2483 return pn_delivery_partial(self._dlv)
2484
2485 @property
2487 return pn_delivery_local_state(self._dlv)
2488
2489 @property
2491 return pn_delivery_remote_state(self._dlv)
2492
2493 @property
2495 return pn_delivery_settled(self._dlv)
2496
2498 pn_delivery_settle(self._dlv)
2499
2500 @property
2502 return wrap_delivery(pn_work_next(self._dlv))
2503
2504 @property
2506 return wrap_link(pn_delivery_link(self._dlv))
2507
2510
2512
2513 TRACE_DRV = PN_TRACE_DRV
2514 TRACE_FRM = PN_TRACE_FRM
2515 TRACE_RAW = PN_TRACE_RAW
2516
2518 if not _trans:
2519 self._trans = pn_transport()
2520 else:
2521 self._shared_trans = True
2522 self._trans = _trans
2523
2525 if hasattr(self, "_trans"):
2526 if not hasattr(self, "_shared_trans"):
2527 pn_transport_free(self._trans)
2528 del self._trans
2529
2531 if err < 0:
2532 exc = EXCEPTIONS.get(err, TransportException)
2533 raise exc("[%s]: %s" % (err, pn_error_text(pn_transport_error(self._trans))))
2534 else:
2535 return err
2536
2537 - def bind(self, connection):
2538 self._check(pn_transport_bind(self._trans, connection._conn))
2539
2541 pn_transport_trace(self._trans, n)
2542
2543 - def tick(self, now):
2544 return pn_transport_tick(self._trans, now)
2545
2547 c = pn_transport_capacity(self._trans)
2548 if c >= PN_EOS:
2549 return c
2550 else:
2551 return self._check(c)
2552
2553 - def push(self, bytes):
2554 self._check(pn_transport_push(self._trans, bytes))
2555
2557 self._check(pn_transport_close_tail(self._trans))
2558
2560 p = pn_transport_pending(self._trans)
2561 if p >= PN_EOS:
2562 return p
2563 else:
2564 return self._check(p)
2565
2566 - def peek(self, size):
2567 cd, out = pn_transport_peek(self._trans, size)
2568 if cd == PN_EOS:
2569 return None
2570 else:
2571 self._check(cd)
2572 return out
2573
2574 - def pop(self, size):
2575 pn_transport_pop(self._trans, size)
2576
2578 self._check(pn_transport_close_head(self._trans))
2579
2581 p = self.pending()
2582 if p < 0:
2583 return None
2584 else:
2585 out = self.peek(min(size, p))
2586 self.pop(len(out))
2587 return out
2588
2600
2601
2603 return pn_transport_get_max_frame(self._trans)
2604
2606 pn_transport_set_max_frame(self._trans, value)
2607
2608 max_frame_size = property(_get_max_frame_size, _set_max_frame_size,
2609 doc="""
2610 Sets the maximum size for received frames (in bytes).
2611 """)
2612
2613 @property
2615 return pn_transport_get_remote_max_frame(self._trans)
2616
2617
2619 return pn_transport_get_idle_timeout(self._trans)
2620
2622 pn_transport_set_idle_timeout(self._trans, value)
2623
2624 idle_timeout = property(_get_idle_timeout, _set_idle_timeout,
2625 doc="""
2626 The idle timeout of the connection (in milliseconds).
2627 """)
2628
2629 @property
2631 return pn_transport_get_remote_idle_timeout(self._trans)
2632
2633 @property
2635 return pn_transport_get_frames_output(self._trans)
2636
2637 @property
2640
2643
2644 -class SASL(object):
2645
2646 OK = PN_SASL_OK
2647 AUTH = PN_SASL_AUTH
2648
2651
2653 if err < 0:
2654 exc = EXCEPTIONS.get(err, SASLException)
2655 raise exc("[%s]" % (err))
2656 else:
2657 return err
2658
2660 pn_sasl_mechanisms(self._sasl, mechs)
2661
2663 pn_sasl_client(self._sasl)
2664
2666 pn_sasl_server(self._sasl)
2667
2668 - def plain(self, user, password):
2669 pn_sasl_plain(self._sasl, user, password)
2670
2671 - def send(self, data):
2672 self._check(pn_sasl_send(self._sasl, data, len(data)))
2673
2675 sz = 16
2676 while True:
2677 n, data = pn_sasl_recv(self._sasl, sz)
2678 if n == PN_OVERFLOW:
2679 sz *= 2
2680 continue
2681 elif n == PN_EOS:
2682 return None
2683 else:
2684 self._check(n)
2685 return data
2686
2687 @property
2689 outcome = pn_sasl_outcome(self._sasl)
2690 if outcome == PN_SASL_NONE:
2691 return None
2692 else:
2693 return outcome
2694
2695 - def done(self, outcome):
2696 pn_sasl_done(self._sasl, outcome)
2697
2698 STATE_CONF = PN_SASL_CONF
2699 STATE_IDLE = PN_SASL_IDLE
2700 STATE_STEP = PN_SASL_STEP
2701 STATE_PASS = PN_SASL_PASS
2702 STATE_FAIL = PN_SASL_FAIL
2703
2704 @property
2706 return pn_sasl_state(self._sasl)
2707
2711
2714
2715 -class SSLDomain(object):
2716
2717 MODE_CLIENT = PN_SSL_MODE_CLIENT
2718 MODE_SERVER = PN_SSL_MODE_SERVER
2719 VERIFY_PEER = PN_SSL_VERIFY_PEER
2720 VERIFY_PEER_NAME = PN_SSL_VERIFY_PEER_NAME
2721 ANONYMOUS_PEER = PN_SSL_ANONYMOUS_PEER
2722
2723 - def __init__(self, mode):
2724 self._domain = pn_ssl_domain(mode)
2725 if self._domain is None:
2726 raise SSLUnavailable()
2727
2728 - def _check(self, err):
2729 if err < 0:
2730 exc = EXCEPTIONS.get(err, SSLException)
2731 raise exc("SSL failure.")
2732 else:
2733 return err
2734
2735 - def set_credentials(self, cert_file, key_file, password):
2736 return self._check( pn_ssl_domain_set_credentials(self._domain,
2737 cert_file, key_file,
2738 password) )
2739 - def set_trusted_ca_db(self, certificate_db):
2740 return self._check( pn_ssl_domain_set_trusted_ca_db(self._domain,
2741 certificate_db) )
2742 - def set_peer_authentication(self, verify_mode, trusted_CAs=None):
2743 return self._check( pn_ssl_domain_set_peer_authentication(self._domain,
2744 verify_mode,
2745 trusted_CAs) )
2746
2748 return self._check( pn_ssl_domain_allow_unsecured_client(self._domain) )
2749
2751
2753 if err < 0:
2754 exc = EXCEPTIONS.get(err, SSLException)
2755 raise exc("SSL failure.")
2756 else:
2757 return err
2758
2759 - def __init__(self, transport, domain, session_details=None):
2760 session_id = None
2761 if session_details:
2762 session_id = session_details.get_session_id()
2763 self._ssl = pn_ssl( transport._trans )
2764 if self._ssl is None:
2765 raise SSLUnavailable()
2766 pn_ssl_init( self._ssl, domain._domain, session_id )
2767
2769 rc, name = pn_ssl_get_cipher_name( self._ssl, 128 )
2770 if rc:
2771 return name
2772 return None
2773
2775 rc, name = pn_ssl_get_protocol_name( self._ssl, 128 )
2776 if rc:
2777 return name
2778 return None
2779
2780 RESUME_UNKNOWN = PN_SSL_RESUME_UNKNOWN
2781 RESUME_NEW = PN_SSL_RESUME_NEW
2782 RESUME_REUSED = PN_SSL_RESUME_REUSED
2783
2785 return pn_ssl_resume_status( self._ssl )
2786
2788 self._check(pn_ssl_set_peer_hostname( self._ssl, hostname ))
2790 err, name = pn_ssl_get_peer_hostname( self._ssl, 1024 )
2791 self._check(err)
2792 return name
2793 peer_hostname = property(_get_peer_hostname, _set_peer_hostname,
2794 doc="""
2795 Manage the expected name of the remote peer. Used to authenticate the remote.
2796 """)
2797
2800 """ Unique identifier for the SSL session. Used to resume previous session on a new
2801 SSL connection.
2802 """
2803
2805 self._session_id = session_id
2806
2808 return self._session_id
2809
2816 """
2817 The DriverException class is the root of the driver exception hierarchy.
2818 """
2819 pass
2820
2823 if not cxtr: return None
2824 ctx = pn_connector_context(cxtr)
2825 if ctx: return ctx
2826 wrapper = Connector(_cxtr=cxtr)
2827 pn_connector_set_context(cxtr, wrapper)
2828 return wrapper
2829
2833
2835 return wrap_connector(pn_connector_next(self._cxtr))
2836
2838 pn_connector_process(self._cxtr)
2839
2841 return wrap_listener(pn_connector_listener(self._cxtr))
2842
2849
2850 @property
2852 trans = pn_connector_transport(self._cxtr)
2853 if trans:
2854 return Transport(trans)
2855 return None
2856
2858 return pn_connector_close(self._cxtr)
2859
2860 @property
2862 return pn_connector_closed(self._cxtr)
2863
2865 return wrap_connection(pn_connector_connection(self._cxtr))
2866
2868 pn_connector_set_connection(self._cxtr, conn._conn)
2869
2870 connection = property(_get_connection, _set_connection,
2871 doc="""
2872 Associate a Connection with this Connector.
2873 """)
2874
2876 if not lsnr: return None
2877 ctx = pn_listener_context(lsnr)
2878 if ctx: return ctx
2879 wrapper = Listener(_lsnr=lsnr)
2880 pn_listener_set_context(lsnr, wrapper)
2881 return wrapper
2882
2886
2888 return wrap_listener(pn_listener_next(self._lsnr))
2889
2891 cxtr = pn_listener_accept(self._lsnr)
2892 return wrap_connector(cxtr)
2893
2895 pn_listener_close(self._lsnr)
2896
2899 self._driver = pn_driver()
2900
2902 if hasattr(self, "_driver"):
2903 pn_driver_free(self._driver)
2904 del self._driver
2905
2906 - def wait(self, timeout):
2907 return pn_driver_wait(self._driver, timeout)
2908
2910 return pn_driver_wakeup(self._driver)
2911
2913 return wrap_listener(pn_listener(self._driver, host, port, None))
2914
2916 return wrap_listener(pn_driver_listener(self._driver))
2917
2919 return wrap_listener(pn_listener_head(self._driver))
2920
2922 return wrap_connector(pn_connector(self._driver, host, port, None))
2923
2925 return wrap_connector(pn_connector_head(self._driver))
2926
2928 return wrap_connector(pn_driver_connector(self._driver))
2929
2930 __all__ = [
2931 "API_LANGUAGE",
2932 "IMPLEMENTATION_LANGUAGE",
2933 "ACCEPTED",
2934 "AUTOMATIC",
2935 "PENDING",
2936 "MANUAL",
2937 "REJECTED",
2938 "UNDESCRIBED",
2939 "Array",
2940 "Condition",
2941 "Connection",
2942 "Connector",
2943 "Data",
2944 "Delivery",
2945 "Disposition",
2946 "Described",
2947 "Driver",
2948 "DriverException",
2949 "Endpoint",
2950 "Link",
2951 "Listener",
2952 "Message",
2953 "MessageException",
2954 "Messenger",
2955 "MessengerException",
2956 "ProtonException",
2957 "Receiver",
2958 "SASL",
2959 "Sender",
2960 "Session",
2961 "SSL",
2962 "SSLDomain",
2963 "SSLSessionDetails",
2964 "SSLUnavailable",
2965 "Terminus",
2966 "Timeout",
2967 "Interrupt",
2968 "Transport",
2969 "TransportException",
2970 "char",
2971 "symbol",
2972 "timestamp",
2973 "ulong"
2974 ]
2975