[Modeling-cvs] ProjectModeling/Modeling/ModelMasons ModelMason.py,1.6,1.7 PyModelMason.py,1.8,1.9
Status: Abandoned
Brought to you by:
sbigaret
From: <sbi...@us...> - 2003-05-26 15:45:21
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons In directory sc8-pr-cvs1:/tmp/cvs-serv21164/ModelMasons Modified Files: ModelMason.py PyModelMason.py Log Message: Merged changes from brch-0_9pre6-1-ModelMasons_base_generation_scheme to trunk Index: ModelMason.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons/ModelMason.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** ModelMason.py 20 Apr 2003 14:16:42 -0000 1.6 --- ModelMason.py 26 May 2003 15:44:48 -0000 1.7 *************** *** 24,30 **** """ - ModelMason ! Documentation forthcoming. See PyModelMason for an example of use. CVS information --- 24,34 ---- """ ! ModelMason contains the base class for every ''mason'' and is of no interest ! except if you plan to design a new module to generate code/files from a Model. ! ! When this is the case, the class' documentation indicate the rules that should ! be respected to ensure easy integration with the framework's tools such as the ! script mdl_generate_python_code or the ZModeler. CVS information *************** *** 40,46 **** class ModelMason: def __init__(self, model, rootPath, concreteBuilder, bricksDir, ! verbose_mode=0): """ Initializes the ModelMason so that the built files are based on the --- 44,84 ---- class ModelMason: + """ + This class should be the base class for every masons. + + When subclassing this class, you should take care of: + + - call ModelMason.__init__() if it is overridden + + - if the subclass needs to change/create sth. on the filesystem, it *must* + check whether 'fake_mode' is set: if it is set, absolutely no changes + should be made on the disk. + + Methods createEmptyFile(), createFileFromTemplate(), copyFile() and + build_package() can be used without this precaution since they already + check 'self.fake_mode' before making any changes on the disk. + + - call log() to record any action relative to the generation (such as the + creation of a file). Please note that you should be ready to log these + actions even when fake_mode is set. For example, suppose 'file.py' + should be generated but not overwritten; if the file does not exist + you'd log('Creating file file.py'), and if it exists you'd log('File.py + exists, skipping') whether fake_mode is set or not. This makes it + possible for the user to see what would happen whene (re)generating the + code without actually making the changes. + + Following these rules makes it easy to integrate a custom ''mason'' into + the script mdl_generate_python_code and the ZModeler. + + All subclasses need to override build() and put there the logic which + generates the code. You will probably override method tmpl_namespace() as + well (see its documentation for details). + + You can also refer to PyModelMason for an example of use. + + """ def __init__(self, model, rootPath, concreteBuilder, bricksDir, ! verbose_mode=0, fake_mode=0): """ Initializes the ModelMason so that the built files are based on the *************** *** 64,67 **** --- 102,108 ---- generating the files + fake_mode -- if true, do not create or change any file, just report what + would be done + Subclasses may decide to supply a default value for the product's base directory when parameter 'rootPath' is not supplied. *************** *** 75,79 **** bricksDir) self.verbose_mode=verbose_mode ! def fullPathForBrick(self, aBrick): """ --- 116,121 ---- bricksDir) self.verbose_mode=verbose_mode ! self.fake_mode=fake_mode ! def fullPathForBrick(self, aBrick): """ *************** *** 98,103 **** return self.log('Creating empty file %s\n'%filename) ! f = open(filename,"w") ! f.close() def copyFile(self, templateFilename, destinationFilename,overwrite=0): --- 140,146 ---- return self.log('Creating empty file %s\n'%filename) ! if not self.fake_mode: ! f = open(filename,"w") ! f.close() def copyFile(self, templateFilename, destinationFilename,overwrite=0): *************** *** 113,121 **** return self.log('Creating file %s\n'%destinationFilename) ! _f1 = open(self.fullPathForGeneratedFile(destinationFilename),'w') ! _f2 = open(self.fullPathForBrick(templateFilename),'r') ! _f1.write(_f2.read()) ! _f1.close() ! _f2.close() _marker=[] --- 156,165 ---- return self.log('Creating file %s\n'%destinationFilename) ! if not self.fake_mode: ! _f1 = open(self.fullPathForGeneratedFile(destinationFilename),'w') ! _f2 = open(self.fullPathForBrick(templateFilename),'r') ! _f1.write(_f2.read()) ! _f1.close() ! _f2.close() _marker=[] *************** *** 159,169 **** namespace=self.fix_tmpl_namespace(namespace) destFile = self.fullPathForGeneratedFile(destFile) ! if not overwrite and os.path.exists(destFile): self.log("File %s exists, skipping\n"%destFile) return ! self.log("Generating %s... " % destFile) ! f = open(destFile,'w') ! f.write("%s"%self.templateObjectForTemplate(template,namespace=namespace)) ! self.log("done\n") def build(self): --- 203,220 ---- namespace=self.fix_tmpl_namespace(namespace) destFile = self.fullPathForGeneratedFile(destFile) ! file_exists=os.path.exists(destFile) ! if not overwrite and file_exists: self.log("File %s exists, skipping\n"%destFile) return ! if not overwrite or (overwrite and not file_exists): ! self.log("Generating %s" % destFile) ! else: ! self.log("Overwriting %s" % destFile) ! ! if not self.fake_mode: ! f = open(destFile,'w') ! f.write("%s"%self.templateObjectForTemplate(template,namespace=namespace)) ! self.log("... done") ! self.log('\n') def build(self): *************** *** 201,205 **** {'model': self.model} ! Subclasses override this method to provide their own namespace """ return {'model': self.model} --- 252,258 ---- {'model': self.model} ! Subclasses override this method to provide their own namespace. This ! namespace is the default one transmitted to the Cheetah template when no ! specific namespace is passed to method createFileFromTemplate(). """ return {'model': self.model} *************** *** 215,224 **** for pack in string.split(self.model.packageName(), '.')[:-1]: currentPath=os.path.join(currentPath, pack) ! self.log('Creating directory %s... '%currentPath) ! try: ! os.mkdir(currentPath) ! except: self.log('no\n') ! else: self.log('ok\n') ! init=os.path.join(currentPath, '__init__.py') if os.path.exists(init): --- 268,279 ---- for pack in string.split(self.model.packageName(), '.')[:-1]: currentPath=os.path.join(currentPath, pack) ! self.log('Creating directory %s'%currentPath) ! if not self.fake_mode: ! try: ! os.mkdir(currentPath) ! except: self.log('... no') ! else: self.log('... ok') ! self.log('\n') ! init=os.path.join(currentPath, '__init__.py') if os.path.exists(init): *************** *** 226,237 **** else: self.log('Creating %s\n'%init) ! f=open(init,'w') ; f.close() # Last, create self.packagePath ! self.log('Creating directory %s... '%self.packagePath) ! try: ! os.mkdir(self.packagePath) ! except: self.log('no\n') ! else: self.log('ok\n') def log(self, msg): --- 281,295 ---- else: self.log('Creating %s\n'%init) ! if not self.fake_mode: ! f=open(init,'w') ; f.close() # Last, create self.packagePath ! self.log('Creating directory %s'%self.packagePath) ! if not self.fake_mode: ! try: ! os.mkdir(self.packagePath) ! except: self.log('... no') ! else: self.log('... ok') ! self.log('\n') def log(self, msg): Index: PyModelMason.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons/PyModelMason.py,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** PyModelMason.py 20 Apr 2003 16:10:39 -0000 1.8 --- PyModelMason.py 26 May 2003 15:44:48 -0000 1.9 *************** *** 24,31 **** """ ! PyModelMason ! Documentation forthcoming CVS information --- 24,45 ---- """ ! PyModelMason generates the python package, modules and classes described ! in a model, ready to be used w/ the modeling framework. ! Its templates are located in sub-package 'Python_bricks'. The generated code ! is compatible with python v2.1 and v2.2. + Given a model, it can generate the appropriate python code in two different + ways: the flat, or 'compact' scheme, and the 'base' scheme. + + The former one generates all files within a single directory (namely: in + package model.packageName()), none of which (except the models) can be + overwritten when the code is regenerated. + + The so-called 'base' scheme adds a subpackage 'MDL' within the generated + package. All files within MDL/ are ALWAYS overwritten when the python code is + regenerated, while others (in the root package) are never overwritten if they + exist. This is probably the one you want to use if your model changes often. + CVS information *************** *** 40,48 **** from Cheetah.Template import Template ! from Python_bricks import init,model,base_module,module_base,module_compact,setup_tmpl class PyModelMason(ModelMason): def __init__(self, model, rootPath=None, verbose_mode=0, ! generation_scheme='compact'): """ Initializes the ModelMason so that the built files are based on the --- 54,118 ---- from Cheetah.Template import Template ! from Python_bricks import init,init_base,model,base_module,module_base,module_compact,setup_tmpl ! ! class InvalidModelError(Exception): ! "Raised by checkModelIsValid()" ! pass ! ! def checkModelIsValid(model, generation_scheme): ! """ ! Checks that the supplied model is valid for a given python-code generation ! scheme: ! ! - if 'generation_scheme' is 'compact', all models are valid, ! ! - if 'generation_scheme' is 'base', the model is valid iff a class/entity does ! not share the same module than any of its subclasses ! ! Parameters: ! ! model -- a instance of Modeling.Model.Model ! ! generation_scheme -- either 'compact' or 'base' ! ! Returns: None ! ! Raises InvalidModelError if the model is invalid. ! ! Note: this is NOT validation of the model itself (responsability of ! Modeling.ModelValidation) ! ! """ ! if generation_scheme=='compact': return ! if generation_scheme=='base': ! ! # Build ordered list of entities ! oe=[] ! entities=list(model.entities()) ! entities_processed=[] ! for entity in [e for e in entities if not e.parentEntity()]: ! oe.append(entity) ! entities_processed.append(entity.name()) ! entities.remove(entity) ! while entities: ! es=[e for e in entities if e.parentEntity().name() in entities_processed] ! for entity in es: ! entities.remove(entity) ! entities_processed.append(entity.name()) ! oe.append(entity) ! # check every parent against it subentities ! for e in oe: ! parent_moduleName=e.moduleName() ! subs=e.allSubEntities() ! for sub in subs: ! if sub.moduleName()==parent_moduleName: ! raise InvalidModelError, "Model is invalid wrt the 'base' generation scheme: entity '%s' and its subentity '%s' share the same moduleName.\nEither correct this or use the 'compact' generation scheme"%(e.name(), sub.name()) ! else: ! raise ValueError, "Invalid value for 'generation_scheme' (%s), should be either 'base' or 'compact'"%use_scheme class PyModelMason(ModelMason): + "See the module's documentation for details" def __init__(self, model, rootPath=None, verbose_mode=0, ! generation_scheme='compact', fake_mode=0): """ Initializes the ModelMason so that the built files are based on the *************** *** 51,71 **** Parameters: ! model -- ! rootPath -- ! verbode_mode -- use_scheme -- 'compact' or 'base' """ import Modeling if generation_scheme not in ('compact', 'base'): raise ValueError,"Parameter generation_scheme can be either 'compact' or 'base'" ModelMason.__init__(self, model, rootPath, Modeling.ModelMasons.PyModelMason, 'Python_bricks', ! verbose_mode) self._entities=[] # used during build self.generation_scheme=generation_scheme def tmpl_namespace(self): --- 121,145 ---- Parameters: ! model -- see ModelMason.__init__() ! rootPath -- see ModelMason.__init__() ! verbode_mode -- see ModelMason.__init__() use_scheme -- 'compact' or 'base' + fake_mode -- see ModelMason.__init__() + """ import Modeling if generation_scheme not in ('compact', 'base'): raise ValueError,"Parameter generation_scheme can be either 'compact' or 'base'" + checkModelIsValid(model, generation_scheme) ModelMason.__init__(self, model, rootPath, Modeling.ModelMasons.PyModelMason, 'Python_bricks', ! verbose_mode, fake_mode) self._entities=[] # used during build self.generation_scheme=generation_scheme + self.base_dir=generation_scheme=='base' and 'MDL' or '' def tmpl_namespace(self): *************** *** 77,80 **** --- 151,156 ---- 'model' : self.model, 'entities': self._entities, + 'base_dir': self.base_dir, + 'entitiesSet': self.entitiesSet, } return nameSpace *************** *** 83,86 **** --- 159,184 ---- def build(self): "-" + #----------------------------------------------------------------- + def create_model_files(self, xml_path, py_path): + # model_<modelName>.xml + self.log('Generating %s'%xml_path) + if not self.fake_mode: + self.model.saveModelAsXMLFile(xml_path) + self.log('... done') + self.log('\n') + # model_<modelName>.py + if not self.fake_mode: + xml=open(xml_path) + modelStr=xml.read() + xml.close() + else: + modelStr='fake' + self.createFileFromTemplate(model.model(), + py_path, + namespace={'model_str':modelStr}, + overwrite=1) + del modelStr + #----------------------------------------------------------------- + # Build as many directories with __init__.py as needed self.build_package() *************** *** 93,120 **** self.createEmptyFile("DEPENDENCIES.txt",overwrite=0) - # model_<modelName>.xml - modelFileName='model_'+self.model.name()+'.xml' - modelFileName=self.fullPathForGeneratedFile(modelFileName) - self.log('Generating %s... '%modelFileName) - self.model.saveModelAsXMLFile(modelFileName) - self.log('done\n') - - # model_<modelName>.py - xml=open(modelFileName) - modelStr=xml.read() - xml.close() - self.createFileFromTemplate(model.model(), - "model_%s.py"%self.model.name(), - namespace={'model_str':modelStr}, - overwrite=1) - del modelStr - # package's __init__.py self.createFileFromTemplate(init.init(),"__init__.py",overwrite=0) # setup.py ! self.createFileFromTemplate(setup_tmpl.setup_tmpl(),"setup.py") # COMPACT generation scheme if self.generation_scheme=='compact': # modules for self._entities in self.entitiesSet(): --- 191,206 ---- self.createEmptyFile("DEPENDENCIES.txt",overwrite=0) # package's __init__.py self.createFileFromTemplate(init.init(),"__init__.py",overwrite=0) # setup.py ! self.createFileFromTemplate(setup_tmpl.setup_tmpl(),"setup.py",overwrite=0) # COMPACT generation scheme if self.generation_scheme=='compact': + # Create model files (.xml/.py) + xmlp=self.fullPathForGeneratedFile('model_'+self.model.name()+'.xml') + pyp="model_%s.py"%self.model.name() + create_model_files(self, xmlp, pyp) + # modules for self._entities in self.entitiesSet(): *************** *** 126,137 **** # BASE generation scheme elif self.generation_scheme=='base': ! # create 'Base' ! #basePath=self.fullPathForGeneratedFile('Base') ! #self.log("Creating directory %s... "%basePath) ! #try: ! # os.mkdir(basePath) ! #except: self.log('no\n') ! #else: self.log('ok\n') ! # modules for self._entities in self.entitiesSet(): --- 212,232 ---- # BASE generation scheme elif self.generation_scheme=='base': ! # create 'Base' and model files (.xml/.py) ! basePath=self.fullPathForGeneratedFile(self.base_dir) ! self.log("Creating directory %s"%basePath) ! if not self.fake_mode: ! try: ! os.mkdir(basePath) ! except: self.log('no\n') ! else: self.log('ok\n') ! self.createFileFromTemplate(init_base.init_base(), ! os.path.join(self.base_dir,"__init__.py"), ! overwrite=1) ! ! create_model_files(self, ! os.path.join(basePath, ! 'model_'+self.model.name()+'.xml'), ! os.path.join(self.base_dir, ! "model_%s.py"%self.model.name())) # modules for self._entities in self.entitiesSet(): *************** *** 141,144 **** overwrite=0) self.createFileFromTemplate(base_module.base_module(), ! "%sBase.py" % module_name, overwrite=1) --- 236,240 ---- overwrite=0) self.createFileFromTemplate(base_module.base_module(), ! os.path.join(self.base_dir, ! "%s.py" % module_name), overwrite=1) |