Package: deep-vars
deep_varsA package providingdeep_varsfunction that serves a purpose similar tovars, but it works with any object and can recursively process attributes as well.ContentBasic useConfigurationHandlersFurther configuration specific to some handlersExtending handlersBasic useThis is used in a way similar tovars. For example, the following code:fromdataclassesimportdataclassfromtypingimportOptionalfromdeep_varsimportdeep_vars@dataclassclassFoo:x:inty:Optional["Foo"]=Nonefoo=Foo(17,y=Foo(19))print("vars:                     ",vars(foo))print("deep_vars:                ",deep_vars(foo))print("deep_vars with maxdepth=2:",deep_vars(foo,2))will print this:vars:                      {'x': 17, 'y': Foo(x=19, y=None)}
deep_vars:                 {'x': 17, 'y': Foo(x=19, y=None)}
deep_vars with maxdepth=2: {'x': 17, 'y': {'x': 19, 'y': None}}Note that, because it covers objects of all classes,deep_varsmight not product a dictionary. For example, if we definefooin the above code like this:foo=[Foo(17),"foo",17]thevarsprint would just raise an exception:TypeError: vars() argument must have __dict__ attribute`while thedeep_varoutputs will be:deep_vars:                 [Foo(x=17, y=None), 'foo', 17]
deep_vars with maxdepth=2: [{'x': 17, 'y': None}, 'foo', 17]Configurationdeep_varsis meant to be simple to use, likevars, so its only arguments are the object being represented and the maximum depth down to witch the conversion should go.However, there are various possibilities for configuring it for the whole project. This is done through the attributes ofDeepVarsclass.HandlersThe main thing one can adjust is how various objects are handled. This is done by assigning "handler types". For example, this will cause allfloatandstrattributes to remain hidden:DeepVars.set_handlers(DeepVarsHandlerHide,float,str)There are severalDeepVarsHandler<something>classes that can be used:DeepVarsHandler: Default class, used as a parent class for all the others. It should not be used directly.DeepVarsHandlerShow: Show the object as it is (i.e., don't process it).DeepVarsHandlerHide: Skip the attribute from the output. Note that this does not affect the top level call ofdeep_vars.DeepVarsHandlerProcess: Process it in the previously described manner (similar tovars).DeepVarsHandlerLoop: Loop the object (usually a list or a tuple) and process each item individually.DeepVarsHandlerLoopDict: Loop the object as a dictionary, using itsitemsmethod (can be changed in inherited classes) and process each(key, value)pair individually.DeepVarsHandlerCallable: Special handler for callables, converting them to signature strings.One can also configure the default handler for those attributes that are not individually set. For example, to have them show without any processing:DeepVars.default_handler=DeepVarsHandlerShowLet us take another look at the above example:DeepVars.set_handlers(DeepVarsHandlerHide,float,str)The first argument is a handler class. The rest of them describe the objects that this class is used for. These are usually types, but they can also be strings. The following are recognised:"magic": A magic attribute. These are usually methods with names starting and ending in double underscores (for example,__init__), butdeep_varswill consider any attribute, even non-callable ones, for the sake of output's consistency."private": Any object that has a name starting with an underscore (for example,_privateor__very_private)."callable": Any callable object (a function, a method, alambda) except classes.The handlers assignment is done in the same way as it is for type-based kinda of arguments:# Hide all "callable" arguments (not including classes):DeepVars.set_handlers(DeepVarsHandlerHide,"callable")# Hide all `float` and all "callable" arguments (not including classes):DeepVars.set_handlers(DeepVarsHandlerHide,float,"callable")Further configuration specific to some handlersSome of the handlers can be fine-tuned.DeepVarsHandlerLoopDictnormally uses object'sitems()method to go through its items. However, this can be replaced by changingDeepVarsHandlerLoopDict.items_method_nameto something other than"items". Further, if this other method requires arguments, these can be set up as a tupleDeepVarsHandlerLoopDict.items_method_argsand a dictionaryDeepVarsHandlerLoopDict.items_method_kwargs.All container handlers (DeepVarsHandlerLoopDict,DeepVarsHandlerLoop, andDeepVarsHandlerProcess) and also have the filtering of their items turned on or off. If turned off (class_name.allow_filtering = False), their items will show even if their handler is set toDeepVarsHandlerHide. This is the default for (DeepVarsHandlerLoopDictandDeepVarsHandlerLoop. If the filtering is turned on (class_name.allow_filtering = True), their items will be hidden if their handler decides so (i.e., if it is set toDeepVarsHandlerHide). This is the default forDeepVarsHandlerProcess.Extending handlersOne can easily define their own special object types. Here is an example from the tests:defspecial_detector(name:Optional[str],obj:Any)->Optional[str]:return("specially_detected"ifgetattr(obj,"specially_detected",False)elseNone)DeepVars.special_type_detectors.append(special_detector)DeepVars.set_handlers(DeepVarsHandlerSpecial,"specially_detected")First, we need to define a callable (usually a function) that detects the special type of the argument. This callable takes attribute's name (either a string orNone, the latter being used for the top level call ofdeep_vars) and the object itself, returning either a string used as the name for that kind of object orNoneif the object was not identified.Second, we add this callable to the listDeepVars.special_type_detectors. The three predefined special types of arguments listed above are built-in, butspecial_type_detectorsis checked before they are used, so its callables can override them.Lastly, one needs to define how is this special is handled, which is done as shown above with "callable" arguments.This allows one to extend the functionality ofdeep_vars. Arguably, this is not very useful in regular projects, but it can be used by other packages to offerdeep_varsfunctionality extended to their own needs.