U
    
W[4                     @   s  d Z ddlmZmZ ddlZddlZzddlZW n ek
rL   ddlZY nX ddl	Z	ddl
Z
ddlmZmZ ddlmZ ddlmZ i ZzddlZW n ek
r   dZY nX edksejejkrejZnG dd dejejZd	d
 Zdd Zdd Zeejee dd Zdd Zeejee dd Zdd Zeejee dd Zdd Z dd Z!dd Z"zddl#m$Z$m%Z%m&Z' W n" ek
r   dd l(m&Z' Y nX ee%ee  ee$e!e" G d!d" d"Z)i a*i a+d#d$ Z,d%d& Z-d'd( Z.G d)d* d*Z/dS )+z(
Different styles of persisted objects.
    )divisionabsolute_importN)_PY3_PYPY)log)reflectc                   @   s   e Zd ZdZdS )_UniversalPicklingErrorzz
        A PicklingError catchable by both L{cPickle.PicklingError} and
        L{pickle.PicklingError} handlers.
        N)__name__
__module____qualname____doc__ r   r   :/usr/lib/python3/dist-packages/twisted/persisted/styles.pyr   &   s   r   c                 C   s4   t rt| j| j| jjffS t| jj| j| jffS dS )z3support function for copy_reg to pickle method refsN)r   unpickleMethodr	   __self__	__class__im_funcim_selfim_class)methodr   r   r   pickleMethod1   s    r   c                 C   s   t | |}tr|S |jS )a  
    Retrieve the function object implementing a method name given the class
    it's on and a method name.

    @param classObject: A class to retrieve the method's function from.
    @type classObject: L{type} or L{types.ClassType}

    @param methodName: The name of the method whose function to retrieve.
    @type methodName: native L{str}

    @return: the function object corresponding to the given method name.
    @rtype: L{types.FunctionType}
    )getattrr   r   )ZclassObjectZ
methodNameZmethodObjectr   r   r   _methodFunction>   s    
r   c              	   C   s   |dkrt || S zt|| }W nN tk
rn   td| d| |dk	sPtd|j|kr\ t| ||j Y S X trzd}n
t	|g}t
j||f| }|S dS )ai  
    Support function for copy_reg to unpickle method refs.

    @param im_name: The name of the method.
    @type im_name: native L{str}

    @param im_self: The instance that the method was present on.
    @type im_self: L{object}

    @param im_class: The class where the method was declared.
    @type im_class: L{types.ClassType} or L{type} or L{None}
    NZMethodznot on classz'No recourse: no instance to guess from.r   )r   r   AttributeErrorr   msgAssertionErrorr   r   r   tupletypes
MethodType)Zim_namer   r   ZmethodFunctionZ
maybeClassZboundr   r   r   r   S   s    


r   c                 C   s4   | j dkrtd| ttd| j| jggfS )a  
    Reduce, in the sense of L{pickle}'s C{object.__reduce__} special method, a
    function object into its constituent parts.

    @param f: The function to reduce.
    @type f: L{types.FunctionType}

    @return: a 2-tuple of a reference to L{_unpickleFunction} and a tuple of
        its arguments, a 1-tuple of the function's fully qualified name.
    @rtype: 2-tuple of C{callable, native string}
    z<lambda>z!Cannot pickle lambda function: {}.)r	   r   format_unpickleFunctionr   joinr
   r   )fr   r   r   _pickleFunctiony   s    
r$   c                 C   s   ddl m} || S )a  
    Convert a function name into a function by importing it.

    This is a synonym for L{twisted.python.reflect.namedAny}, but imported
    locally to avoid circular imports, and also to provide a persistent name
    that can be stored (and deprecated) independently of C{namedAny}.

    @param fullyQualifiedName: The fully qualified name of a function.
    @type fullyQualifiedName: native C{str}

    @return: A function object imported from the given location.
    @rtype: L{types.FunctionType}
    r   )namedAny)Ztwisted.python.reflectr%   )ZfullyQualifiedNamer%   r   r   r   r!      s    r!   c                 C   s   t | jffS )z3support function for copy_reg to pickle module refs)unpickleModuler	   )moduler   r   r   pickleModule   s    r(   c                 C   s6   | t kr(td|   t |  } t|  t| i i dS )z5support function for copy_reg to unpickle module refszModule has moved: %sx)
oldModulesr   r   
__import__)namer   r   r   r&      s
    
r&   c                 C   s   t |  |  ffS )z
    Reduce the given cStringO.

    This is only called on Python 2, because the cStringIO module only exists
    on Python 2.

    @param stringo: The string output to pickle.
    @type stringo: L{cStringIO.OutputType}
    )unpickleStringOgetvaluetell)Zstringor   r   r   pickleStringO   s    r0   c                 C   s   t  }||  || |S )a  
    Convert the output of L{pickleStringO} into an appropriate type for the
    current python version.  This may be called on Python 3 and will convert a
    cStringIO into an L{io.StringIO}.

    @param val: The content of the file.
    @type val: L{bytes}

    @param sek: The seek position of the file.
    @type sek: L{int}

    @return: a file-like object which you can write bytes to.
    @rtype: L{cStringIO.OutputType} on Python 2, L{io.StringIO} on Python 3.
    )
_cStringIOwriteseekvalZsekr)   r   r   r   r-      s    

r-   c                 C   s   t |  |  ffS )aQ  
    Reduce the given cStringI.

    This is only called on Python 2, because the cStringIO module only exists
    on Python 2.

    @param stringi: The string input to pickle.
    @type stringi: L{cStringIO.InputType}

    @return: a 2-tuple of (C{unpickleStringI}, (bytes, pointer))
    @rtype: 2-tuple of (function, (bytes, int))
    )unpickleStringIr.   r/   )Zstringir   r   r   pickleStringI   s    r7   c                 C   s   t | }|| |S )a  
    Convert the output of L{pickleStringI} into an appropriate type for the
    current Python version.

    This may be called on Python 3 and will convert a cStringIO into an
    L{io.StringIO}.

    @param val: The content of the file.
    @type val: L{bytes}

    @param sek: The seek position of the file.
    @type sek: L{int}

    @return: a file-like object which you can read bytes from.
    @rtype: L{cStringIO.OutputType} on Python 2, L{io.StringIO} on Python 3.
    )r1   r3   r4   r   r   r   r6      s    
r6   )	InputType
OutputTypeStringIO)r:   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )		Ephemeralzh
    This type of object is never persisted; if possible, even references to it
    are eliminated.
    c                 C   s   t dfS )zu
        Serialize any subclass of L{Ephemeral} in a way which replaces it with
        L{Ephemeral} itself.
        r   )r;   )selfr   r   r   
__reduce__  s    zEphemeral.__reduce__c                 C   sJ   t d|   tsFdd l}t|dd rF|| D ]}t d|f  q0d S )Nz!WARNING: serializing ephemeral %sr   get_referrersz referred to by %s)r   r   r   gcr   r>   )r<   r?   rr   r   r   __getstate__  s    zEphemeral.__getstate__c                 C   s   t d| j  t| _d S )Nz#WARNING: unserializing ephemeral %s)r   r   r   r;   r<   stater   r   r   __setstate__"  s    zEphemeral.__setstate__N)r	   r
   r   r   r=   rA   rD   r   r   r   r   r;     s   	r;   c                  C   s&   t t D ]} t|  qi ai ad S N)listversionedsToUpgradevaluesrequireUpgradeupgraded)Z	versionedr   r   r   	doUpgrade*  s    
rK   c                 C   s0   t | }|tkr,|tkr,dt|< |   | S dS )zDRequire that a Versioned instance be upgraded completely first.
       N)idrG   rJ   versionUpgrade)objZobjIDr   r   r   rI   1  s
    rI   c                 C   s@   | t g}t| D ] }||krt|t r|| q|dd S )z
    Get all of the parent classes of C{c}, not including C{c} itself, which are
    strict subclasses of L{Versioned}.

    @param c: a class
    @returns: list of classes
       N)	VersionedinspectZgetmro
issubclassappend)clbr   r   r   _aybabtu:  s
    
rX   c                   @   s2   e Zd ZdZdZdZdd ZdddZd	d
 ZdS )rQ   a  
    This type of object is persisted with versioning information.

    I have a single class attribute, the int persistenceVersion.  After I am
    unserialized (and styles.doUpgrade() is called), self.upgradeToVersionX()
    will be called for each version upgrade I must undergo.

    For example, if I serialize an instance of a Foo(Versioned) at version 4
    and then unserialize it when the code is at version 9, the calls::

      self.upgradeToVersion5()
      self.upgradeToVersion6()
      self.upgradeToVersion7()
      self.upgradeToVersion8()
      self.upgradeToVersion9()

    will be made.  If any of these methods are undefined, a warning message
    will be printed.
    r   r   c                 C   s   | t t| < || _d S rE   )rG   rM   __dict__rB   r   r   r   rD   b  s    zVersioned.__setstate__Nc                 C   s~   t  |p| j}t| j}|  || j |D ]F}d|jkrZ|jD ]}||krF||= qFd|jkr2|j|dt	| < q2|S )zAGet state, adding a version number to it on its way out.
        persistenceForgetspersistenceVersion%s.persistenceVersion)
copyrY   rX   r   reverserT   rZ   r[   r   qual)r<   dictZdctbasesbaseZslotr   r   r   rA   f  s    



zVersioned.__getstate__c           
      C   sV  t | j}|  || j d| jkr| jd }| jd= d}d}|D ]$}d|jkrVqF|j|krF|}|j}qF|r|| jdt| < |D ]}t|j	krd|jkrq|j}dt| }| j
|pd}|r| j|= ||kstd||k r|d }|j
d| d}	|	r<tdt|t| jt| |f  |	|  qtd	||f  qqdS )
z)(internal) Do a version upgrade.
        r[   r   Nr\   z"Sorry, can't go backwards in time.rL   zupgradeToVersion%sz'Upgrading %s (of %s @ %s) to version %sz(Warning: cannot upgrade %s to version %s)rX   r   r^   rT   rY   r[   r   r_   rQ   	__bases__getr   r   r   rM   )
r<   ra   ZpverZhighestVersionZhighestBaserb   ZcurrentVersZpverNameZpersistVersr   r   r   r   rN   v  sD    






(
zVersioned.versionUpgrade)N)	r	   r
   r   r   r[   rZ   rD   rA   rN   r   r   r   r   rQ   K  s   
rQ   )0r   Z
__future__r   r   r   pickleZcopy_regImportErrorcopyregr]   rR   Ztwisted.python.compatr   r   Ztwisted.pythonr   r   r*   ZcPickleZPicklingErrorr   r   r   r   r   r$   r!   FunctionTyper(   r&   
ModuleTyper0   r-   r7   r6   	cStringIOr8   r9   r:   r1   ior;   rG   rJ   rK   rI   rX   rQ   r   r   r   r   <module>   sh   
$		