"""
import copy, os, re, sys, time, types
-from bb import note, debug, error, fatal, utils, methodpool
+import bb
+from bb import utils, methodpool
+from COW import COWDictBase
from sets import Set
+from new import classobj
-try:
- import cPickle as pickle
-except ImportError:
- import pickle
- print "NOTE: Importing cPickle failed. Falling back to a very slow implementation."
__setvar_keyword__ = ["_append","_prepend"]
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?')
__expand_python_regexp__ = re.compile(r"\${@.+?}")
-#=====
-#
-# Helper Class
-#
-#====
-class ParentDictSet:
- """
- To avoid DeepCopies of shared dictionaries
- we use a COW/parenting pattern.
-
- This class looks like a dictionary. If we
- set a key that is also present in the parent
- we will make a copy of it.
-
- Currently it is not possible to remove keys
- """
-
- def __init__(self, parent=None):
- self._dict = {}
-
- #set the parent of this dict
- #and save the lists of keys
- if parent:
- self._dict['_PARENT_OF_DICT'] = parent._dict
- self._keys = parent._keys
- else:
- self._keys = []
-
- def _crazy_lookup(self, dict, name):
- # crazy lookup
- while dict:
- if name in dict:
- return (dict[name],True)
- elif '_PARENT_OF_DICT' in dict:
- dict = dict['_PARENT_OF_DICT']
- else:
- break
-
- return (None,False)
-
-
- def get(self, name):
- (var,found) = self._crazy_lookup(self._dict, name)
-
- return var
-
- def add(self, name, value):
- #
- # Check if we have the key already locally
- #
- if name in self._dict:
- self._dict[name].add( value )
- return
-
- #
- # Check if the key is used by our parent
- #
- if '_PARENT_OF_DICT' in self._dict:
- (var,found) = self._crazy_lookup(self._dict['_PARENT_OF_DICT'], name)
- if found:
- self._dict[name] = copy.copy(var)
- self._dict[name].add(value)
- else:
- # a new name is born
- self._keys.append(name)
- self._dict[name] = Set()
- self._dict[name].add(value)
-
- def keys(self):
- return self._keys
-
class DataSmart:
- def __init__(self):
+ def __init__(self, special = COWDictBase.copy(), seen = COWDictBase.copy() ):
self.dict = {}
# cookie monster tribute
- self._special_values = ParentDictSet()
- self._seen_overrides = ParentDictSet()
+ self._special_values = special
+ self._seen_overrides = seen
+
+ self.expand_cache = {}
def expand(self,s, varname):
def var_sub(match):
if type(s) is not types.StringType: # sanity check
return s
- while s.find('$') != -1:
+ if varname and varname in self.expand_cache:
+ return self.expand_cache[varname]
+
+ while s.find('${') != -1:
olds = s
try:
s = __expand_var_regexp__.sub(var_sub, s)
s = __expand_python_regexp__.sub(python_sub, s)
if s == olds: break
if type(s) is not types.StringType: # sanity check
- error('expansion of %s returned non-string %s' % (olds, s))
+ bb.msg.error(bb.msg.domain.Data, 'expansion of %s returned non-string %s' % (olds, s))
except KeyboardInterrupt:
raise
except:
- note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
+ bb.msg.note(1, bb.msg.domain.Data, "%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
raise
+
+ if varname:
+ self.expand_cache[varname] = s
+
return s
def initVar(self, var):
+ self.expand_cache = {}
if not var in self.dict:
self.dict[var] = {}
self.initVar(var)
def setVar(self,var,value):
+ self.expand_cache = {}
match = __setvar_regexp__.match(var)
if match and match.group("keyword") in __setvar_keyword__:
base = match.group('base')
l.append([value, override])
self.setVarFlag(base, keyword, l)
+ # todo make sure keyword is not __doc__ or __module__
# pay the cookie monster
- self._special_values.add( keyword, base )
+ try:
+ self._special_values[keyword].add( base )
+ except:
+ self._special_values[keyword] = Set()
+ self._special_values[keyword].add( base )
return
# more cookies for the cookie monster
if '_' in var:
override = var[var.rfind('_')+1:]
- self._seen_overrides.add( override, var )
+ if not self._seen_overrides.has_key(override):
+ self._seen_overrides[override] = Set()
+ self._seen_overrides[override].add( var )
# setting var
self.dict[var]["content"] = value
return value
def delVar(self,var):
+ self.expand_cache = {}
self.dict[var] = {}
def setVarFlag(self,var,flag,flagvalue):
Create a copy of self by setting _data to self
"""
# we really want this to be a DataSmart...
- data = DataSmart()
+ data = DataSmart(seen=self._seen_overrides.copy(), special=self._special_values.copy())
data.dict["_data"] = self.dict
- # reparent the dicts
- data._seen_overrides = ParentDictSet(self._seen_overrides)
- data._special_values = ParentDictSet(self._special_values)
-
return data
# Dictionary Methods
return keytab.keys()
def __getitem__(self,item):
- start = self.dict
- while start:
- if item in start:
- return start[item]
- elif "_data" in start:
- start = start["_data"]
- else:
- start = None
- return None
+ #print "Warning deprecated"
+ return self.getVar(item, False)
def __setitem__(self,var,data):
- self._makeShadowCopy(var)
- self.dict[var] = data
+ #print "Warning deprecated"
+ self.setVar(var,data)