Conceptually, if multiple master documents are processed by interscript, elaboration of each document is performed in a separate thread. The master frame contains thread local data, whereas the process frame is shared by all threads.
At the 'document' level, the failure to generate a document correctly is at most fatal to that thread of control because documents are in some senses independent. However, when multiple documents form a project, inter-document dependencies may dictate abortion of the whole processes if one of the master threads fails.
1: #line 23 "master_frame.ipk" 2: from interscript.frames.passf import pass_frame 3: from interscript.drivers.sources.disk import parse_source_filename 4: from interscript.languages.interscript_languages import add_translation 5: import pickle 6: import types 7: 8: class master_frame: 9: "Once per document master frame" 10: def _cal_deps(self,t,i): 11: #print 'caldeps',i 12: n = len(t) 13: level0, kind0, filename0, filetime0, changed0, tobuild0 = t[i] 14: tobuild0 = changed0 15: j=i+1 16: while j<n: 17: if t[j][0] <= level0: break 18: tobuild1, j = self._cal_deps(t,j) 19: tobuild0 = tobuild0 or tobuild1 20: t[i][5]=tobuild0 21: return tobuild0, j 22: 23: def __init__(self,process,argument_frame): 24: self.argument_frame = argument_frame 25: self.process = process 26: self.site = process.site 27: self.platform = process.site.platform 28: 29: if 'frames' in process.trace: 30: self.process.acquire_object(self,'MASTER FRAME') 31: for k in argument_frame.__dict__.keys(): 32: if 'options' in self.process.trace: 33: print 'setting MASTER',k,'as',argument_frame.__dict__[k] 34: setattr(self,k,argument_frame.__dict__[k]) 35: self.ids = {} 36: self.iflist = [] 37: self.ftp_list = [] 38: self.flist = [] 39: self.fdict = {} 40: self.toc = [] 41: self.include_files = [] 42: self.classes = {} 43: self.functions = {} 44: self.sequence_limit = -1 45: self.section_index = {} 46: self.tests = {} 47: self.noticedict = {} 48: self.persistent_frames = {} 49: self.cache_age = 1 # very old :-) 50: os = self.platform.os 51: if self.usecache: 52: self.cache_name =self.platform.map_filename( 53: self.source_prefix, self.filename+'.cache') 54: try: 55: if 'cache' in self.process.trace: 56: print 'CACHE NAME=',self.cache_name 57: cache = self.platform.open(self.cache_name,'r') 58: if 'cache' in self.process.trace: 59: print 'CACHE FILE OPENED' 60: self.persistent_frames = pickle.load(cache) 61: cache.close() 62: if 'cache' in self.process.trace: 63: print 'GOT CACHE' 64: self.cache_age = self.platform.getmtime(self.cache_name) 65: if 'cache' in self.process.trace: 66: print 'AGE=',self.cache_age 67: self.dump_cache() 68: del cache 69: except KeyboardInterrupt: raise 70: except: 71: if 'cache' in self.process.trace: 72: print 'UNABLE TO LOAD CACHE' 73: 74: include_files = self.persistent_frames.get('include files',[]) 75: old_options = self.persistent_frames.get('options',{}) 76: 77: self.src_tree = [] 78: for level, kind, filename in include_files: 79: f = self.platform.map_filename(self.source_prefix, filename) 80: filetime = self.platform.getmtime(f) 81: changed = filetime > self.cache_age 82: self.src_tree.append([level, kind, filename, filetime, changed, -1]) 83: 84: if 'deps' in self.process.trace: 85: print 'SOURCE FILE CHANGE STATUS DEPENDENCIES' 86: print 'CACHE TIME=',self.cache_age 87: self.dump_entry(self.src_tree,0) 88: print 89: 90: src_tree_changed = 1 91: dummy = 0 92: if len(self.src_tree)>0: 93: src_tree_changed, dummy = self._cal_deps(self.src_tree,0) 94: del dummy 95: 96: if 'deps' in self.process.trace: 97: print 'COMPUTED DEPENDENCIES' 98: print 'CACHE TIME=',self.cache_age, 99: self.dump_entry(self.src_tree,0) 100: print 101: if src_tree_changed: 102: print 'WORK TO BE DONE' 103: for level, kind, filename, filetime, changed, tobuild in self.src_tree: 104: if changed: print kind,'file',filename,'CHANGED' 105: for level, kind, filename, filetime, changed, tobuild in self.src_tree: 106: if tobuild: print kind,'file',filename,'WILL BE REBUILT' 107: for level, kind, filename, filetime, changed, tobuild in self.src_tree: 108: if not tobuild: print kind,'file',filename,'WILL BE SKIPPED' 109: else: 110: print 'NO FILES CHANGED' 111: if self.autoweave: 112: print 'WEAVING ENABLED' 113: else: print 'NO WEAVING' 114: 115: if src_tree_changed: 116: skiplist = [] 117: for level, kind, filename, filetime, changed, tobuild in self.src_tree: 118: if not tobuild: 119: skiplist.append((level, kind, filename)) 120: current_options = self.argument_frame.__dict__ 121: 122: ign_opt = ['trace','passes'] 123: cur_opt = current_options.copy() 124: old_opt = old_options.copy() 125: for key in cur_opt.keys(): 126: if key in ign_opt: del cur_opt[key] 127: for key in old_opt.keys(): 128: if key in ign_opt: del old_opt[key] 129: 130: options_changed = old_opt != cur_opt 131: del ign_opt, cur_opt, old_opt 132: 133: old_converged = self.persistent_frames.get('converged',0) 134: if 'deps' in self.process.trace: 135: if old_converged: 136: print 'PREVIOUS RUN CONVERGED' 137: else: 138: print 'PREVIOUS RUN DID NOT CONVERGE' 139: if options_changed: 140: print 'OPTIONS CHANGED' 141: else: 142: print 'SAME OPTIONS AS BEFORE' 143: 144: if (not options_changed) and old_converged and (not src_tree_changed): 145: print 'NO WORK TO DO, returning' 146: return 147: 148: old_skiplist = self.persistent_frames.get('skiplist',[]) 149: if options_changed: 150: print 'PROCESSING WHOLE FILE (options changed)' 151: skiplist = [] 152: elif self.autoweave: 153: print 'PROCESSING WHOLE FILE (incremental weaving not supported yet)' 154: skiplist = [] 155: else: 156: if old_converged: 157: print 'SKIPPING (newly changed files)' 158: for sig in skiplist: 159: print ' ',sig 160: else: 161: if src_tree_changed: 162: print 'PROCESSING WHOLE FILE (source changed)' 163: skiplist = [] 164: else: 165: print 'SKIPPING (files skipped last run, which did not converge)' 166: skiplist = old_skiplist 167: self.run_passes(skiplist) 168: self.persistent_frames['skiplist']=skiplist 169: return 170: