Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/python/modules/vrml/utils')
-rw-r--r--intern/python/modules/vrml/utils/__init__.py1
-rw-r--r--intern/python/modules/vrml/utils/collapse.py169
-rw-r--r--intern/python/modules/vrml/utils/err.py37
-rw-r--r--intern/python/modules/vrml/utils/namespace.py225
-rw-r--r--intern/python/modules/vrml/utils/typeclasses.py50
5 files changed, 482 insertions, 0 deletions
diff --git a/intern/python/modules/vrml/utils/__init__.py b/intern/python/modules/vrml/utils/__init__.py
new file mode 100644
index 00000000000..9d708a9084c
--- /dev/null
+++ b/intern/python/modules/vrml/utils/__init__.py
@@ -0,0 +1 @@
+"""utilities"""
diff --git a/intern/python/modules/vrml/utils/collapse.py b/intern/python/modules/vrml/utils/collapse.py
new file mode 100644
index 00000000000..25da50c2adb
--- /dev/null
+++ b/intern/python/modules/vrml/utils/collapse.py
@@ -0,0 +1,169 @@
+'''
+Destructive Functions for "collapsing" Sequences into single levels
+
+>>> from mcf.utils import collapse
+
+>>> collapse.test([[[1],[2,3]],[[]],[4],5,[6]])
+
+[1, 2, 3, 4, 5, 6] # note that is the same root list
+
+>>> collapse.collapse2([[[1],[2,3]],[[]],(4,()),(5,),[6]])
+
+[1, 2, 3, 4, 5, 6] # note is the same root list
+'''
+import copy, types, sys
+from types import ListType, TupleType # this now only supports the obsolete stuff...
+
+def hyperCollapse( inlist, allowedmap, type=type, list=list, itype=types.InstanceType, maxint= sys.maxint):
+ '''
+ Destructively flatten a mixed hierarchy to a single level.
+ Non-recursive, many speedups and obfuscations by Tim Peters :)
+ '''
+ try:
+ # for every possible index
+ for ind in xrange( maxint):
+ # while that index currently holds a list
+ expandable = 1
+ while expandable:
+ expandable = 0
+ if allowedmap.has_key( type(inlist[ind]) ):
+ # expand that list into the index (and subsequent indicies)
+ inlist[ind:ind+1] = list( inlist[ind])
+ expandable = 1
+
+ # alternately you could iterate through checking for isinstance on all possible
+ # classes, but that would be very slow
+ elif type( inlist[ind] ) is itype and allowedmap.has_key( inlist[ind].__class__ ):
+ # here figure out some way to generically expand that doesn't risk
+ # infinite loops...
+ templist = []
+ for x in inlist[ind]:
+ templist.append( x)
+ inlist[ind:ind+1] = templist
+ expandable = 1
+ except IndexError:
+ pass
+ return inlist
+
+
+def collapse(inlist, type=type, ltype=types.ListType, maxint= sys.maxint):
+ '''
+ Destructively flatten a list hierarchy to a single level.
+ Non-recursive, and (as far as I can see, doesn't have any
+ glaring loopholes).
+ Further speedups and obfuscations by Tim Peters :)
+ '''
+ try:
+ # for every possible index
+ for ind in xrange( maxint):
+ # while that index currently holds a list
+ while type(inlist[ind]) is ltype:
+ # expand that list into the index (and subsequent indicies)
+ inlist[ind:ind+1] = inlist[ind]
+ #ind = ind+1
+ except IndexError:
+ pass
+ return inlist
+
+def collapse_safe(inlist):
+ '''
+ As collapse, but works on a copy of the inlist
+ '''
+ return collapse( inlist[:] )
+
+def collapse2(inlist, ltype=(types.ListType, types.TupleType), type=type, maxint= sys.maxint ):
+ '''
+ Destructively flatten a list hierarchy to a single level.
+ Will expand tuple children as well, but will fail if the
+ top level element is not a list.
+ Non-recursive, and (as far as I can see, doesn't have any
+ glaring loopholes).
+ '''
+ ind = 0
+ try:
+ while 1:
+ while type(inlist[ind]) in ltype:
+ try:
+ inlist[ind:ind+1] = inlist[ind]
+ except TypeError:
+ inlist[ind:ind+1] = list(inlist[ind])
+ ind = ind+1
+ except IndexError:
+ pass
+ return inlist
+
+def collapse2_safe(inlist):
+ '''
+ As collapse2, but works on a copy of the inlist
+ '''
+ return collapse( list(inlist) )
+
+def old_buggy_collapse(inlist):
+ '''Always return a one-level list of all the non-list elements in listin,
+ rewritten to be non-recursive 96-12-28 Note that the new versions work
+ on the original list, not a copy of the original.'''
+ if type(inlist)==TupleType:
+ inlist = list(inlist)
+ elif type(inlist)!=ListType:
+ return [inlist]
+ x = 0
+ while 1:
+ try:
+ y = inlist[x]
+ if type(y) == ListType:
+ ylen = len(y)
+ if ylen == 1:
+ inlist[x] = y[0]
+ if type(inlist[x]) == ListType:
+ x = x - 1 # need to collapse that list...
+ elif ylen == 0:
+ del(inlist[x])
+ x = x-1 # list has been shortened
+ else:
+ inlist[x:x+1]=y
+ x = x+1
+ except IndexError:
+ break
+ return inlist
+
+
+def old_buggy_collapse2(inlist):
+ '''As collapse, but also collapse tuples, rewritten 96-12-28 to be non-recursive'''
+ if type(inlist)==TupleType:
+ inlist = list(inlist)
+ elif type(inlist)!=ListType:
+ return [inlist]
+ x = 0
+ while 1:
+ try:
+ y = inlist[x]
+ if type(y) in [ListType, TupleType]:
+ ylen = len(y)
+ if ylen == 1:
+ inlist[x] = y[0]
+ if type(inlist[x]) in [ListType,TupleType]:
+ x = x-1 #(to deal with that element)
+ elif ylen == 0:
+ del(inlist[x])
+ x = x-1 # list has been shortened, will raise exception with tuples...
+ else:
+ inlist[x:x+1]=list(y)
+ x = x+1
+ except IndexError:
+ break
+ return inlist
+
+
+def oldest_buggy_collapse(listin):
+ 'Always return a one-level list of all the non-list elements in listin'
+ if type(listin) == ListType:
+ return reduce(lambda x,y: x+y, map(collapse, listin), [])
+ else: return [listin]
+
+def oldest_buggy_collapse2(seqin):
+
+ if type(seqin) in [ListType, TupleType]:
+ return reduce(lambda x,y: x+y, map(collapse2, seqin), [])
+ else:
+ return [seqin]
+
diff --git a/intern/python/modules/vrml/utils/err.py b/intern/python/modules/vrml/utils/err.py
new file mode 100644
index 00000000000..3c6591a6873
--- /dev/null
+++ b/intern/python/modules/vrml/utils/err.py
@@ -0,0 +1,37 @@
+'''
+err.py Encapsulated writing to sys.stderr
+
+The idea of this module is that, for a GUI system (or a more advanced UI),
+you can just import a different err module (or object) and keep
+your code the same. (For instance, you often want a status window
+which flashes warnings and info, and have error messages pop up an
+alert to get immediate attention.
+'''
+
+import sys
+
+def err(message, Code=0):
+ '''
+ report an error, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Error #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Error: %s\n'%message)
+def warn(message, Code=0):
+ '''
+ report a warning, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Warning #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Warning: %s\n'%message)
+def info(message, Code=0):
+ '''
+ report information/status, with an optional error code
+ '''
+ if Code:
+ sys.stderr.write('Info #%i: %s\n'%(Code,message))
+ else:
+ sys.stderr.write('Info: %s\n'%message)
+
diff --git a/intern/python/modules/vrml/utils/namespace.py b/intern/python/modules/vrml/utils/namespace.py
new file mode 100644
index 00000000000..dd9f0b7dea6
--- /dev/null
+++ b/intern/python/modules/vrml/utils/namespace.py
@@ -0,0 +1,225 @@
+'''
+NameSpace v0.04:
+
+A "NameSpace" is an object wrapper around a _base dictionary
+which allows chaining searches for an 'attribute' within that
+dictionary, or any other namespace which is defined as part
+of the search path (depending on the downcascade variable, is
+either the hier-parents or the hier-children).
+
+You can assign attributes to the namespace normally, and read
+them normally. (setattr, getattr, a.this = that, a.this)
+
+I use namespaces for writing parsing systems, where I want to
+differentiate between sources (have multiple sources that I can
+swap into or out of the namespace), but want to be able to get
+at them through a single interface. There is a test function
+which gives you an idea how to use the system.
+
+In general, call NameSpace(someobj), where someobj is a dictionary,
+a module, or another NameSpace, and it will return a NameSpace which
+wraps up the keys of someobj. To add a namespace to the NameSpace,
+just call the append (or hier_addchild) method of the parent namespace
+with the child as argument.
+
+### NOTE: if you pass a module (or anything else with a dict attribute),
+names which start with '__' will be removed. You can avoid this by
+pre-copying the dict of the object and passing it as the arg to the
+__init__ method.
+
+### NOTE: to properly pickle and/or copy module-based namespaces you
+will likely want to do: from mcf.utils import extpkl, copy_extend
+
+### Changes:
+ 97.05.04 -- Altered to use standard hierobj interface, cleaned up
+ interface by removing the "addparent" function, which is reachable
+ by simply appending to the __parent__ attribute, though normally
+ you would want to use the hier_addchild or append functions, since
+ they let both objects know about the addition (and therefor the
+ relationship will be restored if the objects are stored and unstored)
+
+ 97.06.26 -- Altered the getattr function to reduce the number of
+ situations in which infinite lookup loops could be created
+ (unfortunately, the cost is rather high). Made the downcascade
+ variable harden (resolve) at init, instead of checking for every
+ lookup. (see next note)
+
+ 97.08.29 -- Discovered some _very_ weird behaviour when storing
+ namespaces in mcf.store dbases. Resolved it by storing the
+ __namespace_cascade__ attribute as a normal attribute instead of
+ using the __unstore__ mechanism... There was really no need to
+ use the __unstore__, but figuring out how a functions saying
+ self.__dict__['__namespace_cascade__'] = something
+ print `self.__dict__['__namespace_cascade__']` can print nothing
+ is a bit beyond me. (without causing an exception, mind you)
+
+ 97.11.15 Found yet more errors, decided to make two different
+ classes of namespace. Those based on modules now act similar
+ to dummy objects, that is, they let you modify the original
+ instead of keeping a copy of the original and modifying that.
+
+ 98.03.15 -- Eliminated custom pickling methods as they are no longer
+ needed for use with Python 1.5final
+
+ 98.03.15 -- Fixed bug in items, values, etceteras with module-type
+ base objects.
+'''
+import copy, types, string
+
+from mcf.utils import hierobj
+
+class NameSpace(hierobj.Hierobj):
+ '''
+ An hierarchic NameSpace, allows specification of upward or downward
+ chaining search for resolving names
+ '''
+ def __init__(self, val = None, parents=None, downcascade=1,children=[]):
+ '''
+ A NameSpace can be initialised with a dictionary, a dummied
+ dictionary, another namespace, or something which has a __dict__
+ attribute.
+ Note that downcascade is hardened (resolved) at init, not at
+ lookup time.
+ '''
+ hierobj.Hierobj.__init__(self, parents, children)
+ self.__dict__['__downcascade__'] = downcascade # boolean
+ if val is None:
+ self.__dict__['_base'] = {}
+ else:
+ if type( val ) == types.StringType:
+ # this is a reference to a module which has been pickled
+ val = __import__( val, {},{}, string.split( val, '.') )
+ try:
+ # See if val's a dummy-style object which has a _base
+ self.__dict__['_base']=copy.copy(val._base)
+ except (AttributeError,KeyError):
+ # not a dummy-style object... see if it has a dict attribute...
+ try:
+ if type(val) != types.ModuleType:
+ val = copy.copy(val.__dict__)
+ except (AttributeError, KeyError):
+ pass
+ # whatever val is now, it's going to become our _base...
+ self.__dict__['_base']=val
+ # harden (resolve) the reference to downcascade to speed attribute lookups
+ if downcascade: self.__dict__['__namespace_cascade__'] = self.__childlist__
+ else: self.__dict__['__namespace_cascade__'] = self.__parent__
+ def __setattr__(self, var, val):
+ '''
+ An attempt to set an attribute should place the attribute in the _base
+ dictionary through a setitem call.
+ '''
+ # Note that we use standard attribute access to allow ObStore loading if the
+ # ._base isn't yet available.
+ try:
+ self._base[var] = val
+ except TypeError:
+ setattr(self._base, var, val)
+ def __getattr__(self,var):
+## print '__getattr__', var
+ return self.__safe_getattr__(var, {}) # the {} is a stopdict
+
+ def __safe_getattr__(self, var,stopdict):
+ '''
+ We have a lot to do in this function, if the attribute is an unloaded
+ but stored attribute, we need to load it. If it's not in the stored
+ attributes, then we need to load the _base, then see if it's in the
+ _base.
+ If it's not found by then, then we need to check our resource namespaces
+ and see if it's in them.
+ '''
+ # we don't have a __storedattr__ or it doesn't have this key...
+ if var != '_base':
+ try:
+ return self._base[var]
+ except (KeyError,TypeError), x:
+ try:
+ return getattr(self._base, var)
+ except AttributeError:
+ pass
+ try: # with pickle, it tries to get the __setstate__ before restoration is complete
+ for cas in self.__dict__['__namespace_cascade__']:
+ try:
+ stopdict[id(cas)] # if succeeds, we've already tried this child
+ # no need to do anything, if none of the children succeeds we will
+ # raise an AttributeError
+ except KeyError:
+ stopdict[id(cas)] = None
+ return cas.__safe_getattr__(var,stopdict)
+ except (KeyError,AttributeError):
+ pass
+ raise AttributeError, var
+ def items(self):
+ try:
+ return self._base.items()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.items()
+ except AttributeError:
+ pass
+ def keys(self):
+ try:
+ return self._base.keys()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.keys()
+ except AttributeError:
+ pass
+ def has_key( self, key ):
+ try:
+ return self._base.has_key( key)
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.has_key( key)
+ except AttributeError:
+ pass
+ def values(self):
+ try:
+ return self._base.values()
+ except AttributeError:
+ pass
+ try:
+ return self._base.__dict__.values()
+ except AttributeError:
+ pass
+
+ def __getinitargs__(self):
+ if type( self._base ) is types.ModuleType:
+ base = self._base.__name__
+ else:
+ base = self._base
+ return (base, self.__parent__, self.__downcascade__, self.__childlist__)
+ def __getstate__(self):
+ return None
+ def __setstate__(self,*args):
+ pass
+ def __deepcopy__(self, memo=None):
+ d = id(self)
+ if memo is None:
+ memo = {}
+ elif memo.has_key(d):
+ return memo[d]
+ if type(self._base) == types.ModuleType:
+ rest = tuple(map( copy.deepcopy, (self.__parent__, self.__downcascade__, self.__childlist__) ))
+ new = apply(self.__class__, (self._base,)+rest )
+ else:
+ new = tuple(map( copy.deepcopy, (self._base, self.__parent__, self.__downcascade__, self.__childlist__) ))
+ return new
+## def __del__( self, id=id ):
+## print 'del namespace', id( self )
+
+
+def test():
+ import string
+ a = NameSpace(string)
+ del(string)
+ a.append(NameSpace({'a':23,'b':42}))
+ import math
+ a.append(NameSpace(math))
+ print 'The returned object should allow access to the attributes of the string,\nand math modules, and two simple variables "a" and "b" (== 23 and42 respectively)'
+ return a
+
+
diff --git a/intern/python/modules/vrml/utils/typeclasses.py b/intern/python/modules/vrml/utils/typeclasses.py
new file mode 100644
index 00000000000..ed798dfe3da
--- /dev/null
+++ b/intern/python/modules/vrml/utils/typeclasses.py
@@ -0,0 +1,50 @@
+'''
+Classes of Types
+
+Often you want to be able to say:
+ if type(obj) in MutableTypes:
+ yada
+
+This module is intended to make that easier.
+Just import and use :)
+'''
+import types
+
+MutableTypes = [ types.ListType, types.DictType, types.InstanceType ]
+MutableSequenceTypes = [ types.ListType ]
+SequenceTypes = [ types.ListType, types.StringType, types.TupleType ]
+NumericTypes = [ types.IntType, types.FloatType, types.LongType, types.ComplexType ]
+MappingTypes = [ types.DictType ]
+
+def regarray():
+ if globals().has_key('array'):
+ return 1
+ try:
+ import array
+ SequenceTypes.append( array.ArrayType )
+ MutableTypes.append( array.ArrayType )
+ MutableSequenceTypes.append( array.ArrayType )
+ return 1
+ except ImportError:
+ return 0
+
+def regnumpy():
+ '''
+ Call if you want to register numpy arrays
+ according to their types.
+ '''
+ if globals().has_key('Numeric'):
+ return 1
+ try:
+ import Numeric
+ SequenceTypes.append( Numeric.ArrayType )
+ MutableTypes.append( Numeric.ArrayType )
+ MutableSequenceTypes.append( Numeric.ArrayType )
+ return 1
+ except ImportError:
+ return 0
+
+# for now, I'm going to always register these, if the module becomes part of the base distribution
+# it might be better to leave it out so numpy isn't always getting loaded...
+regarray()
+regnumpy() \ No newline at end of file