This mechanism has several purposes. First, it is used to prevent 'make' systems recompiling unchanged code files. Second, it is used so that the output of a previous run can be read back in while the current run is generating a new copy. Finally, the comparisons on all these files can be used to determine if the literate programming process has converged to a stable point or may require another pass.
Please note that some care is required to ensure convergence is possible. Note also that when line numbers are generated, a single change to the source file will cause comparisons to fail for all files with sections defined after that point, often causing an apparently redundant rebuild. This is not alsways the case, for example, in C, the assert macro reports line numbers at run time, and the rebuild is necessary. It may be useful to turn off line number generation for files once they have compiled successfully (until the production build).
Finally, note that if you put the time into an output file, it is likely to be different each run!
1: #line 270 "sink_drivers.ipk" 2: import string 3: from interscript.drivers.sinks.base import sink 4: from interscript.drivers.sinks import sink_open_error 5: from interscript.drivers.sinks.util import mk_dir, file_exists 6: import tempfile 7: import os 8: 9: class named_file_sink(sink): 10: def __init__(self,pass_frame,input_filename, prefix='', eol='\n'): 11: self.pass_frame = pass_frame 12: self.process = pass_frame.process 13: self.verbosity = self.pass_frame.verbosity 14: self.eol = eol 15: 16: # compute absolute pathname, and create directories if necessary 17: # we don't use posixpath because we're enforcing an _interscript_ 18: # pathname convention here 19: pathlist = string.split(input_filename,'/') 20: self.basename = pathlist[-1] 21: pathname = mk_dir(prefix, pathlist) 22: 23: if file_exists(pathname): 24: self.tmp_filename = tempfile.mktemp() 25: if self.verbosity>=4: 26: print 'Generating temporary',self.tmp_filename,'for',input_filename 27: try: 28: file =open(self.tmp_filename,'w') 29: self.pass_frame.fdict[input_filename]='temporary' 30: except: 31: raise sink_open_error, self.tmp_filename 32: sink.__init__(self, filename = pathname, name = input_filename, file = file ) 33: self.os = os 34: self.pass_frame.flist.append(input_filename) 35: else: 36: if self.verbosity>=3: 37: print 'Generating original',input_filename 38: try: 39: file = open(pathname,'w') 40: self.pass_frame.fdict[input_filename]='original' 41: except: 42: raise sink_open_error,pathname 43: sink.__init__(self, filename = pathname, name = input_filename, file = file) 44: self.pass_frame.flist.append(input_filename) 45: 46: def __del__(self): 47: if self.verbosity>=5: print 'closing', self.name 48: self.file.close() 49: if hasattr(self,'tmp_filename'): 50: if self.process.update_files: 51: original_file = open(self.filename,'r') 52: original_lines = original_file.readlines() 53: original_file.close() 54: 55: new_file = open(self.tmp_filename,'r') 56: new_lines = new_file.readlines() 57: new_file.close() 58: 59: if not original_lines == new_lines: 60: if self.verbosity>=1: print 'File',self.filename,'is CHANGED' 61: self.pass_frame.fdict[self.name]='changed' 62: file = open(self.filename,'w') 63: file.writelines(new_lines) 64: file.close() 65: else: 66: if self.verbosity>=4: print 'File',self.filename,'is unchanged' 67: self.pass_frame.fdict[self.name]='unchanged' 68: else: 69: if self.verbosity>=1: print '*** System error inhibiting file update for',self.filename,'***' 70: self.pass_frame.fdict[self.name]='cancelled' 71: self.os.remove(self.tmp_filename) 72: 73: def raw_write(self,line): self.file.write(line) 74: def raw_eol(self): self.raw_write(self.eol) 75: