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 LANGUAGE = "C"
100
102 """
103 The root of the proton exception hierarchy. All proton exception
104 classes derive from this exception.
105 """
106 pass
107
109 """
110 A timeout exception indicates that a blocking operation has timed
111 out.
112 """
113 pass
114
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
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")
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
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
221 if hasattr(self, "_mng"):
222 pn_messenger_free(self._mng)
223 del self._mng
224
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
234 """
235 The name of the L{Messenger}.
236 """
237 return pn_messenger_name(self._mng)
238
240 return pn_messenger_get_certificate(self._mng)
241
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
256 return pn_messenger_get_private_key(self._mng)
257
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
271 return pn_messenger_get_password(self._mng)
272
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
283 return pn_messenger_get_trusted_certificates(self._mng)
284
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
297 return pn_messenger_get_timeout(self._mng)
298
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
309 return pn_messenger_get_incoming_window(self._mng)
310
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
322 return pn_messenger_get_outgoing_window(self._mng)
323
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
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
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
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
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
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
480 """
481 The outgoing queue depth.
482 """
483 return pn_messenger_outgoing(self._mng)
484
485 @property
487 """
488 The incoming queue depth.
489 """
490 return pn_messenger_incoming(self._mng)
491
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
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
523 if hasattr(self, "_msg"):
524 pn_message_free(self._msg)
525 del self._msg
526
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
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
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
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
589 return pn_message_is_inferred(self._msg)
590
592 self._check(pn_message_set_inferred(self._msg, bool(value)))
593
594 inferred = property(_is_inferred, _set_inferred)
595
597 return pn_message_is_durable(self._msg)
598
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
609 return pn_message_get_priority(self._msg)
610
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
620 return pn_message_get_ttl(self._msg)
621
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
632 return pn_message_is_first_acquirer(self._msg)
633
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
643 return pn_message_get_delivery_count(self._msg)
644
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
661 id = property(_get_id, _set_id,
662 doc="""
663 The id of the message.
664 """)
665
667 return pn_message_get_user_id(self._msg)
668
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
678 return pn_message_get_address(self._msg)
679
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
689 return pn_message_get_subject(self._msg)
690
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
700 return pn_message_get_reply_to(self._msg)
701
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
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
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
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
746 return pn_message_get_expiry_time(self._msg)
747
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
757 return pn_message_get_creation_time(self._msg)
758
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
768 return pn_message_get_group_id(self._msg)
769
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
779 return pn_message_get_group_sequence(self._msg)
780
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
790 return pn_message_get_reply_to_group_id(self._msg)
791
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
803
806
807 format = property(_get_format, _set_format,
808 doc="""
809 The format of the message.
810 """)
811
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
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
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
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
850
853
855 return "UnmappedType(%s)" % self.msg
856
858
860 return "ulong(%s)" % long.__repr__(self)
861
863
865 return "timestamp(%s)" % long.__repr__(self)
866
868
870 return "symbol(%s)" % unicode.__repr__(self)
871
872 -class char(unicode):
873
875 return "char(%s)" % unicode.__repr__(self)
876
878
880 self.descriptor = descriptor
881 self.value = value
882
884 return "Described(%r, %r)" % (self.descriptor, self.value)
885
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")
895
896 - def __init__(self, descriptor, type, *elements):
897 self.descriptor = descriptor
898 self.type = type
899 self.elements = elements
900
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
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
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
1023
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
1033 if self._free and hasattr(self, "_data"):
1034 pn_data_free(self._data)
1035 del self._data
1036
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
1045 """
1046 Clears the data object.
1047 """
1048 pn_data_clear(self._data)
1049
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
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
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
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
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
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
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
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
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
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
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
1208 """
1209 Puts a null value.
1210 """
1211 self._check(pn_data_put_null(self._data))
1212
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1451 """
1452 Checks if the current node is a null.
1453 """
1454 self._check(pn_data_get_null(self._data))
1455
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1582 """
1583 If the current node is binary, returns its value, returns ""
1584 otherwise.
1585 """
1586 return pn_data_get_binary(self._data)
1587
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
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
1615
1617 pn_data_dump(self._data)
1618
1628
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
1652
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
1673
1682
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
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
1767 putter = self.put_mappings[obj.__class__]
1768 putter(self, obj)
1769
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
1781
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
1792 self.condition = None
1793
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
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
1818
1819 - def __init__(self, name, description=None, info=None):
1820 self.name = name
1821 self.description = description
1822 self.info = info
1823
1825 return "Condition(%s)" % ", ".join([repr(x) for x in
1826 (self.name, self.description, self.info)
1827 if x])
1828
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
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
1843
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
1855 if hasattr(self, "_conn"):
1856 pn_connection_free(self._conn)
1857 del self._conn
1858
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
1867 return pn_connection_condition(self._conn)
1868
1870 return pn_connection_remote_condition(self._conn)
1871
1873 return pn_connection_get_container(self._conn)
1875 return pn_connection_set_container(self._conn, name)
1876
1877 container = property(_get_container, _set_container)
1878
1880 return pn_connection_get_hostname(self._conn)
1882 return pn_connection_set_hostname(self._conn, name)
1883
1884 hostname = property(_get_hostname, _set_hostname)
1885
1886 @property
1888 return pn_connection_remote_container(self._conn)
1889
1890 @property
1892 return pn_connection_remote_hostname(self._conn)
1893
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
1914
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
1923 self._update_cond()
1924 pn_connection_close(self._conn)
1925
1926 @property
1928 return pn_connection_state(self._conn)
1929
1930 @property
1932 return pn_connection_writable(self._conn)
1933
1935 return wrap_session(pn_session(self._conn))
1936
1938 return wrap_session(pn_session_head(self._conn, mask))
1939
1941 return wrap_link(pn_link_head(self._conn, mask))
1942
1943 @property
1945 return wrap_delivery(pn_work_head(self._conn))
1946
1947 @property
1949 return pn_error_code(pn_connection_error(self._conn))
1950
1953
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
1965
1969
1971 if hasattr(self, "_ssn"):
1972 pn_session_free(self._ssn)
1973 del self._ssn
1974
1976 return pn_session_condition(self._ssn)
1977
1979 return pn_session_remote_condition(self._ssn)
1980
1982 pn_session_open(self._ssn)
1983
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
1993 return pn_session_state(self._ssn)
1994
1995 @property
1997 return wrap_connection(pn_session_connection(self._ssn))
1998
2000 return wrap_link(pn_sender(self._ssn, name))
2001
2003 return wrap_link(pn_receiver(self._ssn, name))
2004
2007
2009 if link is None: return None
2010 ctx = pn_link_get_context(link)
2011 if ctx:
2012 return ctx
2013 else:
2014 if pn_link_is_sender(link):
2015 wrapper = Sender(link)
2016 else:
2017 wrapper = Receiver(link)
2018 pn_link_set_context(link, wrapper)
2019 return wrapper
2020
2021 -class Link(Endpoint):
2022
2026
2028 if hasattr(self, "_link"):
2029 pn_link_free(self._link)
2030 del self._link
2031
2033 if err < 0:
2034 exc = EXCEPTIONS.get(err, LinkException)
2035 raise exc("[%s]: %s" % (err, pn_link_error(self._link)))
2036 else:
2037 return err
2038
2040 return pn_link_condition(self._link)
2041
2043 return pn_link_remote_condition(self._link)
2044
2046 pn_link_open(self._link)
2047
2049 self._update_cond()
2050 pn_link_close(self._link)
2051
2052 @property
2054 return pn_link_state(self._link)
2055
2056 @property
2058 return Terminus(pn_link_source(self._link))
2059
2060 @property
2062 return Terminus(pn_link_target(self._link))
2063
2064 @property
2066 return Terminus(pn_link_remote_source(self._link))
2067 @property
2069 return Terminus(pn_link_remote_target(self._link))
2070
2071 @property
2073 return wrap_session(pn_link_session(self._link))
2074
2076 return wrap_delivery(pn_delivery(self._link, tag))
2077
2078 @property
2080 return wrap_delivery(pn_link_current(self._link))
2081
2083 return pn_link_advance(self._link)
2084
2085 @property
2087 return pn_link_unsettled(self._link)
2088
2089 @property
2091 return pn_link_credit(self._link)
2092
2093 @property
2095 return pn_link_available(self._link)
2096
2097 @property
2099 return pn_link_queued(self._link)
2100
2101 - def next(self, mask):
2102 return wrap_link(pn_link_next(self._link, mask))
2103
2104 @property
2106 return pn_link_is_sender(self._link)
2107
2108 @property
2110 return pn_link_is_receiver(self._link)
2111
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
2126
2128 if err < 0:
2129 exc = EXCEPTIONS.get(err, LinkException)
2130 raise exc("[%s]" % err)
2131 else:
2132 return err
2133
2135 return pn_terminus_get_type(self._impl)
2137 self._check(pn_terminus_set_type(self._impl, type))
2138 type = property(_get_type, _set_type)
2139
2141 return pn_terminus_get_address(self._impl)
2143 self._check(pn_terminus_set_address(self._impl, address))
2144 address = property(_get_address, _set_address)
2145
2147 return pn_terminus_get_durability(self._impl)
2149 self._check(pn_terminus_set_durability(self._impl, seconds))
2150 durability = property(_get_durability, _set_durability)
2151
2153 return pn_terminus_get_expiry_policy(self._impl)
2155 self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
2156 expiry_policy = property(_get_expiry_policy, _set_expiry_policy)
2157
2159 return pn_terminus_get_timeout(self._impl)
2161 self._check(pn_terminus_set_timeout(self._impl, seconds))
2162 timeout = property(_get_timeout, _set_timeout)
2163
2165 return pn_terminus_is_dynamic(self._impl)
2167 self._check(pn_terminus_set_dynamic(self._impl, dynamic))
2168 dynamic = property(_is_dynamic, _set_dynamic)
2169
2170 @property
2172 return Data(pn_terminus_properties(self._impl))
2173
2174 @property
2176 return Data(pn_terminus_capabilities(self._impl))
2177
2178 @property
2180 return Data(pn_terminus_outcomes(self._impl))
2181
2182 @property
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
2191
2193 pn_link_offered(self._link, n)
2194
2195 - def send(self, bytes):
2196 return self._check(pn_link_send(self._link, bytes))
2197
2199 pn_link_drained(self._link)
2200
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
2215 pn_link_drain(self._link, n)
2216
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
2226
2227 ACCEPTED = PN_ACCEPTED
2228
2231
2232 @property
2234 return pn_delivery_tag(self._dlv)
2235
2236 @property
2238 return pn_delivery_writable(self._dlv)
2239
2240 @property
2242 return pn_delivery_readable(self._dlv)
2243
2244 @property
2246 return pn_delivery_updated(self._dlv)
2247
2249 pn_delivery_update(self._dlv, state)
2250
2251 @property
2253 return pn_delivery_local_state(self._dlv)
2254
2255 @property
2257 return pn_delivery_remote_state(self._dlv)
2258
2259 @property
2261 return pn_delivery_settled(self._dlv)
2262
2264 pn_delivery_settle(self._dlv)
2265
2266 @property
2268 return wrap_delivery(pn_work_next(self._dlv))
2269
2270 @property
2272 return wrap_link(pn_delivery_link(self._dlv))
2273
2277
2279
2280 TRACE_DRV = PN_TRACE_DRV
2281 TRACE_FRM = PN_TRACE_FRM
2282 TRACE_RAW = PN_TRACE_RAW
2283
2285 if not _trans:
2286 self._trans = pn_transport()
2287 else:
2288 self._shared_trans = True
2289 self._trans = _trans
2290
2292 if hasattr(self, "_trans"):
2293 if not hasattr(self, "_shared_trans"):
2294 pn_transport_free(self._trans)
2295 del self._trans
2296
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
2308 pn_transport_trace(self._trans, n)
2309
2310 - def tick(self, now):
2311 return pn_transport_tick(self._trans, now)
2312
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
2327
2328
2330 return pn_transport_get_max_frame(self._trans)
2331
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
2342 return pn_transport_get_remote_max_frame(self._trans)
2343
2344
2346 return pn_transport_get_idle_timeout(self._trans)
2347
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
2358 return pn_transport_get_remote_idle_timeout(self._trans)
2359
2360 @property
2362 return pn_transport_get_frames_output(self._trans)
2363
2364 @property
2367
2370
2371 -class SASL(object):
2372
2373 OK = PN_SASL_OK
2374 AUTH = PN_SASL_AUTH
2375
2378
2380 if err < 0:
2381 exc = EXCEPTIONS.get(err, SASLException)
2382 raise exc("[%s]" % (err))
2383 else:
2384 return err
2385
2387 pn_sasl_mechanisms(self._sasl, mechs)
2388
2390 pn_sasl_client(self._sasl)
2391
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
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
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
2433 return pn_sasl_state(self._sasl)
2434
2438
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
2475 return self._check( pn_ssl_domain_allow_unsecured_client(self._domain) )
2476
2478
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
2496 rc, name = pn_ssl_get_cipher_name( self._ssl, 128 )
2497 if rc:
2498 return name
2499 return None
2500
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
2512 return pn_ssl_resume_status( self._ssl )
2513
2515 self._check(pn_ssl_set_peer_hostname( self._ssl, hostname ))
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
2527 """ Unique identifier for the SSL session. Used to resume previous session on a new
2528 SSL connection.
2529 """
2530
2532 self._session_id = session_id
2533
2535 return self._session_id
2536
2543 """
2544 The DriverException class is the root of the driver exception hierarchy.
2545 """
2546 pass
2547
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
2560
2562 return wrap_connector(pn_connector_next(self._cxtr))
2563
2565 pn_connector_process(self._cxtr)
2566
2568 return wrap_listener(pn_connector_listener(self._cxtr))
2569
2576
2577 @property
2579 trans = pn_connector_transport(self._cxtr)
2580 if trans:
2581 return Transport(trans)
2582 return None
2583
2585 return pn_connector_close(self._cxtr)
2586
2587 @property
2589 return pn_connector_closed(self._cxtr)
2590
2592 return wrap_connection(pn_connector_connection(self._cxtr))
2593
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
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
2613
2615 return wrap_listener(pn_listener_next(self._lsnr))
2616
2618 cxtr = pn_listener_accept(self._lsnr)
2619 return wrap_connector(cxtr)
2620
2622 pn_listener_close(self._lsnr)
2623
2626 self._driver = pn_driver()
2627
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
2637 return pn_driver_wakeup(self._driver)
2638
2640 return wrap_listener(pn_listener(self._driver, host, port, None))
2641
2643 return wrap_listener(pn_driver_listener(self._driver))
2644
2646 return wrap_listener(pn_listener_head(self._driver))
2647
2649 return wrap_connector(pn_connector(self._driver, host, port, None))
2650
2652 return wrap_connector(pn_connector_head(self._driver))
2653
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