DebugClients/Python3/DebugVariables.py

changeset 5169
74e000797a93
child 5171
f1e9eebd5469
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DebugClients/Python3/DebugVariables.py	Wed Sep 14 20:08:16 2016 +0200
@@ -0,0 +1,282 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing classes and functions to dump variable contents.
+"""
+
+#
+# This code was inspired by pydevd.
+#
+
+MaxItemsToHandle = 300
+TooLargeMessage = ("Too large to show contents. Max items to show: " + 
+                   str(MaxItemsToHandle))
+TooLargeAttribute = "Too large to be handled."
+
+############################################################
+## Classes implementing resolvers for various compund types
+############################################################
+
+class BaseResolver(object):
+    """
+    Base class of the resolver class tree.
+    """
+    def resolve(self, var, attribute):
+        """
+        Public method to get an attribute from a variable.
+        
+        @param var variable to extract an attribute or value from
+        @type any
+        @param attribute name of the attribute to extract
+        @type str
+        @return value of the attribute
+        @rtype any
+        """
+        raise NotImplementedError
+    
+    def getDictionary(self, var):
+        """
+        Public method to get the attributes of a variable as a dictionary.
+        
+        @param var variable to be converted
+        @type any
+        @return dictionary containing the variable attributes
+        @rtype dict
+        """
+        raise NotImplementedError
+
+
+class DefaultResolver(BaseResolver):
+    """
+    Class used to resolve the default way.
+    """
+    def resolve(self, var, attribute):
+        """
+        Public method to get an attribute from a variable.
+        
+        @param var variable to extract an attribute or value from
+        @type any
+        @param attribute name of the attribute to extract
+        @type str
+        @return value of the attribute
+        @rtype any
+        """
+        return getattr(var, attribute)
+    
+    def getDictionary(self, var):
+        """
+        Public method to get the attributes of a variable as a dictionary.
+        
+        @param var variable to be converted
+        @type any
+        @return dictionary containing the variable attributes
+        @rtype dict
+        """
+        names = dir(var)
+        if not names and hasattr(var, "__members__"):
+            names = var.__members__
+        
+        d = {}
+        for name in names:
+            try:
+                attribute = getattr(var, name)
+                d[name] = attribute
+            except Exception:
+                pass    # if we can't get it, simply ignore it
+        
+        return d
+
+
+class DictResolver(BaseResolver):
+    """
+    Class used to resolve from a dictionary.
+    """
+    def resolve(self, var, attribute):
+        """
+        Public method to get an attribute from a variable.
+        
+        @param var variable to extract an attribute or value from
+        @type dict
+        @param attribute name of the attribute to extract
+        @type str
+        @return value of the attribute
+        @rtype any
+        """
+        if attribute in ('__len__', TooLargeAttribute):
+            return None
+        
+        if "(" not in attribute:
+            try:
+##                if attribute[0] == "'" and attribute[-1] == "'":
+##                    attribute = attribute[1:-1]
+                return var[attribute]
+            except Exception:
+                return getattr(var, attribute)
+        
+        expectedID = int(attribute.split("(")[-1][:-1])
+        for key, value in var.items():
+            if id(key) == expectedID:
+                return value
+        
+        return None
+    
+    def __keyToStr(self, key):
+        if isinstance(key, str):
+            return repr(key)
+        else:
+            return key
+    
+    def getDictionary(self, var):
+        """
+        Public method to get the attributes of a variable as a dictionary.
+        
+        @param var variable to be converted
+        @type any
+        @return dictionary containing the variable attributes
+        @rtype dict
+        """
+        d = {}
+        count = 0
+        for key, value in var.items():
+            count += 1
+            key = "{0} ({1})".format(self.__keyToStr(key), id(key))
+            d[key] = value
+            if count > MaxItemsToHandle:
+                d[TooLargeAttribute] = TooLargeMessage
+                break
+        
+        d["__len__"] = len(var)
+        
+        # in case it has additional fields
+        additionals = defaultResolver.getDictionary(var)
+        d.update(additionals)
+        
+        return d
+
+
+class ListResolver(BaseResolver):
+    """
+    Class used to resolve from a tuple or list.
+    """
+    def resolve(self, var, attribute):
+        """
+        Public method to get an attribute from a variable.
+        
+        @param var variable to extract an attribute or value from
+        @type tuple or list
+        @param attribute name of the attribute to extract
+        @type str
+        @return value of the attribute
+        @rtype any
+        """
+        if attribute in ('__len__', TooLargeAttribute):
+            return None
+
+        try:
+            return var[int(attribute)]
+        except Exception:
+            return getattr(var, attribute)
+    
+    def getDictionary(self, var):
+        """
+        Public method to get the attributes of a variable as a dictionary.
+        
+        @param var variable to be converted
+        @type any
+        @return dictionary containing the variable attributes
+        @rtype dict
+        """
+        length = len(var)
+        d = {}
+        formatStr = "{0:0" + str(len(str(length))) + "d}"
+        count = 0
+        for value in var:
+            d[formatStr.format(count)] = value
+            count += 1
+            if count > MaxItemsToHandle:
+                d[TooLargeAttribute] = TooLargeMessage
+                break
+        
+        d["__len__"] = length
+        
+        # in case it has additional fields
+        additionals = defaultResolver.getDictionary(var)
+        d.update(additionals)
+        
+        return d
+
+
+defaultResolver = DefaultResolver()
+dictResolver = DictResolver()
+listResolver = ListResolver()
+
+# TODO: add resolver for set and frozenset
+# TODO: add resolver for numpy arrays
+# TODO: add resolver for Django MultiValueDict
+# TODO: add resolver for collections.deque
+
+############################################################
+## Methods to determine the type of a variable and the
+## resolver class to use
+############################################################
+
+_TypeMap = None
+
+def _initTypeMap():
+    """
+    Protected function to initialize the type map
+    """
+    global _TypeMap
+    
+    _TypeMap = [
+        (type(None), None,),
+        (int, None),
+        (float, None),
+        (complex, None),
+        (str, None),
+        (tuple, listResolver),
+        (list, listResolver),
+        (dict, dictResolver),
+    ]
+    
+    try:
+        _TypeMap.append((long, None))           # __IGNORE_WARNING__
+    except Exception:
+        pass    # not available on all python versions
+
+    try:
+        _TypeMap.append((unicode, None))        # __IGNORE_WARNING__
+    except Exception:
+        pass    # not available on all python versions
+
+
+def getType(obj):
+    """
+    Public method to get the type information for an object.
+    
+    @param obj object to get type information for
+    @type any
+    @return tuple containing the type, type name, type string and resolver
+    @rtype tuple of type, str, str, BaseResolver
+    """
+    typeObject = type(obj)
+    typeName = typeObject.__name__
+    typeStr = str(typeObject)[8:-2]
+    
+    if typeStr.startswith(("PyQt5.", "PyQt4.")):
+        resolver = None
+    else:
+        if _TypeMap is None:
+            _initTypeMap()
+        
+        for typeData in _TypeMap:
+            if isinstance(obj, typeData[0]):
+                resolver = typeData[1]
+                break
+        else:
+            resolver = defaultResolver
+    
+    return typeObject, typeName, typeStr, resolver

eric ide

mercurial