[Synopsis-cvs] CVS: Synopsis/Synopsis/Core Action.py,1.4 Executor.py,1.13 Project.py,1.10

Stephen Davies chalky at users.sourceforge.net
Mon Nov 18 19:45:02 UTC 2002


Update of /cvsroot/synopsis/Synopsis/Synopsis/Core
In directory sc8-pr-cvs1:/tmp/cvs-serv26048

Modified Files:
	Action.py Executor.py Project.py 
Log Message:
Changed SourcePath to SourceRule, included an Exclude rule



Index: Executor.py
===================================================================
RCS file: /cvsroot/synopsis/Synopsis/Synopsis/Core/Executor.py,v
retrieving revision 1.4
retrieving revision 1.13
diff -C2 -d -r1.4 -r1.13
*** Executor.py	26 Apr 2002 01:21:13 -0000	1.4
--- Executor.py	19 Nov 2002 03:44:08 -0000	1.13
***************
*** 7,11 ****
  """
  
! import string, re, os, stat
  
  from Action import ActionVisitor
--- 7,11 ----
  """
  
! import string, re, os, stat, sys
  
  from Action import ActionVisitor
***************
*** 13,16 ****
--- 13,19 ----
  import AST
  
+ try: import gc
+ except ImportError: gc = None
+ 
  
  class Executor:
***************
*** 24,27 ****
--- 27,38 ----
  	pass
  
+     def prepare_output(self, name, keep):
+ 	"""Prepares an AST object for returning. For most objects, this does
+ 	nothing. In the case of a cacher, this causes it to process each input
+ 	in turn and store the results to disk. This is as opposed to keeping
+ 	each previous input in memory while the next is parsed!
+ 	Returns the AST if keep is set, else None."""
+ 	if keep: return get_output(name)
+ 
      def get_output(self, name):
  	"""Returns the AST object for the given name. Name must one returned
***************
*** 32,37 ****
  class ExecutorCreator (ActionVisitor):
      """Creates Executor instances for Action objects"""
!     def __init__(self, project):
  	self.__project = project
  
      def project(self):
--- 43,49 ----
  class ExecutorCreator (ActionVisitor):
      """Creates Executor instances for Action objects"""
!     def __init__(self, project, verbose=0):
  	self.__project = project
+ 	self.verbose = verbose or project.verbose()
  
      def project(self):
***************
*** 87,90 ****
--- 99,104 ----
  	def path_to_tuple(path_obj):
  	    if path_obj.type == 'Simple':
+ 		if path_obj.dir.find('/') == -1:
+ 		    return (0, '.', path_obj.dir)
  		return (0,)+os.path.split(path_obj.dir)
  	    elif path_obj.type == 'Dir':
***************
*** 94,113 ****
  
  	names = []
! 	paths = map(path_to_tuple, self.__action.paths())
! 	while len(paths):
! 	    recurse, path, globpath = paths.pop()
! 	    glob = self.compile_glob(globpath)
! 	    # Get list of files matching this path
! 	    for file in os.listdir(path):
! 		# Stat file
! 		filepath = os.path.join(path, file)
! 		stats = os.stat(filepath)
! 		if stat.S_ISDIR(stats[stat.ST_MODE]) and recurse:
! 		    # Add to list of paths to check
! 		    paths.append( (1, filepath, globpath) )
! 		elif stat.S_ISREG(stats[stat.ST_MODE]):
! 		    # Check if matches glob
! 		    if glob.match(file):
! 			names.append((filepath, stats[stat.ST_MTIME]))
  	return names
      def get_output(self, name):
--- 108,139 ----
  
  	names = []
! 	for rule in self.__action.rules():
! 	    if rule.type == 'Simple':
! 		# Add the specified files if they exist
! 		for file in rule.files:
! 		    try:
! 			filepath = os.path.abspath(file)
! 			stats = os.stat(filepath)
! 			if stat.S_ISREG(stats[stat.ST_MODE]):
! 			    names.append((file, stats[stat.ST_MTIME]))
! 		    except OSError, e:
! 			print "Warning:",e
! 	    elif rule.type == 'Glob':
! 		glob = self.compile_glob(rule.glob)
! 		dirs = map(os.path.abspath, rule.dirs)
! 		while len(dirs):
! 		    dir = dirs.pop(0)
! 		    # Get list of files in this dir
! 		    for file in os.listdir(dir):
! 			# Stat file
! 			filepath = os.path.join(dir, file)
! 			stats = os.stat(filepath)
! 			if stat.S_ISDIR(stats[stat.ST_MODE]) and rule.recursive:
! 			    # Add to list of dirs to check
! 			    dirs.append(filepath)
! 			elif stat.S_ISREG(stats[stat.ST_MODE]):
! 			    # Check if matches glob
! 			    if glob.match(file):
! 				names.append((filepath, stats[stat.ST_MTIME]))
  	return names
      def get_output(self, name):
***************
*** 138,145 ****
  
      def get_output(self, name):
  	config = self.__action.config()
  	parser = self.get_parser()
  	# Do the parse
- 	print "Synopsis: parsing", name
  	ast = parser.parse(name, [], config)
  	# Return the parsed AST
--- 164,173 ----
  
      def get_output(self, name):
+ 	if self.__executor.verbose:
+ 	    print self.__action.name()+": Parsing "+name
+ 	    sys.stdout.flush()
  	config = self.__action.config()
  	parser = self.get_parser()
  	# Do the parse
  	ast = parser.parse(name, [], config)
  	# Return the parsed AST
***************
*** 166,183 ****
  	self.__project = executor.project()
  	self.__action = action
      def get_output_names(self):
  	"""Links multiple ASTs together, and/or performs other manipulative
  	actions on a single AST."""
! 	# TODO: figure out timestamp based on input timestamps
! 	return [ ('', 0) ]
  
      def get_output(self, name):
  	# Get input AST(s), probably from a cacher, source or other linker
  	ast = AST.AST()
  	for input in self.__action.inputs():
! 	    exec_obj = self.__executor.create(input)
! 	    names = exec_obj.get_output_names()
! 	    for name, timestamp in names:
! 		input_ast = exec_obj.get_output(name)
  		ast.merge(input_ast)
  	# Pass merged AST to linker
--- 194,236 ----
  	self.__project = executor.project()
  	self.__action = action
+ 	self.__inputs = {}
+ 	self.__names = {}
      def get_output_names(self):
  	"""Links multiple ASTs together, and/or performs other manipulative
  	actions on a single AST."""
! 	# Figure out the output name
! 	myname = self.__action.name()
! 	if not myname: myname = 'LinkerOutput'
! 	myname = myname.replace(' ', '_')
! 	# Figure out the timestamp
! 	ts = 0
! 	for input in self.__action.inputs():
! 	    exec_obj = self.__executor.create(input)
! 	    self.__inputs[input] = exec_obj
! 	    names = exec_obj.get_output_names()
! 	    self.__names[input] = names
! 	    for name, timestamp in names:
! 		if timestamp > ts:
! 		    ts = timestamp
! 	return [ (myname, ts) ]
  
      def get_output(self, name):
  	# Get input AST(s), probably from a cacher, source or other linker
+ 	# Prepare the inputs
+ 	for input in self.__action.inputs():
+ 	    exec_obj = self.__inputs[input]
+ 	    names = self.__names[input]
+ 	    for iname, timestamp in names:
+ 		exec_obj.prepare_output(iname, 0)
+ 	# Merge the inputs into one AST
+ 	if self.__executor.verbose:
+ 	    print self.__action.name()+": Linking "+name
+ 	    sys.stdout.flush()
  	ast = AST.AST()
  	for input in self.__action.inputs():
! 	    exec_obj = self.__inputs[input]
! 	    names = self.__names[input]
! 	    for iname, timestamp in names:
! 		input_ast = exec_obj.get_output(iname)
  		ast.merge(input_ast)
  	# Pass merged AST to linker
***************
*** 207,230 ****
  	self.__action = action
  	self.__execs = {}
      def get_output_names(self):
  	action = self.__action
  	if action.file:
! 	    return action.file
! 	names = []
  	# TODO: add logic here to check timestamps, etc
  	for input in action.inputs():
  	    exec_obj = self.__executor.create(input)
  	    self.__execs[input] = exec_obj
! 	    names.extend(exec_obj.get_out_names())
! 	return map(lambda x, dir=action.dir: (os.join(dir, x[0]), x[1]), names)
      def get_output(self, name):
  	action = self.__action
  	if action.file:
- 	    # TODO: unpickle file
  	    return AST.load(action.file)
! 	else:
! 	    # Call inputs
! 	    pass
! 
  class FormatExecutor (Executor):
      """Formats the input AST given by its single input"""
--- 260,347 ----
  	self.__action = action
  	self.__execs = {}
+ 	self.__timestamps = {}
+ 	self.__input_map = {}
+ 	self.__names = []
      def get_output_names(self):
  	action = self.__action
  	if action.file:
! 	    # Find file
! 	    stats = os.stat(action.file)
! 	    return action.file, stats[stat.ST_MTIME]
! 	names = self.__names
  	# TODO: add logic here to check timestamps, etc
  	for input in action.inputs():
  	    exec_obj = self.__executor.create(input)
  	    self.__execs[input] = exec_obj
! 	    in_names = exec_obj.get_output_names()
! 	    names.extend(in_names)
! 	    # Remember which input for each name
! 	    for name, timestamp in in_names:
! 		self.__input_map[name] = exec_obj
! 		self.__timestamps[name] = timestamp
! 	return names
!     def get_cache_filename(self, name):
! 	"""Returns the filename of the cache for the input with the given
! 	name"""
! 	jname = str(name)
! 	if jname[0] == '/': jname = jname[1:]
! 	cache_filename = os.path.join(self.__action.dir, jname)
! 	if cache_filename[-4:] != ".syn":
! 	    cache_filename = cache_filename + ".syn"
! 	return cache_filename
!     def _get_timestamp(self, filename):
! 	"""Returns the timestamp of the given file, or 0 if not found"""
! 	try:
! 	    stats = os.stat(filename)
! 	    return stats[stat.ST_MTIME]
! 	except OSError:
! 	    # NB: will catch any type of error caused by the stat call, not
! 	    # just Not Found
! 	    return 0
!     def prepare_output(self, name, keep):
! 	"""Prepares the output, which means that it parses it, saves it to
! 	disk, and forgets about it. If keep is set, return the AST anyway"""
! 	action = self.__action
! 	# Check if is a single-file loader (not cache)
! 	if action.file: return
! 	cache_filename = self.get_cache_filename(name)
! 	# Check timestamp on cache
! 	cache_ts = self._get_timestamp(cache_filename)
! 	if cache_ts > 0 and cache_ts >= self.__timestamps[name]:
! 	    # Cache is up to date
! 	    return
! 	# Need to regenerate. Find input
! 	exec_obj = self.__input_map[name]
! 	ast = exec_obj.get_output(name)
! 	# Save to cache file
! 	try:
! 	    # Create dir for file
! 	    dir = os.path.dirname(cache_filename)
! 	    if not os.path.exists(dir):
! 		print "Warning: creating directory",dir
! 		os.makedirs(dir)
! 	    AST.save(cache_filename, ast)
! 	except:
! 	    exc, msg = sys.exc_info()[0:2]
! 	    print "Warning: %s: %s"%(exc, msg)
! 	if keep: return ast
! 	elif gc:
! 	    # Try to free up mem
! 	    ast = None
! 	    #gc.set_debug(gc.DEBUG_STATS)
! 	    gc.collect()
! 
      def get_output(self, name):
+ 	"""Gets the output"""
  	action = self.__action
+ 	# Check if is a single-file loader (not cache)
  	if action.file:
  	    return AST.load(action.file)
! 	# Double-check preparedness (may generate output)
! 	ast = self.prepare_output(name, 1)
! 	if ast: return ast
! 	# Should now be able to just load from cache file
! 	return AST.load(self.get_cache_filename(name))
! 	
  class FormatExecutor (Executor):
      """Formats the input AST given by its single input"""
***************
*** 240,244 ****
  	    raise 'Error', 'Formatter takes exactly one input AST'
  	self.__input_exec = self.__executor.create(inputs[0])
! 	return self.__input_exec.get_output_names()
  
      def get_output(self, name):
--- 357,364 ----
  	    raise 'Error', 'Formatter takes exactly one input AST'
  	self.__input_exec = self.__executor.create(inputs[0])
! 	names = self.__input_exec.get_output_names()
! 	if len(names) != 1:
! 	    raise 'Error', 'Formatter takes exactly one input AST'
! 	return names
  
      def get_output(self, name):
***************
*** 247,250 ****
--- 367,373 ----
  	module = self.__action.config().name
  	# Pass AST to formatter
+ 	if self.__executor.verbose:
+ 	    print self.__action.name()+": Formatting "+name
+ 	    sys.stdout.flush()
  	try:
  	    formatter = Util._import("Synopsis.Formatter." + module)

***** Bogus filespec: Project.py,1.10




More information about the Synopsis-changes mailing list