%PDF- %PDF-
Direktori : /lib/python3/dist-packages/twisted/protocols/__pycache__/ |
Current File : //lib/python3/dist-packages/twisted/protocols/__pycache__/amp.cpython-312.pyc |
� Ϫ�f�z � �� � d Z ddlmZ ddlZddlZddlZddlmZ ddlm Z ddl mZ ddlm Z ddlmZ dd lmZmZmZmZmZmZmZmZmZmZ dd lmZmZ ddlmZm Z m!Z! ddl"m#Z#m$Z$m%Z% dd l&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0m1Z1 ddl2m3Z4m5Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z? e?j� r ddlAmBZBmCZCmDZDmEZE ndZ>e?Z>g d�ZG ededeHf �� ZIdZJdZKdZLdZMd ZNd!ZOd"ZPd#ZQd$ZRd%ZS G d&� d'e� ZT G d(� d)e� ZU G d*� d+e� ZV G d,� d-e� ZW G d.� d/eX� ZY G d0� d1eX� ZZ G d2� d3eY� Z[ G d4� d5eY� Z\ G d6� d7eY� Z] G d8� d9eY� Z^ G d:� d;eY� Z_ G d<� d=eY� Z` G d>� d?e`� Za G d@� dAeY� Zb G dB� dCeY� Zc G dD� dEeY� ZdeQeciZe G dF� dGeefeff � ZgegZh G dH� dIeg� Zi G dJ� dKeg� Zj eeV� G dL� dM� � Zk G dN� dOel� Zm eeW� G dP� dQem�R� � Zn eeW� G dS� dT� � Zog dU�ZpdV� Zq eeT� G dW� dX� � Zr G dY� dZer� Zs G d[� d\er� Zt G d]� d^er� Zu G d_� d`er� Zv G da� dbet� Zw G dc� ddew� Zx G de� dfer� Zy G dg� dher� Zz G di� djes� Z{ edk� Z| G dl� dmel� Z} G dn� doe}�R� Z~ G dp� dq� Z G dr� dseg� Z� G dt� duet� Z� G dv� dwe~� Z� G dx� dye~� Z� ee'� G dz� d{� � Z� eeU� G d|� d}e.e-e�� � Z� G d~� de�ekeneo� Z� G d�� d�� Z�e��j Z�e��j Z�d�� Z�d�� Z� G d�� d�er� Z� G d�� d�er� Z�y# eF$ r dZ>Y ���w xY w)�a� This module implements AMP, the Asynchronous Messaging Protocol. AMP is a protocol for sending multiple asynchronous request/response pairs over the same connection. Requests and responses are both collections of key/value pairs. AMP is a very simple protocol which is not an application. This module is a "protocol construction kit" of sorts; it attempts to be the simplest wire-level implementation of Deferreds. AMP provides the following base-level features: - Asynchronous request/response handling (hence the name) - Requests and responses are both key/value pairs - Binary transfer of all data: all data is length-prefixed. Your application will never need to worry about quoting. - Command dispatching (like HTTP Verbs): the protocol is extensible, and multiple AMP sub-protocols can be grouped together easily. The protocol implementation also provides a few additional features which are not part of the core wire protocol, but are nevertheless very useful: - Tight TLS integration, with an included StartTLS command. - Handshaking to other protocols: because AMP has well-defined message boundaries and maintains all incoming and outgoing requests for you, you can start a connection over AMP and then switch to another protocol. This makes it ideal for firewall-traversal applications where you may have only one forwarded port but multiple applications that want to use it. Using AMP with Twisted is simple. Each message is a command, with a response. You begin by defining a command type. Commands specify their input and output in terms of the types that they expect to see in the request and response key-value pairs. Here's an example of a command that adds two integers, 'a' and 'b':: class Sum(amp.Command): arguments = [('a', amp.Integer()), ('b', amp.Integer())] response = [('total', amp.Integer())] Once you have specified a command, you need to make it part of a protocol, and define a responder for it. Here's a 'JustSum' protocol that includes a responder for our 'Sum' command:: class JustSum(amp.AMP): def sum(self, a, b): total = a + b print 'Did a sum: %d + %d = %d' % (a, b, total) return {'total': total} Sum.responder(sum) Later, when you want to actually do a sum, the following expression will return a L{Deferred} which will fire with the result:: ClientCreator(reactor, amp.AMP).connectTCP(...).addCallback( lambda p: p.callRemote(Sum, a=13, b=81)).addCallback( lambda result: result['total']) Command responders may also return Deferreds, causing the response to be sent only once the Deferred fires:: class DelayedSum(amp.AMP): def slowSum(self, a, b): total = a + b result = defer.Deferred() reactor.callLater(3, result.callback, {'total': total}) return result Sum.responder(slowSum) This is transparent to the caller. You can also define the propagation of specific errors in AMP. For example, for the slightly more complicated case of division, we might have to deal with division by zero:: class Divide(amp.Command): arguments = [('numerator', amp.Integer()), ('denominator', amp.Integer())] response = [('result', amp.Float())] errors = {ZeroDivisionError: 'ZERO_DIVISION'} The 'errors' mapping here tells AMP that if a responder to Divide emits a L{ZeroDivisionError}, then the other side should be informed that an error of the type 'ZERO_DIVISION' has occurred. Writing a responder which takes advantage of this is very simple - just raise your exception normally:: class JustDivide(amp.AMP): def divide(self, numerator, denominator): result = numerator / denominator print 'Divided: %d / %d = %d' % (numerator, denominator, total) return {'result': result} Divide.responder(divide) On the client side, the errors mapping will be used to determine what the 'ZERO_DIVISION' error means, and translated into an asynchronous exception, which can be handled normally as any L{Deferred} would be:: def trapZero(result): result.trap(ZeroDivisionError) print "Divided by zero: returning INF" return 1e1000 ClientCreator(reactor, amp.AMP).connectTCP(...).addCallback( lambda p: p.callRemote(Divide, numerator=1234, denominator=0) ).addErrback(trapZero) For a complete, runnable example of both of these commands, see the files in the Twisted repository:: doc/core/examples/ampserver.py doc/core/examples/ampclient.py On the wire, AMP is a protocol which uses 2-byte lengths to prefix keys and values, and empty keys to separate messages:: <2-byte length><key><2-byte length><value> <2-byte length><key><2-byte length><value> ... <2-byte length><key><2-byte length><value> <NUL><NUL> # Empty Key == End of Message And so on. Because it's tedious to refer to lengths and NULs constantly, the documentation will refer to packets as if they were newline delimited, like so:: C: _command: sum C: _ask: ef639e5c892ccb54 C: a: 13 C: b: 81 S: _answer: ef639e5c892ccb54 S: total: 94 Notes: In general, the order of keys is arbitrary. Specific uses of AMP may impose an ordering requirement, but unless this is specified explicitly, any ordering may be generated and any ordering must be accepted. This applies to the command-related keys I{_command} and I{_ask} as well as any other keys. Values are limited to the maximum encodable size in a 16-bit length, 65535 bytes. Keys are limited to the maximum encodable size in a 8-bit length, 255 bytes. Note that we still use 2-byte lengths to encode keys. This small redundancy has several features: - If an implementation becomes confused and starts emitting corrupt data, or gets keys confused with values, many common errors will be signalled immediately instead of delivering obviously corrupt packets. - A single NUL will separate every key, and a double NUL separates messages. This provides some redundancy when debugging traffic dumps. - NULs will be present at regular intervals along the protocol, providing some padding for otherwise braindead C implementations of the protocol, so that <stdio.h> string functions will see the NUL and stop. - This makes it possible to run an AMP server on a port also used by a plain-text protocol, and easily distinguish between non-AMP clients (like web browsers) which issue non-NUL as the first byte, and AMP clients, which always issue NUL as the first byte. @var MAX_VALUE_LENGTH: The maximum length of a message. @type MAX_VALUE_LENGTH: L{int} @var ASK: Marker for an Ask packet. @type ASK: L{bytes} @var ANSWER: Marker for an Answer packet. @type ANSWER: L{bytes} @var COMMAND: Marker for a Command packet. @type COMMAND: L{bytes} @var ERROR: Marker for an AMP box of error type. @type ERROR: L{bytes} @var ERROR_CODE: Marker for an AMP box containing the code of an error. @type ERROR_CODE: L{bytes} @var ERROR_DESCRIPTION: Marker for an AMP box containing the description of the error. @type ERROR_DESCRIPTION: L{bytes} � )�annotationsN)�partial)�BytesIO)�count)�pack)� MethodType) �Any�Callable�ClassVar�Dict�List�Optional�Tuple�Type�TypeVar�Union)� Interface�implementer)�Deferred�fail� maybeDeferred)�ConnectionClosed�ConnectionLost�PeerVerifyError)�IFileDescriptorReceiver)�CONNECTION_LOST)�Protocol)�Int16StringReceiver�StatefulStringProtocol)�filepath�log)�UTC�FixedOffsetTimeZone)�nativeString)�Failure)�accumulateClassDict)�ssl)�DN�Certificate�CertificateOptions�KeyPair)5�AMP�ANSWER�ASK�AmpBox�AmpError�AmpList�Argument�BadLocalReturn�BinaryBoxProtocol�Boolean�Box� BoxDispatcher�COMMAND�Command�CommandLocator�Decimal� Descriptor�ERROR� ERROR_CODE�ERROR_DESCRIPTION�Float� IArgumentType�IBoxReceiver� IBoxSender�IResponderLocator�IncompatibleVersions�Integer�InvalidSignature�ListOf�MAX_KEY_LENGTH�MAX_VALUE_LENGTH�MalformedAmpBox�NoEmptyBoxes� OnlyOneTLS�PROTOCOL_ERRORS�PYTHON_KEYWORDS�Path�ProtocolSwitchCommand�ProtocolSwitched�QuitBox�RemoteAmpError�SimpleStringLocator�StartTLS�String�TooLong�UNHANDLED_ERROR_CODE�UNKNOWN_ERROR_CODE�UnhandledCommand�utc�Unicode�UnknownRemoteError�parse�parseString�_T_Callable.)�bounds _asks _answers _commands _errors _error_codes _error_descriptions UNKNOWNs UNHANDLED� � c � � e Zd ZdZd� Zd� Zy)rA z� An L{IArgumentType} can serialize a Python object into an AMP box and deserialize information from an AMP box back into a Python object. @since: 9.0 c � � y)a Given an argument name and an AMP box containing serialized values, extract one or more Python objects and add them to the C{objects} dictionary. @param name: The name associated with this argument. Most commonly this is the key which can be used to find a serialized value in C{strings}. @type name: C{bytes} @param strings: The AMP box from which to extract one or more values. @type strings: C{dict} @param objects: The output dictionary to populate with the value for this argument. The key used will be derived from C{name}. It may differ; in Python 3, for example, the key will be a Unicode/native string. See L{_wireNameToPythonIdentifier}. @type objects: C{dict} @param proto: The protocol instance which received the AMP box being interpreted. Most likely this is an instance of L{AMP}, but this is not guaranteed. @return: L{None} N� ��name�strings�objects�protos �7/usr/lib/python3/dist-packages/twisted/protocols/amp.py�fromBoxzIArgumentType.fromBoxI � � � c � � y)a= Given an argument name and a dictionary containing structured Python objects, serialize values into one or more strings and add them to the C{strings} dictionary. @param name: The name associated with this argument. Most commonly this is the key in C{strings} to associate with a C{bytes} giving the serialized form of that object. @type name: C{bytes} @param strings: The AMP box into which to insert one or more strings. @type strings: C{dict} @param objects: The input dictionary from which to extract Python objects to serialize. The key used will be derived from C{name}. It may differ; in Python 3, for example, the key will be a Unicode/native string. See L{_wireNameToPythonIdentifier}. @type objects: C{dict} @param proto: The protocol instance which will send the AMP box once it is fully populated. Most likely this is an instance of L{AMP}, but this is not guaranteed. @return: L{None} Nrg rh s rm �toBoxzIArgumentType.toBoxe ro rp N)�__name__� __module__�__qualname__�__doc__rn rr rg rp rm rA rA A s � ���8rp rA c � � e Zd ZdZd� Zd� Zy)rC z7 A transport which can send L{AmpBox} objects. c � � y)z� Send an L{AmpBox}. @raise ProtocolSwitched: if the underlying protocol has been switched. @raise ConnectionLost: if the underlying connection has already been lost. Nrg ��boxs rm �sendBoxzIBoxSender.sendBox� ro rp c � � y)z� An unhandled error occurred in response to a box. Log it appropriately. @param failure: a L{Failure} describing the error that occurred. Nrg )�failures rm �unhandledErrorzIBoxSender.unhandledError� ro rp N)rs rt ru rv r{ r~ rg rp rm rC rC � s � �� �rp rC c �"