
    "e=                         d Z ddlmZ ddlmZ ddlZddlmZ ddlm	Z	 dZ
dZdZe
Zd	 Zd
 Zd Zd Zd Zd Zd Z G d d      Zy)a[  
Based on the python xreload.

Changes
======================

1. we don't recreate the old namespace from new classes. Rather, we keep the existing namespace,
load a new version of it and update only some of the things we can inplace. That way, we don't break
things such as singletons or end up with a second representation of the same class in memory.

2. If we find it to be a __metaclass__, we try to update it as a regular class.

3. We don't remove old attributes (and leave them lying around even if they're no longer used).

4. Reload hooks were changed

These changes make it more stable, especially in the common case (where in a debug session only the
contents of a function are changed), besides providing flexibility for users that want to extend
on it.



Hooks
======================

Classes/modules can be specially crafted to work with the reload (so that it can, for instance,
update some constant which was changed).

1. To participate in the change of some attribute:

    In a module:

    __xreload_old_new__(namespace, name, old, new)

    in a class:

    @classmethod
    __xreload_old_new__(cls, name, old, new)

    A class or module may include a method called '__xreload_old_new__' which is called when we're
    unable to reload a given attribute.



2. To do something after the whole reload is finished:

    In a module:

    __xreload_after_reload_update__(namespace):

    In a class:

    @classmethod
    __xreload_after_reload_update__(cls):


    A class or module may include a method called '__xreload_after_reload_update__' which is called
    after the reload finishes.


Important: when providing a hook, always use the namespace or cls provided and not anything in the global
namespace, as the global namespace are only temporarily created during the reload and may not reflect the
actual application state (while the cls and namespace passed are).


Current limitations
======================


- Attributes/constants are added, but not changed (so singletons and the application state is not
  broken -- use provided hooks to workaround it).

- Code using metaclasses may not always work.

- Functions and methods using decorators (other than classmethod and staticmethod) are not handled
  correctly.

- Renamings are not handled correctly.

- Dependent modules are not reloaded.

- New __slots__ can't be added to existing classes.


Info
======================

Original: http://svn.python.org/projects/sandbox/trunk/xreload/xreload.py
Note: it seems https://github.com/plone/plone.reload/blob/master/plone/reload/xreload.py enhances it (to check later)

Interesting alternative: https://code.google.com/p/reimport/

Alternative to reload().

This works by executing the module in a scratch namespace, and then patching classes, methods and
functions in place.  This avoids the need to patch instances.  New objects are copied into the
target namespace.

    )execfile)pydevd_dont_traceN)	pydev_log)get_global_debugger      c                     t               }|g }| D ]  }|j                  t        |              dj                  |      }d|d}|j                  j                  |d      }|j                  |j                  j                  |       y y y )N zcode reload: 
r   )r   appendstrjoincmd_factorymake_io_messagewriteradd_command)argspy_dbnew_lstamsgscmds          >/usr/lib/python3/dist-packages/_pydevd_bundle/pydevd_reload.py	write_errr   r   s    !E 	#ANN3q6"	# hhw#&(//15<<#LL$$S) $     c                      t        |   y Nr   r   s    r   notify_info0r!      
    tr   c                  0    t         t        k\  r	t        |   y y r   )DEBUGLEVEL1r   r    s    r   notify_infor&          4 r   c                  0    t         t        k\  r	t        |   y y r   )r$   LEVEL2r   r    s    r   notify_info2r*      r'   r   c                      t        |   y r   r   r    s    r   notify_errorr,      r"   r   c                     t        |       D ]7  }|j                  d      sd|v s|dv rt        | |      t        ||      k7  s7 y y)N_line)replaceco_positionsco_qualnameFT)dir
startswithgetattr)code0code1ds      r   code_objects_equalr9      sP    Z <<!q4^/^5!q 11	
 r   c                     t        |       }|j                          |j                  }d}t        j                          |S )zReload a module in place, updating classes, methods and functions.

    mod: a module object

    Returns a boolean indicating whether a change was done.
    N)Reloadapplyfound_changer   clear_trace_filter_cache)modrr=   s      r   xreloadrA      s6     	sAGGI>>LA..0r   c                   H    e Zd ZddZd ZddZddZd Zd Zd Z	d	 Z
d
 Zy)r;   Nc                     || _         |r|| _        n||j                  nd | _        |r|| _        d| _        y ||j                  nd | _        d| _        y )NF)r?   mod_name__name__mod_filename__file__r=   )selfr?   rD   rF   s       r   __init__zReload.__init__   sU    $DM,/OCLLDM ,D " 14TD!r   c                    | j                   }g | _        	 |j                  }|j                         }|j	                          | j
                  r| j
                  |d<   	 t        |d<   | j                  r| j                  |d<   |d   dk(  rd|d<   t        | j
                  ||       t        |      }t        |      }||z
  D ]  }t        d|d       d| _        ||   ||<     ||z  D ]  }| j                  ||||   ||           | j                  |       | j                  D ]	  } |         | j                  d d = y # t        $ r  w xY w#  t        j                           Y y xY w)	NrG   __builtins__rE   __main____main_reloaded__Added:zto namespaceT)r?   _on_finish_callbacks__dict__copyclearrF   rK   	NameErrorrD   r   setr!   r=   _update_handle_namespacer   	exception)rH   r?   modnsnew_namespaceoldnamesnewnamesnamecs           r   r<   zReload.apply   s   hh$&!0	"LLE "JJLM!  ,0,=,=j)4@M.1 }},0MMj) ,
: 1DM*-T&&}E5zH=)H !8+ 2Xt^<$(!+D1d2 !8+ LUD%+}T7JKL ""5).. ))!,= ! >	"!s%   AE 	D> &CE >E		E E$c                     d }|rt        dd       #d| _        fd}ndv rd   d| _        fd}|| j                  j                  |       y y )N__xreload_after_reload_update__Tc                               S r    )xreload_after_updates   r   <lambda>z*Reload._handle_namespace.<locals>.<lambda>  s    $8$: r   c                              S r   ra   )	namespacerb   s   r   rc   z*Reload._handle_namespace.<locals>.<lambda>  s     4Y ? r   )r5   r=   rO   r   )rH   re   is_class_namespace	on_finishrb   s    `  @r   rV   zReload._handle_namespace  so    	#*96WY]#^ #/$(!:	.);#,-N#O  $D?I %%,,Y7 !r   c           
         	 t        d|       ||u ryt        |      t        |      ur,|dvr't        d|dt        |      dt        |      d       yt        |t        j
                        r| j                  ||       yt        |t        j                        r| j                  ||       yt        |t              r| j                  ||       yt        |t              r| j                  ||       yt        t        d      rt        j                  t        f}nt        }t        ||      r| j                  ||       yt        |d	      r8t        |d
      r,|j                   |j"                  k(  r| j                  ||       y|Cd}|r!t%        |dd      }|/d| _         ||||       yd|v r|d   } |||||       d| _        yyyy#  t        d|d       t)        j*                          Y yxY w)zUpdate oldobj, if possible in place, with newobj.

        If oldobj is immutable, this simply returns newobj.

        Args:
          oldobj: the object to be updated
          newobj: the object used as the source for the update
        z
Updating: N)rK   z	Type of: z (old: z	 != new: z) changed... Skipping.	ClassType__metaclass__	__class____xreload_old_new__TzException found when updating z. Proceeding for other items.)r*   typer,   
isinstancetypesFunctionType_update_function
MethodType_update_methodclassmethod_update_classmethodstaticmethod_update_staticmethodhasattrri   _update_classrj   rk   r5   r=   r   rW   )rH   re   r\   oldobjnewobjrf   	classtypexreload_old_news           r   rU   zReload._update  s   ?	"v.F|4</00 \`bfgmbnptu{p|!}~&%"4"45%%ff5&%"2"23##FF3&+.((8&,/))&&9uk*"__d3	 	&),""662 v/GFK4PU[UiUimsm}m}U}""662$ #'%&-i9NPT&UO&2,0)'ff=*i7&/0E&FO#ItVVD(,D% 8	 3 %&	"\`bc!sC   G AG ,G ,G /"G "G 5AG AG &G ,G %G2c                    |j                   |_         |j                  j                  |j                         	 |j                   d}t        ||      }t        ||      }t        ||      s t        d|       t        |||       d| _
        	 |j                  |_        |S # t        $ r |j
                   d}Y qw xY w# t        $ r |j                  |_        Y |S w xY w)zUpdate a function object.__code__	func_codezUpdated function code:T)__doc__rP   updater   AttributeErrorr   r5   r9   r!   setattrr=   __defaults__func_defaults)rH   oldfuncnewfunc	attr_nameold_codenew_codes         r   rq   zReload._update_functionb  s    !// 0 01	$"I
 7I.7I.!(H517;GY1 $D	:#*#7#7G  !  	$#I	$  	:$+$9$9G!	:s#   B B; B87B8;CCc                 
   t        |d      r6t        |d      r*| j                  dd|j                  |j                         |S t        |d      r4t        |d      r(| j                  dd|j                  |j                         |S )zUpdate a method object.im_funcN__func__)rx   rU   r   r   )rH   oldmethnewmeths      r   rs   zReload._update_method|  sp     7I&77I+FLLtW__gooF  Wj)ggz.JLLtW%5%5w7G7GHr   c                    |j                   }|j                   }t        |      }t        |      }||z
  D ]'  }t        ||||          t        d|d|       d| _        ) ||z  t        ddg      z
  D ]  }| j                  ||||   ||   d         t        |dd      }t        |dd      }	t        |      t        |	      k7  rt        d	|d
       | j                  |d       y)zUpdate a class object.rN   toTrP   r   )rf   	__bases__Nz4Changing the hierarchy of a class is not supported. z may be inconsistent.)
rP   rT   r   r!   r=   rU   r5   r   r,   rV   )
rH   oldclassnewclassolddictnewdictrZ   r[   r\   	old_bases	new_basess
             r   ry   zReload._update_class  s    ####w<w<x' 	%DHdGDM24x8 $D	% (CY0G,HH 	`DLL4Z^L_	` Hk48	Hk48	y>S^+jrtuxDAr   c                 h    | j                  dd|j                  d      |j                  d             y)zUpdate a classmethod update.Nr   rU   __get__)rH   oldcmnewcms      r   ru   zReload._update_classmethod  (     	T4q!15==3CDr   c                 h    | j                  dd|j                  d      |j                  d             y)zUpdate a staticmethod update.Nr   r   )rH   oldsmnewsms      r   rw   zReload._update_staticmethod  r   r   )NN)F)rE   
__module____qualname__rI   r<   rV   rU   rq   rs   ry   ru   rw   ra   r   r   r;   r;      s5    "3"j8"H"X4B8EEr   r;   )r   _pydev_bundle.pydev_importsr   _pydevd_bundler   ro   _pydev_bundler   _pydevd_bundle.pydevd_constantsr   NO_DEBUGr%   r)   r$   r   r!   r&   r*   r,   r9   rA   r;   ra   r   r   <module>r      sb   bH 1 ,  # ?	
	
*

>qE qEr   