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,
|