wL ibddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z ddl mZmZmZmZmZmZddlmZerMej,ej.zej0zej2zej4zej6zZddZddZGdd eZGd d eZ Gd d ejBZ"GddZ#GddeZ$y)) annotationsN) ModuleType) TYPE_CHECKINGAny GeneratorIterable NamedTuplecast)DeduperReloaderPatchingMixinct|trtjj |n|x}yt |ddxsdS)zHReturns the module's file path, or the empty string if it's inaccessible__file__) isinstancestrsysmodulesgetgetattr)modulemods t/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/IPython/extensions/deduperreload/deduperreload.pyget_module_file_namers<*4VS*As{{v&vMV 3 B ' -2-ct|t|uryt|tjrL|jj D].\}}|dvr t ||rt|t||r.yyt|trEt|tr5t|t|k(xrtdt||DS||k(S)zYChecks if node1 and node2 have identical AST structure/values, apart from some attributesF)lineno end_lineno col_offsetend_col_offsetctxparentTc3:K|]\}}t||ywN) compare_ast).0n1n2s r zcompare_ast..;s 0 $*BKB 0 s) typerastAST__dict__itemshasattrr#rlistlenallzip)node1node2kvs rr#r#$s E{$u+%%!NN((* DAq5!$K75!;L,M  E4 Z t&5zSZ' C0 .1%.?0 -  ~rc&eZdZUdZded<ded<y)DependencyNodea Each node represents a function. qualified_name: string which represents the namespace/name of the function abstract_syntax_tree: subtree of the overall module which corresponds to this function qualified_name is of the structure: (namespace1, namespace2, ..., name) For example, foo() in the following would be represented as (A, B, foo): class A: class B: def foo(): pass tuple[str, ...]qualified_nameast.ASTabstract_syntax_treeN)__name__ __module__ __qualname____doc____annotations__rrr7r7Bs $#!!rr7cveZdZUgZded<gZded<gZded<iZded<gZd ed <e dd Z dd Z dd Z y) GatherResultz9list[tuple[tuple[str, ...], ast.Import | ast.ImportFrom]] import_defsz8list[tuple[tuple[str, ...], ast.Assign | ast.AnnAssign]] assign_defszDlist[tuple[tuple[str, ...], ast.FunctionDef | ast.AsyncFunctionDef]] function_defszdict[str, ast.ClassDef]classesz list[ast.AST] unfixablec|gggigSr"rA)clss rcreatezGatherResult.create_s2r2r2&&rcltj|j|j|jSr") itertoolschainrDrErFselfs rall_defszGatherResult.all_defscs't//1A1A4CUCUVVrcv|jj|j|jj|j|jj|j|jj |j|j j|j yr")rDextendrErFrGupdaterH)rPothers r inplace_mergezGatherResult.inplace_mergefs|  1 12  1 12 !!%"5"56 EMM* eoo.rN)returnrC)rWz0Iterable[tuple[tuple[str, ...], TDefinitionAst]])rUrCrWNone) r<r=r>rDr@rErFrGrH classmethodrKrQrVrArrrCrCVs`MOKJOLNKIN  (*G $)!I}!''W/rrCcfeZdZddZej ddZd dZd dZd fd Z d dZ xZ S) ConstexprDetectorc d|_d|_yNT) is_constexpr_allow_builtins_exceptionsrOs r__init__zConstexprDetector.__init__os *.'rc#bK|j}d|_ d||_y#||_wxYwwNF)r_)rP prev_allows rdisallow_builtins_exceptionsz.ConstexprDetector.disallow_builtins_exceptionsss144 */' 9 .8D +jD +s/#/ ,/c|j5|j|jdddy#1swYyxYwr")rdvisitvaluerPnodes rvisit_Attributez!ConstexprDetector.visit_Attribute|s3  . . 0 # JJtzz " # # #s6?c`|jrtt|jryd|_yrb)r_r-builtinsidr^rhs r visit_NamezConstexprDetector.visit_Names#  * *wx/I !rc>|jsyt| |yr")r^superrf)rPri __class__s rrfzConstexprDetector.visits    drcJd|_|j||jSr])r^rfrhs r__call__zConstexprDetector.__call__s"  4   rrWrX)rWzGenerator[None, None, None])riz ast.AttributerWrX)rizast.NamerWrX)rir:rWrX)rir:rWbool) r<r=r>r` contextlibcontextmanagerrdrjrnrfrs __classcell__)rqs@rr[r[ns6/99#"  !rr[c eZdZdZddZddZy)AutoreloadTreea Recursive data structure to keep track of reloadable functions/methods. Each object corresponds to a specific scope level. children: classes inside given scope, maps class name to autoreload tree for that class's scope funcs_to_autoreload: list of function names that can be autoreloaded in given scope. new_nested_classes: Classes getting added in new autoreload cycle cLi|_g|_t|_i|_yr")childrendefs_to_reloadsetdefs_to_deletenew_nested_classesrOs rr`zAutoreloadTree.__init__s#35 EG(+68rc|}|D]6}||jvrt|j|<|j|}8|S)zY Return ref to the AutoreloadTree at the namespace specified by prefixes )r|rz)rPprefixescurprefixs rtraverse_prefixesz AutoreloadTree.traverse_prefixessJ 'FS\\)'5'7 V$,,v&C ' rNrt)rz list[str]rWrz)r<r=r>r?r`rrArrrzrzs9 rrzc^eZdZdZddZeddZejddZddZe Z e ddZ e ddZe ddZ d dd Zdd Zdd Z d dd ZddZ d d dZ d d dZd!dZ d"dZ d d#dZd$dZy )%DeduperReloadera This version of autoreload detects when we can leverage targeted recompilation of a subset of a module and patching existing function/method objects to reflect these changes. Detects what functions/methods can be reloaded by recursively comparing the old/new AST of module-level classes, module-level classes' methods, recursing through nested classes' methods. If other changes are made, original autoreload algorithm is called directly. cLt|_i|_i|_d|_yr])rz_to_autoreloadsource_by_modnamedependency_graph_enabledrOs rr`zDeduperReloader.__init__s$.<.>13MO rcL|jxrtjdk(S)NCPython)rplatformpython_implementationrOs renabledzDeduperReloader.enableds}}N!?!?!AY!NNrc||_yr")r)rPrgs rrzDeduperReloader.enableds  rc |jsytjj|jjz D]}tj|}t |x},d|vs(d|vs$t j|t jsd|j|<_t|d5} |j|j|<dddy#t$rd|j|<Y%wxYw#1swYxYw)zY Update dictionary source_by_modname with current modules' source codes. Nz site-packagesz dist-packagesr r) rrrkeysrrosaccessR_OKopenread Exception)rP new_modname new_modulefnamefs rupdate_sourceszDeduperReloader.update_sourcess|| ;;++-0F0F0K0K0MM =K[1J.z::C"e+"e+yy068&&{3eS! =Q=:;&&(D**;7 = = =!=:D]^}|j@%|j&j|j@|j+|j-|j.|`Nt|tjBtjDfrz|jG||rt|tjHtjJfsJt|tjHr |jLn |jNg}|jPjtd|D|f|j&j|7|S)z Given list of ast elements, return: 1. dict mapping function names to their ASTs. 2. dict mapping class names to their ASTs. 3. list of any other ASTs. c3PK|]}|jxs |j ywr")asnamename)r$rs rr'z3DeduperReloader._gather_children.. s N4;;3$))3Ns$&c3dK|](}ttj|j*ywr")r r)rrm)r$rs rr'z3DeduperReloader._gather_children..,s!!R$sxx"8";";!Rs.0))rCrKrr)Exprrg FunctionDefAsyncFunctionDefrFappendrImport ImportFromrDtuplenamesClassDefrGIfrHtestrV_gather_childrenbodyorelse AsyncWithWithrSr,Try finalbodyhandlersr(ConstantPassrrrrrrE)rJrrresultast_nodeast_elthandlerrs rrz DeduperReloader._gather_childrens $$&. 5H+3GWchh/!--Wchh/'COOS5I5I#JK$$++gll_g,FGGcjj#..%AB""))N NNPWXGS\\2/6w||,GSVV,  '' 5$$S%9%9',, %TU$$S%9%9'..+%VWGcmmSXX%>?  '' 6$$S%9%9',, %TUGSWW-$$S%9%9',, %TU$$S%9%9'..+%VW$$(():):KH '//G||/((// =((,,W\\;G  #,,)AB**7K@%g CMM/JKKK&gszz: %nn- &&--!!R'!RR#$$++G4]. 5^ rNcX|jsy|xsg}|j|j|}|j|j|}|jDcic]\}}|D]}||} }}}|jDcic]\}}|D]}||} }}}t |j |j sy|j j|} |jD]d\}} g} |D]/}| || ur || vst | | |r| j|1| s?| jjt|| ff| xjt| jt| jz zc_ |jjD]c\}}||jvr|| j |<$t ||j|r>|j#|j||||gzrcyycc}}}wcc}}}w)z Returns ------- `True` if we can run our targeted autoreload algorithm safely. `False` if we should instead use IPython's original autoreload implementation. FT)rrrrQr#rHrrrr}rrr~rrGr,rdetect_autoreload)rPold_nodenew_noder old_result new_resultrast_defrold_defs_by_namenew_defs_by_namer new_ast_defnames_to_reloadnew_ast_def_classs rrz!DeduperReloader.detect_autoreload4sc||>r**8==(C **8==(C 0:0C0C0E0 0 ,eWRW0 JND'M0 0 0 1;0C0C0E0 0 ,eWRW0 JND'M0 0 0 ://1E1EF!!33H=","5"5"7 G E; O 1#D)<//{!1$!78$**40  1""))5<*EF G c"2"7"7"9:S  ! ! #>   (2'9'9'?'?'A  #D#:---/@&&t, !:#5#5d#;,,""4(*;X=N E0 0 s H H%cP|jD]}|j|y)z If a decorator function is modified, we should similarly reload the functions which are decorated by this decorator. Iterate through the Dependency Graph to find such cases in the given AutoreloadTree. T)_check_dependents_inner_add_node_to_autoreload_treerhs r_check_dependentsz!DeduperReloader._check_dependentsjs- 002 4D  - -d 3 4rct|jdk(ry|jjt |jdd}|j 6|j j|jdf|j fyy)zj Given a node of the dependency graph, add decorator dependencies to the autoreload tree. rN)r/r9rrr.r;r}r)rPrirs rrz,DeduperReloader._add_node_to_autoreload_treess t"" #q ( !!33D9L9LSb9Q4RS  $ $ 0    % %%%b)+T-F-FG  1rc@|xsg}|jj|}g}|jD]6\^}}}t||gz}|j |j |8|j D]&}|j |j||gz(|Sr")rrr}rrS_gen_dependentsrr)rPrrans func_name_ri class_names rrz'DeduperReloader._check_dependents_inners>r!!33H="%"4"4 3 OYQYK/0D JJt++D1 2 300 NJ JJt33H |4KL M N rcg}||jvrgS|j|D]=}|j|j|j|j |?|Sr")rrSrr9r)rPqualnamerelts rrzDeduperReloader._gen_dependentssc 400 0I((2 C JJt++C,>,>? @ JJsO  rc  |xsg}|jj|}|}|D]}|j|}t}|jD]v\}}t |dk(r|d|vr|j |i} t|tjtjfr|dx} |jvrt |dk(sJ|j| } t| ttfr | j} tjtj |} t |dkDx} rdtj"| dz} |j}t|t$s t%|}t'| ddxr| j(j*xsd}tj,| g}t t/tj|dj0dj2dkDrit5j6t5j8|d}gt/tj|j0d_|j;d||D]}t=||dd }t?||| | rt'| d | }n| | }t|ttfr |j}t| t@rkt|t@r[d D]U}t'| | t'|||jC| ||/|jEt'| |t'||| Wt| t@s%t|t@s|jE| ||  tGd )t?tj ||j|jz| |D]} tI|| | | y|jjK|jLD]} tO|| |jLjK|jTjWD]N\}}i}t?tj ||j|jz|tI||||P|jTjK|jXj[D]}|j]|||gzry|jXjKy #tPtRtFf$rYwxYw)a This function patches module functions and methods. Specifically, only objects with their name in self.to_autoreload will be considered for patching. If an object has been marked to be autoreloaded, new_source_code gets executed in the old version's global environment. Then, replace the old function's attributes with the new function's attributes. rzclass __autoreload_class__: z __code__NzexecT)mode dont_inherit__autoreload_class__)fgetfsetfdelz5adding or removing property decorations not supportedF)/rrr+r~r}r/rTrr)rr staticmethodrY__func__textwrapdedentunparseindentdictrr co_filenameparser rdecorator_listpickleloadsdumpsinsertcompilerpropertytry_patch_attrpatch_function ValueErrorsetattrclearrdelattrAttributeError TypeErrorrr,r|r_patch_namespace)rPnsrrnamespace_to_checkr seen_namesrr local_envr to_patch_to func_code is_method global_envfilename func_astswithout_decorator_listfunc_ast compiled_code to_patch_fromrrclass_ast_nodelocal_env_classs r_patch_namespace_innerz&DeduperReloader._patch_namespace_inners>r!!33H= EF!3!->q-ABQQRUVV-3\\&,,yQR|:T-U*(*)?)D)DQ)G$$$Q(>? )"H$+ (d%M I> (/ :P0QSW(X (1$ !-, 1LM(5(>(> !+x8Z%x>%= "D ' T : B#*=$#?#G $ 3 3KPT U $ 3 3$+K$>$+M4$@$-!" "( X>z%xH++K R(SA"HKK ,KK"4"="== "GD.ioFGYM G\   "&& D *D1    "*-*@*@*F*F*H Q &J.0O  N+ 0999  & OJ4O P Q $$&,,++- J((X -DE  ##Iz:  s4 S33T  T cH |j||S#t$rYywxYw)z Wrapper for patching all elements in a namespace as specified by the to_autoreload member variable. Returns `true` if patching was successful, and `false` if unsuccessful. )rF)rr)rPrrs rrz DeduperReloader._patch_namespace s/ ..rH.E E  s  !!c|jsyt|ddx}syt|x}yt|d5}|j }dddd}|j j |x}r tj|}tj} tj} | 5|j| |j|| r#|jr|j|rd}ddd|j |<t!|_|S#1swYxYw#t$rYywxYw#1swYDxYw)zy Uses Deduperreload to try to update a module. Returns `true` on success and `false` on failure. Fr<NrT)rrrrrrrr)rrrvsuppress_build_dependency_graphrrrrzr) rPrmodnamerrnew_source_code patched_flagold_source_codeold_module_astnew_module_astrs rmaybe_reload_modulez#DeduperReloader.maybe_reload_modulesA ||"6:t<<<)&1 1E : %  'ffhO ' "4488A A? A !$?!;!$?!;%%'C (,,^<**>>J..0--f5#'L (+:w',./ ' '   ( (s*D 1*D,1AD; D), D87D8;EcVt|tjr |jgSt|tjr|r|j |j dSyt|tjsy|j |jdx}r||jgzSy)ze Generates a qualified name for a given decorator by finding its relative namespace. FN) rr)rrmCall_separate_namefuncrrgr)rP decorator accept_callsprefs rr-zDeduperReloader._separate_name9s i *LL> !  388 ,**9>>5AA)S]]3&&y> >4 >9>>** *rc|xsg}|D]}|}t|tjr+|j|j||j gzJt|tj tjfsut||j gz}t||}|jD]M}|j|d}|st|} |jj| gj|Oyr])rr)r_gather_dependentsrrrrrr7rr-r setdefaultr) rPr body_prefixesrrr9cur_dependency_noder/decorator_pathdecorator_path_tuples rr3z"DeduperReloader._gather_dependentsOs&+  H+3G'3<<0'' mw||n6TUg9M9M'NO"=GLL>#ABN"0"I $33  !%!4!4Y!E%',^'<$%%001ErJQQ'   "rc8|j|jS)z Wrapper function for generating dependency graph given some AST. Returns `true` on success. Returns `false` on failure. Currently, only returns `true` as we do not block on failure to build this graph. )r3r)rPnew_asts rr#z'DeduperReloader._build_dependency_graphfs &&w||44rrt)rWru)rgrurWrX)riast.Module | ast.ClassDefrWru)rir:rr;rWru)rlist[ast.stmt]rr;rWrCr")rr;rr;rlist[str] | NonerWru)rir7rWrX)rr=rWlist[DependencyNode])rr8rWr>)rzModuleType | typerr=rWru)rrrWru)r/z.ast.Attribute | ast.Name | ast.Call | ast.exprr0rurWr=)rr<r5r=rWru)r:r;rWru)r<r=r>r?r`rrsetterrr[rrrrYrrrrrrrrrr*r-r3r#rArrrrs OO ^^=,+,   2 2)B 2  2 29!90I9 99~&* 4+4,4# 4  4l ,0 (   CGr#r/?r rjCG # /?   "HA  .GK"3C .5rr)rzModuleType | strrWz str | None)r2ast.AST | list[ast.AST]r3r@rWru)% __future__rr)rlrvrMrrrrrtypesrtypingrrrrr r 7IPython.extensions.deduperreload.deduperreload_patchingr rrrrrrTDefinitionAstrr#r7rC NodeVisitorr[rzrrArrrGs"   LL     **  ..  **   --  .<"Z"(/:/0 ! !F4A52A5r