+def typeToString(obj, options=0):
+    if (isinstance(obj, BooleanType)):
+        return "bool"
+    elif (isinstance(obj, UnicodeType)):
+        if ((options & PRINT_OBJ_DIFFABLE) > 0):
+            return "string"
+        return "unicode"
+    elif (isinstance(obj, basestring)):
+        return "string"
+    elif (isinstance(obj, IntType)):
+        return "int"
+    elif (isinstance(obj, LongType)):
+        if ((options & PRINT_OBJ_DIFFABLE) > 0):
+            return "int"
+        return "long"
+    elif (isinstance(obj, FloatType)):
+        return "float"
+    elif (type(obj) == ListType):
+        return "list"
+    elif (isinstance(obj, DictType)):
+        return "dict"
+    elif (isinstance(obj, TupleType)):
+        return "tuple"
+    elif (isinstance(obj, InstanceType)):
+##        ds = str(type(obj))
+        ds = "<class %s.%s> " % (obj.__module__, obj.__class__.__name__)
+    else:
+        ds = str(type(obj))
+    if (options == 0):
+        import activegrid.util.aglogging
+        options = activegrid.util.aglogging.testMode(0, PRINT_OBJ_DIFFABLE)
+    if ((options & PRINT_OBJ_DIFFABLE) > 0):
+        if (ds.startswith("<class ")):
+            ix = ds.rfind(".")
+            if (ix < 0):
+                ix = 8
+            ds = "<class %s>" % ds[ix+1:-2]
+    return ds
+    
+def nameToString(name, options=0):
+    if (name.startswith("_v_")):
+        return name[3:]
+    if ((options & PRINT_OBJ_DIFFABLE) > 0):
+        ix = name.find("__")
+        if ((ix > 1) and name.startswith("_")):
+            name = name[ix:]
+        return toDiffableString(name)
+    return name
+            
+PRINT_OBJ_GETATTR = 1
+PRINT_OBJ_HIDE_INTERNAL = 2
+PRINT_OBJ_COMPACT = 4
+PRINT_OBJ_NONONE = 8
+PRINT_OBJ_DIFFABLE = 16
+PRINT_OBJ_HIDE_EXCLUDED = 32
+PRINT_OBJ_INTERNAL = 512
+
+def printObject(out, object, name=None, indent=0, flags=0, exclude=None, remove=None, maxIndent=30):
+    if (name == None):
+        name = ""
+##    elif (name.endswith("_") and not name.endswith("__")):
+##        name = name[:-1]
+    if ((remove != None) and (name in asDict(remove))):
+        return False
+    if ((maxIndent != None) and (indent > maxIndent)):
+        print >> out, " "*indent, "%s: %s" % (name, toString(str(object), flags)),
+        if ((flags & PRINT_OBJ_INTERNAL) == 0):
+            print >> out
+        return True
+    finalNewLine = False
+    printed = True
+    if ((flags & (PRINT_OBJ_COMPACT | PRINT_OBJ_HIDE_EXCLUDED)) > 0):
+        if ((exclude != None) and ((object in exclude) or (name in exclude))):
+            return
+        if ((flags & PRINT_OBJ_COMPACT) > 0):
+            indent = 0
+    if ((flags & PRINT_OBJ_INTERNAL) == 0):
+        finalNewLine = True
+    flags |= PRINT_OBJ_INTERNAL
+    if (object is None):
+        if (flags & PRINT_OBJ_NONONE) == 0:
+            print >> out, " "*indent, name, " = None",
+        else:
+            finalNewLine = False
+            printed = False
+    elif (name.startswith("_") and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0) and not name.startswith("_v_")):
+        finalNewLine = False
+        printed = False
+    elif (isinstance(object, (list, tuple))):
+        if ((exclude != None) and object in exclude):
+            print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (already printed)",
+        elif ((exclude != None) and name in exclude):
+            print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (excluded)",
+        else:
+            if ((exclude != None) and (len(object) > 0)): exclude.append(object)
+            print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = %d" % len(object),
+            for i, o in enumerate(object):
+                print >> out
+                printObject(out, o, name="[%d]" % i, indent=indent+2, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent)
+    elif (isinstance(object, dict)):
+        if ((exclude != None) and object in exclude):
+            print >> out, " "*indent, name, " : ", typeToString(object, flags), " (already printed)",
+        else:
+            if ((exclude != None) and (len(object) > 0)): exclude.append(object)
+            if (len(name) > 0):
+                print >> out, " "*indent, name,
+                if ((flags & PRINT_OBJ_COMPACT) == 0):
+                    print >> out
+                    indent += 2
+            print >> out, " "*indent, "{",
+            if ((flags & PRINT_OBJ_COMPACT) == 0):
+                print >> out
+            keys = object.keys()
+            keys.sort()
+            for key in keys:
+                if (key != None):
+                    n = key
+                    if (not (isinstance(n, basestring))):
+                        n = str(n)
+                    else:
+                        n = nameToString(n, flags)
+                    if ((not n.startswith("_") or ((flags & PRINT_OBJ_HIDE_INTERNAL) == 0))):
+                        if printObject(out, object[key], name=n, indent=indent+2, flags=(flags | PRINT_OBJ_INTERNAL), exclude=exclude, remove=remove, maxIndent=maxIndent):
+                            if ((flags & PRINT_OBJ_COMPACT) == 0):
+                                print >> out
+                            else:
+                                print >> out, ",",
+            print >> out, " "*indent, "}",
+    elif (hasattr(object, "__dict__")):
+        if (name.startswith("_")): ## and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)):
+            print >> out, " "*indent, name, " : ", typeToString(object, flags),
+        elif ((exclude != None) and ((object in exclude) or (object.__dict__ in exclude))):
+            print >> out, " "*indent, name, " : ", typeToString(object, flags), " (already printed)",
+        else:
+            if (exclude != None): exclude.append(object)
+            print >> out, " "*indent, name, " : ", typeToString(object, flags),
+            if ((flags & PRINT_OBJ_GETATTR) == 0):
+                if ((flags & PRINT_OBJ_COMPACT) == 0):
+                    print >> out
+                printObject(out, object.__dict__, indent=indent, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent)
+            else:
+                if ((flags & PRINT_OBJ_COMPACT) == 0):
+                    print >> out
+##                    indent += 2
+                print >> out, " "*indent, "{",
+                keys = object.__dict__.keys()
+                keys.sort()
+                printed = True
+                for key in keys:
+                    if ((exclude != None) and (key in exclude)):
+                        continue
+                    if (printed and ((flags & PRINT_OBJ_COMPACT) == 0)):
+                        print >> out
+                    n = nameToString(key, flags)
+                    printed = printObject(out, getattr(object, n), name=n, indent=indent+2, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent)
+                if ((flags & PRINT_OBJ_COMPACT) == 0):
+                    print >> out
+                print >> out, " "*indent, "}",
+    elif (indent < 0):
+        print >> out, object,
+    elif isinstance(object, basestring):
+        if ((exclude != None) and name in exclude):
+            print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (excluded)",
+        elif (len(object) > 100):
+            object = toString(object, flags)
+            print >> out, " "*indent, name, ":", typeToString(object, flags), "[%d] = %s...%s" % (len(object), object[:50], object[-50:]),
+        else:
+            print >> out, " "*indent, name, ":", typeToString(object, flags), "=", toString(object, flags),
+##    elif (isinstance(object, float)):
+##        val = str(object)
+##        if (len(val) > 17):
+##            val = val[:17]
+##        print >> out, " "*indent, name, ":", type(object), "=", val,
+    else:
+        print >> out, " "*indent, name, ":", typeToString(object, flags), "=", toString(object, flags),
+    if (finalNewLine):
+        print >> out
+    return printed