DebugClients/Python3/DebugVariables.py

changeset 5175
9db0b0f15d12
parent 5171
f1e9eebd5469
child 5190
65a2234c6789
diff -r 632257ad7337 -r 9db0b0f15d12 DebugClients/Python3/DebugVariables.py
--- a/DebugClients/Python3/DebugVariables.py	Fri Sep 16 19:34:58 2016 +0200
+++ b/DebugClients/Python3/DebugVariables.py	Mon Sep 19 20:10:33 2016 +0200
@@ -54,6 +54,11 @@
         raise NotImplementedError
 
 
+############################################################
+## Default Resolver
+############################################################
+
+
 class DefaultResolver(BaseResolver):
     """
     Class used to resolve the default way.
@@ -69,7 +74,7 @@
         @return value of the attribute
         @rtype any
         """
-        return getattr(var, attribute)
+        return getattr(var, attribute, None)
     
     def getDictionary(self, var):
         """
@@ -95,6 +100,11 @@
         return d
 
 
+############################################################
+## Resolver for Dictionaries
+############################################################
+
+
 class DictResolver(BaseResolver):
     """
     Class used to resolve from a dictionary.
@@ -117,7 +127,7 @@
             try:
                 return var[attribute]
             except Exception:
-                return getattr(var, attribute)
+                return getattr(var, attribute, None)
         
         expectedID = int(attribute.split("(ID:")[-1][:-1])
         for key, value in var.items():
@@ -126,9 +136,9 @@
         
         return None
     
-    def __keyToStr(self, key):
+    def keyToStr(self, key):
         """
-        Private method to get a string representation for a key.
+        Public method to get a string representation for a key.
         
         @param key key to be converted
         @type any
@@ -153,7 +163,7 @@
         count = 0
         for key, value in var.items():
             count += 1
-            key = "{0} (ID:{1})".format(self.__keyToStr(key), id(key))
+            key = "{0} (ID:{1})".format(self.keyToStr(key), id(key))
             d[key] = value
             if count > MaxItemsToHandle:
                 d[TooLargeAttribute] = TooLargeMessage
@@ -168,6 +178,11 @@
         return d
 
 
+############################################################
+## Resolver for Lists and Tuples
+############################################################
+
+
 class ListResolver(BaseResolver):
     """
     Class used to resolve from a tuple or list.
@@ -189,7 +204,7 @@
         try:
             return var[int(attribute)]
         except Exception:
-            return getattr(var, attribute)
+            return getattr(var, attribute, None)
     
     def getDictionary(self, var):
         """
@@ -218,6 +233,11 @@
         return d
 
 
+############################################################
+## Resolver for Sets and Frozensets
+############################################################
+
+
 class SetResolver(BaseResolver):
     """
     Class used to resolve from a set or frozenset.
@@ -236,12 +256,12 @@
         if attribute in ('___len___', TooLargeAttribute):
             return None
 
-        if attribute.startswith("ID:"):
+        if attribute.startswith("ID: "):
             attribute = attribute.split(None, 1)[1]
         try:
             attribute = int(attribute)
         except Exception:
-            return getattr(var, attribute)
+            return getattr(var, attribute, None)
 
         for v in var:
             if id(v) == attribute:
@@ -276,14 +296,190 @@
         return d
 
 
+############################################################
+## Resolver for Numpy Arrays
+############################################################
+
+
+class NdArrayResolver(BaseResolver):
+    """
+    Class used to resolve from numpy ndarray including some meta data.
+    """
+    def __isNumeric(self, arr):
+        """
+        Private method to check, if an array is of a numeric type.
+        
+        @param arr array to check
+        @type ndarray
+        @return flag indicating a numeric array
+        @rtype bool
+        """
+        try:
+            return arr.dtype.kind in 'biufc'
+        except AttributeError:
+            return False
+    
+    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 id of the value to extract
+        @type str
+        @return value of the attribute
+        @rtype any
+        """
+        if attribute == '__internals__':
+            return defaultResolver.getDictionary(var)
+        
+        if attribute == 'min':
+            if self.__isNumeric(var):
+                return var.min()
+            else:
+                return None
+        
+        if attribute == 'max':
+            if self.__isNumeric(var):
+                return var.max()
+            else:
+                return None
+        
+        if attribute == 'mean':
+            if self.__isNumeric(var):
+                return var.mean()
+            else:
+                return None
+        
+        if attribute == 'shape':
+            return var.shape
+        
+        if attribute == 'dtype':
+            return var.dtype
+        
+        if attribute == 'size':
+            return var.size
+        
+        if attribute.startswith('['):
+            container = NdArrayItemsContainer()
+            count = 0
+            for element in var:
+                setattr(container, str(count), element)
+                count += 1
+                if count > MaxItemsToHandle:
+                    setattr(container, TooLargeAttribute, TooLargeMessage)
+                    break
+            return container
+        
+        return None
+    
+    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 = {}
+        d['__internals__'] = defaultResolver.getDictionary(var)
+        if var.size > 1024 * 1024:
+            d['min'] = 'ndarray too big, calculating min would slow down' \
+                       ' debugging'
+            d['max'] = 'ndarray too big, calculating max would slow down' \
+                       ' debugging'
+        else:
+            if self.__isNumeric(var):
+                d['min'] = var.min()
+                d['max'] = var.max()
+                d['mean'] = var.mean()
+            else:
+                d['min'] = 'not a numeric object'
+                d['max'] = 'not a numeric object'
+                d['mean'] = 'not a numeric object'
+        d['shape'] = var.shape
+        d['dtype'] = var.dtype
+        d['size'] = var.size
+        d['[0:{0}]'.format(len(var) - 1)] = list(var[0:MaxItemsToHandle])
+        return d
+
+
+class NdArrayItemsContainer:
+    """
+    Class to store ndarray items.
+    """
+    pass
+
+
+############################################################
+## Resolver for Django Multi Value Dictionaries
+############################################################
+
+
+class MultiValueDictResolver(DictResolver):
+    """
+    Class used to resolve from Django multi value dictionaries.
+    """
+    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 "(ID:" not in attribute:
+            try:
+                return var[attribute]
+            except Exception:
+                return getattr(var, attribute, None)
+        
+        expectedID = int(attribute.split("(ID:")[-1][:-1])
+        for key in var.keys():
+            if id(key) == expectedID:
+                value = var.getlist(key)
+                return value
+        
+        return None
+    
+    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 in var.keys():
+            count += 1
+            value = var.getlist(key)
+            key = "{0} (ID:{1})".format(self.keyToStr(key), id(key))
+            d[key] = value
+            if count > MaxItemsToHandle:
+                d[TooLargeAttribute] = TooLargeMessage
+                break
+        
+        d["___len___"] = len(var)
+        
+        return d
+
+
 defaultResolver = DefaultResolver()
 dictResolver = DictResolver()
 listResolver = ListResolver()
 setResolver = SetResolver()
-
-# TODO: add resolver for numpy arrays
-# TODO: add resolver for Django MultiValueDict
-# TODO: add resolver for collections.deque
+ndarrayResolver = NdArrayResolver()
+multiValueDictResolver = MultiValueDictResolver()
 
 ############################################################
 ## Methods to determine the type of a variable and the
@@ -329,6 +525,19 @@
         _TypeMap.append((frozenset, setResolver))     # __IGNORE_WARNING__
     except Exception:
         pass    # not available on all python versions
+    
+    try:
+        import numpy
+        _TypeMap.append((numpy.ndarray, ndarrayResolver))
+    except ImportError:
+        pass  # numpy may not be installed
+    
+    try:
+        from django.utils.datastructures import MultiValueDict
+        _TypeMap.insert(0, (MultiValueDict, multiValueDictResolver))
+        # it should go before dict
+    except ImportError:
+        pass  # django may not be installed
 
 
 def getType(obj):

eric ide

mercurial