[Synopsis-cvs] CVS: Synopsis/Synopsis/Core Action.py,1.4 Executor.py,1.13 Project.py,1.10
Stephen Davies chalky at users.sourceforge.netMon Nov 18 19:45:02 UTC 2002
- Previous message: [Synopsis-cvs] CVS: Synopsis/docs ASTHierarchy.dia,1.3 Components.dia,1.3
- Next message: [Synopsis-cvs] CVS: Synopsis/Synopsis Config.py.in,1.16
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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
- Previous message: [Synopsis-cvs] CVS: Synopsis/docs ASTHierarchy.dia,1.3 Components.dia,1.3
- Next message: [Synopsis-cvs] CVS: Synopsis/Synopsis Config.py.in,1.16
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Synopsis-changes mailing list