PKgFJ^ 00frappuccino/.__init__.py.un~VimUnDo)13Ew37,X+5aM 7}wRH sig = hexd.sub('0xffffff', str(inspect.signature(function)))+zPzzX_,+KbvbX5_+-,KbvbXif __name__ == ''5_,.-KbvbXif __name__ == '__main__':if __name__ == '__main__'5_-/. KbvbXzif __nam?!?jedi=3, e__ == '__main__':?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' ' print(''5_.0/KbvbX)zif __nam?!?jedi=3, e__ == '__main__':?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' ' print('let''5_/10KbvbX print("let go")5_021KbvbX module = __import__()5_132KbvbX5_243KbvbX module = __import__('')5_354KbvbXm?!?jedi=0, ?!? (*_*name*_*, globals=None, locals=None, fromlist=(), level=0) ?!?jedi?!?5_465KbvbX5_576KbvbX module_name = ''5_687KbvbX module_name = 'IPython' module = __import__()5_798$KbvbX* $ module = __import__(module_name)$ module = __import__(module_name)5_8:9vbX 5_9;:vbX 5_:<; vbX  class Visitor5_;=<vbXmodule5_<>=vbX5_=?>vbX 5_>@?vbX 5_?A@ vbX,  print(module)  print(module)5_@BAvbX 5_ACBvbX -def 5_BDC vbX(  print(module)5_CED vbX(/ n prin?!?jedi=0, t(module)?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?  print(modue.__qualname__)5_DFE vbX-  print(module)  print(module.__qualname__)5_EGF vbX2 n prin?!?jedi=0, t(module)?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_FHG vbX2  print(module)5_GIH vbX4 n prin?!?jedi=0, t(module)?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_HJI vbX51  print(dir(module)5_IKJvbXF 5_JLKvbXF5_KMLvbXYdef ModuleVisitor:5_LNMvbX\def __init__(self, name):5_MONvbX]2  def __init__(self, name):5_NPOvbXd  self.name = name5_OQP vbX{  if modulenode.5_PRQ vbX|  if not modulenode.5_QSRvbX 5_RTSvbX5_SUT vbX class ModuleVisitor:5_TVU vbX class oduleVisitor:5_UWV vbX class duleVisitor:5_VXW vbX class uleVisitor:5_WYX vbX class leVisitor:5_XZY vbX class eVisitor:5_Y[Z vbX  def __visit__(name)5_Z\[vbX5_[]\vbX 5_\^]vbXclass Visitor:5_]_^ vbX  def __visit__(modulenode):5_^`_ vbX  def _visit__(modulenode):5__a` vbX  def visit__(modulenode):5_`ba vbX  def visit_(modulenode):5_acb vbX  def visit(modulenode):5_bdc vbX  def visit(odulenode):5_ced vbX  def visit(dulenode):5_dfe vbX  def visit(ulenode):5_egf vbX  def visit(lenode):5_fhg vbX  def visit(enode):5_gih vbX  def visit(node):5_hji vbX 5_ikj vbX  type_ = type(node)5_jlk vbX  type_ = str(type(node)5_kml vbX  type_ = str(type(node))5_lnm vbX  def visit(node):5_monvbX   def visit(self, node):  type_ = str(type(node))  visitor = 5_npo&vbX & visitor = getattr(self, type_)5_oqpvbX(  type_ = str(type(node))5_prq vbX* & visitor = getattr(self, type_)5_qsr!vbX+ [ type_ = str(type?!?jedi=0, (node))?!? (*_*object*_*, name, default=None) ?!?jedi?!? ( visitor = getattr(self, ''type_)5_rts(vbX- . visitor = getattr(self, 'visit_'type_)5_sut(vbX/3 [ type_ = str(type?!?jedi=0, (node))?!? (object, *_*name*_*, default=None) ?!?jedi?!? 0 visitor = getattr(self, 'visit_'+ type_)5_tvuvbX3class Visitor: def __init__(self, name): self.name = name def visit(self, node): type_ = str(type(node))1 visitor = getattr(self, 'visit_' + type_) 0 if not modulenode.startswith(self.name): returnif __name__ == '__main__': print("let go") module_name = 'IPython'$ module = __import__(module_name) print(module) print(dir(module))5_uwv vbX6class Visitor: def __init__(self, name): self.name = name def visit(self, node): type_ = str(type(node))1 visitor = getattr(self, 'visit_' + type_) 0 if not modulenode.startswith(self.name): returnif __name__ == '__main__': print("let go") module_name = 'IPython'$ module = __import__(module_name) print(module) print(dir(module))5_vxw1vbX? 1 visitor = getattr(self, 'visit_' + type_)5_wyxvbXN5_xzyvbXO 5_y{zvbXO5_z|{1vbXR4 1 visitor = getattr(self, 'visit_' + type_)5_{}|vbX0 if not modulenode.startswith(self.name):5_|~} vbX return5_}~vbX5_~vbX visitor(node)5_vbX5 visitor(node)5_ vbX retrun visitor(node)5_ vbX retun visitor(node)5_vbX! def visit_ModuleType(module): return visitor(node)5_vbX print(''5_vbX print('visiting '5_"vbX " print('visiting ', module)5_vbX!! def visit_ModuleType(module):5_vbX! if module.__5_ vbX! if module.__name__5_vbX! if not module.__name__5_4vbX!4 if not module.__name__.startswith(self.name)5_vbX4 if not module.__name__.startswith(self.name)" print(''5_*vbX6"* print('wandering too far.....'5_+vbX7"+ print('wandering too far.....')5_vbX&8# return None5_4vbX/:#4 if not module.__name__.startswith(self.name)5_vbX;# return None5_vbXT& if k.starswith(''5_vbXU if k.starswith('_'):& if k.starswith('_'5_vbX\' print(''5_(vbX_ if k.sta?!?jedi=3, rswith('_'):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' ''( print('ignoring private'5_,vbXa<', print('ignoring private', k)5_* vbX>(* print(module)) print(dir(module))5_*vbX?(* print(module))' print(Visitor(module_name)(module))5_*vbXA), print(Visitor(module_name)visit(module))5_vXB*' def visit_ModuleType(self, module):5_ vX * type_ = str(type(node))5_   vX * type_ = str(type(node)5_   vXE * type_ = type(node)5_"  vXJF*# for k,v in module.__dict__:5_"  vXNH** for k,v in module.__dict__items():5_  vXXI* if k.starswith('_'):5_  vXYK*! if k.startswith('_'):5_  vXg* return visitor(node)5_'  vXs-' def visit_function(self, function(:5_&  vXv-* pass5_$  vXv-( pass5_   vXw-$ pass5_  vXw- pass5_  vXw- pass5_  vXx- pass5_  vXx- pass5_   vXxM- pass5_   vX- pass5_  vX def visit_str(self, str5_   vX . def visit(self, node):5_ vX  def visit(self, node): 05_vX 1 type+ = instance5_vX 1 type = instance5_vX 1 type = instance'5_vX15_vX 1# type_ = type(node).__name__5_vX 11 visitor = getattr(self, 'visit_' + type_)5_ vX 15 visitor = getattr(self, 'visit_' + type_)5_ vX1 pass5_vX3 def visit_type(self, 5_vX&N3 def visit_instance(self, 5_vX0' def visit_instance(self, instance):5_vX1Pd def visit_inst?!?jedi=0, ance(self, instance):?!? (*_*object_or_name*_*, bases, dict) ?!?jedi?!?4 return type(self)5_vXNR 4 type = 'instance'5_/vX^S.04 print("let go")5_&vX%' else:%(4 else:5_'vX&(5 print(''5_'"vX%'q else:?!?jedi=0, ?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?&(5" print('will visit'5_'&vXU&(5& print('will visit', k(5_""")v)X!#5+ for k,v in module.__dict__.items():5_!"")v)X "5!"55_! "")v)X "5( itemps = module.__dict__.items()5_""")v)XV!#5 for k,v in :5_!'"")v)XX #5' items = module.__dict__.items()5_!'##)v)XY "6' items = module.__dict__.items()5_!##)v)X\ "6 items = module.__dict__5_66 6vX5- print(Visitor(module_name).visit(module))5_6'6 6vX5' Visitor(module_name).visit(module))5_56 6vX]45 print(module)5_4$5 5vX^365$ module = __import__(module_name)5_16 6vX1 visitor = getattr(self, 'visit_' + type_)61 visitor = getattr(self, 'visit_' + type_)5_7 7vX visi?!?jedi=3, tor = getattr(self, 'visit_' + type_)?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '7 print(''5_7 7vXa visi?!?jedi=3, tor = getattr(self, 'visit_' + type_)?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '7 print('using visitor'5_7 7vX 7 return type(instance)5_7 7vX#b7 print(type(instance)5_7 7vX$d7 print(type(instance))5_!7 7vX*f7! print(type(instance))5_ B7 7vX8g 7C if isinstance(node, object) and not isinstance(node, type):5_ c7 7vXE 7d if isinstance(node, object) and not isinstance(node, type) and not isinstance(node, module):5_7 7vXKh75_ \7 7vXTj  def visit(self, node): 7d if isinstance(node, object) and not isinstance(node, type) and not isinstance(node, module):5_$7 7vXek#%7 for k,v in items :5_#7 7vXim"$7 print(items)5_#7 7vXo"# print(items.keys())5_(6 6vXq'(& print('will visit', k)5_5 5vX" print('visiting ', module)5_*4 4vXr5 if not module.__name__.startswith(self.name): 4+ print('wandering too far.....')5_;4 4vX5 if not module.__name__.startswith(self.name):5_:4 4vXt if not m?!?jedi=0, odule.__name__.startswith(self.name):?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_4 4vXv' print('using visitor', visitor)5_'3 3vX3' type_ = type(node).__name__5_4 4vX4 if type_ == ''5_'4 4vXw4' if type_ == 'MetaHasTraits'5_5 5vXy55_8 8vXs* import pdb;pdb.set_trace()5_(7 7vXt7( if type_ == 'MetaHasTraits':5_(8 8vXxz8( if type_ == 'MetaHasTraits':5_9 9vX|{9 # TODO5_)9 9vX|(*9, print('ignoring private', k)5_)9 9vX}()- #print('ignoring private', k)5_ 8 8vX 8 self.name = name5_ 9 9vX 9 self._visited5_ 9 9vX~ 9 self.visited5_ 9 9vX 9 def visit(self, node):5_= =vX = if node in visited:5_ = =vX= visited.add(node)5_ = =vX = self.visited = {}5_ = =vX  self.name = name = self.visited = set(){}5_ = =vX ; self.name = name?!?jedi=0, ?!? (*_**_*) ?!?jedi?!? = self.visited = set(}5_ = =vX  def visit(self, node): = def visit(self, node):5_? ?vX, ? if isinstance(node, dict):5_? ?vX1? print5_? ?vX3 " if isinstance(node, dict):? print5_ ? ?vX: ? self.visited = set()5_? ?vXE?" self.visited.add(node)5_ ? ?vXJ print(got unhas5_> >vXK " if isinstance(node, dict):5_= =vX_=( if type_ == 'MetaHasTraits':5_= =vXb=( if type_ in 'MetaHasTraits':5_(= =vXd=) if type_ in ('MetaHasTraits':5_*= =vXs=, if type_ in ('MetaHasTraits','':=5_2= =vXt=3 if type_ in ('MetaHasTraits','ABCMeta':5_ = =vX¹  print(type(instance))5_'< <vX¹!<' def visit_instance(self, instance):5_0= =vX return=1 visitor = getattr(self, 'visit_' + type_)5_?= =vX return5_?= =vX=@ visitor = getattr(self, 'visit_' + type_, visit_unknown)5_2= =vXT return?!?jedi=0, ?!? (object, name, *_*default=None*_*) ?!?jedi?!?=A visitor = getattr(self, 'visit_' + type_, visit_unknown')5_ = =vX% def visit_unknown(self, unknown):= return visitor(node)5_  @ @vX def visi?!?jedi=0, t_unknown(self, unknown):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?@ print(''5_   '@ @vX% def visit_unknown(self, unknown):@' print('no clue what to do with'5_    @ @vX4 if type_ in ('MetaHasTraits','ABCMeta'):5_   ? ?vX # TODO5_  > >vX return5_ 2= =vX=B visitor = getattr(self, 'visit_' + type_, 'visit_unknown')5_E= =vX=F visitor = getattr(self, 'visit_' + type_, self.visit_unknown')5_D= =vX' type_ = type(node).__name__5_C= =vXc type_ = type?!?jedi=0, (node).__name__?!? (object, name, *_*default=None*_*) ?!?jedi?!?5_= =vX=1 print('no clue what to do with', unknown)5_1= =vX=1 print('No clue what to do with', unknown)5_%> >vX% def visit_unknown(self, unknown):>% def visit_unknown(self, unknown):5_ ? ?vX1 print('No clue what to do with', unknown)? print5_? ?vX prin?!?jedi=3, t('No clue what to do with', unknown)?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '? print(''5_(&v&X1 print('No clue what to do with', unknown)?( print('isinstance(node, object)'?5_B&v&X ??5_&v&XC print('isinstance(node, object)', isinstance(node, object))5_&v&X@@5_?&v&XAA? print('isinstance(node, type)', isinstance(node, type))5_&v&XC? print('isinstance(node, type)', isinstance(node, type))B print(''5_&v&XI prin?!?jedi=3, t('isinstance(node, type)', isinstance(node, type))?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '5_&v&XI prin?!?jedi=3, t('isinstance(node, type)', isinstance(node, type))?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' 'B print('type(node)'5_ 558v8Xe1 print('No clue what to do with', unknown)BC print('isinstance(node, object)', isinstance(node, object))5_! 358v8XjB? print('isinstance(node, type)', isinstance(node, type))5_ "!!58v8XlB' print('type(node)', type(node))5_!#"*58v8XĢ* print('type(node)', type(unknown)) C print(' C B* print('type(node)', type(unknown))5_"$#*58v8XĪ* print('type(node)', type(unknown)) C* print('issubclass(MetaClass, type) C5_#%$G58v8XĮ prin?!?jedi=3, t('type(node)', type(unknown))?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '5_$&%A58v8Xįf print('type(node)', type(unknown))?!?jedi=0, ?!? (x, *_*(A*_*, B, ...)) ?!?jedi?!? CH print('issubclass(MetaClass, type)', issubclass(MetaClass, type)5_%'&F58v8Xķ* print('type(node)', type(unknown)) CF print('issubclass(MetaClass, type)', issubclass(unknown, type)5_&(' 58v8X  def visit(self, node): C def visit(self, node):5_')(58v8X)  def visit(self, node):5_(*)58v8X) J def visit(self, ?!?jedi=0, node):?!? (*_*x*_*, (A, B, ...)) ?!?jedi?!? D if isinstance(node)5_)+*'58v8X3 D' if isinstance(node, ModuleType)5_*,+58v8X;E if node in self.visited:5_+-,58v8X> ( if isinstance(node, ModuleType): type_ = 'module'5_,.-58v8X@CC5_-/.58v8XBEh if isinstance(node, object) and not isinstance(node, type) and not isinstance(node, ModuleType):5_.0/i58v8XFEj elif isinstance(node, object) and not isinstance(node, type) and not isinstance(node, ModuleType):5_/10!!!"v"X] "EG print('issubclass(MetaClass, type)', issubclass(unknown, type))!"E5_021!6!!"v"X{ "EE print('issubclass(unknown, type)', issubclass(unknown, type))5_132!B!!"v"X} "EJ print('issubclass(unknown, type)', issubclass(type(unknown, type))5_243!;!!"v"X~!* print('type(node)', type(unknown))5_354!;!!"v"X~!v print('type(node)', type(unknown))?!?jedi=0, ?!? (*_*object_or_name*_*, bases, dict) ?!?jedi?!? "EJ print('issubclass(unknown, type)', issubclass(type(unknown, type))5_465!5!!"v"Xŀ!#E!"E5_576"!!"v"XŃ!#FE print('issubclass(unknown, type)', issubclass(unknown, type))5_687"&!!"v"Xń!#FJ print('issubclass(type(unknown, type)', issubclass(unknown, type))5_798"<!!"v"Xņ!#FK print('issubclass(type(unknown), type)', issubclass(unknown, type))5_8:9"H!!"v"Xň!#FP print('issubclass(type(unknown), type)', issubclass(type(unknown, type))5_9;:"I!!"v"XŊ "E print('issubclass(unknown, type)', issubclass(unknown, type))5_:<;"H!!"v"Xő "u print('issubclass(unknown, type)', issubclass(unkn?!?jedi=0, own, type))?!? (*_*x*_*, (A, B, ...)) ?!?jedi?!?5_;=<"Q!*!*v*Xŕ "E print('issubclass(unknown, type)', issubclass(unknown, type))!#FQ print('issubclass(type(unknown), type)', issubclass(type(unknown), type))"#F5_<>="P!*!*v*Xř " print('issubclass(unknown, type)', issubclass(unknown, type))?!?jedi=0, ?!? (*_*object_or_name*_*, bases, dict) ?!?jedi?!?5_=?>"P!*!*v*Xř!#FQ print('issubclass(type(unknown), type)', issubclass(type(unknown), type))"#F " prin?!?jedi=3, t('issubclass(unknown, type)', issubclass(unknown, type))?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '5_>@?"1!*!*v*X"$F"#F5_?A@###vX"$G` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_@BA###vX!#` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))"$GU print('type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_ACB#$###v#X"$GW print('type(unknown) is type)', issubclass(type(unknown), type), type(unknown))5_BDC#$###v#X"$GW print('type(unknown) is type ', issubclass(type(unknown), type), type(unknown))5_CED#*#*#XvXX"$GY print('type(unknown) is type : ', issubclass(type(unknown), type), type(unknown))#$G5_DFE#?#*#XvXX"$G? print('type(unknown) is type : ', type(unknown) is type5_EGF #*#XvXXGG5_FHG%*%XvXXI type_ = 'instance'5_GIH0v0XJ` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_HJI0v0XJ elif7 issubclass(type(unknown), type), type(unknown))5_IKJ 5v0XI< elif issubclass(type(unknown), type), type(unknown))5_JLK))9v9XI9 elif issubclass(type(node), type), type(unknown))@ print('type(unknown) is type : ', type(unknown) is type)5_KML))QvQXHi elif issubclass(type(node), type) print('type(unknown) is type : ', type(unknown) is type)5_LNM))QvQXH@ elif issubclass(type(node), type) type(unknown) is type)5_MON?)QvQXHD elif issubclass(type(node), type) and type(unknown) is type)5_NPOH)QvQXHH elif issubclass(type(node), type) and type(unknown) is not type)5_OQP)QvQXI' type_ = metaclass_instance'5_PRQvXK KI return visitor(node)5_QSR3  vX: type_ = 'instance'LH elif issubclass(type(node), type) and type(unknown) is not type:5_RTS8   vXU78< print('wandering too far.....', module.__name__)5_SUTK  vX_J& Visitor(module_name).visit(module)5_TVUK  vXcJ* V = Visitor(module_name).visit(module)5_UWVL  vXeK V.visit(module)5_VXWM  vXnL V.visited5_WYXM  vXpL print(V.visited5_XZYA  vX@A5_Y[ZA  vX@A5_Z\[A  vX@A5_[]\A  vX@A5_\^]I  vXHI print(V.visited)5_]_^H  vXGI V.visit(module)G V.visit(module)5_^`_I  vXH print(len(V.visited))5__a`2   vX413 def visit_type(self, type_):14I def visit_type(self, type_):5_`ba3  vXW24J print(type_.__dict__)5_acb3  vXX24J print(type_.__dict__5_bdc3!  vX]24J! for k,v in type_.__dict__5_ced4  vXb35J pass5_dfe4  vXc34 pass5_egf3*  vXe25I* for k,v in type_.__dict__.items():5_fhg3  vXk24J* for k,v in type_.__dict__.items():5_gih3*  vXm25J* for k,v in type_.__dict__.items():5_hji4   vXz35K! if not k.starswith(''5_ikj4"  vX}36K" if not k.starswith('_'5_jlk5  vX455_kml5   vXǀ46K visit5_lnm5  vXǁ46K self.visit5_mon5  vXǂ35$ if not k.starswith('_'):46K self.visit5_npo4  vXǓ35K$ if not k.starswith('_'):5_oqp4  vXǕ35K% if not k.startswith('_'):5_prq4  vXǘ35K& if not k.start!!vXȣ=?N items = module.__dict__5_>&!!vXȥ=?N& items = sorted(module.__dict__5_>'!!vXȨ=?N' items = sorted(module.__dict__)5_>!!vXȪ<> return None5_>!!vXȪ=?N& items = sorted(module.__dict__5_?!!vXȬ<>d return No?!?jedi=0, ne?!? (*_*iterable*_*, cmp=None, key=None, reverse=False) ?!?jedi?!?5_?!!vXȬ>@N" for k,v in items.items() :5_?'!!vXȯ=? items = module.__dict__5_?'!!vXȯ>@N) for k,v in sorted(items.items() :5_?)!!vXȰ=?l items = module._?!?jedi=0, _dict__?!? (*_*iterable*_*, cmp=None, key=None, reverse=False) ?!?jedi?!?>@N* for k,v in sorted(items.items()) :5_5#5#51v1X46N3 print('visit class', type_, type_.__dict__)5_5"5#51v1X46N$ print('visit class', type_,)5_7%5#51v1X68% if not k.startswith('_'):69N% if not k.startswith('_'):5_85#51v1X79O" print(visiting, k)5_85#51v1X79O# print('visiting, k)5_85#51v1X68 if not k?!?jedi=3, .startswith('_'):?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '79O$ print('visiting', k)5_85#51v1X68% if not k.startswith('_'):5_85#51v1X68 if not k?!?jedi=3, .startswith('_'):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?' '5_0'5#51v1X1/1' def visit_instance(self, instance):/2O' def visit_instance(self, instance):5_16#61v1X4/1 def visi?!?jedi=0, t_instance(self, instance):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_16#61v1X502P print(''5_16#61v1X702P print('vis instance'5_16#61v1X9/1' def visit_instance(self, instance):5_1 6#61v1X9/1 def visi?!?jedi=0, t_instance(self, instance):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?02P print(' vis instance'5_1+6#61v1X<02P+ print(' vis instance', instance(5_D6#61v1XɧPE elif isinstance(node, object) and not isinstance(node, type):5_V6#61v1Xɲ type_ = 'module'PX elif isinstance(node, object) and not isinstance(node, type) and not hasattr('':5_V6#61v1Xɴ~ type_ = 'module'?!?jedi=0, ?!? (*_*obj*_*, name) ?!?jedi?!?PW elif isinstance(node, object) and not isinstance(node, type) and not hasattr(':5_'E)*)>v>X')Q if ()Q&)PE print('issubclass(unknown, type)', issubclass(unknown, type))5_)***>v>X(*Q` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_) ***>v>X(*Qd print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_(***>v>X'(! if type(unknown) is type:5_')*)>v>X&(P'(P5_(***>v>X')QE print('issubclass(unknown, type)', issubclass(unknown, type))5_2***>v>X'13Q+ print(' vis instance', instance)5_.***>v>X/,.' def visit_function(self, function):5_.***>v>X/,. def visi?!?jedi=0, t_function(self, function):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?-/Q$ print(function.__qualname__)5_. ***>v>X7-/Q5 print(visiting function : 'function.__qualname__)5_.***>v>X8,. def visi?!?jedi=0, t_function(self, function):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?-/Q6 print('visiting function : 'function.__qualname__)5_.$***>v>X>,.' def visit_function(self, function):-/Q: print('visiting function : 'function.__qualname__)5_.&***>v>X@,.' def visit_function(self, function):5_.%***>v>XI,. def visi?!?jedi=0, t_function(self, function):?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_.***>v>XK,.' def visit_function(self, function):5_.***>v>XL,. def visi?!?jedi=0, t_function(self, function):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?-/Q< print('visiting function : ', function.__qualname__)5_.***>v>XO,.' def visit_function(self, function):5_.***>v>X^,. def visi?!?jedi=0, t_function(self, function):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_:***>v>X_9:' print(' visiting', k)5_!%***>v>X!#Q if unknown in "#Q #P% def visit_unknown(self, unknown):5_"+*+>v>X!#Q3 if unknown in in builtins.__dict__.values()5_!%+*+>v>X #Q% def visit_unknown(self, unknown):5_",*,>v>X!#R import builtins:5_#0,*,>v>X"%R0 if unknown in builtins.__dict__.values()5_$-*->v>X#'S return5_&/*/>v>X%& if 5_.*.>v>X T if node in self.visited:5_#.*.>v>X"#1 if unknown in builtins.__dict__.values():5_# -*->v>X"# return5_",*,>v>X!" import builtins5_+*+>v>XQQ5_,*,>v>XR import builtins5_4,*,>v>XR= if node in self.visited or node in builtins.values():5_DvDX\RF if node in self.visited or node in builtins.__dict__.values():5_DvDX]R return5_%DvDXcR% self.visited.append(node)5_DvDXd% self.visited.append(node)T5_&DvDX% self.visited.append(node)U' mod = getattr(node, __module__)5_ DvDXU if 5_DvDXU if mod.starswith(''5_DvDXU if mod.starswith('_'5_DvDXV+ mod = getattr(node, __module__, '')5_'DvDXV, mod = getattr(node, '__module__, '')5_(DvDX% self.visited.append(node)5_(DvDXa self.vis?!?jedi=0, ited.append(node)?!? (object, *_*name*_*, default=None) ?!?jedi?!?V- mod = getattr(node, '__module__', '')5_DvDXV if mod.starswith('_'):5_DvDXV if mod.startswith('_'):5_DvDXV return5_DvDXY if node == list.append5_ DvDX Z if mod.startswith('_'):5_!DvDX Z# if not mod.startswith('_'):5_)DvDX 0) if not mod.startswith(self.name):Z) if not mod.startswith(self.name):5_DvDX 8 if not m?!?jedi=0, od.startswith(self.name):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?[ print(''5_DvDX ; if not m?!?jedi=0, od.startswith(self.name):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?[ print('skipping'5_,DvDX A% self.visited.append(node)5_,DvDX Ba self.vis?!?jedi=0, ited.append(node)?!? (object, name, *_*default=None*_*) ?!?jedi?!?[- mod = getattr(node, '__module__', '')5_ DvDX E[) if not mod.startswith(self.name):5_DvDX L[2 if mode and not mod.startswith(self.name):5_DvDX T[2 if mode and not mod.startswith(self.name):5_" v!X x1 if mod and not mod.startswith(self.name):[# print('skipping', node)5_3 v!X |1 if mod and not mod.startswith(self.name):5_3 v!X } if mod a?!?jedi=0, nd not mod.startswith(self.name):?!? (value, ..., *_*sep=' '*_*, end='\n', file=sys.stdout, flush=False) ?!?jedi?!?[4 print('skipping', node, node.__module__)5_9* v!X 79' def visit_function(self, function):5_9* v!X 8:[@ print(' visiting function : ', function.__qualname__)5_99 v!X 8:[Q print(' visiting function : ', self.__module__""function.__qualname__)5_9; v!X 8:[R print(' visiting function : ', self.__module__+""function.__qualname__)5_9= v!X 8:[S print(' visiting function : ', self.__module__+"+"function.__qualname__)5_9< v!X 79 def visi?!?jedi=0, t_function(self, function):?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?8:[T print(' visiting function : ', self.__module__+"+"+function.__qualname__)5_9' v!X 79' def visit_function(self, function):8:[T print(' visiting function : ', self.__module__+"."+function.__qualname__)5_9- v!X 8:[\ print(' visiting function : {},{},{}', self.__module__+"."+function.__qualname__)5_9* v!X 8:[\ print(' visiting function : {},{}.{}', self.__module__+"."+function.__qualname__)5_9, v!X 79 def visi?!?jedi=0, t_function(self, function):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_91 v!X 79' def visit_function(self, function):8:[\ print(' visiting function : {}.{}.{}', self.__module__+"."+function.__qualname__)5_9/ v!X 79 def visi?!?jedi=0, t_function(self, function):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_9/ v!X 8:[b print(' visiting function : {}.{}.{}.format( self.__module__+"."+function.__qualname__)5_9L v!X 79' def visit_function(self, function):8:[c print(' visiting function : {}.{}.{}'.format( self.__module__+"."+function.__qualname__)5_9d v!X 8:[z print(' visiting function : {}.{}.{}'.format( self.__module__, self.__class__.__name__. +function.__qualname__)5_9x v!X 79g def visit_function(self, function):?!?jedi=0, ?!? (*args, *_***kwargs*_*) ?!?jedi?!?5_9w v!X 79a def visit_function(self, function):?!?jedi=0, ?!? (*args, **kwargs) ?!?jedi?!?5_: v!X 9: pass5_9y v!X 8:Zy print(' visiting function : {}.{}.{}'.format( self.__module__, self.__class__.__name__, function.__qualname__)5_$$2v2X Z4 print('skipping', node, node.__module__)5_$2v2X 1 if mod and not mod.startswith(self.name):Z% print('skipping', node, )Z5_$2v2X! if mod a?!?jedi=0, nd not mod.startswith(self.name):?!? (value, ..., *_*sep=' '*_*, end='\n', file=sys.stdout, flush=False) ?!?jedi?!?Z7 print('skipping', node.__module__ , node, )5_3$2v2X! if mod a?!?jedi=0, nd not mod.startswith(self.name):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_3$2v2X!Z: print('skipping | ', node.__module__ , node, )5_3$2v2X! if mod a?!?jedi=0, nd not mod.startswith(self.name):?!? (value, ..., *_*sep=' '*_*, end='\n', file=sys.stdout, flush=False) ?!?jedi?!?Z; print('skipping | ', node.__module__ , ,node, )5_4$2v2X! if mod a?!?jedi=0, nd not mod.startswith(self.name):?!? (value, ..., *_*sep=' '*_*, end='\n', file=sys.stdout, flush=False) ?!?jedi?!?Z= print('skipping | ', node.__module__ , '',node, )5_=$2v2X!1 if mod and not mod.startswith(self.name):Z> print('skipping | ', node.__module__ , '|',node, )5_<$2v2X! 1 if mod and not mod.startswith(self.name):5_;$2v2X!  if mod a?!?jedi=0, nd not mod.startswith(self.name):?!? (value, ..., sep=' ', *_*end='\n'*_*, file=sys.stdout, flush=False) ?!?jedi?!?5_$2v2X! Zfrom types import ModuleTypeimport builtinsclass Visitor: def __init__(self, name): self.name = name self.visited = list() def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):= print('skipping | ', node.__module__ , '|',node ) return if node == list.append:' import pdb; pdb.set_trace()( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):9 print(' visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown): print('========')1 print('No clue what to do with', unknown)F print('isinstance(node, object)', isinstance(unknown, object))B print('isinstance(node, type)', isinstance(unknown, type))* print('type(node)', type(unknown))! if type(unknown) is type:I print('issubclass(unknown, type)', issubclass(unknown, type))` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))@ print('type(unknown) is type : ', type(unknown) is type) print('========')' def visit_function(self, function):z print(' visiting function : {}.{}.{}'.format( self.__module__, self.__class__.__name__, function.__qualname__))' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):# print('visit class', type_)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module):5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module) print(len(V.visited))5_$2v2X!Zfrom types import ModuleTypeimport builtinsclass Visitor: def __init__(self, name): self.name = name self.visited = list() def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):= print('skipping | ', node.__module__ , '|',node ) return if node == list.append:' import pdb; pdb.set_trace()( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):9 print(' visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown): print('========')1 print('No clue what to do with', unknown)F print('isinstance(node, object)', isinstance(unknown, object))B print('isinstance(node, type)', isinstance(unknown, type))* print('type(node)', type(unknown))! if type(unknown) is type:I print('issubclass(unknown, type)', issubclass(unknown, type))` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))@ print('type(unknown) is type : ', type(unknown) is type) print('========')' def visit_function(self, function):z print(' visiting function : {}.{}.{}'.format( self.__module__, self.__class__.__name__, function.__qualname__))' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):# print('visit class', type_)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module):5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module) print(len(V.visited))5_$2v2X!' import pdb; pdb.set_trace()5_$2v2X! if node == list.append:5_$2v2X!5_$2v2X!5_  $2v2X!dV< print('skipping | ', node.__module__, '|', node)5_  $$2v2X!y#%V9 print(' visiting meta instance', meta_instance)5_   =$2v2X!;= def visit_type(self, type_):<>V# print('visit class', type_)5_   =$2v2X!<>V print(' class', type_)5_   =$2v2X!;=} def visi?!?jedi=0, t_type(self, type_):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?<>V print('class', type_)5_  =$2v2X!;= def visit_type(self, type_):<>V print('Class', type_)5_ $$2v2X!#%V6 print('visiting meta instance', meta_instance)5_59595<v<X!46Vz print(' visiting function : {}.{}.{}'.format( self.__module__, self.__class__.__name__, function.__qualname__))56V5_5N5N5QvQX!46V~ print(' visiting function : {}.{}.{}'.format( function.__module__, self.__class__.__name__, function.__qualname__))56V5_5*5N5QvQX"&46V print(' visiting function : {}.{}.{}'.format( function.__module__, function.__class__.__name__, function.__qualname__))5_5-5N5QvQX"'35' def visit_function(self, function):46V print(' visiting function : {}.-{}.{}'.format( function.__module__, function.__class__.__name__, function.__qualname__))5_5.5N5QvQX")35' def visit_function(self, function):5_5-5N5QvQX"35 def visi?!?jedi=0, t_function(self, function):?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_4'5P5avaX"48W klass = 56W36V' def visit_function(self, function):5_78P8avaX"6:Y name = ''5_7:;:MvMX"68[ name = ''78[5_7(:;:MvMX"68[( name = 'function.__module__'5_7:;:MvMX"68[' name = 'function.__module__5_955!v!X"8:[ name = 9:[5_955!v!X"8:[0 name = function.__class__.__module__5_955!v!X"8:[2 name = ''function.__class__.__module__5_955!v!X"8:[3 name = '.'function.__class__.__module__5_955!v!X"8:[5 name = '%s.'function.__class__.__module__5_ 955!v!X"8:[7 name = '%s.%s'function.__class__.__module__5_! 955!v!X"8:[; name = '%s.%s' % *function.__class__.__module__5_ "!9;55!v!X"8:[; name = '%s.%s' % (function.__class__.__module__5_!#":):):.v.X"9;[ print(' visiting function : {}.-{}-.{}'.format( function.__module__, function.__class__.__name__, function.__qualname__))5_"$#:):):.v.X"8:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)9;[~ print(' visiting function : {}{}'.format( function.__module__, function.__class__.__name__, function.__qualname__))5_#%$:6:6:_v_X"9;[ print(' visiting function : {}.{}'.format( function.__module__, function.__class__.__name__, function.__qualname__))5_$&%:::6:_v_X"9;[U print(' visiting function : {}.{}'.format( name__, function.__qualname__))5_%'&:::6:_v_X"9;[T print(' visiting function : {}.{}'.format( name_, function.__qualname__))5_&('6%:6:_v_X#c57[& if klass is builtins.function:67[5_')(:6:_v_X#l[import builtins5_(*);6;_v_X#\ def visit(self, node):5_)+*=6=_v_X#^5_*,+)>6>_v_X#_+ if node is frozenset.__contains__: 5_+-,>6>_v_X# if node is frozenset: ' import pdb; pdb.set_trace()5_,.-<6<_v_X#]]5_-/.>6>_v_X# if node is frozenset: ' import pdb; pdb.set_trace()5_.0/<6<_v_X#]]5_/10>6>_v_X#_ if node is frozenset: 5_021(>6>_v_X$+ if node is frozenset.__contains__: ' import pdb; pdb.set_trace()5_1323 <6<_v_X$ 36]34]5_2434>6>_v_X$ 35_+ if node is frozenset.__contains__: 5_3544>6>_v_X$ 34+ sf node is frozenset.__contains__: 5_4654 =6=_v_X$ 35^' import pdb; pdb.set_trace()5_5764=6=_v_X&a34# import pdb; pdb.set_trace()5_687;Y<6<_v_X&l:=]Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_798<='=PvPX&<>_ fullqual = ;= self.collected.add()=>_;>^ self.collected.add()5_8:9=>'>PvPX&;=F self.collected.add()?!?jedi=0, ?!? (format_spec) ?!?jedi?!?5_9;:=>'>PvPX&<>_> fullqual = {}.{}'.format( name, function.__qualname__'5_:<;>>'>PvPX&=>S print(' visiting function : {}.{}'.format( name, function.__qualname__))5_;=< >'>PvPX& ^ self.visited = list()5_<>= ?'?PvPX& _ self.collected = []5_=?> ?'?PvPX& _ self.collected = {}5_>@? ?'?PvPX& _ self.collected = {}5_?A@ ?'?PvPX& _ self.collected = set({}5_@BA=?'?PvPX&;=Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_ACB=?'?PvPX&;=| name = '%s.%s?!?jedi=1, ' % (fun?!? (*_**_*) ?!?jedi?!?'ction.__class__.__module__, function.__class__.__name__)<>_ self.collected.add()5_BDC>?'?PvPX&=>? fullqual = '{}.{}'.format( name, function.__qualname__'5_CED=>'>PvPX&<>^=>^5_DFE=??'?PvPX&;=Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)<>_? fullqual = '{}.{}'.format( name, function.__qualname__'5_EGF="?'?PvPX& <>_? fullqual = '{}.{}'.format( name, function.__qualname__)5_FHG ?'?PvPX& _ import types5_GIHE'EPvPX'edef fully_qualified(obj):5_HJIE'EPvPX' e def fully_qualified(obj:object):5_IKJE'EPvPX' e """5_JLK F'FPvPX'*  5_KML ?BXvXX'7 f  f e """5_LNM CFXvXX': i& name = function.__module__5_MON CFXvXX': i% name = function.__module__5_NPO CFXvXX': i$ name = function.__module__5_OQP CFXvXX'; i# name = function.__module__5_PRQ CFXvXX'; i else:5_QSR CFXvXX'; i else:5_RTS CFXvXX'; i else:5_SUT CFXvXX'; i else:5_TVU CFXvXX'< iY name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_UWV CFXvXX'< iX name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_VXW CFXvXX'< iW name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_WYX CFXvXX'<  iV name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_XZY UCFXvXX'@ iU name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_Y[Z CC v X'S j# if klass is types.FunctionType:5_Z\[  vX'g j return name5_[]\  vX'i j return ''name5_\^] vX'u  return '%s'name5_]_^  vX'y i" name = function.__module__5_^`_  vX'| i$ return = function.__module__5__a`  vX' i" return function.__module__5_`ba  vX' i$ return ''function.__module__5_acb  vX' i) return '%s.%s'function.__module__5_bdc   !v!X' i, return '%s.%s' % function.__module__ iU name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)5_ced 4  v X' iP name = '%s.%s' % (obj.__class__.__module__, function.__class__.__name__)5_dfe   v X' i' return '%s.%s' % obj.__module__5_egf (  v X' i( return '%s.%s' % (obj.__module__5_fhg 7  v X' j7 return '%s.%s' % (obj.__module__, obj.__class__5_gih v X' jK name = '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)5_hxi  v X' 5_iyjxG>HH"v"X(FH> fullqual = '{}.{}'.format(name, function.__qualname__)FJi> fullqual = '{}.{}'.format(name, function.__qualname__)5_xzyHII"v"X(#FH> fullqual = '{}.{}'.format(name, function.__qualname__)GIj print(' ', full5_y{zHII"v"X('GIj print(' ', fullqua5_z|{QII"v"X(MOQ def visit_type(self, type_):PRj& print('Class', type_.__name__)5_{}|QII"v"X([PRj; print('Class', type._module__ +'.'+ type_.__name__)5_|~}QII"v"X(jPRj< print('Class', type.__module__ +'.'+ type_.__name__)5_}~QII"v"X(kOQ def visit_type(self, type_):5_~QII"v"X(OQ} def visi?!?jedi=0, t_type(self, type_):?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_W#QQVX(WYkXYkVYj# def visit_module(self, module):5_YQQVX(XY 5_X<QQVX(VX# def visit_module(self, module):WYk= print('Class', type_.__module__ +'.'+ type_.__name__)5_XQQVX( VX def visi?!?jedi=0, t_module(self, module):?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?WYk print('Class', module)5_!QQVX7sk! self.collected = set({})5_TTVX7|n! self.collected = set({})5_!TTVX7~n! self.collected = set({})5_ UUVX7o def _consistent(key, value):5_%WWVX7q& assert self._consistency[]5_&WWVX7q( assert self._consistency['']5_+WWVX7q+ assert self._consistency['key']5_*YYVX7s4 assert self._consistency['key'] is value5_&YYVX7s3 assert self._consistency['key] is value5_YYVX7s self.5_YYVX7s self._consistency[]5_"YYVX7!s" self._consistency[key]5_Q$YYVX7#PR$ self.collected.add(fullqual)PSs$ self.collected.add(fullqual)5_ZZVX8$t def _consistent(key, value):5_ZZVX8tfrom types import ModuleTypeimport builtins import types'def fully_qualified(obj:object) -> str: """9 (try to) return the fully qualified name of an object """! if obj is types.FunctionType:; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = name self.visited = list()! self.collected = set({}) self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:2 assert self._consistency[key] is value else :* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown): print('========')1 print('No clue what to do with', unknown)F print('isinstance(node, object)', isinstance(unknown, object))B print('isinstance(node, type)', isinstance(unknown, type))* print('type(node)', type(unknown))! if type(unknown) is type:I print('issubclass(unknown, type)', issubclass(unknown, type))` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))@ print('type(unknown) is type : ', type(unknown) is type) print('========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):= print('Class', type_.__module__ +'.'+ type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module) print(len(V.visited))5_VX8$tfrom types import ModuleTypeimport builtins import types'def fully_qualified(obj:object) -> str: """9 (try to) return the fully qualified name of an object """! if obj is types.FunctionType:; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = name self.visited = list()! self.collected = set({}) self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:2 assert self._consistency[key] is value else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown): print('========')1 print('No clue what to do with', unknown)F print('isinstance(node, object)', isinstance(unknown, object))B print('isinstance(node, type)', isinstance(unknown, type))* print('type(node)', type(unknown))! if type(unknown) is type:I print('issubclass(unknown, type)', issubclass(unknown, type))` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))@ print('type(unknown) is type : ', type(unknown) is type) print('========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):= print('Class', type_.__module__ +'.'+ type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module) print(len(V.visited))5_ VX8(tfrom types import ModuleTypeimport builtins import types'def fully_qualified(obj:object) -> str: """9 (try to) return the fully qualified name of an object """! if obj is types.FunctionType:; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = name self.visited = list() self.collected = set({}) self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:2 assert self._consistency[key] is value else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown): print('========')1 print('No clue what to do with', unknown)F print('isinstance(node, object)', isinstance(unknown, object))B print('isinstance(node, type)', isinstance(unknown, type))* print('type(node)', type(unknown))! if type(unknown) is type:I print('issubclass(unknown, type)', issubclass(unknown, type))` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))@ print('type(unknown) is type : ', type(unknown) is type) print('========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):= print('Class', type_.__module__ +'.'+ type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module) print(len(V.visited))5_VX8-&tfrom types import ModuleTypeimport builtins import types'def fully_qualified(obj:object) -> str: """9 (try to) return the fully qualified name of an object """! if obj is types.FunctionType:; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = name self.visited = list() self.collected = set({}) self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:2 assert self._consistency[key] is value else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown): print('========')1 print('No clue what to do with', unknown)F print('isinstance(node, object)', isinstance(unknown, object))B print('isinstance(node, type)', isinstance(unknown, type))* print('type(node)', type(unknown))! if type(unknown) is type:I print('issubclass(unknown, type)', issubclass(unknown, type))` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))@ print('type(unknown) is type : ', type(unknown) is type) print('========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):= print('Class', type_.__module__ +'.'+ type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module) print(len(V.visited))5_ !VX8L t! if obj is types.FunctionType:5_ #VX8N' t' if obj is types.FunctionType: #noqu5_ $VX8Q t( if obj is types.FunctionType: # noqu5_ (VX8S) t( if obj is types.FunctionType: # noqu5_*VX8st* self._consistency[key] = value5_-VX8vt. self._consistency[key] = value, ""5_:VX8}t: self._consistency[key] = value, "%s is not %s"5_>VX8t? self._consistency[key] = value, "%s is not %s" % ()5_PVX8tR self._consistency[key] = value, "%s is not %s" % (self._consistency[])5_TVX8+tU self._consistency[key] = value, "%s is not %s" % (self._consistency[key])5_**[v[X8t\ self._consistency[key] = value, "%s is not %s" % (self._consistency[key], value)5_2*[v[X8,t2 assert self._consistency[key] is valuet5_4*[v[X8/tf assert self._consistency[key] is value, , "%s is not %s" % (self._consistency[key], value)5_ *[v[X8te assert self._consistency[key] is value, "%s is not %s" % (self._consistency[key], value)5_)*[v[X8ta if self._consistency[key] is value, "%s is not %s" % (self._consistency[key], value)5_5*[v[X8te if self._consistency[key] is not value, "%s is not %s" % (self._consistency[key], value)5_F*[v[X8uF print("%s is not %s" % (self._consistency[key], value)5_G*[v[X80uG print("%s is not %s" % (self._consistency[key], value))5_ * [v[X>{1+ import pdb; pdb.set_trace()5_#*[v[X>3 if self._consistency[key] is not value:5_!*[v[X>2 if self.?!?jedi=0, _consistency[key] is not value:?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?uG print("%s is not %s" % (self._consistency[key], value))5_*[v[X>3 if self._consistency[key] is not value:uW print("%s is not consistent with %s" % (self._consistency[key], value))5_*[v[X>u` print(" Warning %s is not consistent with %s" % (self._consistency[key], value))5_8*[v[X> if self.?!?jedi=0, _consistency[key] is not value:?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?u_ print("Warning %s is not consistent with %s" % (self._consistency[key], value))5_+*[v[X>33 if self._consistency[key] is not value:uO print("Warning %s is not %s" % (self._consistency[key], value))5_J*[v[X>3 if self._consistency[key] is not value:5_I*[v[X> if self.?!?jedi=0, _consistency[key] is not value:?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_m*[v[X>louif __name__ == '__main__':5_*[v[X>vimport builtins5_  * [v[X>4w import sy5_p * [v[X>6orw print("let's go")5_q * [v[X>oq print("let's go")5_q * [v[X>prx print(sys.argv)5_q * [v[X>7oqw prin?!?jedi=5, t("let's go")?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?" ' "prx print(sys.argv[])5_q * [v[X>oq print("let's go")5_q * [v[X>8oqw prin?!?jedi=5, t("let's go")?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?" ' "prx print(sys.argv[2])5_p * [v[X>orx print("let's go")5_q  * [v[X>pry if len sys5_q * [v[X>pry if len(sys5_r * [v[X>qsy print(sys.argv[1])5_r * [v[X>pr if len(sys.argv) > 1:5_r * [v[X>prv if len(s?!?jedi=0, ys.argv) > 1:?!? (*_*value*_*, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?qsy print(sys.argv[1])5_r * [v[X>qr print(sys)5_q * [v[X>psx if len(sys.argv) > 1:5_r  * [v[X?qsy modu5_r! * [v[X?qty! module_name = sys.argv[1]5_u * [v[X?tvz module_name = 'IPython'5_t * [v[X?9st5_t * [v[X?:svy module_name = 'IPython'5_@@DX?r@Ez1 print('No clue what to do with', unknown)F print('isinstance(node, object)', isinstance(unknown, object))B print('isinstance(node, type)', isinstance(unknown, type))* print('type(node)', type(unknown))>@?Az print('========')5_@@DX?x?Azprint('Unknown: ========')5_@@DX?x;?Az print('Unknown: ========')5_ X?z import types5_X?{5_X? import sys 5_X?<5_X?5_X?5_X?=5_>>AX?>BwG print(' isinstance(node, object)', isinstance(unknown, object))C print(' isinstance(node, type)', isinstance(unknown, type))+ print(' type(node)', type(unknown))=?w2 print(' No clue what to do with', unknown)5_D>AX?CEw` print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_D >AX?CEwm print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_C >AX?BDwI print('issubclass(unknown, type)', issubclass(unknown, type))5_C>AX?BDwE print('issubclass(unknown, type)', issubclass(unknown, type))5_C>AX?>BDwI print('issubclass(unknown, type)', issubclass(unknown, type))5_E>AX?DFw@ print('type(unknown) is type : ', type(unknown) is type)5_F>AX??EGw print('========')5_E>AX@ EGwEFw5_FFF-v-X@EGxI print('Unknown: type(unknown) is type : ', type(unknown) is type)5_F FF-v-X@@EGxF print('Unknown: hasattr('__call__'): ', type(unknown) is type)5_F)FF3v3X@%EGxO print('Unknown: hasattr(unknown, '__call__'): ', type(unknown) is type)5_F2FF3v3X@&EGxO print('Unknown: hasattr(unknown, "__call__'): ', type(unknown) is type)5_F9F9FNvNX@+AEGxO print('Unknown: hasattr(unknown, "__call__"): ', type(unknown) is type)FGx5_FUF9FNvNX@6CEGxU print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__")5_x F9FNvNX@iw print(len(V.visited))5_x"F9FNvNX@rw# print("Visited",len(V.visited))5_x%F9FNvNX@tDw' print("Visited",len(V.visited), "")5_x F9FNvNX@xx5_yF9FNvNX@x. print("Visited",len(V.visited), "objects")5_y F9FNvNX@Ex0 print("Visited",len(V.collected), "objects")5_y0F9FNvNX@Fx2 print("Collected",len(V.collected), "objects")5_ F9FNvNX@y self.collected = set({})5_Q$F9FNvNXC4PSy$ self.collected.add(fullqual)5_F9FNvNXC?z self.name = name5_G9GNvNXCR{ self.name = name5_H9HNvNXCUG|class Visitor:5_J9JNvNXCc~from types import ModuleTypeimport builtins import sys import types(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: visited:list def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle. self.visited = list() self.ollected = set({}) self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual) self., self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):= print('Class', type_.__module__ +'.'+ type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module). print("Visited",len(V.visited), "objects")0 print("Collected",len(V.collected), "items")5_9NvNXCfH visited: list5_9NvNXCn visited: list5_9NvNXCnI5_9NvNXCw| self.visited = list()5_ 9NvNXCy~ self.ollected = set({})5_9NvNXC{~5_ 9NvNXC~ self.collected = set({})5_ 9NvNXC self.collected = set({})5_9NvNXCJ self.collected = set({}5_9NvNXC self.collected = {}5_9NvNXC self.collected = {}5_9NvNXC self.collected = set({}5_9NvNXC5_9NvNXC self.spec()5_9NvNXCK self.spec()5_ 9NvNXCL; # list of object that where deemed worth collecting5_9NvNXC: # set of object that where deemed worth collecting5_G9NvNXCG # list of visited nodes to avoid recursion and going in circle.5_-9NvNXD/ # can't be a set we store non-hashable 5_/9NvNXD 0 # can't be a set we store non-hashabl1e 5_ &9NvNXD/ # can't be a set we store non-hashable 5_  &9NvNXDM/ # can't be a set we store non-washable 5_   79NvNXD7 # can't be a set we store non-hashable objects 5_    9NvNXD7N # anyay...5_   9NvNXD=!5_  9NvNXDX" # later.5_ !9NvNXD^O !5_` 9NvNXDi_a self.5_`9NvNXDn_a self.spec[]5_`9NvNXDs_a self.spec[fullqual]5_`9NvNXD|_a self.spec[fullqual] = 5_`9NvNXD_a9 self.spec[fullqual] = inspect.signature(function)5_`=9NvNXDR_a= self.spec[fullqual] = str(inspect.signature(function)5_9NvNXDSimport builtins5_9NvNXDTimport builtins5_9NvNXDfrom types import ModuleTypeimport inspect import sys import types(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.7 # can't be a set we store non-hashable objects B # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual)> self.spec[fullqual] = str(inspect.signature(function)), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):= print('Class', type_.__module__ +'.'+ type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module). print("Visited",len(V.visited), "objects")0 print("Collected",len(V.collected), "items")5_i9NvNXDfrom types import ModuleTypeimport inspect import sys import types(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual)> self.spec[fullqual] = str(inspect.signature(function)), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):= print('Class', type_.__module__ +'.'+ type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module). print("Visited",len(V.visited), "objects")0 print("Collected",len(V.collected), "items")5_j9NvNXDfrom types import ModuleTypeimport inspect import sys import types(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual)> self.spec[fullqual] = str(inspect.signature(function)), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):? print('Class', type_.__module__ + '.' + type_.__name__)2 for k,v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module). print("Visited",len(V.visited), "objects")0 print("Collected",len(V.collected), "items")5_t9NvNXDfrom types import ModuleTypeimport inspect import sys import types(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual)> self.spec[fullqual] = str(inspect.signature(function)), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):? print('Class', type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__) for k,v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module). print("Visited",len(V.visited), "objects")0 print("Collected",len(V.collected), "items")5_9NvNXDfrom types import ModuleTypeimport inspect import sys import types(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual)> self.spec[fullqual] = str(inspect.signature(function)), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):? print('Class', type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__* for k, v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module). print("Visited",len(V.visited), "objects")0 print("Collected",len(V.collected), "items")5_9NvNXDVfrom types import ModuleTypeimport inspect import sys import types(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual)> self.spec[fullqual] = str(inspect.signature(function)), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):? print('Class', type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__* for k, v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module)/ print("Visited", len(V.visited), "objects")0 print("Collected",len(V.collected), "items")5_19NvNXD1 print("Collected", len(V.collected), "items")5_9NvNXD import pprint5_ 19NvNXDW1 print("Collected", len(V.collected), "items")5_! 9NvNXE9 pprint(V.spec)5_ "!9NvNXE< from pprint import pprint5_!#"9NvNXEE with open()5_"$#9NvNXEH with open('')5_#%${9NvNXENzif __name__ == '__main__':5_$&%9NvNXE\~ argparse.ArgumentParser5_%'&9NvNXEj~ argparse.ArgumentParser()5_&('&9NvNXEl~& parser = argparse.ArgumentParser()5_')(9NvNXEz parser.add_argument(''5_(*) 9NvNXE} parser.add_argument('--save'5_)+* 9NvNXEX~& parser = argparse.ArgumentParser()5_*,+"9NvNXE" parser.add_argument('--save', 5_+-,69NvNXE6 parser.add_argument('--save', action='store_true')5_,.-9NvNXE parser.parse_args(sys.argv)5_-/.%9NvNXE% res = parser.parse_args(sys.argv)5_.0/9NvNXE print(5_/109NvNXE5_021 9NvNXEY print(5_1329NvNXEZ with open('%s')5_2439NvNXE5_3549NvNXE6 parser.add_argument('--save', action='store_true')5_4659NvNXE5 parser.add_argument('-save', action='store_true')5_5769NvNXE4 parser.add_argument('save', action='store_true')5_68759NvNXE6 parser.add_argument('module', action='store_true')5_798!9NvNXE! parser.add_argument('module')5_8:99NvNXF! parser.add_argument('module')5_9;:!9NvNXF" parser.add_argument('modules')5_:<;*9NvNXF[, parser.add_argument('modules', nargs='')5_;=<%9NvNXF\% res = parser.parse_args(sys.argv)5_<>=9NvNXF% res = parser.parse_args(sys.argv)5_=?>%9NvNXF]% res = parser.parse_args(sys.argv)5_>@?9NvNXF^ print(res)5_?A@9NvNXF_ print(parser.modules)5_@BA9NvNXF` print(parser.modules)dd5_ACB%9NvNXF% res = parser.parse_args(sys.argv)5_BDC9NvNXF res.modules.pop()5_CED9NvNXFa res.modules.pop('')5_DFE9NvNXFb" res.modules.pop('__init__.py')5_EGF9NvNXG 5_FHG9NvNXGc6 parser.add_argument('--save', action='store_true')5_GIH9NvNXG print(res)5_HJI%9NvNXG% res.modules.remove('__init__.py')5_IKJ9NvNXG if save5_JLK9NvNXG if res.__subclasshook__save5_KMLvXGd% res = parser.parse_args(sys.argv)% res.modules.remove('__init__.py')5_LNM)vXG!) options.modules.remove('__init__.py')5_MON'vXG]' if options.save and option.compare:5_NPOvXG` print()5_OQPvXGa print('')5_PRQvXGd print('--save')5_QSR$vXGl% print('--save and --compare')5_RTS#vXGne% print('--save and --compare')5_SUTvXGt3 print('--save and --compare are exclusive')5_TVUvXGw< print('options `--save and --compare are exclusive')5_UWV$vXGx= print('options `--save` and --compare are exclusive')5_VXW.vXGzg> print('options `--save` and `--compare are exclusive')5_WYXvXG from pprint import pprint5_XZYvXG with open(''5_Y[ZvXG with open('%s.json'5_Z\[vXG from pprint import pprint5_[]\vXG5_\^]vXG from pprint import pprint5_]_^vXGhfrom types import ModuleType5_^`_ vXGj import types5__a`vXHimport inspect5_`bavXH5_acbvXH"""5_bdcvXH l5_ced)vXH. with open('%s.json' % module_name as f5_dfe)vXH/ with open('%s.json' % module_name) as f5_egf)vXH1 with open('%s.json' % module_name'') as f5_fhg,vXHm3 with open('%s.json' % module_name, '') as f5_gih4vXHn4 with open('%s.json' % module_name, 'w') as f5_hjivXHo print(res)5_ikjvXHp if save:5_jlkvXHr""" Frappucinno"""import inspectfrom pprint import pprint import sys import types import json(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) print(' ', fullqual)$ self.collected.add(fullqual)> self.spec[fullqual] = str(inspect.signature(function)), self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):? print('Class', type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'): self.visit(v)# def visit_module(self, module): print('Module', module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__* for k, v in sorted(items.items()):! if k.startswith('_'): continue else: self.visit(v)if __name__ == '__main__': import argparse% parser= argparse.ArgumentParser()6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')- parser.add_argument('modules', nargs='*')( argparse.ArgumentParser.add_argument) options = parser.parse_args(sys.argv)) options.modules.remove('__init__.py')' if options.save and option.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() sys.exit(0) print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module)/ print("Visited", len(V.visited), "objects")1 print("Collected", len(V.collected), "items") if options.save:5 with open('%s.json' % module_name, 'w') as f:' f.write(json.dumps(V.spec)) pprint(V.spec)5_kmlvXHs' if options.save and option.compare:5_lnmvXIt sys.exit(0)5_monvXI 5_npovXIfrom pprint import pprint5_oqp vXI  5_prq vXI  import json5_qsr vXIv from pprint import pprint5_rts vXI*x from typing import ModuleType5_sutvXI6y pprint(V.spec)5_tvu8vXI?5_uwv"vXIBz9 parser.add_argument('--compare', action='store_true')5_vxwvXIL{ def __init__(self, name):5_wyx   v.XIX from types import ModuleType5_xzy  v.XIe| from log5_y{z  v.XIi} 5_z|{  v.XI from logging import logger5_{}|  v.XI from logging import Logger5_|~}  v.XI~ 5_}~  v.XI import logging5_~  v.XI5_  v.XIlogger = logging.getLogger()5_  v.XI logger.set5_  v.XI5_  v.XI parser.print_help()5_h 3vXIgi print(' ', fullqual)5_z 3vXJy{ print('Module', module)5_s 3vXJrt? print('Class', type_.__module__ + '.' + type_.__name__)5_ 3vXJA logger.setLevel("DEBUG")5_ 3vXJD5_ 4vXJE logger.setLevel("DEBUG")5_ 4vXJN5_ 4vXJZ logger.setLevel("DEBUG")5_vXJlogger = logging.getLogger()5_vXKd logger.setLevel(50)5_vXK import logging5_vXKlogger.setLevel("DEBUG")5_vXLlogger.setLevel(0)5_vXL logger.setLevel(50)5_ vXL logger.log()5_ vXLlogger.log('')5_ vXLlogger.log('HO')5_vXL'logger.info('HO')5_vXL.logger.critical('HO')5_vXL6logger.setLevel(50)5_vXLBlogger.setLevel(0)5_vXLElogger.setLevel(0')5_vXL logger.setLevel(0)5_vXL logger.setLevel('')5_vXL if options.debug:5_vXL logger.debug()5_vXL logger.debug('')5_vXL5_vXL logger.debug('before')5_jvXLik& logger.debug(' ', fullqual)5_jvXLik( logger.debug(' %s', fullqual)5_jvXLik( logger.debug(' {}', fullqual)5_j(vXLik) logger.debug(' {f}', fullqual)5_j vXLik) logger.debug(' {f}', fullqual)5_j vXLik, logger.debug(' {f}', if=fullqual)5_j vXLik+ logger.debug(' {f}', f=fullqual)5_j1vXLik1 logger.debug(' {f}'.format(f=fullqual)5_|vXL{}& logger.debug('Module', module)5_|!vXL{}) logger.debug('Module %s', module)5_uvXLtvF logger.debug('Class', type_.__module__ + '.' + type_.__name__)5_u vXLtvI logger.debug('Class %s', type_.__module__ + '.' + type_.__name__)5_%vXM' f.write(json.dumps(V.spec))5_vXQ5_1vXT1 f.write(json.dumps(V.spec, indent=2))5_vXT5_-vXT5 with open('%s.json' % module_name, 'w') as f:5_ vXU1 f.write(json.dumps(V.spec, indent=2))5_ vXU5 jsonf.write(json.dumps(V.spec, indent=2))5_DvXUE loaded = jons.loads(f.write(json.dumps(V.spec, indent=2))5_)vXU) loaded = jons.loads(f.write()5_'vXU* loaded = jons.loads(f.write())5_)vXU ) loaded = jons.loads(f.read())5_vXU\ for l,g in sorted(V.spec), 5_vXU for (l,g in sorted(V.spec), 5_vXU5_vXU lkeys = set(loaded.keys())5_vXU skeys = set(V.spec.keys())5_$vXU$ common_keys = skeys.union(skeys)5_*vXU* removed_keys = lkeys.difference(skeys)5_&vXU& new_keys = skeys.difference(lkeys)5_(vXU( print("The following items are new")5_vXU pprint(new_keys5_vXU pprint(new_keys)5_vXV5_ vXV print()5_vXV0 print("The following itmes have disapeared")5_vXV/ print("The following ites have disapeared")5_$vXV0 print("The following items have disapeared")5_/vXV1 print("The following items have disappeared")5_vXV5_vXV pprint(new_keys)5_ vXV% )5_ v'XV, lkeys = set(loaded.keys()) skeys = set(V.spec.keys())$ common_keys = skeys.union(skeys)* removed_keys = lkeys.difference(skeys)& new_keys = skeys.difference(lkeys)( print("The following items are new") pprint(new_keys) print()2 print("The following items have been removed") pprint(removed_keys print()5_ v'XVE pprint(removed_keys5_  v'XVL if not save:5_ v'XVU) loaded = jons.loads(f.read())5_vXVr for key in  print()5_vXV{ if []5_vXV for key in common_keys:5_vXV l = loaded[]5_vXV l = loaded[key]5_vXV s = V..spec5_vXV s = V.spec5_vXV s = V.spec[]5_vXV if []5_vXV print(""5_vXV5_vXV print(""5_vXV print(""5_vXV- print("THe following signature differ5_-vXV- print("The following signature differ5_vXV if s != v:5_vXV print(k,l 5_vXV print(l 5_vXV print("" 5_vXV print("%s%s" 5_ vXV" print("%s%s" 5 () 5_vXV if s != v:5_vXV print()5_vXV5_!vXV$ print("%s%s" 5 (kl) 5_!vXV$ print("%s%s" 5 (kl) 5_vXV% print("%s%s" 5 (k,l) 5_vXV% print("%s%s" 5 (k,l) 5_%vXV% print("%s%s" % (k,l) 5_%vXV% print("%s%s" % (k,l) 5_vXV if s != v:5_#vXV% print("%s%s" % (k,l))5_vXV% print("%s%s" % (k,s))5_vXV% print("%s%s" % (k,l))5_vXV' print("> %s%s" % (k,s))5_vXW' print(" %s%s" % (k,l))5_vXW  if s != v:5_vXW( common_keys = skeys.union(skeys)5_)vXW/ common_keys = skeys.intersection(skeys)5_nnn=v=X[mo> self.spec[fullqual] = str(inspect.signature(function))5_k>nn=v=X[km sig= lmjm> fullqual = '{}.{}'.format(name, function.__qualname__)5_l oo=v=X[km- sig= str(inspect.signature(function))5_moo=v=X[ln2 logger.debug(' {f}'.format(f=fullqual))5_moo=v=X[ln4 logger.debug(' {f}{}'.format(f=fullqual))5_m4oo=v=X[ln5 logger.debug(' {f}{s}'.format(f=fullqual))5_ m3oo=v=X[ln5 logger.debug(' {f}{s}'.format(f=fullqual))5_  ooo=v=X[np self.spec[fullqual] = 5_   oo=v=X[ if s != s:5_   .oo=v=X[. print("current> %s%s" % (k,s))5_   oo=v=X[ print(loaded[]5_  7oo=v=X[8 print(loaded['nbconvert.filters.ansi.strip_ansi]5_ 9oo=v=X[9 print(loaded['nbconvert.filters.ansi.strip_ansi']5_Coo=v=X[C print(loaded['nbconvert.filters.ansi.strip_ansi'], V.spec()5_Boo=v=X[C print(loaded['nbconvert.filters.ansi.strip_ansi'], V.spec[]5_foo=v=X[f print(loaded['nbconvert.filters.ansi.strip_ansi'], V.spec['nbconvert.filters.ansi.strip_ansi']5_*oo=v=X[. print(" %s%s" % (k,l))5_*oo=v=X[. print("current> %s%s" % (k,s))5_oo=v=X\$g print(loaded['nbconvert.filters.ansi.strip_ansi'], V.spec['nbconvert.filters.ansi.strip_ansi'])5_oo=v=X]m items = module.__dict__5_oo=v=X]t self.visit(v)5_oo=v=X] attribs = []5_/v/X]1 attribs = [k for k in module.__dict__ is]5_{/v/X]z~ self.visit(v)5_w x"xHvHX]wy local_key = xyvy def visit_type(self, type_):5_|y"yHvHX]{~ self.visit(v)5_y"yHvHX` self.visit(v)5_#y"yHvHX`# res = self.visit(v)5_x;y"yHvHX`wz; local_key = type_.__module__ + '.' + type_.__name__5_ }z"zHvHX`|~ self.visit(v)5_! ~z"zHvHX`} return local_key5_ "!~'z"zHvHX`}' return local_key = list(filter(5_!#"~0z"zHvHX`}3 return local_key = list(filter(None, itmes)5_"$#~0z"zHvHX`}2 return local_key = list(filter(None, ites)5_#%$~3z"zHvHX`}3 return local_key = list(filter(None, items)5_$&%}z"zHvHX`|~% items = self.visit(v)5_%'&}z"zHvHX`|~* items = list(self.visit(v)5_&('}*z"zHvHX`|~* items.append(self.visit(v)5_')(~z"zHvHXa)}4 return local_key = list(filter(None, items))5_(*)~2z"zHvHXa-}2 local_key = list(filter(None, items))5_)+*~ z"zHvHXa0}~2 local_key = list(filter(None, items))5_*,+}+z"zHvHXa2|+ items.append(self.visit(v))5_+-,~z"zHvHXa>}~5_,.-}+z"zHvHXa{|+ items.append(self.visit(v))5_-/.~ z"zHvHXa} self.5_.0/~z"zHvHXa} self.spec[]5_/10~z"zHvHXa} self.spec[local_key]5_021}+z"zHvHXa|+ items.append(self.visit(v))5_132z"zHvHXa""" Frappucinno"""import inspect import sys import types import jsonfrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__)logger.debug('HO')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({})M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): if node in self.visited: return else:% self.visited.append(node)/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):7 #print('visiting meta instance', meta_instance) pass% def visit_unknown(self, unknown):" print('Unknown: ========'): print('Unknown: No clue what to do with', unknown)O print('Unknown: isinstance(node, object)', isinstance(unknown, object))K print('Unknown: isinstance(node, type)', isinstance(unknown, type))3 print('Unknown: type(node)', type(unknown))! if type(unknown) is type:R print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))i print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))I print('Unknown: type(unknown) is type : ', type(unknown) is type)V print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))" print('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__). sig = str(inspect.signature(function))< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function)' def visit_instance(self, instance):, #print(' vis instance', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))% self.spec[local_key] = items return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name): return None items = module.__dict__* for k, v in sorted(items.items()):! if k.startswith('_'): continue else:# res = self.visit(v)if __name__ == '__main__': import argparse& parser = argparse.ArgumentParser()6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')- parser.add_argument('modules', nargs='*')( argparse.ArgumentParser.add_argument) options = parser.parse_args(sys.argv)) options.modules.remove('__init__.py')( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after') print("let's go") if len(sys.argv) > 1:! module_name = sys.argv[1] else: module_name = 'IPython'$ module = __import__(module_name) V = Visitor(module_name) V.visit(module)/ print("Visited", len(V.visited), "objects")1 print("Collected", len(V.collected), "items") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if not options.save:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys: l = loaded[key] s = V.spec[key] if l != s: print()0 print(" %s%s" % (key,l))0 print("current> %s%s" % (key,s))5_243*"HvHXc** for k, v in sorted(items.items()):5_354 "HvHXcJ print(k)5_465x;"HvHXcRw{; local_key = type_.__module__ + '.' + type_.__name__5_576z"HvHXcXxz print(local_key)y{ )5_687"HvHXcq5_798"HvHXcr5_8:9"HvHXcr5_9;:r'"HvHXc{qt' def visit_instance(self, instance):5_:<;PE"HvHXdORE visitor = getattr(self, 'visit_' + type_, self.visit_unknown)5_;=<Q"HvHXd:PQ print(visitor, node)5_<>=T"HvHXdEST7 #print('visiting meta instance', meta_instance)5_=?>S6"HvHXdFRU6 def visit_metaclass_instance(self, meta_instance):5_>@?T#"HvHXdcSU2 return self.visit_type(metaclass_instance)5_?A@+"HvHXd~+ items.append(self.visit(v))5_@BA"HvHXd5_ACBp,"HvHXdos, self._consistent(fullqual, function)5_BDCr"HvHXdqr5_CEDq"HvHXdpr return fully_qualified5_DFE"HvHXif __name__ == '__main__':5_EGF"HvHX5_FHG"HvHXif __name__ == '__main__':5_GIH"HvHX5_HJI"HvHXmain()5_ILJ "HvHX def main()5_JMKLt"HvHXst print(instance)5_LNMt"HvHXsu, #print(' vis instance', instance)5_MONt"HvHXsu+ print(' vis instance', instance)5_NPOz"HvHX yz print(local_key)5_OQP"HvHX#"""5_PRQ"HvHX(__version__ = ''5_QSR"HvHXP) options.modules.remove('__init__.py')5_RTSv"HvHX[uw/ log.debug(' vis instance', instance)5_SUT v Xt if not options.save:5_TVU v Xv if options.save:5_UWV v X if len(sys.argv) > 1:5_VXW v X! module_name = sys.argv[1]5_WYX v X else:5_XZY v X module_name = 'IPython'5_Y[Z v X print("let's go")5_Z\[ v X5_[^\ v X5_\_]^ v X V = Visitor(module_name)5_^`_ v X5__a` v X V = Visitor(module_name)5_`ba v X V = Visitor(rootname)5_acb v X5_bdc v X V.visit(module)5_ced v X5_dfe v X,$ module = __import__(module_name)5_egf v X, V.visit(module)5_fhg v XO V = Visitor(rootname)5_gih v X print(options.modules)5_hji0 v X 0 print("current> %s%s" % (key,s))5_ikjX Fparser = argparse.ArgumentParser(description='Process some integers.')Aparser.add_argument('integers', metavar='N', type=int, nargs='+',: help='an integer for the accumulator')Eparser.add_argument('--sum', dest='accumulate', action='store_const',+ const=sum, default=max,D help='sum the integers (default: find the max)')args = parser.parse_args()%print(args.accumulate(args.integers))5_jlkX   import argparseJ parser = argparse.ArgumentParser(description='Process some integers.')E parser.add_argument('integers', metavar='N', type=int, nargs='+',> help='an integer for the accumulator')I parser.add_argument('--sum', dest='accumulate', action='store_const',/ const=sum, default=max,H help='sum the integers (default: find the max)') args = parser.parse_args()) print(args.accumulate(args.integers)) def main():5_kml*X- parser.add_argument('modules', nargs='*')5_lnmX% # def main():# import argparse# L# parser = argparse.ArgumentParser(description='Process some integers.')G# parser.add_argument('integers', metavar='N', type=int, nargs='+',@# help='an integer for the accumulator')K# parser.add_argument('--sum', dest='accumulate', action='store_const',1# const=sum, default=max,J# help='sum the integers (default: find the max)')# # args = parser.parse_args()+# print(args.accumulate(args.integers))5_monX& def main(): import argparse K parser = argparse.ArgumentParser(description='Process some integers.')F parser.add_argument('integers', metavar='N', type=int, nargs='+',? help='an integer for the accumulator')J parser.add_argument('--sum', dest='accumulate', action='store_const',0 const=sum, default=max,I help='sum the integers (default: find the max)')  args = parser.parse_args()* print(args.accumulate(args.integers))5_npoX* args = parser.parse_args()5_oqp,XJ5_prqXO- parser.add_argument('modules', nargs='+')5_qsrXP5_rts#XS- parser.add_argument('modules', nargs='+')5_sut,XY7 parser.add_argument('modules', metavar=''nargs='+')5_tvu4X[> parser.add_argument('modules', metavar='modules'nargs='+')5_uwvIXaJ parser.add_argument('modules', metavar='modules', type=str, nargs='+')5_vxwQXdS parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='')5_wyxXnE parser.add_argument('integers', metavar='N', type=int, nargs='+',5_xzyXn> help='an integer for the accumulator')5_y{zXx  import argparseJ parser = argparse.ArgumentParser(description='Process some integers.')E parser.add_argument('integers', metavar='N', type=int, nargs='+',> help='an integer for the accumulator')I parser.add_argument('--sum', dest='accumulate', action='store_const',/ const=sum, default=max,H help='sum the integers (default: find the max)') args = parser.parse_args() print(sys.argv)) print(args.accumulate(args.integers)) def main():5_z|{X( argparse.ArgumentParser.add_argument5_{}|X5_|~}%X& parser = argparse.ArgumentParser()5_}~&X( parser = argparse.ArgumentParser('')5_~ X) options = parser.parse_args(sys.argv)5_X sys.exit(0)5_X print(sys.argv)5_X print(options.modules)5_ X # def main():# import argparse# L# parser = argparse.ArgumentParser(description='Process some integers.')G# parser.add_argument('integers', metavar='N', type=int, nargs='+',@# help='an integer for the accumulator')K# parser.add_argument('--sum', dest='accumulate', action='store_const',1# const=sum, default=max,J# help='sum the integers (default: find the max)')# # args = parser.parse_args()# print(sys.argv)+# print(args.accumulate(args.integers))5_X 5_X2/ print("Visited", len(V.visited), "objects")5_&v&X>1 print("Collected", len(V.collected), "items")5_&v&X?9 print("Collected/Visited", len(V.visited), "objects")5_&v&XB! print("Collected", , "items")5_L&v&XCL print("Collected/Visited", len(V.collected) , len(V.visited), "objects")5_&v&XR print([]5_<&v&Xc< print([i for i in V.visited if i not in V.collected]5_&v&Xl if self.debug:5_&v&X if options.debug:5_&v&X= print([i for i in V.visited if i not in V.collected])5_9&v&X9 print([i for i in V.visited if i not in V.collected])5_9&v&X9 print([i for i in V.visited if i not in V.collected])5_LvXv collectdII = list(L print("Collected/Visited", len(V.collected) , len(V.visited), "objects")5_,,6v6X9 print([i for i in V.visited if i not in V.collected])5_ ,6v6X8 print([i for i in V.visited if i not in collectdII])5_ ,6v6XA print([i.module__ for i in V.visited if i not in collectdII])5_ ,6v6XC print([i.__module__ for i in V.visited if i not in collectdII])5_,6v6XK print([getattr(i.__module__ for i in V.visited if i not in collectdII])5_",6v6XM print([getattr(i, '__module__ for i in V.visited if i not in collectdII])5_P %v%XR print([getattr(i, '__module__', i) for i in V.visited if i not in collectdII])5_t %v%Xw print([getattr(i, '__module__', i) for i in V.visited if i not in collectdII if getattr(i, '__module__', i) is ''])5_r %v%X print([getattr(i, '__module__', i) for i in V.visited if i not in collectdII if getattr(i, '__module__', i) is 'matplotlib'])5_Q %v%X print([getattr(i, '__module__', i) for i in V.visited if i not in collectdII if getattr(i, '__module__', i) == 'matplotlib'])5_  vX print([getattr(i, '__module__', i) for i in V.visited if i not in collectdII and getattr(i, '__module__', i) == 'matplotlib'])5_  vX z print([i, '__module__', i) for i in V.visited if i not in collectdII and getattr(i, '__module__', i) == 'matplotlib'])5_  vX k print([i i) for i in V.visited if i not in collectdII and getattr(i, '__module__', i) == 'matplotlib'])5_  vX j print([ii) for i in V.visited if i not in collectdII and getattr(i, '__module__', i) == 'matplotlib'])5_  vX i print([i) for i in V.visited if i not in collectdII and getattr(i, '__module__', i) == 'matplotlib'])5_g' vXHgi from matplotlib import hifi' def visit_function(self, function):5_h2 vXZgk2 from matplotlib import unpack_labeled_data5_j vXiik sys.exit()5_j vXjik sys.exit('')5_h vX{gh2 from matplotlib import unpack_labeled_data+ if function is unpack_labeled_data: sys.exit('got it')5_? vX~?C?@5_A  vX@B+ if function is unpack_labeled_data:5_B vXAC sys.exit('got it')5_@& vX?@2 from matplotlib import unpack_labeled_data' if node is unpack_labeled_data:' import pdb; pdb.set_trace()5_h! vXgkhi5_i  vXhj' if node is unpack_labeled_data:5_ v X"" collectdII = list(V.collected)5_77eveX-h print([i for i in V.visited if i not in collectdII and getattr(i, '__module__', i) == 'matplotlib'])5_67eveX.9 print([i for i in V.visited if i not in collectdII ])5_j 7eveX<ij' import pdb; pdb.set_trace()5_i7eveX<hi+ if function is unpack_labeled_data:5_h7eveX>gh2 from matplotlib import unpack_labeled_data5_,5v5Xw sys.exit(0)5_,5v5XB V.visit(module)5_),5v5X(+ self.visited = list()5_*,5v5X)* self5_,,5v5X,.,-5_- ,5v5X ,. self5_G1,5v5X FI1 if mod and not mod.startswith(self.name):5_[$,5v5X[][\5_\ ,5v5X []& self.rejected.append(node)5_y),5v5Xxzyz5_y ,5v5X xz& self.rejected.append(node)5_$,5v5X$ self.spec[local_key] = items5_,5v5X$ self.collected.add(local_key )5_,5v5X IPython.embed()5_,5v5X! #IPython.embed()5_y!,5v5X&xz" self.rejected.append(node)5_\!,5v5X.[]" self.rejected.append(node)5_,5v5X?L print("Collected/Visited", len(V.collected) , len(V.visited), "objects")5_,5v5XAM #print("Collected/Visited", len(V.collected) , len(V.visited), "objects")5_,5v5XDL print("Collected/Visited", len(V.collected) , len(V.visited), "objects")5_K,5v5XHU print("Collected/Visited/rejected", len(V.collected) , len(V.visited), "objects")5_M,5v5XPh print("Collected/Visited/rejected", len(V.collected) , len(V.visited), , len(V.rejected), "objects")5_,5v5X8 print([i for i in V.visited if i not in collectdII])5_,5v5X& collectdII = list(V.spec.values())5_^,5v5X]_" print('Unknown: ========')5__,5v5X^`: print('Unknown: No clue what to do with', unknown)5_`,5v5X_aO print('Unknown: isinstance(node, object)', isinstance(unknown, object))5_a,5v5X`bK print('Unknown: isinstance(node, type)', isinstance(unknown, type))5_b,5v5Xac3 print('Unknown: type(node)', type(unknown))5_d ,5v5XceR print('Unknown: issubclass(unknown, type)', issubclass(unknown, type))5_e,5v5Xdfi print('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_f,5v5XegI print('Unknown: type(unknown) is type : ', type(unknown) is type)5_g,5v5XfhV print('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))5_h,5v5Xgi" print('Unknown: ========')5_:,5v5X9;n print("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value))5_,5v5XO5_,5v5XP* logger.debug('Module %s' % module)5_ ,5v5XQ. logger.debug('Module %s' % module)5_#X[2 logger.debug('Module %s' % module)5_%#Xa2 logger.debug(' %s' % module)5_4#Xl5 logger.debug(' -> %s' % module)5_(#Xs0 logger.debug(' -> %s' % k)5_1#Xw3 logger.debug(' -> %s.%s' % k)5_3#X{4 logger.debug(' -> %s.%s' % (k)5_2#X}5 logger.debug(' -> %s.%s' % (k))5_B#XE logger.debug(' -> %s.%s' % (module.__name__.k))5_%#XE logger.debug(' -> %s.%s' % (module.__name__,k))5_#X5_&#XE logger.debug(' +> %s.%s' % (module.__name__,k))5_#X5_#XE logger.debug(' -> %s.%s' % (module.__name__,k))5_?v?XA logger.debug(' -> %s.%s' % (module.__name__,k))5_?v?X logger.debug('')5_0?v?X1 logger.debug('out of scope %s vs %s')5_2vX4 logger.debug('out of scope %s vs %s'%())5_/3v3XN logger.debug('out of scope %s vs %s'%(module.__name__, self.name))5_Q3v3X S logger.debug('out of scope %s vs %s : %s'%(module.__name__, self.name))5_z3v3X!z logger.debug('out of scope %s vs %s : %s'%(module.__name__, self.name, module.__name__.startswith(self.name)))5_3v3X> V = Visitor(rootname)5_3v3XA! V = Visitor(rootname.split())5_ 3v3XB# V = Visitor(rootname.split(''))5_#3v3XC$ V = Visitor(rootname.split('.'))5_$3v3XE"& V = Visitor(rootname.split('.')[])5_ 3v3XN#+ import IPython; IPython.embed()5_p>3v3Xor> fullqual = '{}.{}'.format(name, function.__qualname__)5_r3v3Xqs. sig = str(inspect.signature(function))5_r23v3Xqt2 sig = str(inspect.signature(function))5_s 3v3Xrt expect V5_s3v3Xrs exect V5_r23v3X$qv2 sig = str(inspect.signature(function))5_u 3v3Xtu IPython.embed()5_t3v3Xst import IPython5_s3v3X%ru except ValueError:5_}&3v3X&|~2 logger.debug(' vis instance', instance)5__63v3X^`A logger.debug('Unknown: No clue what to do with', unknown)5_`73v3X_aV logger.debug('Unknown: isinstance(node, object)', isinstance(unknown, object))5_a53v3X`bR logger.debug('Unknown: isinstance(node, type)', isinstance(unknown, type))5_b)3v3Xac: logger.debug('Unknown: type(node)', type(unknown))5_d<3v3XceY logger.debug('Unknown: issubclass(unknown, type)', issubclass(unknown, type))5_e>3v3Xdfp logger.debug('Unknown: issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))5_ f73v3XegP logger.debug('Unknown: type(unknown) is type : ', type(unknown) is type)5_  g=3v3X'fh] logger.debug('Unknown: hasattr(unknown, "__call__"): ', hasattr(unknown, "__call__"))5_   eA3v3X(dfs logger.debug('Unknown: issubclass(type(unknown), type) %s', issubclass(type(unknown), type), type(unknown))5_   3v3X) V.visit(module)5_   (3v3X( module = __import__(module_name)5_  3v3X* V.visit(module)5_ 3v3X+ print(module)5_ 3v3X,! print(module, module_name )5_'3v3X! ' for module_name in options.modules:5_(3v3X$( module = __import__(module_name)5_3v3X( module = 5_3v3X)5_3v3X* module = 5 importlib.import_module('matplotlib.widgets')5_=3v3X-> module = importlib.import_module('matplotlib.widgets')5_(3v3X2-4 module = importlib.import_module(module_name* )5_'3v3X:.' for module_name in options.modules:5_3v3X> import importlib5_ 3v3XA/  5_ 3v3XC  import importlib5_ 3v3XC0  import importlib5_3v3XM sys.exit(0)5_3v3XN" print(module, module_name)5_3v3XN1 #V.visit(module)5_ B3v3X]pAC5_! C3v3X]tBD if node in self.visited:5_ "!D 3v3X]tCE return5_!#"E3v3X]uDF else:5_"$#F3v3X]uEG% self.visited.append(node)5_#%$F)3v3X]v2EJ) self.visited.append(node)5_$&%G3v3X^3FI except TypeError:5_%'&I 3v3X^7HI import IPython5_&('I 3v3X^8HI IPython.embed()5_')(H43v3X^94GJ4 # non equalable things (eg dtype/moduel)5_(*)I3v3X_5HM return5_)+*C3v3X_BD$ if node in self.visited:5_*,+C'3v3X_6BD( if any(node in self.visited:5_+-,C(3v3X_BD) if any(node in self.visited):5_,.-C3v3X_BD( if any(node in self.visited:5_-/.C3v3X_BD' if id(node in self.visited:5_.0/C3v3X_BD( if id(node) in self.visited:5_/20C73v3X_9BD8 if id(node) in [id(x) for x in self.visited:5_0312'3v3X`' for module_name in options.modules:5_2433v3X`5 module = importlib.import_module(module_name)5_3543v3X` V.visit(module)5_4653v3X` V.visit(module)5_5763v3X` except ImportError:5_6873v3X`" print(''5_7983v3X`&: print('skip...'5_8:93v3X`:; except ImportError:5_9;:(3v3X`A) except ImportError, RuntimeError:5_:=;3v3X`C<* except ImportError, RuntimeError):5_;><=y23v3Xdxz2 sig = str(inspect.signature(function))5_=?>x 3v3Xdwz try:5_>@?y3v3Xdx{ import re5_?A@z3v3Xdy{ re.compile()5_@BAz3v3Xdy{ re.compile('')z{5_ACBz3v3Xdy{% re.compile('0x103e29c80')5_BDCz3v3Xdy{ re.compile('0x[]')5_CEDz"3v3Xdy{$ re.compile('0x[0-9a-F]')5_DFEz#3v3Xdy{& re.compile('0x[0-9a-F]{}')5_EGFz 3v3Xdy{' re.compile('0x[0-9a-F]{9}')5_FHGz3v3Xd=y{- hex = re.compile('0x[0-9a-F]{9}')5_GIH{:3v3Xdz|: sig = str(inspect.signature(function)).replace5_HJI{A3v3Xdz|B sig = str(inspect.signature(function)).replace(hexd,''5_IKJz(3v3Xey{. hexd = re.compile('0x[0-9a-F]{9}')5_JLKz,3v3Xey{. hexd = re.compile('0x[0-9a-f]{9}')5_KML{E3v3Xez|F sig = str(inspect.signature(function)).replace(hexd,'0xFF'5_LNM{J3v3Xe>z|J sig = str(inspect.signature(function)).replace(hexd,'0xffffff'5_MONz 3v3Xeyz, hexd = re.compile('0x[0-9a-f]+')5_NPO3v3Xe"5_OQP 3v3Xe$, hexd = re.compile('0x[0-9a-f]+')5_PRQ3v3Xe$( hexd = re.compile('0x[0-9a-f]+')5_QSR3v3Xe%$ hexd = re.compile('0x[0-9a-f]+')5_RTS3v3Xe&logger.debug('HO')5_SUT 3v3Xe'? hexd = re.compile('0x[0-9a-f]+')5_TVU3v3Xe/ l = loaded[key]5_UWV$3v3Xe2% l = loaded[key].replace()5_VXW%3v3Xe3' l = loaded[key].replace('')5_WYX*3v3Xe5+ l = loaded[key].replace('hexd')5_XZY%3v3Xe6* l = loaded[key].replace('hexd)5_Y[Z(3v3Xe7) l = loaded[key].replace(hexd)5_Z][+3v3Xe8- l = loaded[key].replace(hexd, '')5_[^\]3v3Xe@ s = V.spec[key]5_]_^3v3XeG s = V.spec[key].5_^`_53v3XeI6 s = V.spec[key]replace(hexd, '0xfffffff').5__a`3v3XeM@5 s = V.spec[key]replace(hexd, '0xfffffff')5_`ba 3v3XeWA  import json5_acb3v3Xe[B improt re5_bdc|3v3Xe{}K sig = str(inspect.signature(function)).replace(hexd,'0xffffff')5_ced|L|L|UvUXe{}W sig = hexd.repace(str(inspect.signature(function)).replace(hexd,'0xffffff')5_dfe||L|UvUXe{}M sig = hexd.repace(str(inspect.signature(function)).replace(hexd,)|}5_egf|Y|L|UvUXeC{}Y sig = hexd.repace('0xffffff', str(inspect.signature(function)).replace(hexd,)5_fhg|I|L|UvUXeD{}I sig = hexd.repace('0xffffff', str(inspect.signature(function)5_gih6|L|UvUXe6 l = loaded[key].replace(hexd, '0xfffffff')5_hji|L|UvUXe5_ikj |L|UvUXeK sig = hexd.repace('0xffffff', str(inspect.signature(function)))5_jlk((GvGXeI l = hexd.repace('0xffffff', str(inspect.signature(function)))5_kml(GvGXe5_lnm (GvGXe5_mon (GvGXe6 l = loaded[key].replace(hexd, '0xfffffff')5_npo (GvGXe4 l = hexd.repace('0xffffff', loaded[key])5_oqp (GvGXe5_prq((2v2XeE4 l = hexd.repace('0xffffff', loaded[key])5_qsr (2v2XeF6 s = V.spec[key].replace(hexd, '0xfffffff')5_rts(2v2Xe4 l = hexd.repace('0xffffff', loaded[key])5_sut(2v2XeG4 l = hexd.repace('0xffffff', V.spec[key])5_tvu|(2v2XeI{}K sig = hexd.repace('0xffffff', str(inspect.signature(function)))5_uwv(2v2Xe5 l = hexd.replace('0xffffff', loaded[key])5_vxw(2v2Xe5 l = hexd.replace('0xffffff', V.spec[key])5_wyx|(2v2XeJ{}L sig = hexd.replace('0xffffff', str(inspect.signature(function)))5_xzy (2v2XfK1 l = hexd.sub('0xffffff', V.spec[key])5_y{z(2v2Xf! for key in common_keys:5_z|{   Xf%1 l = hexd.sub('0xffffff', loaded[key])1 s = hexd.sub('0xffffff', V.spec[key]) if l != s: print()0 print(" %s%s" % (key,l))0 print("current> %s%s" % (key,s))5_{}|4  Xf'L4 print("current> %s%s" % (key,s))5_|~}  Xfj try:5_}~  Xfr if type.loaded5_~  Xfs if type(loaded5_  Xfu if type(loaded)5_  Xfv! if type(loaded[])5_$  Xfx$ if type(loaded[key])5_  Xf{5 l = hexd.sub('0xffffff', loaded[key])5_  Xf|5 s = hexd.sub('0xffffff', V.spec[key])5_9  Xf~9 s = hexd.sub('0xffffff', V.spec[key])5_  Xf, if type(loaded[key]) == str:5_)  Xf2 if isinstance(loaded[key]) == str:5_6  Xf7 if isinstance(loaded[key], str) == str:5_  Xf5_9  Xf9 l = hexd.sub('0xffffff', loaded[key])5_9  Xf9 s = hexd.sub('0xffffff', V.spec[key])5_,XfM8 l = hexd.sub('0xffffff', loaded[key]8 s = hexd.sub('0xffffff', V.spec[key]5_,XfN else:5_,Xg  IPython.embed()5_,Xg! import IPython5_,Xg! except :5_,Xg# try:5_ VXg+O""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]: return else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return except ValueError: import IPython IPython.embed()/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):z logger.debug('out of scope %s vs %s : %s'%(module.__name__, self.name, module.__name__.startswith(self.name))) return None items = module.__dict__* for k, v in sorted(items.items()):! if k.startswith('_'):E logger.debug(' -> %s.%s' % (module.__name__,k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))# res = self.visit(v) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) pass import IPython #IPython.embed()f print("Collected/Visited/rejected", len(V.collected) , len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:0 if isinstance(loaded[key], str):9 l = hexd.sub('0xffffff', loaded[key])9 s = hexd.sub('0xffffff', V.spec[key]) else:# l = loaded[key]# s = V.spec[key] if l != s: print()4 print(" %s%s" % (key,l))4 print("current> %s%s" % (key,s))if __name__ == '__main__': main()5_ VXg2""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]: return else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return except ValueError: import IPython IPython.embed()/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) return visitor(node)6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):z logger.debug('out of scope %s vs %s : %s'%(module.__name__, self.name, module.__name__.startswith(self.name))) return None items = module.__dict__* for k, v in sorted(items.items()):! if k.startswith('_'):E logger.debug(' -> %s.%s' % (module.__name__,k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))# res = self.visit(v) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) pass import IPython #IPython.embed()f print("Collected/Visited/rejected", len(V.collected) , len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:0 if isinstance(loaded[key], str):9 l = hexd.sub('0xffffff', loaded[key])9 s = hexd.sub('0xffffff', V.spec[key]) else:# l = loaded[key]# s = V.spec[key] if l != s: print()5 print(" %s%s" % (key, l))5 print("current> %s%s" % (key, s))if __name__ == '__main__': main()5_ VXg6 #IPython.embed()5_ VXg6 import IPython5_ VXg7P5_5v=XgJ 0 if isinstance(loaded[key], str):9 l = hexd.sub('0xffffff', loaded[key])9 s = hexd.sub('0xffffff', V.spec[key]) else:# l = loaded[key]# s = V.spec[key] if l != s: print()5 print(" %s%s" % (key, l))5 print("current> %s%s" % (key, s))5_,| |GvGXi+. self.visited = list()5_-} }GvGXiQ,- self_back_ref5_E9| |GvGXiDG9 if id(node) in [id(x) for x in self.visited]:5_F)} }GvGXiSEG) ## todo, if visited check5_FE} }GvGXiEHE ## todo, if visited check the localkey and return it.5_G=~ ~GvGXjTFHF ## otherwise methods moved to superclass will be lost.5_GJ~ ~GvGXj UFIJ ## otherwise methods moved to superclass will/may be lost.5_, GvGX~V+. self.visited = list()5_J GvGX~IK return5_- GvGX~W,. self._has_cache = dict()5_J& GvGX~XIK& return self._has_cache5_F GvGX~EG9 if id(node) in [id(x) for x in self.visited]:5_F GvGX~EG8 if d(node) in [id(x) for x in self.visited]:5_F GvGX~EG7 if (node) in [id(x) for x in self.visited]:5_F GvGX~EG6 if node) in [id(x) for x in self.visited]:5_F GvGX~EG5 if node in [id(x) for x in self.visited]:5_F GvGX~EG4 if node in [d(x) for x in self.visited]:5_F GvGX~EG3 if node in [(x) for x in self.visited]:5_F GvGX~ZEG2 if node in [x) for x in self.visited]:5_aE GvGX~`cE visitor = getattr(self, 'visit_' + type_, self.visit_unknown)5_cccvX~bd return visitor(node)5_bccvX~ac hashv = bc5_bccvX~ad hashv = visitor(node)5_cddvX~bd self['hash5_cddvX~bd self.hash5_cddvX~bd self._hash_cache[hashv]5_c"ddvX~bd" self._hash_cache[id(node)]5_dddvX~[ce return 5_J ddvX]IK4 return self._has_cache.get(id(node))5_FFF/v/XlEG1 if node in [x for x in self.visited]:5_FFF/v/XnEG4 if node in [id(x for x in self.visited]:5_FFF/v/XvEG5 if node in [id(x) for x in self.visited]:5_FFF/v/Xx^EG8 if id(node in [id(x) for x in self.visited]:5_PFF/v/XOP except ValueError:5_P FF/v/XOP import IPython5_P FF/v/X_OP IPython.embed()5_1 ,v,X 1 print("current> %s%s" % (key, s))5_+ ,v,X 0 if isinstance(loaded[key], str):5_) ,v,X1 if isinstance(loaded[key], list):5_ ,v,X print()5_ ,v,X print('')5_* ,v,X+ print('new values are')5_- ,v,X!/ print('new values are', [])5_F ,v,X*5_ ,v,X,I print('new values are', [k for k in s if k not in l])5_< ,v,X1M print('removed values are', [k for k in s if k not in l])5_K ,v,X3`M print('removed values are', [k for k in l if k not in l])5_X\aM print('removed values are', [k for k in l if k not in s])I print('new values are', [k for k in s if k not in l])5_X if  items = []5_ X if InvertedLogTransform5_1X1 if type_.__name__ == InvertedLogTransform5_X2 if type_.__name__ == InvertedLogTransform'5_3Xb3 if type_.__name__ == 'InvertedLogTransform'5_X@ items = module.__dict__5_XI* for k, v in sorted(items.items()):5_+XQ; for k, v in dirmodule):(items.items()):5_#XS# items = dir(module.__dict__5_XT# items = dir(module.__dict__5_XU+ for k, v in dirmodule):5_XV' for k, v in dirmodule):5_ XWc# for k, v in dirmodule):5_X\d for k, v in dirmodule):5_"X^e# res = self.visit(v)5_Xo for k, v in dir(module):5_Xo for k, in dir(module):5_ Xpf for k, in dir(module):5_Xt""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []4 if type_.__name__ == 'InvertedLogTransform': import pdb; pdb.set_trace()J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):z logger.debug('out of scope %s vs %s : %s'%(module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):E logger.debug(' -> %s.%s' % (module.__name__,k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s: print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))' if isinstance(s, list):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])if __name__ == '__main__': main()5_Xv""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []4 if type_.__name__ == 'InvertedLogTransform': import pdb; pdb.set_trace()J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):z logger.debug('out of scope %s vs %s : %s'%(module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):E logger.debug(' -> %s.%s' % (module.__name__,k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s: print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))' if isinstance(s, list):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])if __name__ == '__main__': main()5_Xw""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []4 if type_.__name__ == 'InvertedLogTransform': import pdb; pdb.set_trace()J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):9 logger.debug('out of scope %s vs %s : %s' % (S module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):E logger.debug(' -> %s.%s' % (module.__name__,k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s: print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))' if isinstance(s, list):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])if __name__ == '__main__': main()5_X{""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []4 if type_.__name__ == 'InvertedLogTransform': import pdb; pdb.set_trace()J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):9 logger.debug('out of scope %s vs %s : %s' % (S module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):F logger.debug(' -> %s.%s' % (module.__name__, k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s: print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))' if isinstance(s, list):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])if __name__ == '__main__': main()5_X|""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []4 if type_.__name__ == 'InvertedLogTransform': import pdb; pdb.set_trace()J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):9 logger.debug('out of scope %s vs %s : %s' % (S module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):F logger.debug(' -> %s.%s' % (module.__name__, k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s: print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))' if isinstance(s, list):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])if __name__ == '__main__': main()5_X""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []4 if type_.__name__ == 'InvertedLogTransform': import pdb; pdb.set_trace()J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):9 logger.debug('out of scope %s vs %s : %s' % (S module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):F logger.debug(' -> %s.%s' % (module.__name__, k)) continue else:E logger.debug(' +> %s.%s' % (module.__name__,k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s: print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))' if isinstance(s, list):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])if __name__ == '__main__': main()5_X""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):; local_key = type_.__module__ + '.' + type_.__name__ items = []4 if type_.__name__ == 'InvertedLogTransform': import pdb; pdb.set_trace()J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)3 for k, v in sorted(type_.__dict__.items()):% if not k.startswith('_'):+ items.append(self.visit(v))) items = list(filter(None, items))$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):9 logger.debug('out of scope %s vs %s : %s' % (S module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):F logger.debug(' -> %s.%s' % (module.__name__, k)) continue else:F logger.debug(' +> %s.%s' % (module.__name__, k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)+ except (ImportError, RuntimeError):) print('skip...', module_name) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys), print("The following items are new") pprint(new_keys) print()6 print("The following items have been removed") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s: print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))' if isinstance(s, list):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])if __name__ == '__main__': main()5_4X4 res = self.visit(getattr(module, k))5_Xi5_ X>3 for k, v in sorted(type_.__dict__.items()):5_ X?2 for k v in sorted(type_.__dict__.items()):5_ X@1 for kv in sorted(type_.__dict__.items()):5_XB0 for k in sorted(type_.__dict__.items()):5_!XE4 for k in sorted(dir(type_.__dict__.items()):5_"XMj5 for k in sorted(dir(type_).__dict__.items()):5_(XS+ items.append(self.visit(v))5_-X]8 items.append(self.visit(type.getattr(v))5_0X`3 items.append(self.visit(getattr(v))5_8Xe: items.append(self.visit(getattr(type_, v))5_:Xjk: items.append(self.visit(getattr(type_, k))5_ Xql pdb.set_trace()5_vXum items = []5_vX; items.append(self.visit(getattr(type_, k)))5_vX6 items[](self.visit(getattr(type_, k)))5_vXn7 items[k](self.visit(getattr(type_, k)))5_)vX) items = list(filter(None, items))5_9vXo9 items[k] = self.visit(getattr(type_, k)))5_vX$ items = {k:v 5_ vX items = {k:v 5_vXr items = {k:v 5_!vXt' if isinstance(s, list):5_vX' if isinstance(s, dict):R print(' new values are', [k for k in s if k not in l])V print(' removed values are', [k for k in l if k not in s])5_vX5_VvX V print(' removed values are', [k for k in l if k not in s])5_X$ print()1 print(" %s%s" % (key, l))1 print("current> %s%s" % (key, s))5_'X&' if isinstance(s, dict):5_;5PvPX> news = ; if isinstance(s, dict): # Classes / Module?5_;9TvTXD; if isinstance(s, dict): # Classes / Module?5_ 79TvTXF removed = 7 news = [k for k in s if k not in l]5_  :9TvTXP: removed = [k for k in l if k not in s]5_   ,9TvTXp5_   &&&&Xx5 print("current> %s%s" % (key, s))5 print(" %s%s" % (key, l))5_   &&&X5 print("current> %s%s" % (key, s))5_ #&&&Xy5 print(" %s%s" % (key, l))5_"&&&X6 print("current> %s:%s" % (key, s))5_#&&&X6 print(" %s:%s" % (key, l))5_####XV print(' removed values are', [k for k in l if k not in s])R print(' new values are', [k for k in s if k not in l])5_####XW print(' removed values are', [k for k in l if k not in s])S print(' new values are', [k for k in s if k not in l])5_####XX print(' removed values are', [k for k in l if k not in s])T print(' new values are', [k for k in s if k not in l])5_####XY print(' removed values are', [k for k in l if k not in s])U print(' new values are', [k for k in s if k not in l])5_####XzZ print(' removed values are', [k for k in l if k not in s])V print(' new values are', [k for k in s if k not in l])5_1v1Xa4 if type_.__name__ == 'InvertedLogTransform':5_ 1v1Xc{ #pdb.set_trace()5_ 1v1X% if type_.__name__ == 'XAxis': import pdb; pdb.set_trace()5_1v1X5_X% if type_.__name__ == 'XAxis': import pdb; pdb.set_trace()5_(X) if type_.__name__ == 'XAxis':5_1X2 if type_.__name__ == 'XAxis' and k ==:5_1X5 if type_.__name__ == 'XAxis' and k == '':5_:X= if type_.__name__ == 'XAxis' and k.startswith '':5_ ;X= if type_.__name__ == 'XAxis' and k.startswith('':5_! AX|B if type_.__name__ == 'XAxis' and k.startswith('get_l':5_ "!AXC if type_.__name__ == 'XAxis' and k.startswith('get_l'): import pdb; pdb.set_trace()5_!#" X 5_"$#   X C if type_.__name__ == 'XAxis' and k.startswith('get_l'): import pdb; pdb.set_trace()5_#%$  XB if type_.__name__ == 'XAxis' and k.startswith('get_l'): import pdb; pdb.set_trace()5_$&%  XA if type_.__name__ == 'XAxis' and k.startswith('get_l'): import pdb; pdb.set_trace()5_%'&  X@ if type_.__name__ == 'XAxis' and k.startswith('get_l'): import pdb; pdb.set_trace()5_&('>  X}? if type_.__name__ == 'XAxis' and k.startswith('get_l'):5_')(  X& if type_.__name__ == 'XAxis' :5_(*)   X import pdb;5_)+*   X~ pdb.set_trace()5_*,+  X6 print("The following items have been removed")5_+-,>  X@ print("The following canonical items have been removed")5_,.-*  X, print("The following items are new")5_-/.B  XT print("The following canonical items have been removed or are now aliases.")5_.0/P  XR print("The following canonical items have been removed, are now aliases.")5_/10a  Xh print("The following canonical items have been removed, are now aliases or moved to superclass")5_021/  X@ print("The following items are new, or former aliases.")5_132;  X= print("The following items are new, former aliases.")5_243# v X# def visit_module(self, module):5_354&v&X5( if module.__name__ == 'patches':5_465 &v&X7 if module.__name__ == :5_576+&v&X8, if 'patches' in module.__name__ == :5_687&v&XO) if 'patches' in module.__name__ :5_798*&v&X+ except (ImportError, RuntimeError):5_8:9)&v&X) print('skip...', module_name)5_9;:&v&X' import Pdb; Pdb.set_trace()5_:<;&v&X' import pdb; Pdb.set_trace()5_;><&v&X% if 'pat' in module.__name__ :5_<?=> &v&XG5_>@?&v&XH) if 'patches' in module.__name__ :5_?A@ &v&XI' import pdb; pdb.set_trace()5_@BA&v&XJ- if 'patches' in module.__name__ :5_ACB+&v&XN, if 'ArrowS' in module.__name__ :5_BDC3v3X if 'ArrowS' in k:+ import pdb; pdb.set_trace()5_CED$3v3X5_DFE 3v3X if 'ArrowS' in k:5_EGF3v3X+ import pdb; pdb.set_trace()5_FHG3v3X if 'ArrowS' in k:5_GIH 3v3X' import pdb; pdb.set_trace()5_HJI3v3X) if 'patches' in module.__name__ :5_IKJ3v3X""" Frappucinno"""__version__ = '0.0.1'import importlibimport inspect import sys import types import json import refrom pprint import pprintfrom types import ModuleTypeimport logginglogging.basicConfig()$logger = logging.getLogger(__name__) hexd = re.compile('0x[0-9a-f]+')(def fully_qualified(obj: object) -> str: """9 (try to) return the fully qualified name of an object """( if obj is types.FunctionType: # noqa; return '%s.%s' % (obj.__module__, obj.__qualname__) else:K return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor: def __init__(self, name): self.name = nameG # list of visited nodes to avoid recursion and going in circle.6 # can't be a set we store non-hashable objectsB # which is weird why not store memory-location -> object ? # anyway... self.visited = list()! self._hash_cache = dict()? # set of object keys that where deemed worth collecting self.collected = set({}) self.rejected = list()M # dict of key -> custom spec that should be serialised for comparison # later. self.spec = dict()A # debug, make sure 2 objects are not getting the same key self._consistency = {}& def _consistent(self, key, value):$ if key in self._consistency:3 if self._consistency[key] is not value:u logger.debug("Warning %s is not %s, results may not be consistent" % (self._consistency[key], value)) else:* self._consistency[key] = value def visit(self, node): try:9 if id(node) in [id(x) for x in self.visited]:E ## todo, if visited check the localkey and return it.J ## otherwise methods moved to superclass will/may be lost., ## or not correctly reported5 return self._hash_cache.get(id(node)) else:) self.visited.append(node) except TypeError:4 # non equalable things (eg dtype/moduel) return/ mod = getattr(node, '__module__', None)1 if mod and not mod.startswith(self.name):& self.rejected.append(node)> # print('skipping | ', node.__module__, '|', node) return( if isinstance(node, ModuleType): type_ = 'module'g elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'): type_ = 'instance'E elif issubclass(type(node), type) and type(node) is not type:( type_ = 'metaclass_instance' else:' type_ = type(node).__name__E visitor = getattr(self, 'visit_' + type_, self.visit_unknown) hashv = visitor(node)* self._hash_cache[id(node)] = hashv return hashv6 def visit_metaclass_instance(self, meta_instance):- return self.visit_type(meta_instance) pass% def visit_unknown(self, unknown):% self.rejected.append(unknown)) logger.debug('Unknown: ========')D logger.debug('Unknown: No clue what to do with %s', unknown)Y logger.debug('Unknown: isinstance(node, object) %s', isinstance(unknown, object))U logger.debug('Unknown: isinstance(node, type) %s', isinstance(unknown, type))= logger.debug('Unknown: type(node) %s', type(unknown))! if type(unknown) is type:\ logger.debug('Unknown: issubclass(unknown, type) %s', issubclass(unknown, type))v logger.debug('Unknown: issubclass(type(unknown), type) %s %s', issubclass(type(unknown), type), type(unknown))S logger.debug('Unknown: type(unknown) is type : %s', type(unknown) is type)` logger.debug('Unknown: hasattr(unknown, "__call__"): %s', hasattr(unknown, "__call__"))) logger.debug('Unknown: ========')' def visit_function(self, function):" klass = function.__class__' if klass is types.FunctionType:& name = function.__module__ else:Y name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)> fullqual = '{}.{}'.format(name, function.__qualname__) try: import reH sig = hexd.sub('0xffffff', str(inspect.signature(function))) except ValueError: return< logger.debug(' {f}{s}'.format(f=fullqual, s=sig))$ self.collected.add(fullqual)! self.spec[fullqual] = sig, self._consistent(fullqual, function) return fullqual' def visit_instance(self, instance):& self.rejected.append(instance)5 logger.debug(' vis instance %s', instance) pass def visit_type(self, type_):& if 'ArrowS' in type_.__name__:' import pdb; pdb.set_trace(); local_key = type_.__module__ + '.' + type_.__name__ items = {}J logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)$ for k in sorted(dir(type_)):% if not k.startswith('_'):8 items[k] = self.visit(getattr(type_, k))3 items = {k:v for k,v in items.items() if v}$ self.spec[local_key] = items% self.collected.add(local_key) return local_key# def visit_module(self, module):* logger.debug('Module %s' % module)5 if not module.__name__.startswith(self.name):9 logger.debug('out of scope %s vs %s : %s' % (S module.__name__, self.name, module.__name__.startswith(self.name))) return None for k in dir(module):! if k.startswith('_'):F logger.debug(' -> %s.%s' % (module.__name__, k)) continue else:F logger.debug(' +> %s.%s' % (module.__name__, k))4 res = self.visit(getattr(module, k)) def main(): import argparse9 parser = argparse.ArgumentParser('Argparser for foo')n parser.add_argument('modules', metavar='modules', type=str, nargs='+', help='root modules and submodules')6 parser.add_argument('--save', action='store_true')9 parser.add_argument('--compare', action='store_true')7 parser.add_argument('--debug', action='store_true')! options = parser.parse_args()( if options.save and options.compare:? print('options `--save` and `--compare` are exclusive') parser.print_help() if options.debug: logger.debug('before') logger.setLevel('DEBUG') logger.debug('after')! rootname = options.modules[0]' V = Visitor(rootname.split('.')[0])' for module_name in options.modules: try:9 module = importlib.import_module(module_name) V.visit(module)/ except (ImportError, RuntimeError)as e:) print('skip...', module_name) print(e) passe print("Collected/Visited/rejected", len(V.collected), len(V.visited), len(V.rejected), "objects") if options.save:5 with open('%s.json' % module_name, 'w') as f:1 f.write(json.dumps(V.spec, indent=2)) if options.compare:5 with open('%s.json' % module_name, 'r') as f:) loaded = json.loads(f.read())" lkeys = set(loaded.keys())" skeys = set(V.spec.keys())/ common_keys = skeys.intersection(lkeys). removed_keys = lkeys.difference(skeys)* new_keys = skeys.difference(lkeys)\ print("The following items are new, former aliases, or where present on superclass") pprint(new_keys) print()i print("The following canonical items have been removed, are now aliases or moved to super-class") pprint(removed_keys) print()A print("The following signature differ between versions:") for key in common_keys:, if isinstance(loaded[key], str):5 l = hexd.sub('0xffffff', loaded[key])5 s = hexd.sub('0xffffff', V.spec[key]) else: l = loaded[key] s = V.spec[key] if l != s:; if isinstance(s, dict): # Classes / Module?7 news = [k for k in s if k not in l]: removed = [k for k in l if k not in s]# if not removed: continue print(); print(" %s:%s" % (key, l)); print("Class/Module> %s:%s" % (key, s))W print(' new values are', [k for k in s if k not in l])[ print(' removed values are', [k for k in l if k not in s]) else: print()6 print(" %s%s" % (key, l))6 print("function> %s%s" % (key, s))if __name__ == '__main__': main()5_JLK3v3X& if 'ArrowS' in type_.__name__:' import pdb; pdb.set_trace()5_KML3v3X5_LNM3v3Xm& if 'ArrowS' in type_.__name__:5_MON 3v3Xm' import pdb; pdb.set_trace()5_NPO$3v3X$ self.spec[local_key] = items5_OQP3v3X% if "Arrow" in type_.__name__:5_PRQ,3v3X, print(type_.__name__, local_key)5_QSR 3v3X i5_RVS63v3X6 print("function> %s%s" % (key, s))5_SWTV3v3X+ import IPython IPython.embed()5_VXW03v3X25_WYX3v3X4 import IPython5_XZY3v3X4 import IPython5_Y[Z3v3X5 IPython.embed()5_Z\[3v3X6 IPython.embed()5_[]\ 3v3X8 import IPython5_\^]3v3X9 IPython.embed()5_]_^(v(Xt5 with open('%s.json' % module_name, 'w') as f:5_^`_(v(Xu5 with open('%s.json' % module_name, 'r') as f:5__a`(v(X IPython.embed()5_`ba(v(X import IPython5_acb (v(X' import pdb; pdb.set_trace()5_bdc(v(X, print(type_.__name__, local_key)5_ced(v(X' if "ArrowSt" in type_.__name__:5_dfe3(v(X3 items = {k:v for k,v in items.items() if v}5_egf(v(X if type_.__name__ == ''5_fhg%(v(X% if type_.__name__ == 'Circle'5_gih5(v(X; local_key = type_.__module__ + '.' + type_.__name__5_hji9(v(XJ logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)5_ikj:(v(XK logger.debug('Class %s' % type_.__module__ + '.' A+ type_.__name__)5_jlkC(v(XJ logger.debug('Class %s' % type_.__module__ + '.' + type_.__name__)5_kml(v(X& if type_.__name__ == 'Circle':5_lnm (v(X' import pdb; pdb.set_trace()5_mon)(v(X/ except (ImportError, RuntimeError)as e:5_npo:(v(X? except (ImportError, RuntimeError, AttributeError)as e:5_oqp(v(X except ValueError:5_prq(v(X return5_qsr}(v(X|~ try:5_rts~(v(X} import re5_sut~(v(X} import re5_tvu~(v(X} import re5_uwv~(v(X} import re5_vxw(v(X~H sig = hexd.sub('0xffffff', str(inspect.signature(function)))5_wyx(v(X~G sig = hexd.sub('0xffffff', str(inspect.signature(function)))5_xzy(v(X~F sig = hexd.sub('0xffffff', str(inspect.signature(function)))5_yz(v(X~E sig = hexd.sub('0xffffff', str(inspect.signature(function)))5_SUVT3v3X&5_TU3v3X'5_<>=(&v&X5_   &&&&X5 print(" %s%s" % (key, l))5_XH5_ X5_X5_Xh5_FFF/v/XgEG3 if annode in [x for x in self.visited]:5_J ddvXIK5 return self._hash_cache.get(id(node))5_F GvGX~EG4 if node in [d(x) for x in self.visited]:5_F| |GvGXiREG5_[]\3v3Xe?$ s = V.spec[key0xfffffff]5_;=<3v3Xd2 except ignatureImportError, RuntimeError):5_021C73v3X` BD@ if id(node) in [id(x) for x in self.visitedmportli]:5_#XW5_^,5v5X]_ ('Unknown: ========')5_,5v5XW5_,5v5XX5_i vXhj, if functionG is unpack_labeled_data:5_ X'5_\^] v X 5_JLKu"HvHXtv5_##vXQimport mistunefrom pygments import highlight-from pygments.lexers import get_lexer_by_name*class HighlightRenderer(mistune.Renderer):% def block_code(self, code, lang): if not lang:7 return '\n
%s
\n' % \$ mistune.escape(code)6 lexer = get_lexer_by_name(lang, stripall=True)* formatter = Terminal256Formatter()0 return highlight(code, lexer, formatter)renderer = HighlightRenderer().markdown = mistune.Markdown(renderer=renderer)0print(markdown('```python\nassert 1 == 1\n```'))0print(markdown('```python\nassert 1 == 1\n```')) def print5_-$$vXQ-from pygments.lexers import get_lexer_by_nameimport builtins5_&&vXQ import builtins builtins.pr5_ %%vXQ 5_ $$vXQ 5_$$vXQ8builtin.print(markdown('```python\nassert 1 == 1\n```'))5_ 0$$vXR * return '\n
%s\n' % \5_
!$$vXR            return '\n%s\n' % \5_%%vXR"
        if not lang:            return code5_$$vXR%
5_##vXR%
5_W9NvNXCVX         self.collected(fullqual)5_W9NvNXCVX         self.collected[fullqual)5_W 9NvNXCVX         self.collected[fullqual]5_*[v[X8uufrom types import ModuleTypeimport builtinsimport types(def fully_qualified(obj: object) -> str:    """9    (try to) return the fully qualified name of an object    """(    if obj is types.FunctionType: # noqa;        return '%s.%s' % (obj.__module__, obj.__qualname__)	    else:K        return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)class Visitor:    def __init__(self, name):        self.name = name        self.visited = list()         self.collected = set({})        self._consistency = {}&    def _consistent(self, key, value):$        if key in self._consistency:G            assert self._consistency[key] is value,  "%s is not %s" % (.                self._consistency[key], value)
        else:*            self._consistency[key] = value    def visit(self, node):         if node in self.visited:            return
        else:%            self.visited.append(node)/        mod = getattr(node, '__module__', None)1        if mod and not mod.startswith(self.name):>            # print('skipping | ', node.__module__, '|', node)            return(        if isinstance(node, ModuleType):            type_ = 'module'g        elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'):            type_ = 'instance'E        elif issubclass(type(node), type) and type(node) is not type:(            type_ = 'metaclass_instance'
        else:'            type_ = type(node).__name__E        visitor = getattr(self, 'visit_' + type_, self.visit_unknown)        return visitor(node)6    def visit_metaclass_instance(self, meta_instance):7        #print('visiting meta instance', meta_instance)        pass%    def visit_unknown(self, unknown):        print('========')1        print('No clue what to do with', unknown)F        print('isinstance(node, object)', isinstance(unknown, object))B        print('isinstance(node, type)', isinstance(unknown, type))*        print('type(node)', type(unknown))!        if type(unknown) is type:I            print('issubclass(unknown, type)', issubclass(unknown, type))`        print('issubclass(type(unknown), type)', issubclass(type(unknown), type), type(unknown))@        print('type(unknown) is type : ', type(unknown) is type)        print('========')'    def visit_function(self, function):"        klass = function.__class__'        if klass is types.FunctionType:&            name = function.__module__
        else:Y            name = '%s.%s' % (function.__class__.__module__, function.__class__.__name__)>        fullqual = '{}.{}'.format(name, function.__qualname__)        print('    ', fullqual)$        self.collected.add(fullqual),        self._consistent(fullqual, function)'    def visit_instance(self, instance):,        #print('    vis instance', instance)        pass     def visit_type(self, type_):=        print('Class', type_.__module__ +'.'+ type_.__name__)2        for k,v in sorted(type_.__dict__.items()):%            if not k.startswith('_'):                self.visit(v)#    def visit_module(self, module):        print('Module', module)5        if not module.__name__.startswith(self.name):            return None        items = module.__dict__)        for k,v in sorted(items.items()):!            if k.startswith('_'):                continue            else:                self.visit(v)if __name__ == '__main__':    print("let's go")    module_name = 'IPython'$    module = __import__(module_name)    V = Visitor(module_name)    V.visit(module)    print(len(V.visited))5_
VX88	t,    if isinstance(obj is types.FunctionType:
@    """?!?jedi=0, ?!?          (*_*x*_*, (A, B, ...)) ?!?jedi?!?5_
VX8<	t)    if isinstance(obj,types.FunctionType:5_
(VX8>%	t*    if isinstance(obj,types.FunctionType):
    """5_ikxjHHH"v"X'HIiGIi+        self.collected.add(fully_qualified)5_jlkH*HH"v"X'GIi5        self.collected.add(fully_qualified(function))FH>        fullqual = '{}.{}'.format(name, function.__qualname__)5_kmlGGG"v"X'FH5_lnmFFF"v"X'EG5_monEEE"v"X'DF5_npoDDD"v"X'CE5_oqpCCC"v"X'BD5_puqB
&
vX'AC5_qvruA'CC3v3X(@Bc'    def visit_function(self, function):5_uwvBCC3v3X(	ACd        print()5_vwBCC3v3X(
@B'    def visit_function(self, function):BCdACd0        print('    ', fully_qualified(function))5_qsurJBB"v"X'HJ}    def visi?!?jedi=0, t_type(self, type_):?!? (value, *_*...*_*, sep=' ', end='\n', file=sys.stdout, flush=False) ?!?jedi?!?5_rtsJBB"v"X'IKc6        print('Class', fully_qualified(type_.__name__)HJQ    def visit_type(self, type_):?!?jedi=0, ?!?      (*_*obj:object*_*) ?!?jedi?!?5_stJ5BB"v"X'IKc.        print('Class', fully_qualified(type_))HJ     def visit_type(self, type_):5_=	=vX
=$        if node in self.namevisited:5PKIEJ&3]frappuccino/.__main__.py.un~VimUnDo7ȯ3X݋;GKuuX&.X_X5PK0Jhŭ11frappuccino/__init__.py"""
Frappuccino
===========

> Yes there is only one N.

Freeze your API.

Frappucino allows you during development to make sure you haven't broken API. By
first taking an imprint of your API, at one point in time and then compare it to
the current project state it can warn you whether you have introduced
incompatible changes, and list theses.

You should (of course) integrate it in you CI to make sure you don't
inadvertently break things.

Example:

```python
# old function
def read(name, *, options=None):
    with open(name. 'rb') as f:
        return process(data)

# new function
def read(name_or_buffer, *, options=None):
    if isinstance(name, str):
        with open(name, 'rb') as f:
            data = f.read()
    else:
        data = name_or_buffer.read()
    return process(data)
```

There is a subtle breakage of API in the above, as you may not remember
positional parameters can be use a keyword arguments. That is to say one of your customer may use:

```python
read(name='dump.csv')
```

Hence changing the _name_ of the positional parameter from `name` to
`name_or_buffer` is a change of API. There are a number of details like this one
where you _may_ end up breaking API without realizing. It's hard to keep track
of this when working on dev branches, unit test may not catch all of that.
Frappuccino is there to help.
"""

__version__ = '0.0.1'


import importlib
import inspect
import types
import json
import re

from pprint import pprint
from types import ModuleType

import logging
logging.basicConfig()
logger = logging.getLogger(__name__)

hexd = re.compile('0x[0-9a-f]+')


def hexuniformify(s: str)->str:
    """
    Uniforming hex addresses to `0xffffff` to avoid difference between rerun.

    Difference  may be due to object id varying in reprs.
    """
    return hexd.sub('0xffffff', s)


### likely unused code used for testing at some point

def foo():
    pass

def signature_from_text(text):
    loc = {}
    glob = {}
    try:
        exec(compile('from typing import *\ndef function%s:pass' %
                     text, '', 'exec'), glob, loc)
        sig = inspect.signature(loc['function'])
    except Exception as e:
        print(' failed:>>> def function%s:pass' % text)
        return inspect.signature(foo)
        raise
    return sig


####



def parameter_dump(p):
    """
    Given a parameter (from inspect signature), dump ti to json
    """
    # TODO: mapping of kind  and drop default if inspect empty + annotations.
    return {'kind': str(p.kind),
            'name': p.name,
            'default': hexuniformify(str(p.default))}


def sig_dump(sig):
    """
    Given a signature (from inspect signature), dump ti to json
    """
    return {k: parameter_dump(v) for k, v in sig.parameters.items()}



def fully_qualified(obj: object) -> str:
    """
    (try to) return the fully qualified name of an object
    """
    if obj is types.FunctionType:  # noqa
        return '%s.%s' % (obj.__module__, obj.__qualname__)
    else:
        return '%s.%s' % (obj.__class__.__module__, obj.__class__.__name__)


class Visitor:

    def __init__(self, name):
        self.name = name

        # list of visited nodes to avoid recursion and going in circle.
        # can't be a set we store non-hashable objects
        # which is weird why not store memory-location -> object ?
        # anyway...
        self.visited = list()
        self._hash_cache = dict()

        # set of object keys that where deemed worth collecting
        self.collected = set({})
        self.rejected = list()

        # dict of key -> custom spec that should be serialised for comparison
        # later.
        self.spec = dict()

        # debug, make sure 2 objects are not getting the same key
        self._consistency = {}

    def _consistent(self, key, value):
        if key in self._consistency:
            if self._consistency[key] is not value:
                logger.debug("Warning %s is not %s, results may not be consistent" % (
                    self._consistency[key], value))
        else:
            self._consistency[key] = value

    def visit(self, node):
        try:
            if id(node) in [id(x) for x in self.visited]:
                # todo, if visited check the localkey and return it.
                # otherwise methods moved to superclass will/may be lost.
                # or not correctly reported
                return self._hash_cache.get(id(node))
            else:
                self.visited.append(node)
        except TypeError:
            # non equalable things (eg dtype/moduel)
            return
        mod = getattr(node, '__module__', None)
        if mod and not mod.startswith(self.name):
            self.rejected.append(node)
            # print('skipping | ', node.__module__, '|', node)
            return

        if isinstance(node, ModuleType):
            type_ = 'module'
        elif isinstance(node, object) and not isinstance(node, type) and not hasattr(node, '__call__'):
            type_ = 'instance'
        elif issubclass(type(node), type) and type(node) is not type:
            type_ = 'metaclass_instance'
        else:
            type_ = type(node).__name__
        visitor = getattr(self, 'visit_' + type_, self.visit_unknown)
        hashv = visitor(node)
        self._hash_cache[id(node)] = hashv
        return hashv

    def visit_metaclass_instance(self, meta_instance):
        return self.visit_type(meta_instance)
        pass

    def visit_unknown(self, unknown):
        self.rejected.append(unknown)

        logger.debug('Unknown: ========')
        logger.debug('Unknown: No clue what to do with %s', unknown)
        logger.debug('Unknown: isinstance(node, object) %s',
                     isinstance(unknown, object))
        logger.debug('Unknown: isinstance(node, type) %s',
                     isinstance(unknown, type))
        logger.debug('Unknown: type(node) %s', type(unknown))
        if type(unknown) is type:
            logger.debug('Unknown: issubclass(unknown, type) %s',
                         issubclass(unknown, type))
        logger.debug('Unknown: issubclass(type(unknown), type) %s %s',
                     issubclass(type(unknown), type), type(unknown))
        logger.debug('Unknown: type(unknown) is type :  %s',
                     type(unknown) is type)
        logger.debug('Unknown: hasattr(unknown, "__call__"):  %s',
                     hasattr(unknown, "__call__"))
        logger.debug('Unknown: ========')

    def visit_function(self, function):
        klass = function.__class__
        if isinstance(klass, types.FunctionType):
            name = function.__module__
        else:
            name = '%s.%s' % (function.__class__.__module__,
                              function.__class__.__name__)
        fullqual = '{}.{}'.format(name, function.__qualname__)
        # try:
        sig = hexuniformify(str(inspect.signature(function)))
        # except ValueError:
        #    return
        logger.debug('    {f}{s}'.format(f=fullqual, s=sig))
        self.collected.add(fullqual)
        # self.spec[fullqual] = sig
        self.spec[fullqual] = {
            ':signature:': sig_dump(inspect.signature(function))}
        self._consistent(fullqual, function)
        return fullqual

    def visit_instance(self, instance):
        self.rejected.append(instance)
        logger.debug('    vis instance %s', instance)
        pass

    def visit_type(self, type_):
        local_key = type_.__module__ + '.' + type_.__qualname__
        items = {}
        logger.debug('Class %s' % type_.__module__ + '.' + type_.__qualname__)
        for k in sorted(dir(type_)):
            if not k.startswith('_'):
                items[k] = self.visit(getattr(type_, k))
        items = {k: v for k, v in items.items() if v}
        self.spec[local_key] = items
        self.collected.add(local_key)
        return local_key

    def visit_module(self, module):
        logger.debug('Module %s' % module)
        if not module.__name__.startswith(self.name):
            logger.debug('out of scope %s vs %s : %s' % (
                module.__name__, self.name, module.__name__.startswith(self.name)))
            return None
        for k in dir(module):
            if k.startswith('_'):
                logger.debug('       -> %s.%s' % (module.__name__, k))
                continue
            else:
                logger.debug('       +> %s.%s' % (module.__name__, k))
                self.visit(getattr(module, k))


def param_compare(old, new):
    if old is None:
        print('     New paramters', repr(new))
        return
    print('    ', old, '!=', new)


def params_compare(old_ps, new_ps):
    try:
        from itertools import zip_longest
        for (o, ov), (n, nv) in zip_longest(old_ps.items(), new_ps.items(), fillvalue=(None, None)):
            if o == n and ov == nv:
                continue
            param_compare(ov, nv)
    except:
        import ipdb
        ipdb.set_trace()


def main():
    import argparse

    parser = argparse.ArgumentParser('Argparser for foo')
    parser.add_argument('modules', metavar='modules', type=str,
                        nargs='+', help='root modules and submodules')
    parser.add_argument('--save', action='store_true')
    parser.add_argument('--compare', action='store_true')
    parser.add_argument('--debug', action='store_true')

    options = parser.parse_args()

    if options.save and options.compare:
        print('options `--save` and `--compare` are exclusive')
        parser.print_help()

    if options.debug:
        logger.debug('before')
        logger.setLevel('DEBUG')
        logger.debug('after')

    rootname = options.modules[0]
    tree_visitor = Visitor(rootname.split('.')[0])
    for module_name in options.modules:
        try:
            module = importlib.import_module(module_name)
            tree_visitor.visit(module)
        except (ImportError, RuntimeError, AttributeError) as e:
            print('skip...', module_name)
            print(e)

    print("Collected/Visited/rejected", len(tree_visitor.collected),
          len(tree_visitor.visited), len(tree_visitor.rejected), "objects")

    if options.save:
        with open('%s.json' % rootname, 'w') as f:
            f.write(json.dumps(tree_visitor.spec, indent=2))
        #import IPython
        # IPython.embed()
    if options.compare:
        with open('%s.json' % rootname, 'r') as f:
            loaded = json.loads(f.read())

        lkeys = set(loaded.keys())
        skeys = set(tree_visitor.spec.keys())

        common_keys = skeys.intersection(lkeys)
        removed_keys = lkeys.difference(skeys)
        new_keys = skeys.difference(lkeys)
        if new_keys:
            print(
                "The following items are new, former aliases, or where present on superclass")
            pprint(new_keys)
            print()
        if removed_keys:
            print(
                "The following canonical items have been removed, are now aliases or moved to super-class")
            pprint(removed_keys)
            print()

        print("The following signature differ between versions:")
        for key in common_keys:
            if isinstance(loaded[key], str):
                from_dump = hexuniformify(loaded[key])
                current_spec = hexuniformify(tree_visitor.spec[key])
            else:
                from_dump = loaded[key]
                current_spec = tree_visitor.spec[key]

            if from_dump != current_spec:
                if isinstance(current_spec, dict):  # Classes / Module / Fucntion
                    if ':signature:' not in current_spec.keys():
                        removed = [k for k in from_dump if k not in current_spec]
                        if not removed:
                            continue
                        print()
                        print("Class/Module> %current_spec" % (key))
                        new = [k for k in current_spec if k not in from_dump]
                        if new:
                            print('              new values are', new)
                        removed = [k for k in from_dump if k not in current_spec]
                        if removed:
                            print('              removed values are', removed)
                    else:
                        from_dump = from_dump[':signature:']
                        current_spec = current_spec[':signature:']
                        print()
                        print("function> %s" % (key))
                        print("          %s" % (key))
                        params_compare(from_dump, current_spec)


if __name__ == '__main__':
    main()
PKIEJo$$frappuccino/__main__.pyfrom frappuccino import main
main()
PK6CJ		frappuccino/astinit.py"""Frappucinno

Freeze your API and make sure you do not introduce backward incompatibilities
"""
import ast
from pprint import pprint
__version__ = '0.0.1'

test1 = """


class Bird:
    def bar(a,b, *args, kow, **kw ):
        pass

    def foo(c):
        pass


    def missing():
        pass

    def _private():
        pass
"""

test2 = """
class Bird:
    def bar(a,b, *args, kow, **kw ):
        pass

    def foo(c):
        pass

    def _private():
        pass
"""

def keyfy(s):
    return '"%s":' % s

class APIVisitor:
    """
    A node visitor base class that walks the abstract syntax tree and calls a
    visitor function for every node found.  This function may return a value
    which is forwarded by the `visit` method.

    This class is meant to be subclassed, with the subclass adding visitor
    methods.

    Per default the visitor functions for the nodes are ``'visit_'`` +
    class name of the node.  So a `TryFinally` node visit function would
    be `visit_TryFinally`.  This behavior can be changed by overriding
    the `visit` method.  If no visitor function exists for a node
    (return value `None`) the `generic_visit` visitor is used instead.

    Don't use the `NodeVisitor` if you want to apply changes to nodes during
    traversing.  For this a special visitor exists (`NodeTransformer`) that
    allows modifications.
    """

    def visit(self, node):
        """Visit a node."""
        method = 'visit_' + node.__class__.__name__
        visitor = getattr(self, method, self.generic_visit)
        return visitor(node)

    def generic_visit(self, node):
        """Called if no explicit visitor function exists for a node."""
        res = []
        for field, value in ast.iter_fields(node):
            if isinstance(value, list):
                for item in value:
                    vv = self.visit(item)
                    res.append(vv)
            elif isinstance(value, dict):
                for k,v in value:
                    res.append(self.visit(v))
                res.append(self.visit(value))
        if not res:
            print("visiting", node)
        return list(filter(None, res))

    def visit_FunctionDef(self, node):
        if node.name.startswith('_'):
            return None
        args = node.args
        return {node.name: {'type': node.__class__.__name__,
                            'args': [a.arg for a in args.args],
                            'kwonlyargs': [a.arg for a in args.kwonlyargs],
                            'vararg': args.vararg.arg if args.vararg else [],
                            'kwarg': args.kwarg.arg if args.kwarg else [],
                            }}

    def visit_ClassDef(self, node):
        vis = self.generic_visit(node)
        d = {}
        for item in vis:
            d.update(item)
        return {node.name: {'type': node.__class__.__name__, 'attributes': d}}


def is_compatible(old_tree, new_tree):
    pass


class DoubleTreeVisitor:
    """
    Like AstVisitor, but compare two tree for compatibility. 
    """

    def visit(self, old_list, new_list, name=None):
        """Visit a node."""
        for old_node, new_node in zip(old_list, new_list):
            for k, v in old_node.items():
                if k in new_node:
                    method = 'visit_' + v['type']
                    visitor = getattr(self, method, self.generic_visit)
                    visitor(v, new_node[k], k)

    def generic_visit(self, old_node, new_node):
        """Called if no explicit visitor function exists for a node."""
        res = []
        for field, value in old_node.items():
            if isinstance(value, list):
                for item in value:
                    if isinstance(item, ast.AST):
                        res.append(self.visit(item))
            elif isinstance(value, ast.AST):
                res.append(self.visit(value))
        return list(filter(None, res))


    def visit_ClassDef(self, old_class, new_class, name):
        missing_attributes = set(old_class['attributes'].keys()).difference(set(new_class['attributes'].keys()))
        if missing_attributes:
            print('Class `{}` has lost non deprecated and non private following attributes : {}'.format(name,  *missing_attributes))
        
        self.generic_visit(old_class, new_class)




if __name__ == '__main__':
    tree = ast.parse(test1)
    serialized_tree = APIVisitor().visit(tree)
    
    # pprint(serialized_tree)

    tree2 = ast.parse(test2)
    serialized_tree2 = APIVisitor().visit(tree2)


    dt = DoubleTreeVisitor().visit(serialized_tree, serialized_tree2)
PKUDJO9"frappuccino/.ropeproject/config.py# The default ``config.py``
# flake8: noqa


def set_prefs(prefs):
    """This function is called before opening the project"""

    # Specify which files and folders to ignore in the project.
    # Changes to ignored resources are not added to the history and
    # VCSs.  Also they are not returned in `Project.get_files()`.
    # Note that ``?`` and ``*`` match all characters but slashes.
    # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
    # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
    # '.svn': matches 'pkg/.svn' and all of its children
    # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
    # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
    prefs['ignored_resources'] = [
        '*.pyc', '*~', '.ropeproject', '.hg', '.svn', '_svn',
        '.git', '.tox', '.env', 'env', 'venv', 'node_modules',
        'bower_components'
    ]

    # Specifies which files should be considered python files.  It is
    # useful when you have scripts inside your project.  Only files
    # ending with ``.py`` are considered to be python files by
    # default.
    #prefs['python_files'] = ['*.py']

    # Custom source folders:  By default rope searches the project
    # for finding source folders (folders that should be searched
    # for finding modules).  You can add paths to that list.  Note
    # that rope guesses project source folders correctly most of the
    # time; use this if you have any problems.
    # The folders should be relative to project root and use '/' for
    # separating folders regardless of the platform rope is running on.
    # 'src/my_source_folder' for instance.
    #prefs.add('source_folders', 'src')

    # You can extend python path for looking up modules
    #prefs.add('python_path', '~/python/')

    # Should rope save object information or not.
    prefs['save_objectdb'] = True
    prefs['compress_objectdb'] = False

    # If `True`, rope analyzes each module when it is being saved.
    prefs['automatic_soa'] = True
    # The depth of calls to follow in static object analysis
    prefs['soa_followed_calls'] = 0

    # If `False` when running modules or unit tests "dynamic object
    # analysis" is turned off.  This makes them much faster.
    prefs['perform_doa'] = True

    # Rope can check the validity of its object DB when running.
    prefs['validate_objectdb'] = True

    # How many undos to hold?
    prefs['max_history_items'] = 32

    # Shows whether to save history across sessions.
    prefs['save_history'] = True
    prefs['compress_history'] = False

    # Set the number spaces used for indenting.  According to
    # :PEP:`8`, it is best to use 4 spaces.  Since most of rope's
    # unit-tests use 4 spaces it is more reliable, too.
    prefs['indent_size'] = 4

    # Builtin and c-extension modules that are allowed to be imported
    # and inspected by rope.
    prefs['extension_modules'] = []

    # Add all standard c-extensions to extension_modules list.
    prefs['import_dynload_stdmods'] = True

    # If `True` modules with syntax errors are considered to be empty.
    # The default value is `False`; When `False` syntax errors raise
    # `rope.base.exceptions.ModuleSyntaxError` exception.
    prefs['ignore_syntax_errors'] = False

    # If `True`, rope ignores unresolvable imports.  Otherwise, they
    # appear in the importing namespace.
    prefs['ignore_bad_imports'] = False

    # If `True`, rope will insert new module imports as
    # `from  import ` by default.
    prefs['prefer_module_from_imports'] = False

    # If `True`, rope will transform a comma list of imports into
    # multiple separate import statements when organizing
    # imports.
    prefs['split_imports'] = False

    # If `True`, rope will sort imports alphabetically by module name
    # instead of alphabetically by import statement, with from imports
    # after normal imports.
    prefs['sort_imports_alphabetically'] = False


def project_opened(project):
    """This function is called after opening the project"""
    # Do whatever you like here!
PKFJ+Gۤ$frappuccino/.ropeproject/globalnames}q(Xq]q(XloggerqXhexdqXfully_qualifiedqXVisitorqXmainqeXastppq]q	(Xdumpq
X
parseprintqXpdpqXload_ipython_extensionq
XfilenameqXfqXfstrqeXastinitq]q(Xtest1qXtest2qXkeyfyqX
APIVisitorqX
is_compatibleqXDoubleTreeVisitorqXtreeqXserialized_treeqXtree2qXserialized_tree2qXdtqeX__main__q]qu.PKFJ}
 frappuccino/.ropeproject/history]q(]q]qe.PKFJ3'\11!frappuccino/.ropeproject/objectdb}q(Xe/Users/bussonniermatthias/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/argparse/argparse.pyq}qXArgumentParser.parse_argsqcrope.base.oi.memorydb
ScopeInfo
q)q}qXinstanceqXdefinedqXe/Users/bussonniermatthias/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/argparse/argparse.pyq	XArgumentParserq
qqXunknownq
qXnoneqqqhs}qqbsXj/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/__init__.pyq}qX	getLoggerqh)q}q(hqhhXj/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/__init__.pyqX
RootLoggerqqqhqhhXj/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/logging/__init__.pyqhq q!u}q"q#bsX\/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/os.pyq$}q%X_createenvironq&h)q'}q()hhX\/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/os.pyq)X_Environq*q+q,s}q-q.bsXf/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/decoder.pyq/}q0XJSONDecoder.raw_decodeq1h)q2}q3hhXf/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/decoder.pyq4XJSONDecoderq5q6q7h
q8hq9(Xbuiltinq:Xtupleq;h8h8tqbsX\/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.pyq?}q@(X_compileqAh)qB}qCh:XstrqDqEh8qFhEs}qGqHbXcompileqIh)qJ}qKhEhqLhEs}qMqNbuX?/Users/bussonniermatthias/dev/ipython/IPython/core/completer.pyqO}qP(Xposition_to_cursorqQh)qR}qSh8h8qT(h:h;h8h8tqUs}qVqWbXCompletionSplitter.split_lineqXh)qY}qZhhX?/Users/bussonniermatthias/dev/ipython/IPython/core/completer.pyq[XCompletionSplitterq\q]q^h8h8q_hEs}q`qabXIPCompleter._completeqbh)qc}qd(hhX?/Users/bussonniermatthias/dev/ipython/IPython/core/completer.pyqeXIPCompleterqfqgqhh8h8h8tqih:h;hEqjs}qkqlbuu.PK!H+2,frappuccino-0.0.1.dist-info/entry_points.txtN+I/N.,()J+J,((MNWU@Y&fqqPK-DJA3#frappuccino-0.0.1.dist-info/LICENSEBSD 3-Clause License

Copyright (c) 2017, Matthias Bussonnier
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PK!HuNRR!frappuccino-0.0.1.dist-info/WHEEL1
0RZq+D-Dv;_[*7Fp 6ՆKŵ|4|cBQaL2PK!Hѯ $frappuccino-0.0.1.dist-info/METADATAMJ@)ioۊ(ڴtto
;9DJTp,\ߩ#yNSW<3=Wm6&W)uK^w+
)׷ұ%|4]9
. )A(2ؐW`s?qK}oڞS~zjuXiaӾ0PK!HhE"frappuccino-0.0.1.dist-info/RECORD}9@P삈Ka_*B`~9͞=7}p.b?Xn-2 XQSwژAT!Ib3F}^Κ
MmB\pr_]8هO_>[}->uyo	/%],4hoΠ3k1If?Vyrs:IFVV-P@	3q=΅)BǸmNRm#[lWZ~͢I㗫2:+NMVEQڐmm}U2(ӟIjA-E`3Gء
qgw]hP+ճc-xk7|&56xda%c_MKRV~O܇҂bC