6.19.8.1. Run the passes

At present, we just run the number of passes specified as the limit. This will change when convergence testing is implemented.

The pass loop moves the identifier list, input and output file lists, and table of contents from the pass frame to the master frame after each pass. This permits this data to be read by the next pass (while it is also regenerating the data for the pass after that).

Conceptually, the loop is said to converge when this data is the same twice in a row. However we do not test this yet because the state information is not complete.

To be complete, it must determine whether the input and output files have changed between passes. This will be done by comparing the file lists, and comparing the last modification dates on the files between passes.

Finally, output to simple files will be ignored. It is necessary to also add user controlled hooks into the convergence tests, because user script can have arbitrary side effects.

Start python section to interscript/frames/masterf.py[2 /2 ] Prev First
   171: #line 216 "master_frame.ipk"
   172:   def run_passes(self, skiplist):
   173:     #print 'STARTING PASSES'
   174:     for passno in range(self.passes):
   175:       converged = self.process_pass(passno, skiplist)
   176:       if converged: break
   177:     #print 'FINISHED PASSES'
   178:     self.persistent_frames['options']=self.argument_frame.__dict__
   179:     self.persistent_frames['include files']=self.include_files
   180:     self.persistent_frames['converged']=converged
   181:     if self.usecache:
   182:       try:
   183:         #print 'WRITING CACHE'
   184:         cache = self.platform.open(self.cache_name,'w')
   185:         pickle.dump(self.persistent_frames, cache)
   186:         cache.close()
   187:         del cache
   188:       except KeyboardInterrupt: raise
   189:       except:
   190:         print 'Pickle FAILURE saving cache',self.cache_name
   191:       if 'cache' in self.process.trace:
   192:         self.dump_cache()
   193: 
   194:   def __del__(self):
   195:     if 'frames' in self.process.trace:
   196:       self.process.release_object(self)
   197: 
   198:   def get_master_frame(self):
   199:     "Get the current master frame"
   200:     return self
   201: 
   202:   def get_persistent_frame(self, seq):
   203:     "Get the persistent frame object with given index"
   204:     if not self.persistent_frames.has_key(seq):
   205:       self.persistent_frames[seq]={}
   206:     return self.persistent_frames[seq]
   207: 
   208:   def set_title(self, title, **trlat):
   209:     "Specify the document title"
   210:     self.persistent_frames['title'] = title
   211:     apply(add_translation,(title,),trlat)
   212: 
   213:   def add_author(self, author, **data):
   214:     "Add an author to the list of document authors"
   215:     if not self.persistent_frames.has_key('authors'):
   216:       self.persistent_frames['authors']={}
   217:     if not self.persistent_frames['authors'].has_key(author):
   218:       self.persistent_frames['authors'][author]={}
   219:     self.persistent_frames['authors'][author].update(data)
   220: 
   221:   def get_title(self):
   222:     "Get the current document title"
   223:     return self.persistent_frames.get('title',None)
   224: 
   225:   def set_native_language(self, language):
   226:     "Set the native language in which this document is written"
   227:     self.persistent_frames['native_language']=language
   228: 
   229:   def get_native_language(self):
   230:     "Get the native language in which this document is written"
   231:     return self.persistent_frames.get('native_language','en')
   232: 
   233:   def set_document_data(self, key, data):
   234:     "Save some data under a key in the persistent store"
   235:     self.persistent_frames[key]=data
   236: 
   237:   def get_document_data(self,key):
   238:     "Retrive some data using a key from the persistent store"
   239:     return self.persistent_frames.get(key,None)
   240: 
   241:   def dump_cache(self):
   242:     "Dump out the persistent store to standard output"
   243:     print '--- CACHE DUMP ------------------------------',
   244:     self.dump_dict(self.persistent_frames, 0)
   245:     print
   246: 
   247:   def dump_sequence(self,s, level):
   248:     for entry in s[:-1]:
   249:       print
   250:       print ' ' * (level * 2),
   251:       self.dump_entry(entry,level)
   252:       print ',',
   253:     if len(s)>0:
   254:       print
   255:       print ' ' * (level * 2),
   256:       self.dump_entry(s[-1],level)
   257: 
   258:   def dump_dict(self,d, level):
   259:     keys = d.keys()
   260:     keys.sort()
   261:     for key in keys[:-1]:
   262:       print
   263:       if level == 0: print
   264:       print ' '*(level*2)+str(key),':',
   265:       v = d[key]
   266:       self.dump_entry(v, level)
   267:       print ',',
   268:     if len(keys)>0:
   269:       print
   270:       key = keys[-1]
   271:       print ' '*(level*2)+str(key),':',
   272:       v = d[key]
   273:       self.dump_entry(v, level)
   274: 
   275:   def dump_entry(self,e,level):
   276:       t = type(e)
   277:       if t is types.DictType:
   278:         print '<dict>',
   279:         self.dump_dict(e,level+1)
   280:       elif t is types.TupleType:
   281:         print '<tuple>',
   282:         self.dump_sequence(e, level+1)
   283:       elif t is types.ListType:
   284:         print '<list>',
   285:         self.dump_sequence(e, level+1)
   286:       else:
   287:         print repr(e),
   288: 
   289:   def process_pass(self, passno, skiplist):
   290:     curpass = pass_frame(self, passno, skiplist)
   291:     self.ids = curpass.ids        # idlist
   292:     self.ftp_list = curpass.ftp_list # ftp list
   293:     self.flist = curpass.flist    # output file list
   294:     self.iflist = curpass.iflist  # input file list
   295:     self.toc = curpass.toc        # table of contents
   296:     self.include_files = curpass.include_files # include files
   297:     self.classes = curpass.classes # classes
   298:     self.functions = curpass.functions # functions
   299:     self.tests = curpass.tests # functions
   300:     self.section_index = curpass.section_index # functions
   301: 
   302:     if self.sequence_limit == -1:
   303:       self.sequence_limit = curpass.sequence
   304:     elif self.sequence_limit != curpass.sequence:
   305:       print 'WARNING: SEQUENCE COUNTER DISPARITY BETWEEN PASSES'
   306:     fdict = curpass.fdict
   307:     del curpass
   308:     return self.check_convergence(passno, fdict)
   309: 
   310:   def check_convergence(self, passno, ds):
   311:     dd = self.fdict
   312: 
   313:     file_count = 0
   314:     stable_file_count = 0
   315:     unstable_file_count = 0
   316:     new_file_count = 0
   317:     for k in ds.keys():
   318:       file_count = file_count + 1
   319:       #print 'Checking file',file_count,':',k,'Status',ds[k]
   320:       if not dd.has_key(k):
   321:         dd[k]=(ds[k],passno)
   322: 
   323:       if ds[k]=='original':
   324:         new_file_count = new_file_count + 1
   325:       elif ds[k]=='unchanged':
   326:         stable_file_count = stable_file_count + 1
   327:       else:
   328:         unstable_file_count = unstable_file_count + 1
   329:       if ds[k]!='unchanged' or dd[k][0]!='unchanged':
   330:         dd[k]=(ds[k],passno)
   331:     converged = file_count == stable_file_count
   332:     if converged:
   333:       print 'All',file_count,'output files stable on pass',passno+1,' -- breaking'
   334:     else:
   335:       print 'Pass',passno+1,'status: <not converged>'
   336:       print '  Files    :',file_count
   337:       print '  New      :',new_file_count
   338:       print '  Changed  :',unstable_file_count
   339:       print '  Unchanged:',stable_file_count
   340:     return converged
   341: 
   342: 
End python section to interscript/frames/masterf.py[2]