modeling-cvs Mailing List for Object-Relational Bridge for python (Page 31)
Status: Abandoned
Brought to you by:
sbigaret
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
(54) |
Apr
(29) |
May
(94) |
Jun
(47) |
Jul
(156) |
Aug
(132) |
Sep
(40) |
Oct
(6) |
Nov
(18) |
Dec
(24) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(18) |
Feb
(59) |
Mar
(7) |
Apr
|
May
(8) |
Jun
(2) |
Jul
(12) |
Aug
(15) |
Sep
(12) |
Oct
(6) |
Nov
(25) |
Dec
(1) |
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2006 |
Jan
|
Feb
(27) |
Mar
|
Apr
(16) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sbi...@us...> - 2003-04-20 16:10:44
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons/Python_bricks In directory sc8-pr-cvs1:/tmp/cvs-serv30397/ModelMasons/Python_bricks Added Files: module_base.tmpl module_compact.tmpl base_module.tmpl Removed Files: module.tmpl Log Message: ModelMasons: added a new generation scheme. The existing one is named 'compact', the new one, 'base'. The latter generates two different modules for a given entity, in modules <className> (which is not overwritten when re-generating) and <className>Base (which IS overwritten upon regeneration) Updated scripts/mdl_generate_python_code.py --- NEW FILE: module_base.tmpl --- ## This template will build the module #for entity in $entities: from $(entity.className())Base import $(entity.className())Base #end for from Modeling.Validation import ValidationException from mx.DateTime import DateTimeFrom #from Modeling import utils #for entity in $entities: #set $class_name = str($entity.className) #if $entity.parentEntity(): class $(class_name)($(class_name)Base): #derive from $(entity.parentEntity().className()) #else class $(class_name)($(class_name)Base): #end if """ $(class_name)s are objects ... """ def __init__(self): "Initializer" # Note: if you modify this method, it is a strong requirement that # every parameter gets a default value, since the framework needs to be # able to instanciate an object with no parameter at all. $(class_name)Base.__init__(self) #end for --- NEW FILE: module_compact.tmpl --- ## This template will build the module # Modeling #set $custom = 1 #for entity in $entities: #if $entity.parentEntity() and $entity.parentEntity() not in $entities: from $entity.parentEntity().moduleName() import $entity.parentEntity().className() #elif $custom: from Modeling.CustomObject import CustomObject #set $custom=0 #end if #end for from Modeling.Validation import ValidationException from mx.DateTime import DateTimeFrom #from Modeling import utils #for entity in $entities: #set $class_name = str($entity.className) #set $l_class_name = utils.lower($entity.className) #set $type_name = $entity.typeName #set $type_name_id = utils.stringToPythonIdentifier(str($entity.typeName)) #set $entity_props=list($entity.newOrOverriddenPythonProperties()) $entity_props.sort(lambda x,y: cmp(x.name(), y.name())) #if $entity.parentEntity(): class $(class_name)($(entity.parentEntity().className())): #else class $(class_name)(CustomObject): #end if """ $(class_name)s are objects ... """ #unless $entity.parentEntity() __implements__ = CustomObject.__implements__ #end unless def __init__(self): "Initializer" # Note: if you modify this method, it is a strong requirement that # every parameter gets a default value, since the framework needs to be # able to instanciate an object with no parameter at all. #if $entity.parentEntity: $(entity.parentEntity().name()).__init__(self) #end if #for attr in $entity_props: #if hasattr($attr, 'defaultValueAsPythonStatement'): #if not $attr in $entity.primaryKeyAttributes(): self._$attr.name = $attr.defaultValueAsPythonStatement #else self._$attr.name = $attr.defaultValueAsPythonStatement # Primary Key: read-only! #end if #end if #end for #for rel in $entity_props: #if not hasattr($rel, 'defaultValueAsPythonStatement'): #if $rel.isToMany(): self._$rel.name()=[] #else self._$rel.name()=None #end if #end if #end for def entityName(self): "Used by the framework to link this object to its entity" return "$(entity.name)" # do not change #for attr in $entity_props: #if hasattr($attr, 'defaultValueAsPythonStatement'): # Attribute: $attr.name #if $attr in $entity.primaryKeyAttributes(): # This attribute is a primary key: it is a READ-ONLY attribute that should # not be changed #end if def get$utils.capitalizeFirstLetter(attr.name())(self): "Return the $class_name / $attr.name attribute value" self.willRead() return self._$attr.name #if not $attr in $entity.primaryKeyAttributes(): def set$utils.capitalizeFirstLetter(attr.name())(self, $attr.name): "Change the $class_name / $attr.name attribute value" self.willChange() self._$attr.name = $attr.name #end if def validate$utils.capitalizeFirstLetter(attr.name())(self, value): "Edit this to enforce custom business logic" if 0: # your custom bizlogic raise ValidationException return #end if ##* isClassProperty *# #slurp #end for ##* Attributes *# #slurp #for rel in $entity_props: #if not hasattr($rel, 'defaultValueAsPythonStatement'): # Relationship: $rel.name #if $rel.isToMany(): def get$(utils.capitalizeFirstLetter($rel.name()))(self): "Returns the $(rel.name) relationship (toMany)" self.willRead() return self._$rel.name() def addTo$(utils.capitalizeFirstLetter($rel.name()))(self, object): "Add the $rel.name relationship (toMany)" if object not in self._$rel.name(): self.willChange() _$rel.name()=list(self._$rel.name()) _$(rel.name()).append(object) self._$rel.name()=tuple(_$rel.name()) def removeFrom$(utils.capitalizeFirstLetter($rel.name()))(self, object): "Remove the $rel.name relationship (toMany)" self.willChange() _$rel.name()=list(self._$rel.name()) _$(rel.name()).remove(object) self._$rel.name()=tuple(_$rel.name()) #else def get$(utils.capitalizeFirstLetter($rel.name()))(self): "Return the $rel.name relationship (toOne)" self.willRead() return self._$rel.name def set$(utils.capitalizeFirstLetter($rel.name()))(self, object): "Set the $rel.name relationship (toOne)" self.willChange() self._$rel.name=object #end if ##* isToMany *# #end if ##* isClassProperty *# #end for #end for --- NEW FILE: base_module.tmpl --- ## This template will build the <module>Base.py module # Modeling #set $custom = 1 #for entity in $entities: #if $entity.parentEntity() and $entity.parentEntity() not in $entities: from $entity.parentEntity().moduleName() import $entity.parentEntity().className() #elif $custom: from Modeling.CustomObject import CustomObject #set $custom=0 #end if #end for from Modeling.Validation import ValidationException from mx.DateTime import DateTimeFrom #from Modeling import utils #for entity in $entities: #set $class_name = str($entity.className) #set $l_class_name = utils.lower($entity.className) #set $type_name = $entity.typeName #set $type_name_id = utils.stringToPythonIdentifier(str($entity.typeName)) #set $entity_props=list($entity.newOrOverriddenPythonProperties()) $entity_props.sort(lambda x,y: cmp(x.name(), y.name())) #if $entity.parentEntity(): class $(class_name)Base($(entity.parentEntity().className())): #else class $(class_name)Base(CustomObject): #end if """ Base module for $(class_name)s """ #unless $entity.parentEntity() __implements__ = CustomObject.__implements__ #end unless def __init__(self): "Initializer" # Note: if you modify this method, it is a strong requirement that # every parameter gets a default value, since the framework needs to be # able to instanciate an object with no parameter at all. #if $entity.parentEntity: $(entity.parentEntity().name()).__init__(self) #end if #for attr in $entity_props: #if hasattr($attr, 'defaultValueAsPythonStatement'): #if not $attr in $entity.primaryKeyAttributes(): self._$attr.name = $attr.defaultValueAsPythonStatement #else self._$attr.name = $attr.defaultValueAsPythonStatement # Primary Key: read-only! #end if #end if #end for #for rel in $entity_props: #if not hasattr($rel, 'defaultValueAsPythonStatement'): #if $rel.isToMany(): self._$rel.name()=[] #else self._$rel.name()=None #end if #end if #end for def entityName(self): "Used by the framework to link this object to its entity" return "$(entity.name)" # do not change #for attr in $entity_props: #if hasattr($attr, 'defaultValueAsPythonStatement'): # Attribute: $attr.name #if $attr in $entity.primaryKeyAttributes(): # This attribute is a primary key: it is a READ-ONLY attribute that should # not be changed #end if def get$utils.capitalizeFirstLetter(attr.name())(self): "Return the $class_name / $attr.name attribute value" self.willRead() return self._$attr.name #if not $attr in $entity.primaryKeyAttributes(): def set$utils.capitalizeFirstLetter(attr.name())(self, $attr.name): "Change the $class_name / $attr.name attribute value" self.willChange() self._$attr.name = $attr.name #end if def validate$utils.capitalizeFirstLetter(attr.name())(self, value): "Edit this to enforce custom business logic" if 0: # your custom bizlogic raise ValidationException return #end if ##* isClassProperty *# #slurp #end for ##* Attributes *# #slurp #for rel in $entity_props: #if not hasattr($rel, 'defaultValueAsPythonStatement'): # Relationship: $rel.name #if $rel.isToMany(): def get$(utils.capitalizeFirstLetter($rel.name()))(self): "Returns the $(rel.name) relationship (toMany)" self.willRead() return self._$rel.name() def addTo$(utils.capitalizeFirstLetter($rel.name()))(self, object): "Add the $rel.name relationship (toMany)" if object not in self._$rel.name(): self.willChange() _$rel.name()=list(self._$rel.name()) _$(rel.name()).append(object) self._$rel.name()=tuple(_$rel.name()) def removeFrom$(utils.capitalizeFirstLetter($rel.name()))(self, object): "Remove the $rel.name relationship (toMany)" self.willChange() _$rel.name()=list(self._$rel.name()) _$(rel.name()).remove(object) self._$rel.name()=tuple(_$rel.name()) #else def get$(utils.capitalizeFirstLetter($rel.name()))(self): "Return the $rel.name relationship (toOne)" self.willRead() return self._$rel.name def set$(utils.capitalizeFirstLetter($rel.name()))(self, object): "Set the $rel.name relationship (toOne)" self.willChange() self._$rel.name=object #end if ##* isToMany *# #end if ##* isClassProperty *# #end for #end for --- module.tmpl DELETED --- |
From: <sbi...@us...> - 2003-04-20 14:35:47
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons/Python_bricks In directory sc8-pr-cvs1:/tmp/cvs-serv1729/ModelMasons/Python_bricks Modified Files: module.tmpl Log Message: Fixed Python_bricks/module.tmpl: do not generate e.g. setId() if 'id' is a primary key marked as a class property Index: module.tmpl =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons/Python_bricks/module.tmpl,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** module.tmpl 9 Oct 2002 13:43:26 -0000 1.4 --- module.tmpl 20 Apr 2003 14:35:44 -0000 1.5 *************** *** 44,48 **** --- 44,52 ---- #for attr in $entity_props: #if hasattr($attr, 'defaultValueAsPythonStatement'): + #if not $attr in $entity.primaryKeyAttributes(): self._$attr.name = $attr.defaultValueAsPythonStatement + #else + self._$attr.name = $attr.defaultValueAsPythonStatement # Primary Key: read-only! + #end if #end if #end for *************** *** 65,69 **** # Attribute: $attr.name ! def get$utils.capitalizeFirstLetter(attr.name())(self): "Return the $class_name / $attr.name attribute value" --- 69,76 ---- # Attribute: $attr.name ! #if $attr in $entity.primaryKeyAttributes(): ! # This attribute is a primary key: it is a READ-ONLY attribute that should ! # not be changed ! #end if def get$utils.capitalizeFirstLetter(attr.name())(self): "Return the $class_name / $attr.name attribute value" *************** *** 71,79 **** return self._$attr.name def set$utils.capitalizeFirstLetter(attr.name())(self, $attr.name): "Change the $class_name / $attr.name attribute value" self.willChange() self._$attr.name = $attr.name ! def validate$utils.capitalizeFirstLetter(attr.name())(self, value): "Edit this to enforce custom business logic" --- 78,87 ---- return self._$attr.name + #if not $attr in $entity.primaryKeyAttributes(): def set$utils.capitalizeFirstLetter(attr.name())(self, $attr.name): "Change the $class_name / $attr.name attribute value" self.willChange() self._$attr.name = $attr.name ! #end if def validate$utils.capitalizeFirstLetter(attr.name())(self, value): "Edit this to enforce custom business logic" |
From: <sbi...@us...> - 2003-04-20 14:35:47
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv1729 Modified Files: CHANGES Log Message: Fixed Python_bricks/module.tmpl: do not generate e.g. setId() if 'id' is a primary key marked as a class property Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.92 retrieving revision 1.93 diff -C2 -d -r1.92 -r1.93 *** CHANGES 20 Apr 2003 14:16:40 -0000 1.92 --- CHANGES 20 Apr 2003 14:35:44 -0000 1.93 *************** *** 11,14 **** --- 11,16 ---- they used to be. See PyModelMason for an example of use. Fixed: bug #710817 + Fixed Python_bricks/module.tmpl: do not generate e.g. setId() if 'id' is a + primary key marked as a class property * Fixed: name clash for invalidatesObjectsWhenFinalized in EditingContext |
From: <sbi...@us...> - 2003-04-20 14:17:16
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/scripts In directory sc8-pr-cvs1:/tmp/cvs-serv28351/scripts Modified Files: mdl_generate_python_code.py Log Message: Refactored ModelMasons: ModelMason and PyModelMason are now clearer than they used to be. See PyModelMason for an example of use. Fixed: bug #710817 Index: mdl_generate_python_code.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/scripts/mdl_generate_python_code.py,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** mdl_generate_python_code.py 20 Feb 2003 22:14:40 -0000 1.2 --- mdl_generate_python_code.py 20 Apr 2003 14:16:41 -0000 1.3 *************** *** 56,60 **** def build_python_code(model, rootPath=None, typeOfCode='python', ! verbose_mode=0, overwrite=0): """ Builds the python-code templates for the supplied model --- 56,60 ---- def build_python_code(model, rootPath=None, typeOfCode='python', ! verbose_mode=0): """ Builds the python-code templates for the supplied model *************** *** 69,81 **** future dev. will probably include generation of zope products. - overwrite -- when set to false (the default), it makes the building - process abort if the ModelMason.productBaseDirectory() already exists. - Please note that only the productBaseDirectory() is checked for - existence ; if the directory exists but does not contain any of the - files that are to be generated, the process will be aborted as well. - - When set to true, the building process will ignore already existing - files and it will OVERWRITE them, so please be careful! - verbose_mode -- if set to true, the building process logs some informational message onto sys.stderr while building the files. Default --- 69,72 ---- *************** *** 94,102 **** mason = PyModelMason(model, rootPath, verbose_mode=verbose_mode) - if not overwrite: - import os - if os.path.exists(mason.productBaseDirectory()): - raise TargetDirectoryAlreadyExists, 'Error: Target directory %s exists. Aborted'%mason.productBaseDirectory() - mason.build() --- 85,88 ---- *************** *** 116,136 **** -------- -h --help gives this help ! -v --verbose verbose mode ! ! --overwrite-existing-files overwrites any existing files -- USE WITH CARE! ! There is no short option, this is intended: a ! typo would otherwise too easily overwrite ! valuable code. ! ! Important note: ! ! The building process will immediately abort if the target directory exists ! (except if option --overwrite-existing-files is given). However and despite ! the name of the option, the building process does not look for files it is ! about to create. The decision is simpler: if the target directory already ! exists, the build process is stopped, even if the files it contains would ! not be overriden by the code-generation process (and even if this directory ! is empty!) --for the curious, this is due to the lack of such a feature in ! Modeling.ModelMasons package and it has been added to the TODO list. --- 102,107 ---- -------- -h --help gives this help ! -v --verbose verbose mode (default) ! -q --quiet quiet mode *************** *** 139,157 **** # Global variables ! verbose=0 def main(args): me=args[0] try: options, args = getopt.getopt(sys.argv[1:], ! 'hv', ! ["help", "verbose", ! "overwrite-existing-files"]) except: usage(me); return 1 global verbose - overwrite=0 for k, v in options: if k in ('-h', '--help'): usage(me); return 0 if k in ('-v', '--verbose'): verbose=1; continue - if k=='--overwrite-existing-files': overwrite=1; continue if len(args) not in (1,2): usage(me) ; return 1 --- 110,126 ---- # Global variables ! verbose=1 def main(args): me=args[0] try: options, args = getopt.getopt(sys.argv[1:], ! 'hqv', ! ["help", "quiet", "verbose"]) except: usage(me); return 1 global verbose for k, v in options: if k in ('-h', '--help'): usage(me); return 0 + if k in ('-q', '--quiet'): verbose=0; continue if k in ('-v', '--verbose'): verbose=1; continue if len(args) not in (1,2): usage(me) ; return 1 *************** *** 173,177 **** model=ms.models()[0] try: ! build_python_code(model, rootPath, verbose_mode=verbose, overwrite=overwrite) except TargetDirectoryAlreadyExists, exc: sys.stderr.write(str(sys.exc_info()[1])+'\n') --- 142,146 ---- model=ms.models()[0] try: ! build_python_code(model, rootPath, verbose_mode=verbose) except TargetDirectoryAlreadyExists, exc: sys.stderr.write(str(sys.exc_info()[1])+'\n') |
From: <sbi...@us...> - 2003-04-20 14:17:15
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv28351 Modified Files: CHANGES Log Message: Refactored ModelMasons: ModelMason and PyModelMason are now clearer than they used to be. See PyModelMason for an example of use. Fixed: bug #710817 Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.91 retrieving revision 1.92 diff -C2 -d -r1.91 -r1.92 *** CHANGES 27 Mar 2003 13:39:13 -0000 1.91 --- CHANGES 20 Apr 2003 14:16:40 -0000 1.92 *************** *** 7,10 **** --- 7,14 ---- * ** Distributed under the GNU General Public License ** -------------------------------------------------------- + + * Refactored ModelMasons: ModelMason and PyModelMason are now clearer than + they used to be. See PyModelMason for an example of use. + Fixed: bug #710817 * Fixed: name clash for invalidatesObjectsWhenFinalized in EditingContext |
From: <sbi...@us...> - 2003-04-20 14:16:52
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons In directory sc8-pr-cvs1:/tmp/cvs-serv28351/ModelMasons Modified Files: ModelMason.py PyModelMason.py Log Message: Refactored ModelMasons: ModelMason and PyModelMason are now clearer than they used to be. See PyModelMason for an example of use. Fixed: bug #710817 Index: ModelMason.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons/ModelMason.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** ModelMason.py 4 Feb 2003 08:06:35 -0000 1.5 --- ModelMason.py 20 Apr 2003 14:16:42 -0000 1.6 *************** *** 26,30 **** ModelMason ! Documentation forthcoming CVS information --- 26,30 ---- ModelMason ! Documentation forthcoming. See PyModelMason for an example of use. CVS information *************** *** 40,86 **** class ModelMason: - _bricksBaseDirectory=None ! def __init__(self, model, rootPath, verbose_mode=0): """ Initializes the ModelMason so that the built files are based on the supplied model. - The following instance variable must be initialized: - - - self._bricksBaseDirectory: where the bricks should be found - - - self._productBaseDirectory: where to put the generated files - - Subclasses may decide to supply a default value for the product's base - directory when parameter 'rootPath' is not supplied. - Parameters: ! model -- a Modeling.Model instance ! ! rootPath -- the directory in which the generated files should be dropped ! ! verbose_mode -- if set to a true value, the building process will log ! some informations in sys.stderr while generating the files ! """ ! self._model = model ! self._productBaseDirectory = rootPath ! self._verbose_mode=verbose_mode ! def bricksBaseDirectory(self): """ ! ! Returns the directory where the bricks/templates can be found. Any ! statement which generates files shouldn't put these anywhere but inside ! the directory path returned by this method. - Default implementation returns self._bricksBaseDirectory ; this variable - shouldn't be directly manipulated, rather it should be set at - initialization time and accessed through this method. - """ - return self._bricksBaseDirectory - def fullPathForBrick(self, aBrick): """ --- 40,79 ---- class ModelMason: ! def __init__(self, model, rootPath, concreteBuilder, bricksDir, ! verbose_mode=0): """ Initializes the ModelMason so that the built files are based on the supplied model. Parameters: ! model -- the model from which the generated python package should be ! generated ! rootPath -- path of a directory where the corresponding package should ! be dropped ! ! concreteBuilder -- the module containing the concrete builder ! ! bricksDir -- path for the directory containing the templates, relative ! to the path where the module of 'concreteBuilder' is stored ! ! verbose_mode -- whether logging is activated or not, see log(). When ! true, the building process logs some informations in sys.stderr while ! generating the files ! Subclasses may decide to supply a default value for the product's base ! directory when parameter 'rootPath' is not supplied. """ ! self.model = model ! self.rootPath=rootPath ! packagePathList=[rootPath] ! packagePathList.extend(string.split(self.model.packageName(), '.')) ! self.packagePath = apply(os.path.join, packagePathList) ! self.bricksPath=os.path.join(os.path.dirname(concreteBuilder.__file__), ! bricksDir) ! self.verbose_mode=verbose_mode def fullPathForBrick(self, aBrick): """ *************** *** 88,120 **** This is the preferred way for accessing bricks """ ! return os.path.join(self.bricksBaseDirectory(), aBrick) - def productBaseDirectory(self): - """ - Returns the directory where the generated file should be put. Any methods - manipulating templates must search them whithin the directory returned - by this method. - - Default implementation returns self._productBaseDirectory ; this variable - shouldn't be directly manipulated, rather it should be set at - initialization time and accessed through this method --since subclasses - may decide to return a dynamically computed value for this instead of a - value predetermined at initialization time. - """ - return self._productBaseDirectory - def fullPathForGeneratedFile(self, filename): "Returns the full path for a given generated filename." ! return os.path.join(self.productBaseDirectory(), filename) ! def createEmptyFile(self,filename): """ Create the empty file 'filename' ; the filename is a relative path (relative to 'self.productBaseDirectory()') """ ! f = open(self.fullPathForGeneratedFile(filename),"w") f.close() ! def copyFile(self, templateFilename, destinationFilename): """ Copy the template file to the destination file, unchanged. Both filenames --- 81,105 ---- This is the preferred way for accessing bricks """ ! return os.path.join(self.bricksPath(), aBrick) def fullPathForGeneratedFile(self, filename): "Returns the full path for a given generated filename." ! return os.path.join(self.packagePath, filename) ! def createEmptyFile(self,filename,overwrite=0): """ Create the empty file 'filename' ; the filename is a relative path (relative to 'self.productBaseDirectory()') """ ! if not os.path.isabs(filename): ! filename=self.fullPathForGeneratedFile(filename) ! if not overwrite and os.path.exists(filename): ! self.log('File %s exists, skipping\n'%filename) ! return ! self.log('Creating empty file %s\n'%filename) ! f = open(filename,"w") f.close() ! def copyFile(self, templateFilename, destinationFilename,overwrite=0): """ Copy the template file to the destination file, unchanged. Both filenames *************** *** 122,125 **** --- 107,116 ---- productBaseDirectory. """ + if not os.path.isabs(filename): + filename=self.fullPathForGeneratedFile(filename) + if not overwrite and os.path.exists(filename): + self.log('File %s exists, skipping\n'%filename) + return + self.log('Creating file %s\n'%destinationFilename) _f1 = open(self.fullPathForGeneratedFile(destinationFilename),'w') _f2 = open(self.fullPathForBrick(templateFilename),'r') *************** *** 128,168 **** _f2.close() ! def templateObjectForFile(self, templateFile, searchList=[]): """ Initializes a Template object from the supplied templateFile. Overrides this to perform any additional initializations for Templates, such as ! building a namespace/searchList for the template. ! Parameter 'templateFile' is a relative path: relative to the bricksBaseDir. Default implementation simply returns the Template object """ ! templateFile = self.fullPathForBrick(templateFile) ! ! templateObj = Template(file=templateFile, searchList=searchList) ! return templateObj - def createFileFromTemplateFile(self, templateFile, destFile, searchList=[]): - """ - Both filenames should be relative to, respectively, bricksBaseDirectory - and productBaseDirectory. - """ - if self._verbose_mode: sys.stderr.write(">> Generating %s..." % destFile) - destFile = self.fullPathForGeneratedFile(destFile) - f = open(destFile,'w') - f.write("%s" % self.templateObjectForFile(templateFile, - searchList=searchList)) - if self._verbose_mode: sys.stderr.write("Done\n") ! def createFileFromTemplate(self, template, destFile, searchList=[]): """ ! template: a Cheetah.Template object ! destFile: the destination file path, relative to productBaseDirectory """ ! if self._verbose_mode: sys.stderr.write(">> Generating %s... " % destFile) destFile = self.fullPathForGeneratedFile(destFile) f = open(destFile,'w') ! f.write("%s" % self.templateObjectForTemplate(template, ! searchList=searchList)) ! if self._verbose_mode: sys.stderr.write("Done\n") def build(self): --- 119,169 ---- _f2.close() ! _marker=[] ! def templateObjectForTemplate(self, template, namespace=_marker): """ Initializes a Template object from the supplied templateFile. Overrides this to perform any additional initializations for Templates, such as ! building a namespace for the template. ! Parameters: ! ! template -- a Cheetah.Template object ! ! namespace -- the template will use that namespace. If ommitted, it ! defaults to self.tmpl_namespace() ! Default implementation simply returns the Template object """ ! if namespace is self._marker: namespace=self.tmpl_namespace() ! namespace=self.fix_tmpl_namespace(namespace) ! #for dict in namespace: ! for key in namespace.keys(): ! setattr(template, key, namespace[key]) ! return template ! def createFileFromTemplate(self, template, destFile, namespace=_marker, ! overwrite=0): """ ! Parameters: ! ! template -- a Cheetah.Template object ! ! namespace -- the template will use that namespace. If ommitted, it ! defaults to self.tmpl_namespace() ! ! destFile -- the destination file path, relative to productBaseDirectory ! """ ! if namespace is self._marker: namespace=self.tmpl_namespace() ! 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): *************** *** 172,174 **** """ pass ! --- 173,256 ---- """ pass ! ! ! def fix_tmpl_namespace(self, namespace): ! """ ! Internally used to make any values in the namespace callable --if a value ! is an instance or a python object, it is by a lambda function returning ! the value. We make this because Cheetah sometimes requires a callable. ! """ ! # builtin callable() does not work on instances derived from ! # ZODB.Persistent, we use that one instead ! def _callable(o): ! if hasattr(o,'__class__'): return hasattr(o,'__call__') ! return callable(o) ! d={} ! for k,v in namespace.items(): ! if _callable(v): d[k]=v ! else: d[k]=lambda p=v: p ! return d ! ! def tmpl_namespace(self): ! """ ! This method returns a dictionary used by templates to search for specific ! values. ! ! Default implementation returns:: ! ! {'model': self.model} ! ! Subclasses override this method to provide their own namespace ! """ ! return {'model': self.model} ! ! def build_package(self): ! """ ! Creates all the necessary directories for the package, which can be ! something like A.B.C.MyPackage. Creates an empty '__init__.py' in each ! sub-directories if needed: existing __init__.py are not overwritten. ! """ ! currentPath=self.rootPath ! packList=[] ! 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): ! self.log('%s exists, skipping\n'%init) ! 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): ! "Logs the msg to stderr if self.verbose_mode is true" ! if self.verbose_mode: ! sys.stderr.write(msg) ! ! ! def entitiesSet(self): ! """ ! Returns a list of list of entities, where Entities in the same list share ! the same 'moduleName' ! """ ! d={} ! for entity in self.model.entities(): ! moduleName=entity.moduleName() ! if d.get(moduleName): ! d[moduleName].append(entity) ! else: d[moduleName]=[entity] ! ! return d.values() ! Index: PyModelMason.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/ModelMasons/PyModelMason.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** PyModelMason.py 4 Feb 2003 08:08:28 -0000 1.6 --- PyModelMason.py 20 Apr 2003 14:16:43 -0000 1.7 *************** *** 48,171 **** supplied model. """ - self._model = model - self._verbose_mode=verbose_mode - self._rootPath=_path = rootPath - packagePath=apply(os.path.join, string.split(model.packageName(), '.')) - self._productBaseDirectory = os.path.join(_path,"%s/" %packagePath) import Modeling ! self._bricksBaseDirectory = os.path.join( ! os.path.dirname(Modeling.ModelMasons.PyModelMason.__file__), ! "Python_bricks/") ! ! # ! packList=[] ! for pack in string.split(self._model.packageName(), '.'): ! packList.append(pack) ! packagePath=apply(os.path.join, packList) ! self._productBaseDirectory=os.path.join(self._rootPath,"%s/" %packagePath) ! ! ! def templateObjectForFile(self,templateFile, searchList=[]): ! """ ! Overrides ModelMason implementation so that the namespace passed to the ! Template object contains: self, an Entity, a Model and a Relationship ! """ ! templateFile = self.fullPathForBrick(templateFile) ! ! # The following lambda forms are needed since the Cheetah framework ! # sometimes really wants callable objects. This obviously solves the pb. ! if not searchList: ! _self = lambda p=self: p ! entities = lambda p=self._entities: p ! model = lambda p=self._model: p ! nameSpace = {'myself': _self, ! 'model' : model, ! 'entities': entities, ! } ! searchList=[nameSpace] ! templateObj = Template(file=templateFile, searchList=searchList) ! return templateObj ! def templateObjectForTemplate(self,template, searchList=[]): """ ! Overrides ModelMason implementation so that the namespace passed to the ! Template object contains: self, an Entity, a Model and a Relationship """ ! if not searchList: ! _self = lambda p=self: p ! entities = lambda p=self._entities: p ! model = lambda p=self._model: p ! nameSpace = {'myself': _self, ! 'model' : model, ! 'entities': entities, ! } ! searchList=[nameSpace] ! for dict in searchList: ! for key in dict.keys(): ! setattr(template, key, dict[key]) ! return template def build(self): "-" ! try: ! packagePath='' ! packList=[] ! for pack in string.split(self._model.packageName(), '.'): ! packList.append(pack) ! packagePath=apply(os.path.join, packList) ! intermediate_dir=os.path.join(self._rootPath,"%s/" %packagePath) ! os.makedirs(intermediate_dir, 0700) ! self.createEmptyFile('__init__.py') ! ! #os.makedirs(self.productBaseDirectory(), 0700) ! self.createEmptyFile("TODO.txt") ! self.createEmptyFile("README.txt") ! self.createEmptyFile("VERSION.txt") ! self.createEmptyFile("INSTALL.txt") ! self.createEmptyFile("DEPENDENCIES.txt") ! except OSError: ! pass ! ! # quick and DIRTY ! self._entities=[]#=self._model.entities()[0] ! modelFileName='model_'+self._model.name()+'.xml' ! self._model.saveModelAsXMLFile(self.fullPathForGeneratedFile(modelFileName)) ! encoding='iso-8859-1' ! doc=self._model.getXMLDOM(encoding=encoding) ! from xml.dom.ext import PrettyPrint ! import StringIO ! _strIO=StringIO.StringIO() ! PrettyPrint(doc, stream=_strIO, encoding=encoding) ! modelStr=_strIO.getvalue() ! _strIO.close() self.createFileFromTemplate(model.model(), ! "model_%s.py"%self._model.name(), ! searchList=[{'model_str':modelStr}]) del modelStr ! self.createFileFromTemplate(init.init(),"__init__.py") self.createFileFromTemplate(setup_tmpl.setup_tmpl(),"setup.py") ! # Attention : self._entity is used by method createFileFromTemplate. for self._entities in self.entitiesSet(): - #l_class_name = string.lower(self._entity.className()) module_name = self._entities[0].moduleName() self.createFileFromTemplate(module.module(),"%s.py" % module_name) - def entitiesSet(self): - """ - Returns a list of list of entities, where Entities in the same list share - the same 'moduleName' - """ - d={} - for entity in self._model.entities(): - moduleName=entity.moduleName() - if d.get(moduleName): - d[moduleName].append(entity) - else: d[moduleName]=[entity] - - return d.values() - - --- 48,106 ---- supplied model. """ import Modeling ! ModelMason.__init__(self, model, rootPath, ! Modeling.ModelMasons.PyModelMason, 'Python_bricks', ! verbose_mode) ! self._entities=[] # used during build ! def tmpl_namespace(self): """ ! Namespace for templates: contains keys 'myself', 'model' and 'entities' ! NB: 'entities' is set during build(), when generating modules. """ ! nameSpace = {'myself': self, ! 'model' : self.model, ! 'entities': self._entities, ! } ! return nameSpace def build(self): "-" ! # Build as many directories with __init__.py as needed ! self.build_package() ! # empty files ! self.createEmptyFile("TODO.txt",overwrite=0) ! self.createEmptyFile("README.txt",overwrite=0) ! self.createEmptyFile("VERSION.txt",overwrite=0) ! self.createEmptyFile("INSTALL.txt",overwrite=0) ! 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") ! # modules for self._entities in self.entitiesSet(): module_name = self._entities[0].moduleName() self.createFileFromTemplate(module.module(),"%s.py" % module_name) |
From: <sbi...@us...> - 2003-03-27 13:39:56
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv12723 Modified Files: CHANGES EditingContext.py Log Message: Fixed: name clash for invalidatesObjectsWhenFinalized in EditingContext. Default behaviour is now set with EditingContext.invalidatesObjectsWhenFinalized_default Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.90 retrieving revision 1.91 diff -C2 -d -r1.90 -r1.91 *** CHANGES 27 Mar 2003 13:22:22 -0000 1.90 --- CHANGES 27 Mar 2003 13:39:13 -0000 1.91 *************** *** 8,11 **** --- 8,15 ---- -------------------------------------------------------- + * Fixed: name clash for invalidatesObjectsWhenFinalized in EditingContext + Default behaviour is now set with + EditingContext.invalidatesObjectsWhenFinalized_default + * Fixed: an newly inserted object with a PK, say, 'id', marked as class property did not get its value after EditingContext.saveChanges(). Index: EditingContext.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/EditingContext.py,v retrieving revision 1.22 retrieving revision 1.23 diff -C2 -d -r1.22 -r1.23 *** EditingContext.py 27 Mar 2003 11:47:57 -0000 1.22 --- EditingContext.py 27 Mar 2003 13:39:16 -0000 1.23 *************** *** 286,290 **** ######## # Class ! invalidatesObjectsWhenFinalized=toBoolean(1) def __init__(self, parentObjectStore=None): --- 286,290 ---- ######## # Class ! invalidatesObjectsWhenFinalized_default=toBoolean(1) def __init__(self, parentObjectStore=None): *************** *** 897,907 **** default==true==when finalized, sends 'clearProperties' to all objects """ ! return self.invalidatesObjectsWhenFinalized ! def setInvalidatesObjectsWhenFinalized(self, aBool): """ - """ ! self.invalidatesObjectsWhenFinalized=toBoolean(aBool) def dispose(self): --- 897,910 ---- default==true==when finalized, sends 'clearProperties' to all objects """ ! if hasattr(self, '_invalidatesObjectsWhenFinalized'): ! return self._invalidatesObjectsWhenFinalized ! return self.invalidatesObjectsWhenFinalized_default ! def setInvalidatesObjectsWhenFinalized(self, aBool): """ - + See also: invalidatesObjectsWhenFinalized() """ ! self._invalidatesObjectsWhenFinalized=toBoolean(aBool) def dispose(self): *************** *** 913,917 **** for object in self._uniquingTable.objects(): self.forgetObject(object) ! if self.invalidatesObjectsWhenFinalized: object.clearProperties() except: --- 916,920 ---- for object in self._uniquingTable.objects(): self.forgetObject(object) ! if self.invalidatesObjectsWhenFinalized(): object.clearProperties() except: |
From: <sbi...@us...> - 2003-03-27 13:39:28
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide In directory sc8-pr-cvs1:/tmp/cvs-serv12723/doc/UserGuide Modified Files: ManipulatingGraphOfObjects.tex Log Message: Fixed: name clash for invalidatesObjectsWhenFinalized in EditingContext. Default behaviour is now set with EditingContext.invalidatesObjectsWhenFinalized_default Index: ManipulatingGraphOfObjects.tex =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide/ManipulatingGraphOfObjects.tex,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** ManipulatingGraphOfObjects.tex 11 Mar 2003 07:53:03 -0000 1.7 --- ManipulatingGraphOfObjects.tex 27 Mar 2003 13:39:23 -0000 1.8 *************** *** 425,429 **** \begin{description} ! \item[\member{EditingContext.invalidatesObjectsWhenFinalized}] is a class attribute that controls the global behaviour for all \class{EditingContext} instances {\em except those which were specifically configured} (see below). If --- 425,429 ---- \begin{description} ! \item[\member{EditingContext.invalidatesObjectsWhenFinalized_default}] is a class attribute that controls the global behaviour for all \class{EditingContext} instances {\em except those which were specifically configured} (see below). If |
From: <sbi...@us...> - 2003-03-27 13:22:36
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv2248 Modified Files: CHANGES Log Message: Fixed wrong year in dates for releases... Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.89 retrieving revision 1.90 diff -C2 -d -r1.89 -r1.90 *** CHANGES 27 Mar 2003 11:51:20 -0000 1.89 --- CHANGES 27 Mar 2003 13:22:22 -0000 1.90 *************** *** 18,22 **** ! 0.9-pre-5 (2002/03/17) Project milestone -- no public release --------- --- 18,22 ---- ! 0.9-pre-5 (2003/03/17) Project milestone -- no public release --------- *************** *** 44,48 **** 0 for a type=='int') ! 0.9-pre-4 (2002/03/14) Second release candidate for 0.9 --------- --- 44,48 ---- 0 for a type=='int') ! 0.9-pre-4 (2003/03/14) Second release candidate for 0.9 --------- *************** *** 113,117 **** ! 0.9-pre-3 (2002/03/02) Release candidate for 0.9 --------- --- 113,117 ---- ! 0.9-pre-3 (2003/03/02) Release candidate for 0.9 --------- *************** *** 130,134 **** only once, not for each entity of the added model ! 0.9-pre-2 (2002/02/23) --------- --- 130,134 ---- only once, not for each entity of the added model ! 0.9-pre-2 (2003/02/23) --------- *************** *** 152,156 **** announce on sourceforge's mailing-list for more details. ! 0.9-pre-1 (2002/02/23) Project milestone, CVS-tagged but no public tarball --------- --- 152,156 ---- announce on sourceforge's mailing-list for more details. ! 0.9-pre-1 (2003/02/23) Project milestone, CVS-tagged but no public tarball --------- *************** *** 209,213 **** ! 0.8.6 (2002/02/21) ----- --- 209,213 ---- ! 0.8.6 (2003/02/21) ----- |
From: <sbi...@us...> - 2003-03-27 11:51:27
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv18468 Modified Files: CHANGES Log Message: Updated Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.88 retrieving revision 1.89 diff -C2 -d -r1.88 -r1.89 *** CHANGES 27 Mar 2003 11:47:57 -0000 1.88 --- CHANGES 27 Mar 2003 11:51:20 -0000 1.89 *************** *** 11,14 **** --- 11,16 ---- property did not get its value after EditingContext.saveChanges(). [Details in: EditingContext.handleNotification()] + Thanks to soif <Jer...@fi...> for identifying and + reporting the pb. * Fixed SQLExpression.sqlStringForAttributeNamed(): now raises ValueError |
From: <sbi...@us...> - 2003-03-27 11:48:01
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/AuthorBooks In directory sc8-pr-cvs1:/tmp/cvs-serv15541/tests/testPackages/AuthorBooks Modified Files: Book.py model_AuthorBooks.xml Log Message: Fixed: an newly inserted object with a PK attribute marked as class property did not get its value after EditingContext.saveChanges(). Details in: - EditingContext.handleNotification() - test_EC_Global.test_17_insertedObject_and_PK_as_classProperty() - testPackages.AuthorBooks: entity Book now has its PK 'id' set as class property Index: Book.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/Book.py,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Book.py 2 Oct 2002 08:39:50 -0000 1.3 --- Book.py 27 Mar 2003 11:47:57 -0000 1.4 *************** *** 16,19 **** --- 16,20 ---- # every parameter gets a default value, since the framework needs to be # able to instanciate an object with no parameter at all. + self._id = 0 ## please consider this as a read-only attribute self._title = 'D\'la balle' self._price=None *************** *** 27,30 **** --- 28,36 ---- # =================== title ========================== + + def getId(self): + "Return the Book / id attribute value" + self.willRead() + return self._id def getTitle(self): Index: model_AuthorBooks.xml =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/testPackages/AuthorBooks/model_AuthorBooks.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** model_AuthorBooks.xml 1 Feb 2003 16:15:07 -0000 1.4 --- model_AuthorBooks.xml 27 Mar 2003 11:47:57 -0000 1.5 *************** *** 1,3 **** --- 1,4 ---- <?xml version='1.0' encoding='iso-8859-1'?> + <!-- <!DOCTYPE model SYSTEM "mdl_model.dtd"> --> <model name='AuthorBooks' packageName='AuthorBooks' adaptorName='Postgresql' connectionDictionary="{'database': 'AUTHOR_BOOKS', 'user': 'postgres', 'password': '', 'host': 'localhost'}"> <entity isReadOnly='0' externalName='WRITER' name='Writer' parentEntity='' className='Writer' typeName='Writer' isAbstract='0'> *************** *** 25,29 **** <attributesUsedForLocking attributeName='FK_Writer_Id'/> <attribute isClassProperty='1' columnName='title' name='title' isRequired='1' precision='0' defaultValue='None' externalType='VARCHAR' width='40' scale='0' type='string' displayLabel='Title'/> ! <attribute isClassProperty='0' columnName='id' name='id' isRequired='1' precision='0' defaultValue='0' externalType='INT' width='0' scale='0' type='int' displayLabel=''/> <attribute isClassProperty='0' columnName='FK_WRITER_ID' name='FK_Writer_Id' isRequired='0' precision='0' defaultValue='None' externalType='INTEGER' width='0' scale='0' type='string' displayLabel=''/> <attribute isClassProperty='1' columnName='PRICE' name='price' isRequired='0' precision='10' defaultValue='None' externalType='NUMERIC' width='0' scale='2' type='float' displayLabel=''/> --- 26,30 ---- <attributesUsedForLocking attributeName='FK_Writer_Id'/> <attribute isClassProperty='1' columnName='title' name='title' isRequired='1' precision='0' defaultValue='None' externalType='VARCHAR' width='40' scale='0' type='string' displayLabel='Title'/> ! <attribute isClassProperty='1' columnName='id' name='id' isRequired='1' precision='0' defaultValue='0' externalType='INT' width='0' scale='0' type='int' displayLabel=''/> <attribute isClassProperty='0' columnName='FK_WRITER_ID' name='FK_Writer_Id' isRequired='0' precision='0' defaultValue='None' externalType='INTEGER' width='0' scale='0' type='string' displayLabel=''/> <attribute isClassProperty='1' columnName='PRICE' name='price' isRequired='0' precision='10' defaultValue='None' externalType='NUMERIC' width='0' scale='2' type='float' displayLabel=''/> |
From: <sbi...@us...> - 2003-03-27 11:48:01
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv15541/tests Modified Files: test_EditingContext_Global.py Log Message: Fixed: an newly inserted object with a PK attribute marked as class property did not get its value after EditingContext.saveChanges(). Details in: - EditingContext.handleNotification() - test_EC_Global.test_17_insertedObject_and_PK_as_classProperty() - testPackages.AuthorBooks: entity Book now has its PK 'id' set as class property Index: test_EditingContext_Global.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_EditingContext_Global.py,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** test_EditingContext_Global.py 14 Mar 2003 11:40:13 -0000 1.18 --- test_EditingContext_Global.py 27 Mar 2003 11:47:57 -0000 1.19 *************** *** 864,867 **** --- 864,877 ---- self.failIf(len(toManySnap)!=1) + def test_17_insertedObject_and_PK_as_classProperty(self): + "[EC] Checks that a PK/class prop. gets its value after saving changes" + ec=EditingContext() + b=Book() + b.setTitle('dummy title') + ec.insertObject(b) + ec.saveChanges() + gid=ec.globalIDForObject(b) + self.failUnless(b.getId() == gid.keyValues()['id']) + def test_999_customSQLQuery(self): "[EditingContext] customSQLQuery" |
From: <sbi...@us...> - 2003-03-27 11:48:01
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv15541 Modified Files: CHANGES EditingContext.py Log Message: Fixed: an newly inserted object with a PK attribute marked as class property did not get its value after EditingContext.saveChanges(). Details in: - EditingContext.handleNotification() - test_EC_Global.test_17_insertedObject_and_PK_as_classProperty() - testPackages.AuthorBooks: entity Book now has its PK 'id' set as class property Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.87 retrieving revision 1.88 diff -C2 -d -r1.87 -r1.88 *** CHANGES 17 Mar 2003 12:43:22 -0000 1.87 --- CHANGES 27 Mar 2003 11:47:57 -0000 1.88 *************** *** 8,11 **** --- 8,15 ---- -------------------------------------------------------- + * Fixed: an newly inserted object with a PK, say, 'id', marked as class + property did not get its value after EditingContext.saveChanges(). + [Details in: EditingContext.handleNotification()] + * Fixed SQLExpression.sqlStringForAttributeNamed(): now raises ValueError with an explicit message when it receives an invalid attribute's name Index: EditingContext.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/EditingContext.py,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** EditingContext.py 12 Mar 2003 15:45:54 -0000 1.21 --- EditingContext.py 27 Mar 2003 11:47:57 -0000 1.22 *************** *** 1361,1364 **** --- 1361,1390 ---- db=self.rootObjectStore().objectStoreForObject(obj).database() db.incrementSnapshotCountForGlobalID(key_gid) + + # Time to update the object if a PK is set as class properties + + # Note: One might say this could have been done earlier, e.g. in + # DatabaseContext.prepareForSaveWithCoordinator() where PK values + # are requested and assigned to the inserted objects + + # THIS IS INTENTIONAL: until finalizeCommitChanges() is called by + # the ObjectStoreCoordinator, we can't be sure that no exception + # will be raised in the process of saving changes. If an exception + # is actually raised, the transaction is rolled back and the object + # is not saved and as a consequence should NOT appear as if it + # received a valid PK value. + + # Now, since DBContext.finalizeCommitChanges() does notify the EC + # that inserted objects did receive a valid GlobalID (thus a valid + # PK value) after all changes were supplied and committed to the + # database, we know it is safe here to assign the inserted & saved + # object its PK value --if the PK is a class property, obviously! + + from ModelSet import defaultModelSet + entity=defaultModelSet().entityNamed(obj.entityName()) + pk_values=key_gid.keyValues() + for pk in entity.primaryKeyAttributes(): + if pk.isClassProperty(): + obj.takeStoredValueForKey(pk_values[pk.name()], pk.name()) else: obj=self.objectForGlobalID(gid) |
From: <ru...@us...> - 2003-03-21 20:24:10
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide In directory sc8-pr-cvs1:/tmp/cvs-serv8979/UserGuide Modified Files: FrameworkTypicalUsage.tex NestedEditingContext.tex Log Message: language corrections Index: FrameworkTypicalUsage.tex =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide/FrameworkTypicalUsage.tex,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** FrameworkTypicalUsage.tex 13 Mar 2003 18:01:30 -0000 1.4 --- FrameworkTypicalUsage.tex 21 Mar 2003 20:24:05 -0000 1.5 *************** *** 3,11 **** When writing an application using the framework, you normally do not care ! about any of its component except \class{EditingContext}s. ! An \class{EditingContext} is basically the place where your object lives, ! i.e. where they are inserted, fetched, deleted, or updated. This is an ! important object, like a container, holding your graph of objects as it gets changed, until the point where these changes are saved as a whole. --- 3,11 ---- When writing an application using the framework, you normally do not care ! about any of its components -- except \class{EditingContext}s. ! An \class{EditingContext} is the place where your objects live, ! i.e. where they are inserted, fetched, deleted, or updated. This ! important container holds your graph of objects as it gets changed, until the point where these changes are saved as a whole. *************** *** 14,18 **** pure-python application or within application servers like Zope or others. We suggest that you read the whole chapter, whatever your specific needs are: ! it contains important informations explaining how the framework reacts and how it can be used in standard situations. --- 14,18 ---- pure-python application or within application servers like Zope or others. We suggest that you read the whole chapter, whatever your specific needs are: ! it contains important information explaining how the framework reacts and how it can be used in standard situations. *************** *** 31,37 **** point of the process. See chapter~\ref{nested-editing-context} for details. ! \paragraph*{Python ''batches'':} if you're designing python scripts ! fetching and manipulating a lot of objects, please also read ! section~\ref{ec-discard-changes} which enlightens valuable details about finalization of an \class{EditingContext}. --- 31,37 ---- point of the process. See chapter~\ref{nested-editing-context} for details. ! \paragraph*{Python ''batches'':} if you're designing python scripts that ! fetch and manipulate a lot of objects, please also read ! section~\ref{ec-discard-changes} that gives valuable details about finalization of an \class{EditingContext}. *************** *** 48,52 **** application requires that an \class{EditingContext} is concurrently accessed by different threads, you have to make sure that you lock it before use (e.g., ! before saving changes) ; methods \method{lock()} and \method{unlock()} are provided for that purpose. Typical usage follows: \begin{verbatim} --- 48,52 ---- application requires that an \class{EditingContext} is concurrently accessed by different threads, you have to make sure that you lock it before use (e.g., ! before saving changes); methods \method{lock()} and \method{unlock()} are provided for that purpose. Typical usage follows: \begin{verbatim} *************** *** 69,73 **** managed by two different threads can concurrently save their changes to their parent without explictly locking it --this is managed automatically. This is ! worth noticing, even if this is logical since the framework is supposed to ensure that any operations made on an \class{EditingContext} is safe in a multi-threaded environment (given that the \class{EditingContext} is not --- 69,73 ---- managed by two different threads can concurrently save their changes to their parent without explictly locking it --this is managed automatically. This is ! worth noting, even if this is logical since the framework is supposed to ensure that any operations made on an \class{EditingContext} is safe in a multi-threaded environment (given that the \class{EditingContext} is not *************** *** 94,98 **** \end{enumerate} ! Each option has its counter-part ; some are inherently bound to what they are, some are due to specific features not being implemented yet. Let's look at the details. --- 94,98 ---- \end{enumerate} ! Each option has its drawbacks: some are inherently bound to what they are, some are due to specific features not being implemented yet. Let's look at the details. *************** *** 115,119 **** \class{EditingContext} in this case, see chapter~\ref{nested-editing-context}. For the same reason, the \class{EditingContext} used for registering and ! saving the modifications should not be shared by --- 115,119 ---- \class{EditingContext} in this case, see chapter~\ref{nested-editing-context}. For the same reason, the \class{EditingContext} used for registering and ! saving the modifications should not be shared by different users. *************** *** 122,126 **** up. The main problem with such an approach is that you will probably end up with all your objects being loaded in the shared \class{EditingContext} after ! some hours or days (depending on the number of hits your app. receives, the number of objects that a request can load, etc.). If your database is quite big and/or if it quickly grows, your application is likely to end with --- 122,126 ---- up. The main problem with such an approach is that you will probably end up with all your objects being loaded in the shared \class{EditingContext} after ! some hours or days (depending on the number of hits your application receives, the number of objects that a request can load, etc.). If your database is quite big and/or if it quickly grows, your application is likely to end with *************** *** 128,132 **** ! What happens here is you do not have any mean to distinguish between the objects loaded by session $S_1$ and objects loaded by session $S_2$ ; as a consequence you cannot clean up the shared \class{EditingContext} when a --- 128,132 ---- ! What happens here is you do not have any means to distinguish between the objects loaded by session $S_1$ and objects loaded by session $S_2$ ; as a consequence you cannot clean up the shared \class{EditingContext} when a *************** *** 143,157 **** \begin{notice} ! At some point in the future it is possible that we change our mind and support ! such a configuration. This is related to a feature which is not implemented ! yet ; it is possible that we support in the future a special attribute for you ! to specify how many (unchanged) objects you want an \class{EditingContext} to ! contain at most. Then, when the maximum number of objects is reached, it would be possible to automatically clean the \class{EditingContext} (the oldest object would be re-faulted/invalidated, or ''ghostified'' in ZODB ! jargon). ! ! There is no ETA for this feature however, it is just a TODO item. If you think ! you need the feature, please go ahead and let us know! \end{notice} --- 143,155 ---- \begin{notice} ! At some point in the future, with the implementation of the following ! feature described below, this negative recommendation may change: ! We may support a special attribute for you to specify the maximum ! number of (unchanged) objects you want an \class{EditingContext} to ! contain. Then, when the maximum number of objects is reached, it would be possible to automatically clean the \class{EditingContext} (the oldest object would be re-faulted/invalidated, or ''ghostified'' in ZODB ! jargon). There is no ETA for this feature however, it is just a TODO item. ! If you think you need the feature, please go ahead and let us know! \end{notice} *************** *** 182,188 **** \begin{quote} This is due to a feature missing in the framework, where changes to an ! EditingContext are not broadcasted to others. This is a TODO, highly ! prioritary, which is planned to be solved in the release after 0.9 (ETA: end ! of march 2003). \end{quote} --- 180,185 ---- \begin{quote} This is due to a feature missing in the framework, where changes to an ! EditingContext are not broadcasted to others. This is a TODO with high ! priority, planned to be solved in the release after 0.9. \end{quote} Index: NestedEditingContext.tex =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/doc/UserGuide/NestedEditingContext.tex,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** NestedEditingContext.tex 7 Mar 2003 17:59:57 -0000 1.3 --- NestedEditingContext.tex 21 Mar 2003 20:24:06 -0000 1.4 *************** *** 13,18 **** the modifications at any point in the sub-process. Most of the time, you also want all the changes made during these steps to be applied as a whole, ! or not at all--this is Atomicity. Now the question is: how can this be ! done? One possibility could be to use an other \EC. It might be suitable for very --- 13,17 ---- the modifications at any point in the sub-process. Most of the time, you also want all the changes made during these steps to be applied as a whole, ! or not at all--this is Atomicity. How can this be done? One possibility could be to use an other \EC. It might be suitable for very *************** *** 31,35 **** changes in the first \EC) that were made but not saved before the complex operation began. ! This, agains, is probably not what you would want. \end{itemize} --- 30,34 ---- changes in the first \EC) that were made but not saved before the complex operation began. ! This, again, is probably not what you would want. \end{itemize} *************** *** 60,64 **** A nested \EC\ is the solution for the problem. It provides a clean and ! handful way of making changes on an other \EC, while exposing three of the four ACID properties at the object level: --- 59,63 ---- A nested \EC\ is the solution for the problem. It provides a clean and ! convenient way of making changes on an other \EC, while exposing three of the four ACID properties at the object level: *************** *** 80,90 **** In other words, you can think of a nested EditingContext as a transaction made at the object level. ! ! Last, since a nested \EC\ uses its parent \EC as its parent object store, ! the objects you'll get when e.g. fetching will all reflect the state of ! the parent. For example, inserted objects will show up in the result set ! of a fetch, but deleted objects won't. Moreover, any object you will get in a nested \EC will reflect the changes made on it in its parent, even ! the uncommitted/unsaved ones. % Declaration --- 79,87 ---- In other words, you can think of a nested EditingContext as a transaction made at the object level. ! ! Moreover, any object you will get in a nested \EC will reflect the changes made on it in its parent, even ! the uncommitted/unsaved ones, e.g. inserted objects will show up in the ! result set of a fetch, but deleted objects won't. % Declaration *************** *** 171,175 **** \begin{description} \item[How to dynamically identify a nested \EC?] ! Simply invoke \method{parentObjectStore()} on it ; if the result is an another \EC, it is nested. Otherwise it is a regular \EC. \begin{verbatim} --- 168,172 ---- \begin{description} \item[How to dynamically identify a nested \EC?] ! Simply invoke \method{parentObjectStore()} on it ; if the result is another \EC, it is nested. Otherwise it is a regular \EC. \begin{verbatim} *************** *** 208,217 **** \section{Limitations with multiple child {\EC}s \label{nested-ec-limitations}} ! You may wonder how the child {\EC}s behave when changes in ! one of them is saved to its parent. The answer is, for now, quite simple: the other children won't notice anything. This leads to some ! problems, depending on their respective actions. - In practice, this means two important things: \begin{enumerate} --- 205,213 ---- \section{Limitations with multiple child {\EC}s \label{nested-ec-limitations}} ! You may wonder how child {\EC}s behave when changes in any ! one of them is saved to its parent. The answer, for now, is quite simple: the other children won't notice anything. This leads to some ! problems, depending on the changes affected in the child {\EC}: \begin{enumerate} |
From: <sbi...@us...> - 2003-03-17 12:53:32
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv16626 Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT CHANGES Log Message: tests.test_EditingContext_Global: added: test_17_fetchSpecWithSortOrderings(), test_18_fetchSpecWithFetchLimit() and updated the way the test-db 'AUTHOR_BOOKS' is generated: added prices for all books. Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.86.2.4 retrieving revision 1.86.2.5 diff -C2 -d -r1.86.2.4 -r1.86.2.5 *** CHANGES 17 Mar 2003 12:47:34 -0000 1.86.2.4 --- CHANGES 17 Mar 2003 12:53:28 -0000 1.86.2.5 *************** *** 8,12 **** -------------------------------------------------------- ! brch-0_9pre5-SQL_SortOrdering_and_LIMIT initiated (2002/03/17) --------------------------------------- --- 8,12 ---- -------------------------------------------------------- ! brch-0_9pre5-SQL_SortOrdering_and_LIMIT initiated 2002/03/17 --------------------------------------- *************** *** 18,22 **** --- 18,27 ---- - FetchSpecification.setFetchSlice(), making it possible to fetch a certain limited number of objects at a time. + + * tests.test_EditingContext_Global: added: + test_17_fetchSpecWithSortOrderings(), test_18_fetchSpecWithFetchLimit() + and updated the way the test-db 'AUTHOR_BOOKS' is generated: added prices + for all books. * MySQL/PostgresqlSQLExpression: added support for fetch slices, implemented |
From: <sbi...@us...> - 2003-03-17 12:53:32
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/tests In directory sc8-pr-cvs1:/tmp/cvs-serv16626/tests Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT test_EditingContext_Global.py Log Message: tests.test_EditingContext_Global: added: test_17_fetchSpecWithSortOrderings(), test_18_fetchSpecWithFetchLimit() and updated the way the test-db 'AUTHOR_BOOKS' is generated: added prices for all books. Index: test_EditingContext_Global.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/tests/test_EditingContext_Global.py,v retrieving revision 1.18 retrieving revision 1.18.2.1 diff -C2 -d -r1.18 -r1.18.2.1 *** test_EditingContext_Global.py 14 Mar 2003 11:40:13 -0000 1.18 --- test_EditingContext_Global.py 17 Mar 2003 12:53:29 -0000 1.18.2.1 *************** *** 763,767 **** "[EditingContext] objectsWithFetchSpec. & NULL value" ## Note: this used to fail w/ MySQL, cf bug #614261 ! q=qualifierWithQualifierFormat('author.pygmalion.books.price == NULL"') fs=FetchSpecification('Book', qualifier=q) ec=EditingContext() --- 763,767 ---- "[EditingContext] objectsWithFetchSpec. & NULL value" ## Note: this used to fail w/ MySQL, cf bug #614261 ! q=qualifierWithQualifierFormat('author.pygmalion.books.price != NULL"') fs=FetchSpecification('Book', qualifier=q) ec=EditingContext() *************** *** 863,867 **** #print toManySnap self.failIf(len(toManySnap)!=1) ! def test_999_customSQLQuery(self): "[EditingContext] customSQLQuery" --- 863,943 ---- #print toManySnap self.failIf(len(toManySnap)!=1) ! ! def test_17_fetchSpecWithSortOrderings(self): ! "[EditingContext] fetchSpec w/ SortOrderings" ! q=qualifierWithQualifierFormat('author.lastName != NULL"') ! fs=FetchSpecification('Book', q) ! from Modeling.SortOrdering import \ ! SortOrdering, compareDescending, compareCaseInsensitiveAscending ! so0=SortOrdering('author.lastName', compareDescending) ! so1=SortOrdering('price', compareDescending) ! so2=SortOrdering('title', compareCaseInsensitiveAscending) ! fs.setSortOrderings([so0, so1, so2]) ! ec=EditingContext() ! objs=ec.objectsWithFetchSpecification(fs) ! titles=[o.getTitle() for o in objs] ! self.assertEqual(titles[1], "T'assieds pas sur le compte-gouttes") ! self.assertEqual(titles[0], "Gargantua") ! self.assertEqual(titles[2], "Le coup du pere Francois") ! self.assertEqual(titles[3], "Bouge ton pied que je voie la mer") ! ! def test_18_fetchSpecWithFetchLimit(self): ! "[EditingContext] fetchSpec w/ FetchLimit" ! q=qualifierWithQualifierFormat('author.lastName != NULL"') ! fs=FetchSpecification('Book', q) ! from Modeling.SortOrdering import \ ! SortOrdering, compareAscending, compareCaseInsensitiveAscending ! so1=SortOrdering('id', compareAscending) ! fs.setSortOrderings([so1]) ! fs.setFetchLimit(2) ! ec=EditingContext() ! objs=ec.objectsWithFetchSpecification(fs) ! self.failUnless(len(objs)==2) ! ! titles=[o.getTitle() for o in objs] ! self.assertEqual(titles[0], "Gargantua") ! self.assertEqual(titles[1], "Bouge ton pied que je voie la mer") ! ! # w/ offset ! fs.setFetchSlice(2, offset=2) ! objs=ec.objectsWithFetchSpecification(fs) ! self.failUnless(len(objs)==2) ! titles=[o.getTitle() for o in objs] ! self.assertEqual(titles[0], "Le coup du pere Francois") ! self.assertEqual(titles[1], "T'assieds pas sur le compte-gouttes") ! ! self.assertRaises(ValueError, fs.getPreviousSlice) # no page set ! ! # w/ page ! fs.setFetchSlice(2, page=1) ! objs=ec.objectsWithFetchSpecification(fs) ! self.failUnless(len(objs)==2) ! titles=[o.getTitle() for o in objs] ! self.assertEqual(titles[0], "Gargantua") ! self.assertEqual(titles[1], "Bouge ton pied que je voie la mer") ! ! self.assertRaises(ValueError, fs.getPreviousSlice) # Already at page 1 ! # getNextSlice ! fs.getNextSlice() ! objs=ec.objectsWithFetchSpecification(fs) ! self.failUnless(len(objs)==2) ! titles=[o.getTitle() for o in objs] ! self.assertEqual(titles[0], "Le coup du pere Francois") ! self.assertEqual(titles[1], "T'assieds pas sur le compte-gouttes") ! ! # next page is empty ! fs.getNextSlice() ! objs=ec.objectsWithFetchSpecification(fs) ! self.failUnless(len(objs)==0) ! ! # go for the previous one, once again (tests getPreviousSlice()) ! fs.getPreviousSlice() ! objs=ec.objectsWithFetchSpecification(fs) ! self.failUnless(len(objs)==2) ! titles=[o.getTitle() for o in objs] ! self.assertEqual(titles[0], "Le coup du pere Francois") ! self.assertEqual(titles[1], "T'assieds pas sur le compte-gouttes") ! ! def test_999_customSQLQuery(self): "[EditingContext] customSQLQuery" *************** *** 962,981 **** bookPKs=[pk.values()[0] for pk in bookPKs] sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id) "\ ! "values (%i,'Gargantua',%i)"%(bookPKs[0], pks[1])) channel.evaluateExpression(sqlExpr) sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id) "\ ! "values (%i,'Bouge ton pied que je voie la mer',%i)"%\ ! (bookPKs[1], pks[2])) channel.evaluateExpression(sqlExpr) sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id) "\ ! "values (%i,'Le coup du pere Francois',%i)"%\ (bookPKs[2], pks[2])) channel.evaluateExpression(sqlExpr) sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id) "\ ! "values(%i,'T\'\'assieds pas sur le compte-gouttes',%i)"% (bookPKs[3], pks[2])) channel.evaluateExpression(sqlExpr) #Fautil tuer les petits garçons qui ont les mains sur les hanches ? --- 1038,1056 ---- bookPKs=[pk.values()[0] for pk in bookPKs] sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id, price) "\ ! "values (%i,'Gargantua',%i,9.50)"%(bookPKs[0], pks[1])) channel.evaluateExpression(sqlExpr) sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id, price) "\ ! "values (%i,'Bouge ton pied que je voie la mer',%i,8.0)"%(bookPKs[1], pks[2])) channel.evaluateExpression(sqlExpr) sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id, price) "\ ! "values (%i,'Le coup du pere Francois',%i,9.49)"%\ (bookPKs[2], pks[2])) channel.evaluateExpression(sqlExpr) sqlExpr.setStatement("insert into BOOK "\ ! "(id, title, fk_writer_id, price) "\ ! "values(%i,'T\'\'assieds pas sur le compte-gouttes',%i,10)"% (bookPKs[3], pks[2])) channel.evaluateExpression(sqlExpr) #Fautil tuer les petits garçons qui ont les mains sur les hanches ? |
From: <sbi...@us...> - 2003-03-17 12:47:38
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer In directory sc8-pr-cvs1:/tmp/cvs-serv14304/DatabaseAdaptors/MySQLAdaptorLayer Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT MySQLSQLExpression.py Log Message: MySQL/PostgresqlAdaptorLayers: SQLExpression: added support for fetch slices, implemented limitString() Index: MySQLSQLExpression.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/DatabaseAdaptors/MySQLAdaptorLayer/MySQLSQLExpression.py,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -C2 -d -r1.4 -r1.4.2.1 *** MySQLSQLExpression.py 8 Mar 2003 16:21:01 -0000 1.4 --- MySQLSQLExpression.py 17 Mar 2003 12:47:35 -0000 1.4.2.1 *************** *** 44,47 **** --- 44,64 ---- available SQL data types. """ + def limitString(self): + """ + Returns LIMIT [<offset>,]<limit> + + where <limit> and <offset> are the values of the dictionary returned by + SQLExpression.fetchLimit() + + The 'offset' part of the string is not included if offset is zero. + """ + slice=self.fetchSlice() + if tuple(slice.values())!=(0,0): + if not slice['offset']: + return 'LIMIT %(limit)s'%slice + else: + return 'LIMIT %(offset)s,%(limit)s'%slice + return '' + def valueTypeForExternalTypeMapping(self): """ |
From: <sbi...@us...> - 2003-03-17 12:47:38
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv14304 Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT CHANGES Log Message: MySQL/PostgresqlAdaptorLayers: SQLExpression: added support for fetch slices, implemented limitString() Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.86.2.3 retrieving revision 1.86.2.4 diff -C2 -d -r1.86.2.3 -r1.86.2.4 *** CHANGES 17 Mar 2003 12:44:21 -0000 1.86.2.3 --- CHANGES 17 Mar 2003 12:47:34 -0000 1.86.2.4 *************** *** 20,23 **** --- 20,26 ---- + * MySQL/PostgresqlSQLExpression: added support for fetch slices, implemented + limitString() + * SQLExpression: added support for FetchSpecification's sortOrderings() and fetchSlice() -- support for fetchSlice() depends on limitString() which |
From: <sbi...@us...> - 2003-03-17 12:47:38
|
Update of /cvsroot/modeling/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer In directory sc8-pr-cvs1:/tmp/cvs-serv14304/DatabaseAdaptors/PostgresqlAdaptorLayer Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT PostgresqlSQLExpression.py Log Message: MySQL/PostgresqlAdaptorLayers: SQLExpression: added support for fetch slices, implemented limitString() Index: PostgresqlSQLExpression.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/DatabaseAdaptors/PostgresqlAdaptorLayer/PostgresqlSQLExpression.py,v retrieving revision 1.1 retrieving revision 1.1.2.1 diff -C2 -d -r1.1 -r1.1.2.1 *** PostgresqlSQLExpression.py 28 Jan 2003 18:15:34 -0000 1.1 --- PostgresqlSQLExpression.py 17 Mar 2003 12:47:34 -0000 1.1.2.1 *************** *** 43,46 **** --- 43,63 ---- """ + def limitString(self): + """ + Returns LIMIT <limit> [OFFSET <offset>] + + where <limit> and <offset> are the values of the dictionary returned by + SQLExpression.fetchLimit() + + The 'OFFSET' part of the string is not included if offset is zero. + """ + slice=self.fetchSlice() + if tuple(slice.values())!=(0,0): + if not slice['offset']: + return 'LIMIT %(limit)s'%slice + else: + return 'LIMIT %(limit)s OFFSET %(offset)s'%slice + return '' + def valueTypeForExternalTypeMapping(self): """ |
From: <sbi...@us...> - 2003-03-17 12:44:25
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv12693 Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT CHANGES SQLExpression.py Log Message: SQLExpression: added support for FetchSpecification's sortOrderings() and fetchSlice() -- support for fetchSlice() depends on limitString() which has no default implementation and should be implemented by concrete AdaptorLayers willing to support it. Added: fetchSlice, limitString, setFetchSlice, Modified: __init__, addOrderByAttributeOrdering, assembleSelectStatementWithAttributes, orderByString, _prepareSelectExpressionWithAttributes, Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.86.2.2 retrieving revision 1.86.2.3 diff -C2 -d -r1.86.2.2 -r1.86.2.3 *** CHANGES 17 Mar 2003 12:32:06 -0000 1.86.2.2 --- CHANGES 17 Mar 2003 12:44:21 -0000 1.86.2.3 *************** *** 20,23 **** --- 20,32 ---- + * SQLExpression: added support for FetchSpecification's sortOrderings() and + fetchSlice() -- support for fetchSlice() depends on limitString() which + has no default implementation and should be implemented by concrete + AdaptorLayers willing to support it. + Added: fetchSlice, limitString, setFetchSlice, + Modified: __init__, addOrderByAttributeOrdering, + assembleSelectStatementWithAttributes, orderByString, + _prepareSelectExpressionWithAttributes, + * FetchSpecification: added (set)fetchSlice(), getNext/PreviousSlice() Index: SQLExpression.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/SQLExpression.py,v retrieving revision 1.16 retrieving revision 1.16.2.1 diff -C2 -d -r1.16 -r1.16.2.1 *** SQLExpression.py 14 Mar 2003 11:40:10 -0000 1.16 --- SQLExpression.py 17 Mar 2003 12:44:21 -0000 1.16.2.1 *************** *** 259,263 **** --- 259,265 ---- """ self._entity=anEntity + self._fetchSlice={'limit':0, 'offset':0} self._listString=StringIO() + self._orderByString=StringIO() self._valueList=StringIO() self._statement='' *************** *** 327,333 **** """ ! def addOrderByAttributeOrdering(self, sortOrdering): """ """ def addSelectListAttribute(self, attribute): --- 329,368 ---- """ ! def addOrderByAttributeOrdering(self, aSortOrdering): """ + + Parameter: + + aSortOrdering -- instance of SortOrdering + + Raises ValueError if aSortOrdering references an invalid key/keypath + + See also: orderByString(), + prepareSelectExpressionWithAttributes(), + sqlStringForAttributeNamed(), appendItemToListString(), + SortOrdering """ + from SortOrdering import \ + compareAscending, compareDescending,\ + compareCaseInsensitiveAscending, compareCaseInsensitiveDescending + + operator=aSortOrdering.operator() + if operator in (compareDescending, compareCaseInsensitiveDescending): + order='DESC' + else: + order='ASC' + + try: + attr=self.sqlStringForAttributeNamed(aSortOrdering.key()) + except ValueError: + raise ValueError, "The FetchSpecification has a SortOrdering referencing attribute '%s' but this attribute cannot be found"%(aSortOrdering.key(),) + + if operator in (compareCaseInsensitiveDescending, + compareCaseInsensitiveAscending): + orderStr='UPPER(%s) '%attr + else: + orderStr='(%s) '%attr + orderStr+=order + self.appendItemToListString(orderStr, self._orderByString) def addSelectListAttribute(self, attribute): *************** *** 476,480 **** columnList, tableList, whereClause, joinClause, orderByClause, ! lockClause): """ """ --- 511,515 ---- columnList, tableList, whereClause, joinClause, orderByClause, ! lockClause, limitClause): """ """ *************** *** 491,494 **** --- 526,533 ---- if orderByClause: statement+=' ORDER BY '+orderByClause + + if limitClause: + statement += ' '+limitClause + self._statement=statement *************** *** 578,581 **** --- 617,627 ---- __unimplemented__() + def fetchSlice(self): + """ + + See also: setFetchSlice(), FetchSpecification.fetchSlice() + """ + return self._fetchSlice + def formatSQLString(self, sqlString, format): """ *************** *** 637,640 **** --- 683,700 ---- __unimplemented__() + def limitString(self): + """ + Returns the SQL statement to be used to reflect + FetchSpecification.fetchSlice() in a SELECT statement + + By default the framework does not offer any support for this. It may or + may not be implemented by a given AdaptorLayer (those for Postgresql and + MySQL support the feature). + + """ + if self.fetchSlice()!={'limit':0, 'offset':0}: + raise NotImplementedError, 'You probably supplied a FetchSpecification where fetchSlice() is set, but the framework does not offer any default implementation for this. It is likely that the adaptor layer you are currently using does not support this feature ; please refer to its documenntation for more details' + return '' + def listString(self): """ *************** *** 664,669 **** def orderByString(self): """ """ ! __unimplemented__() def prepareConstraintStatementForRelationship(self, relationship, sourceColumns, destinationColumns): --- 724,736 ---- def orderByString(self): """ + Returns the part of the SQL statement used to order the result set. The + returned string only contains the SQL attribute and the corresponding + sorting scheme (ascending/descending, it is NOT prepended by the usual + 'ORDER BY' statement. + + See also: addOrderByAttributeOrdering(), + assembleSelectStatementWithAttributes() """ ! return self._orderByString.getvalue() def prepareConstraintStatementForRelationship(self, relationship, sourceColumns, destinationColumns): *************** *** 681,685 **** - the use of aliases is disabled (see setUseAliases()) ! - the whereClauseString() is compuuted ans set by calling 'sqlStringForQualifier(aQualifier)' on itself, --- 748,752 ---- - the use of aliases is disabled (see setUseAliases()) ! - the whereClauseString() is computed and set by calling 'sqlStringForQualifier(aQualifier)' on itself, *************** *** 741,744 **** --- 808,813 ---- prepareSelectExpressionWithAttributes(). + The object's fetchSlice() receives fetchSpec.fetchSlice() + Parameters: *************** *** 788,793 **** fetchOrder=None whereClause=self.whereClauseString() # orderBy: see fetchSpec... ! orderByClause='' if count: --- 857,871 ---- fetchOrder=None whereClause=self.whereClauseString() + + # LIMIT + ## TBD LIMIT: if limit -> add SortingOrdering('id',compareAscending) + ## TBD LIMIT: if isDeep=1 --> error + if fetchSpec: + self.setFetchSlice(fetchSpec.fetchSlice()) + # orderBy: see fetchSpec... ! for so in fetchSpec and fetchSpec.sortOrderings() or (): ! self.addOrderByAttributeOrdering(so) ! orderByClause=self.orderByString() if count: *************** *** 795,799 **** else: columnList=self.listString() ! self.assembleSelectStatementWithAttributes(attributes=attributes, lock=lock, --- 873,879 ---- else: columnList=self.listString() ! ! limitClause=self.limitString() ! self.assembleSelectStatementWithAttributes(attributes=attributes, lock=lock, *************** *** 806,810 **** joinClause=joinClause, orderByClause=orderByClause, ! lockClause=lockClause) --- 886,891 ---- joinClause=joinClause, orderByClause=orderByClause, ! lockClause=lockClause, ! limitClause=limitClause) *************** *** 851,854 **** --- 932,948 ---- updateList, self.whereClauseString()) + def setFetchSlice(self, slice): + """ + + Parameter: + + slice -- a mapping with both keys 'limit' and 'offset' + + See also: fetchSlice(), FetchSpecification.fetchSlice() + """ + if 'limit' not in slice.keys() or 'offset' not in slice.keys(): + raise ValueError, "Parameter slice should have keys 'limit' and 'offset'" + self._fetchSlice=slice + def setStatement(self, statement): """ *************** *** 945,948 **** --- 1039,1044 ---- description of what 'building the path' means). + Raises ValueError in case 'name' is not a valid attribute's name. + See also: sqlStringForAttribute, sqlStringForAttributePath() Attribute.isFlattened(), Attribute.relationshipPathObjects(), *************** *** 954,957 **** --- 1050,1055 ---- attribute=self.entity().attributeNamed(name) + if not attribute: + raise ValueError, "Unknown attribute '%s' for entity '%s'"%(name, self.entity().name()) if attribute.isDerived() and not attribute.isFlattened(): raise ValueError, "Error: attribute %s shouldn't be derived"%name |
From: <sbi...@us...> - 2003-03-17 12:43:25
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv12320 Modified Files: SQLExpression.py CHANGES Log Message: Fixed SQLExpression.sqlStringForAttributeNamed(): now raises ValueError with an explicit message when it receives an invalid attribute's name Index: SQLExpression.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/SQLExpression.py,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** SQLExpression.py 14 Mar 2003 11:40:10 -0000 1.16 --- SQLExpression.py 17 Mar 2003 12:43:21 -0000 1.17 *************** *** 945,948 **** --- 945,950 ---- description of what 'building the path' means). + Raises ValueError in case 'name' is not a valid attribute's name. + See also: sqlStringForAttribute, sqlStringForAttributePath() Attribute.isFlattened(), Attribute.relationshipPathObjects(), *************** *** 954,957 **** --- 956,961 ---- attribute=self.entity().attributeNamed(name) + if not attribute: + raise ValueError, "Unknown attribute '%s' for entity '%s'"%(name, self.entity().name()) if attribute.isDerived() and not attribute.isFlattened(): raise ValueError, "Error: attribute %s shouldn't be derived"%name Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.86 retrieving revision 1.87 diff -C2 -d -r1.86 -r1.87 *** CHANGES 17 Mar 2003 11:53:49 -0000 1.86 --- CHANGES 17 Mar 2003 12:43:22 -0000 1.87 *************** *** 8,11 **** --- 8,15 ---- -------------------------------------------------------- + * Fixed SQLExpression.sqlStringForAttributeNamed(): now raises ValueError + with an explicit message when it receives an invalid attribute's name + + 0.9-pre-5 (2002/03/17) Project milestone -- no public release --------- |
From: <sbi...@us...> - 2003-03-17 12:32:09
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv8527 Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT FetchSpecification.py CHANGES Log Message: FetchSpecification: added (set)fetchSlice(), getNext/PreviousSlice() Index: FetchSpecification.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/FetchSpecification.py,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -C2 -d -r1.4 -r1.4.2.1 *** FetchSpecification.py 14 Mar 2003 11:40:08 -0000 1.4 --- FetchSpecification.py 17 Mar 2003 12:32:05 -0000 1.4.2.1 *************** *** 45,49 **** __implements__ = (IFetchSpecification,) ! def __init__(self, entityName, qualifier=None, sortOrderings=(), distinctFlag=0, deepFlag=0, hints={}): "Initializes the FetchSpecification" --- 45,49 ---- __implements__ = (IFetchSpecification,) ! def __init__(self, entityName, qualifier=None, sortOrderings=None, distinctFlag=0, deepFlag=0, hints={}): "Initializes the FetchSpecification" *************** *** 56,59 **** --- 56,62 ---- self.setIsDeep(deepFlag) self._fetchLimit=0 + self._fetchOffset=0 + self._currentPage=0 + #self._sortOrderings=() self._refreshesRefreshedObject=0 *************** *** 69,72 **** --- 72,92 ---- return self._fetchLimit + def fetchSlice(self): + return {'limit':self._fetchLimit, 'offset': self._fetchOffset} + + def getPreviousSlice(self): + if not self._currentPage: + raise ValueError, 'No page was previously set' + if self._currentPage==1: + raise ValueError, 'Already at page one' + self._currentPage-=1 + self.setFetchSlice(self._fetchLimit, page=self._currentPage) + + def getNextSlice(self): + if not self._currentPage: + raise ValueError, 'No page was previously set' + self._currentPage+=1 + self.setFetchSlice(self._fetchLimit, page=self._currentPage) + def isDeep(self): return self._isDeep *************** *** 85,91 **** def setFetchLimit(self, limit): ! assert(limit>=0) ! self._fetchLimit=limit def setIsDeep(self, deepFlag): self._isDeep=toBoolean(deepFlag) --- 105,130 ---- def setFetchLimit(self, limit): ! self.setFetchSlice(limit, offset=0) + __sFS_marker=[] + def setFetchSlice(self, limit, offset=__sFS_marker, page=__sFS_marker): + # Check arguments + if offset and page: + raise ValueError, 'Parameters offset and page are mutually exclusive' + if limit<0: + raise ValueError, 'limit should be a positive integer' + if offset and offset<0: + raise ValueError, 'offset should be a positive integer' + if page and page<=0: + raise ValueError, 'page should be a strictly positive integer' + + # back to real work + self._fetchLimit=limit + if offset is not self.__sFS_marker: + self._fetchOffset=offset + elif page is not self.__sFS_marker: + self._currentPage=page + self._fetchOffset=limit*(page-1) + def setIsDeep(self, deepFlag): self._isDeep=toBoolean(deepFlag) *************** *** 112,116 **** def sortOrderings(self): ! return self._sortOrderings def usesDistinct(self): --- 151,155 ---- def sortOrderings(self): ! return self._sortOrderings or () def usesDistinct(self): Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.86.2.1 retrieving revision 1.86.2.2 diff -C2 -d -r1.86.2.1 -r1.86.2.2 *** CHANGES 17 Mar 2003 12:28:47 -0000 1.86.2.1 --- CHANGES 17 Mar 2003 12:32:06 -0000 1.86.2.2 *************** *** 19,22 **** --- 19,25 ---- certain limited number of objects at a time. + + * FetchSpecification: added (set)fetchSlice(), getNext/PreviousSlice() + 0.9-pre-5 (2002/03/17) Project milestone -- no public release |
From: <sbi...@us...> - 2003-03-17 12:28:50
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv7188/Modeling Modified Files: Tag: brch-0_9pre5-SQL_SortOrdering_and_LIMIT CHANGES Log Message: Info for branch brch-0_9pre5-SQL_SortOrdering_and_LIMIT Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.86 retrieving revision 1.86.2.1 diff -C2 -d -r1.86 -r1.86.2.1 *** CHANGES 17 Mar 2003 11:53:49 -0000 1.86 --- CHANGES 17 Mar 2003 12:28:47 -0000 1.86.2.1 *************** *** 7,10 **** --- 7,22 ---- * ** Distributed under the GNU General Public License ** -------------------------------------------------------- + + brch-0_9pre5-SQL_SortOrdering_and_LIMIT initiated (2002/03/17) + --------------------------------------- + + Goal: offer a support for + + - generating SQL SELECT statements taking + FetchSpecification.sortOrderings() into account, + + - FetchSpecification.setFetchSlice(), making it possible to fetch a + certain limited number of objects at a time. + 0.9-pre-5 (2002/03/17) Project milestone -- no public release |
From: <sbi...@us...> - 2003-03-17 11:53:55
|
Update of /cvsroot/modeling/ProjectModeling/Modeling In directory sc8-pr-cvs1:/tmp/cvs-serv26029/Modeling Modified Files: CHANGES Log Message: Release 0.9-pre-5 / Project milestone, no public release Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/Modeling/CHANGES,v retrieving revision 1.85 retrieving revision 1.86 diff -C2 -d -r1.85 -r1.86 *** CHANGES 17 Mar 2003 11:15:12 -0000 1.85 --- CHANGES 17 Mar 2003 11:53:49 -0000 1.86 *************** *** 3,11 **** Module Modeling --------------- ! Current release is: 0.9-pre-4 / See also: TODO, INSTALL and doc/ * ** Distributed under the GNU General Public License ** -------------------------------------------------------- * Attribute: fixed defaultValueAsPythonStatement() and convertStringToAttributeType(): they were failing to operate properly --- 3,14 ---- Module Modeling --------------- ! Current release is: 0.9-pre-5 / See also: TODO, INSTALL and doc/ * ** Distributed under the GNU General Public License ** -------------------------------------------------------- + 0.9-pre-5 (2002/03/17) Project milestone -- no public release + --------- + * Attribute: fixed defaultValueAsPythonStatement() and convertStringToAttributeType(): they were failing to operate properly |
From: <sbi...@us...> - 2003-03-17 11:53:55
|
Update of /cvsroot/modeling/ProjectModeling In directory sc8-pr-cvs1:/tmp/cvs-serv26029 Modified Files: setup.py Log Message: Release 0.9-pre-5 / Project milestone, no public release Index: setup.py =================================================================== RCS file: /cvsroot/modeling/ProjectModeling/setup.py,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** setup.py 14 Mar 2003 09:42:56 -0000 1.20 --- setup.py 17 Mar 2003 11:53:49 -0000 1.21 *************** *** 46,50 **** setup(name="ModelingCore", ! version="0.9-pre-4", licence ="GNU General Public License", description=short_description, --- 46,50 ---- setup(name="ModelingCore", ! version="0.9-pre-5", licence ="GNU General Public License", description=short_description, |