o
    @Biu                     @   s  d dl mZ d dlmZmZ d dlZd dlmZ d dlZe	  d dl
Zd dlmZ d dlmZmZ d dlmZmZmZ d dlmZ d d	lmZ d d
lmZmZ d dlmZ d dlmZmZm Z m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z'm(Z( d dl)m*Z*m+Z+m,Z,m-Z- dZ.dd Z/dd Z0dd Z1dd Z2G dd de%Z3G dd dej4j#j5Z6eG dd de6e#j7Z7eG d d! d!e6e#j8Z8G d"d# d#e9Z:eG d$d% d%e:e#j;ej4j#j<Z;eG d&d' d'e:e#j=ej4j#j>Z=eeG d(d) d)e9Z?G d*d+ d+e?e7Z@G d,d- d-e?e8ZAG d.d/ d/e;ZBG d0d1 d1e=ZCedAd3d4ZDedBd7d8ZEeG d9d: d:ejFe7ZFeG d;d< d<ejGe;ZGeG d=d> d>ejHe8ZHeG d?d@ d@ejIe=ZIdS )C    )absolute_import)	b64encode	b64decodeN)implementer)	endpoints)
ITransportISSLTransport)ConnectionDoneConnectionAbortedConnectionLost)Deferred)public)_is_tls_error_maybe_tls_reason)	websocket)ConnectionRequestConnectionResponseConnectionDenyTransportDetails)protocol)IWebSocketClientAgent)peer2strtransport_channel_id)PerMessageDeflateOfferPerMessageDeflateOfferAcceptPerMessageDeflateResponsePerMessageDeflateResponseAccept)create_client_agentWebSocketAdapterProtocolWebSocketServerProtocolWebSocketClientProtocolWebSocketAdapterFactoryWebSocketServerFactoryWebSocketClientFactoryWrappingWebSocketAdapterWrappingWebSocketServerProtocolWrappingWebSocketClientProtocolWrappingWebSocketServerFactoryWrappingWebSocketClientFactorylistenWS	connectWSWampWebSocketServerProtocolWampWebSocketServerFactoryWampWebSocketClientProtocolWampWebSocketClientFactoryc                 C   s   t | S )zB
    :returns: an instance implementing IWebSocketClientAgent
    )_TwistedWebSocketClientAgentreactor r2   Z/var/www/html/Trade-python/venv/lib/python3.10/site-packages/autobahn/twisted/websocket.pyr   V   s   r   c                 C   s>   t | tjstdt| | ds| dstddS )z>
    raises a ValueError if `transport_config` is invalid
    z-'transport_config' must be a string, found {}zws://zwss://z6'transport_config' must start with 'ws://' or 'wss://'N)
isinstancesix	text_type
ValueErrorformattype
startswith)transport_configr2   r2   r3   check_transport_config]   s   
r<   c                 C   sB   t | ts	tdg d}|  D ]}||vrtd|qdS )z5
    raises a ValueError if `options` is invalid
    z'options' must be a dict)origin	protocols	useragentheadersproxyz'options' may not contain '{}'N)r4   dictr7   keysr8   )options
valid_keysactual_kr2   r2   r3   check_client_optionsq   s   
rG   c                 C   s   |j rddlm} ||j}|jd ur&||_t| |jd |jd }|S |j r;ddlm} t	| |j|j
|}|S t| |j|j
}|S )Nr   sslhostport)isSecuretwisted.internetrI   optionsForClientTLSrJ   rA   contextFactoryr   HostnameEndpointSSL4ClientEndpointrK   )r1   factoryr;   rD   rI   context_factoryendpointr2   r2   r3   _endpoint_from_config   s4   
rU   c                   @   s"   e Zd ZdZdd ZdddZdS )r/   z6
    This agent creates connections using Twisted
    c                 C   s
   || _ d S N)_reactor)selfr1   r2   r2   r3   __init__   s   
z%_TwistedWebSocketClientAgent.__init__Nc                    s   t | t| td|| jd|}|du rtn||_t| j|||}t ||}fdd  fdd}|	|  S )a-  
        Open a new connection.

        :param dict transport_config: valid transport configuration

        :param dict options: additional options for the factory

        :param protocol_class: a callable that returns an instance of
            the protocol (WebSocketClientProtocol if the default None
            is passed in)

        :returns: a Deferred that fires with an instance of
            `protocol_class` (or WebSocketClientProtocol by default)
            that has successfully shaken hands (completed the
            handshake).
        )urlr1   Nc                    s     |  d S rV   )errback)f)rtn_dr2   r3   failed      z1_TwistedWebSocketClientAgent.open.<locals>.failedc                    s     fdd} j |  S )Nc                    s      | S rV   )callback)arg)protor]   r2   r3   handshake_completed   s   
zQ_TwistedWebSocketClientAgent.open.<locals>.got_proto.<locals>.handshake_completed)is_openaddCallbacks)rb   rc   r^   r]   )rb   r3   	got_proto   s   z4_TwistedWebSocketClientAgent.open.<locals>.got_protor2   )
r<   rG   r#   rW   r    r   rU   r   connectre   )rX   r;   rD   protocol_classrR   rT   proto_drg   r2   rf   r3   open   s    
z!_TwistedWebSocketClientAgent.openrV   )__name__
__module____qualname____doc__rY   rk   r2   r2   r2   r3   r/      s    r/   c                   @   s   e Zd ZdZdZe Zdd Zdd Z	dd Z
d'd
dZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&S )(r   zJ
    Adapter class for Twisted WebSocket client and server protocols.
    z<never connected>c                 C   st   z
t | j | _W n ty   d| jj| _Y nw |   | jj	d| jd z
| j
| j W d S    Y d S )Nz
process:{}zConnection made to {peer}peer)r   	transportgetPeerrq   AttributeErrorr8   pid_connectionMadelogdebugsetTcpNoDelay
tcpNoDelayrX   r2   r2   r3   connectionMade   s   z'WebSocketAdapterProtocol.connectionMadec                 C   s   t |jtr| jjd| jd nNt|jr| jt|j n?t |jt	r/| jjd| jd n/t |jt
rOt|j}t|jdrD|jj}| jjd| j|d n| jjd| jt|j|jd | | d S )	Nz,Connection to/from {peer} was closed cleanlyrp   z-Connection to/from {peer} was aborted locallymessagezDConnection to/from {peer} was lost in a non-clean fashion: {message})rq   r}   z7Connection to/from {peer} lost ({error_type}): {error}))rq   
error_typeerror)r4   valuer	   rw   rx   rq   r   r   r   r
   r   strhasattrr}   r9   _connectionLost)rX   reasonr}   r2   r2   r3   connectionLost  s.   

z'WebSocketAdapterProtocol.connectionLostc                 C      |  | d S rV   )_dataReceivedrX   datar2   r2   r3   dataReceived"  r_   z%WebSocketAdapterProtocol.dataReceivedFc                 C   s,   |rt | jdr| j  d S | j  d S )NabortConnection)r   rr   r   loseConnection)rX   abortr2   r2   r3   _closeConnection%  s   z)WebSocketAdapterProtocol._closeConnectionc                 C      |    d S rV   )onOpenr{   r2   r2   r3   _onOpen,     z WebSocketAdapterProtocol._onOpenc                 C   r   rV   )onMessageBegin)rX   isBinaryr2   r2   r3   _onMessageBegin/  r_   z(WebSocketAdapterProtocol._onMessageBeginc                 C   r   rV   )onMessageFrameBegin)rX   lengthr2   r2   r3   _onMessageFrameBegin2  r_   z-WebSocketAdapterProtocol._onMessageFrameBeginc                 C   r   rV   )onMessageFrameDatarX   payloadr2   r2   r3   _onMessageFrameData5  r_   z,WebSocketAdapterProtocol._onMessageFrameDatac                 C   r   rV   )onMessageFrameEndr{   r2   r2   r3   _onMessageFrameEnd8  r   z+WebSocketAdapterProtocol._onMessageFrameEndc                 C   r   rV   )onMessageFramer   r2   r2   r3   _onMessageFrame;  r_   z(WebSocketAdapterProtocol._onMessageFramec                 C   r   rV   )onMessageEndr{   r2   r2   r3   _onMessageEnd>  r   z&WebSocketAdapterProtocol._onMessageEndc                 C   s   |  || d S rV   )	onMessage)rX   r   r   r2   r2   r3   
_onMessageA     z#WebSocketAdapterProtocol._onMessagec                 C   r   rV   )onPingr   r2   r2   r3   _onPingD  r_   z WebSocketAdapterProtocol._onPingc                 C   r   rV   )onPongr   r2   r2   r3   _onPongG  r_   z WebSocketAdapterProtocol._onPongc                 C   s   |  ||| d S rV   )onCloserX   wasCleancoder   r2   r2   r3   _onCloseJ  s   z!WebSocketAdapterProtocol._onClosec                 C   s   | j || dS )z
        Register a Twisted producer with this protocol.

        :param producer: A Twisted push or pull producer.
        :type producer: object
        :param streaming: Producer type.
        :type streaming: bool
        N)rr   registerProducer)rX   producer	streamingr2   r2   r3   r   M  s   	z)WebSocketAdapterProtocol.registerProducerc                 C   s   | j   dS )zA
        Unregister Twisted producer with this protocol.
        N)rr   unregisterProducerr{   r2   r2   r3   r   X     z+WebSocketAdapterProtocol.unregisterProducerN)F)rl   rm   rn   ro   rq   txaiomake_loggerrw   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r2   r2   r2   r3   r      s*    
r   c                   @   s"   e Zd ZdZe ZdddZdS )r   z
    Base class for Twisted-based WebSocket server protocols.

    Implements :class:`autobahn.websocket.interfaces.IWebSocketChannel`.
    
tls-uniquec                 C      t | jd|S )W
        Implements :func:`autobahn.wamp.interfaces.ITransport.get_channel_id`
        Tr   rr   rX   channel_id_typer2   r2   r3   get_channel_idi  r   z&WebSocketServerProtocol.get_channel_idNr   )rl   rm   rn   ro   r   r   rw   r   r2   r2   r2   r3   r   _  s    r   c                   @   s:   e Zd ZdZe Zdd Zdd ZdddZ	d	d
 Z
dS )r    z
    Base class for Twisted-based WebSocket client protocols.

    Implements :class:`autobahn.websocket.interfaces.IWebSocketChannel`.
    c                 C   r   rV   )	onConnect)rX   responser2   r2   r3   
_onConnectz  r_   z"WebSocketClientProtocol._onConnectc                 C   s    | j d | j| jj d S )NzStarting TLS upgrade)rw   rx   rr   startTLSrR   rO   r{   r2   r2   r3   r   }  s   z WebSocketClientProtocol.startTLSr   c                 C   r   )r   Fr   r   r2   r2   r3   r     r   z&WebSocketClientProtocol.get_channel_idc                 C   s8   t | j}|rdt| jddi}ni }t| j||dS )z]
        Internal helper.
        Base class calls this to create a TransportDetails
        r   F)rq   	is_securesecure_channel_id)r   
providedByrr   r   r   rq   )rX   r   r   r2   r2   r3   _create_transport_details  s   z1WebSocketClientProtocol._create_transport_detailsNr   )rl   rm   rn   ro   r   r   rw   r   r   r   r   r2   r2   r2   r3   r    p  s    
r    c                   @      e Zd ZdZdS )r!   zP
    Adapter class for Twisted-based WebSocket client and server factories.
    Nrl   rm   rn   ro   r2   r2   r2   r3   r!         r!   c                   @      e Zd ZdZdd ZdS )r"   z
    Base class for Twisted-based WebSocket server factories.

    Implements :class:`autobahn.websocket.interfaces.IWebSocketServerChannelFactory`
    c                 O   sD   | dd}|du rddlm} || _tjj| g|R i | dS )a  

        .. note::
            In addition to all arguments to the constructor of
            :meth:`autobahn.websocket.interfaces.IWebSocketServerChannelFactory`,
            you can supply a ``reactor`` keyword argument to specify the
            Twisted reactor to be used.
        r1   Nr   r0   )poprM   r1   r   r"   rY   )rX   argskwargsr1   r2   r2   r3   rY     s
   
zWebSocketServerFactory.__init__Nrl   rm   rn   ro   rY   r2   r2   r2   r3   r"         r"   c                   @   r   )r#   z
    Base class for Twisted-based WebSocket client factories.

    Implements :class:`autobahn.websocket.interfaces.IWebSocketClientChannelFactory`
    c                 O   sv   | dd}|du rddlm} || _tjj| g|R i | | jr7| jdur9ddlm} |	| j
| _dS dS dS )a  

        .. note::
            In addition to all arguments to the constructor of
            :func:`autobahn.websocket.interfaces.IWebSocketClientChannelFactory`,
            you can supply a ``reactor`` keyword argument to specify the
            Twisted reactor to be used.
        r1   Nr   r0   rH   )r   rM   r1   r   r#   rY   rL   rA   rI   rN   rJ   rO   )rX   r   r   r1   rI   r2   r2   r3   rY     s   
zWebSocketClientFactory.__init__Nr   r2   r2   r2   r3   r#     r   r#   c                   @   sX   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd ZdS )r$   a  
    An adapter for stream-based transport over WebSocket.

    This follows `websockify <https://github.com/kanaka/websockify>`_
    and should be compatible with that.

    It uses WebSocket subprotocol negotiation and supports the
    following WebSocket subprotocols:

      - ``binary`` (or a compatible subprotocol)
      - ``base64``

    Octets are either transmitted as the payload of WebSocket binary
    messages when using the ``binary`` subprotocol (or an alternative
    binary compatible subprotocol), or encoded with Base64 and then
    transmitted as the payload of WebSocket text messages when using
    the ``base64`` subprotocol.
    c                 C   s   t |tr'|}|jD ]}|| jjv r|dk| _|  S q
ttjd| jjt |t	rJ|}|j
| jjvrB| t
jjd| jj |j
dk| _d S td)Nbase64z2this server only speaks {0} WebSocket subprotocolsz2this client only speaks {0} WebSocket subprotocolszlogic error)r4   r   r>   rR   _subprotocols_binaryModer   NOT_ACCEPTABLEr8   r   r   _fail_connectionWebSocketProtocol CLOSE_STATUS_CODE_PROTOCOL_ERROR	Exception)rX   requestOrResponserequestpr   r2   r2   r3   r     s   



z"WrappingWebSocketAdapter.onConnectc                 C   s   | j   d S rV   )_protor|   r{   r2   r2   r3   r     r_   zWrappingWebSocketAdapter.onOpenc              
   C   sz   || j kr| tjjd d S |s5zt|}W n ty4 } z| tjjd| W Y d }~nd }~ww | j	
| d S )Nz>message payload type does not match the negotiated subprotocolz*message payload base64 decoding error: {0})r   r   r   r   "CLOSE_STATUS_CODE_UNSUPPORTED_DATAr   r   !CLOSE_STATUS_CODE_INVALID_PAYLOADr8   r   r   )rX   r   r   er2   r2   r3   r     s   
"z"WrappingWebSocketAdapter.onMessagec                 C   s   | j d  d S rV   )r   r   r   r2   r2   r3   r     r   z WrappingWebSocketAdapter.onClosec                 C   sB   t |tksJ | jr| j|dd d S t|}| j|dd d S )NT)r   F)r9   bytesr   sendMessager   r   r2   r2   r3   write  s
   zWrappingWebSocketAdapter.writec                 C   s   |D ]}|  | qd S rV   )r   )rX   r   dr2   r2   r3   writeSequence&  s   z&WrappingWebSocketAdapter.writeSequencec                 C   r   rV   )	sendCloser{   r2   r2   r3   r   +  s   z'WrappingWebSocketAdapter.loseConnectionc                 C   
   | j  S rV   )rr   rs   r{   r2   r2   r3   rs   /     
z WrappingWebSocketAdapter.getPeerc                 C   r   rV   )rr   getHostr{   r2   r2   r3   r   3  r   z WrappingWebSocketAdapter.getHostN)rl   rm   rn   ro   r   r   r   r   r   r   r   rs   r   r2   r2   r2   r3   r$     s    	r$   c                   @   r   )r%   zD
    Server protocol for stream-based transport over WebSocket.
    Nr   r2   r2   r2   r3   r%   8  r   r%   c                   @   r   )r&   zD
    Client protocol for stream-based transport over WebSocket.
    Nr   r2   r2   r2   r3   r&   >  r   r&   c                   @   s:   e Zd ZdZ				dddZdd Zd	d
 Zdd ZdS )r'   zL
    Wrapping server factory for stream-based transport over WebSocket.
    NTr   c                 C   sl   || _ ddg| _|r| j| tj| ||| jd | j|d | jdd |r4dd }| j|d	 d
S d
S )z

        :param factory: Stream-based factory to be wrapped.
        :type factory: A subclass of ``twisted.internet.protocol.Factory``
        :param url: WebSocket URL of the server this server factory will work for.
        :type url: unicode
        binaryr   rZ   r1   r>   autoFragmentSizeF
failByDropc                 S   s$   | D ]}t |trt|  S qd S rV   )r4   r   r   )offersofferr2   r2   r3   acceptl  s
   
z7WrappingWebSocketServerFactory.__init__.<locals>.acceptperMessageCompressionAcceptN)_factoryr   appendr"   rY   setProtocolOptions)rX   rR   rZ   r1   enableCompressionr   subprotocolr   r2   r2   r3   rY   I  s   
z'WrappingWebSocketServerFactory.__init__c                 C   &   t  }| |_| j||_||j_|S rV   )r%   rR   r   buildProtocolr   rr   rX   addrrb   r2   r2   r3   r   s  
   z,WrappingWebSocketServerFactory.buildProtocolc                 C      | j   t|  d S rV   )r   startFactoryr"   r{   r2   r2   r3   r   z     
z+WrappingWebSocketServerFactory.startFactoryc                 C   r   rV   )r   stopFactoryr"   r{   r2   r2   r3   r   ~  r   z*WrappingWebSocketServerFactory.stopFactoryNTr   N)rl   rm   rn   ro   rY   r   r   r   r2   r2   r2   r3   r'   D  s    
*r'   c                   @   s*   e Zd ZdZ				d	ddZdd ZdS )
r(   zL
    Wrapping client factory for stream-based transport over WebSocket.
    NTr   c           	      C   s   || _ ddg| _|r| j| tj| ||| jd | j|d | jdd |r>t g}| j|d dd	 }| j|d
 dS dS )a  

        :param factory: Stream-based factory to be wrapped.
        :type factory: A subclass of ``twisted.internet.protocol.Factory``
        :param url: WebSocket URL of the server this client factory will connect to.
        :type url: unicode
        r   r   r   r   Fr   )perMessageCompressionOffersc                 S   s   t | tr	t| S d S rV   )r4   r   r   )r   r2   r2   r3   r     s   
z7WrappingWebSocketClientFactory.__init__.<locals>.acceptr   N)r   r   r   r#   rY   r   r   )	rX   rR   rZ   r1   r   r   r   r   r   r2   r2   r3   rY     s"   
z'WrappingWebSocketClientFactory.__init__c                 C   r   rV   )r&   rR   r   r   r   rr   r   r2   r2   r3   r     r   z,WrappingWebSocketClientFactory.buildProtocolr   )rl   rm   rn   ro   rY   r   r2   r2   r2   r3   r(     s    
-r(      c                 C   s   t | dr	| j}nddlm} | jr |du r ddlm} | }| jdur9|| _|| jd | jd | ||}|S | jrJ|	| j
| j| |||}|S || j
| j| ||}|S )a  
    Establish WebSocket connection to a server. The connection parameters like target
    host, port, resource and others are provided via the factory.

    :param factory: The WebSocket protocol factory to be used for creating client protocol instances.
    :type factory: An :class:`autobahn.websocket.WebSocketClientFactory` instance.

    :param contextFactory: SSL context factory, required for secure WebSocket connections ("wss").
    :type contextFactory: A `twisted.internet.ssl.ClientContextFactory <http://twistedmatrix.com/documents/current/api/twisted.internet.ssl.ClientContextFactory.html>`_ instance.

    :param timeout: Number of seconds to wait before assuming the connection has failed.
    :type timeout: int

    :param bindAddress: A (host, port) tuple of local address to bind to, or None.
    :type bindAddress: tuple

    :returns: The connector.
    :rtype: An object which implements `twisted.interface.IConnector <http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IConnector.html>`_.
    r1   r   r0   NrH   rJ   rK   )r   r1   rM   rL   rI   ClientContextFactoryrA   rO   
connectTCP
connectSSLrJ   rK   )rR   rO   timeoutbindAddressr1   rI   connr2   r2   r3   r*     s    

r*   2    c                 C   sb   t | dr	| j}nddlm} | jr&|du rtd|| j| |||}|S || j| ||}|S )a  
    Listen for incoming WebSocket connections from clients. The connection parameters like
    listening port and others are provided via the factory.

    :param factory: The WebSocket protocol factory to be used for creating server protocol instances.
    :type factory: An :class:`autobahn.websocket.WebSocketServerFactory` instance.

    :param contextFactory: SSL context factory, required for secure WebSocket connections ("wss").
    :type contextFactory: A twisted.internet.ssl.ContextFactory.

    :param backlog: Size of the listen queue.
    :type backlog: int

    :param interface: The interface (derived from hostname given) to bind to, defaults to '' (all).
    :type interface: str

    :returns: The listening port.
    :rtype: An object that implements `twisted.interface.IListeningPort <http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IListeningPort.html>`_.
    r1   r   r0   NzCSecure WebSocket listen requested, but no SSL context factory given)r   r1   rM   rL   r   	listenSSLrK   	listenTCP)rR   rO   backlog	interfacer1   listenerr2   r2   r3   r)     s   
r)   c                   @   r   )r+   z
    Twisted-based WAMP-over-WebSocket server protocol.

    Implements:

    * :class:`autobahn.wamp.interfaces.ITransport`
    Nr   r2   r2   r2   r3   r+         r+   c                   @      e Zd ZdZeZdd ZdS )r,   zD
    Twisted-based WAMP-over-WebSocket server protocol factory.
    c                 O   B   | dd}tj| || | j|d< tj| g|R i | dS )a  

        :param factory: A callable that produces instances that implement
            :class:`autobahn.wamp.interfaces.ITransportHandler`
        :type factory: callable

        :param serializers: A list of WAMP serializers to use (or ``None``
            for all available serializers).
        :type serializers: list of objects implementing
            :class:`autobahn.wamp.interfaces.ISerializer`
        serializersNr>   )r   r   r,   rY   
_protocolsr"   rX   rR   r   r   r  r2   r2   r3   rY      s   
z#WampWebSocketServerFactory.__init__N)rl   rm   rn   ro   r+   r   rY   r2   r2   r2   r3   r,         r,   c                   @   r   )r-   z
    Twisted-based WAMP-over-WebSocket client protocol.

    Implements:

    * :class:`autobahn.wamp.interfaces.ITransport`
    Nr   r2   r2   r2   r3   r-   7  r  r-   c                   @   r  )r.   zD
    Twisted-based WAMP-over-WebSocket client protocol factory.
    c                 O   r  )a  

        :param factory: A callable that produces instances that implement
            :class:`autobahn.wamp.interfaces.ITransportHandler`
        :type factory: callable

        :param serializer: The WAMP serializer to use (or ``None`` for
           "best" serializer, chosen as the first serializer available from
           this list: CBOR, MessagePack, UBJSON, JSON).
        :type serializer: object implementing :class:`autobahn.wamp.interfaces.ISerializer`
        r  Nr>   )r   r   r.   rY   r  r#   r  r2   r2   r3   rY   J  s   
z#WampWebSocketClientFactory.__init__N)rl   rm   rn   ro   r-   r   rY   r2   r2   r2   r3   r.   B  r  r.   )Nr  N)Nr	  r
  )J
__future__r   r   r   r   r5   zope.interfacer   r   use_twistedtwisted.internet.protocoltwistedrM   r   twisted.internet.interfacesr   r   twisted.internet.errorr	   r
   r   twisted.internet.deferr   autobahn.utilr   r   r   autobahn.wampr   autobahn.websocket.typesr   r   r   r   autobahn.websocketr   autobahn.websocket.interfacesr   autobahn.twisted.utilr   r   autobahn.websocket.compressr   r   r   r   __all__r   r<   rG   rU   r/   internetProtocolr   r   r    objectr!   r"   ServerFactoryr#   ClientFactoryr$   r%   r&   r'   r(   r*   r)   r+   r,   r-   r.   r2   r2   r2   r3   <module>   sj   )7u+'S?:+#

