Copyright (C) 2003, 2004 Chris Larson
Copyright (C) 2004, 2005 Seb Frankengul
-Copyright (C) 2005 Holger Hans Peter Freyther
+Copyright (C) 2005, 2006 Holger Hans Peter Freyther
Copyright (C) 2005 Uli Luckas
Copyright (C) 2005 ROAD GmbH
"""
import copy, os, re, sys, time, types
-from bb import note, debug, fatal
+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","_delete"]
-__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend|_delete)(_(?P<add>.*))?')
+__setvar_keyword__ = ["_append","_prepend"]
+__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?')
__expand_var_regexp__ = re.compile(r"\${[^{}]+}")
__expand_python_regexp__ = re.compile(r"\${@.+?}")
class DataSmart:
- def __init__(self):
+ def __init__(self, special = COWDictBase.copy(), seen = COWDictBase.copy() ):
self.dict = {}
+ # cookie monster tribute
+ self._special_values = special
+ self._seen_overrides = seen
+
+ self.expand_cache = {}
+
def expand(self,s, varname):
def var_sub(match):
key = match.group()[2:-1]
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
- import bb
- bb.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] = {}
- def pickle_prep(self, cfg):
- if "_data" in self.dict:
- if self.dict["_data"] == cfg:
- self.dict["_data"] = "cfg";
- else: # this is an unknown array for the moment
- pass
-
- def unpickle_prep(self, cfg):
- if "_data" in self.dict:
- if self.dict["_data"] == "cfg":
- self.dict["_data"] = cfg;
-
def _findVar(self,var):
_dest = self.dict
return _dest[var]
return None
- def _copyVar(self,var,name):
- local_var = self._findVar(var)
- if local_var:
- self.dict[name] = copy.copy(local_var)
- else:
- debug(1,"Warning, _copyVar %s to %s, %s does not exists" % (var,name,var))
-
-
def _makeShadowCopy(self, var):
if var in self.dict:
return
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')
keyword = match.group("keyword")
override = match.group('add')
l = self.getVarFlag(base, keyword) or []
- if override == 'delete':
- if l.count([value, None]):
- del l[l.index([value, None])]
l.append([value, override])
- self.setVarFlag(base, match.group("keyword"), l)
+ self.setVarFlag(base, keyword, l)
+
+ # todo make sure keyword is not __doc__ or __module__
+ # pay the cookie monster
+ try:
+ self._special_values[keyword].add( base )
+ except:
+ self._special_values[keyword] = Set()
+ self._special_values[keyword].add( base )
+
return
if not var in self.dict:
self.delVarFlag(var, 'matchesenv')
self.setVarFlag(var, 'export', 1)
+ # more cookies for the cookie monster
+ if '_' in var:
+ override = var[var.rfind('_')+1:]
+ 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
return data
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
-
-
-class DataSmartPackage(DataSmart):
- """
- Persistent Data Storage
- """
- def sanitize_filename(bbfile):
- return bbfile.replace( '/', '_' )
- sanitize_filename = staticmethod(sanitize_filename)
-
- def unpickle(self):
- """
- Restore the dict from memory
- """
- cache_bbfile = self.sanitize_filename(self.bbfile)
- p = pickle.Unpickler( file("%s/%s"%(self.cache,cache_bbfile),"rb"))
- self.dict = p.load()
- funcstr = self.getVar('__functions__', 0)
- if funcstr:
- comp = compile(funcstr, "<pickled>", "exec")
- exec comp in __builtins__
-
- def linkDataSet(self,parent):
- if not parent == None:
- # assume parent is a DataSmartInstance
- self.dict = copy.deepcopy(parent.dict)
+ #print "Warning deprecated"
+ self.setVar(var,data)
- def __init__(self,cache,name,clean,parent):
- """
- Construct a persistent data instance
- """
- #Initialize the dictionary
- DataSmart.__init__(self)
-
- self.cache = cache
- self.bbfile = os.path.abspath( name )
-
- # Either unpickle the data or do copy on write
- if clean:
- self.linkDataSet(parent)
- else:
- self.unpickle()
-
- def commit(self, mtime):
- """
- Save the package to a permanent storage
- """
- cache_bbfile = self.sanitize_filename(self.bbfile)
- p = pickle.Pickler(file("%s/%s" %(self.cache,cache_bbfile), "wb" ), -1 )
- p.dump( self.dict )
-
- def mtime(cache,bbfile):
- cache_bbfile = DataSmartPackage.sanitize_filename(bbfile)
- try:
- return os.stat( "%s/%s" % (cache,cache_bbfile) )[8]
- except OSError:
- return 0
- mtime = staticmethod(mtime)