modeling-users Mailing List for Object-Relational Bridge for python (Page 18)
Status: Abandoned
Brought to you by:
sbigaret
You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
(3) |
Oct
|
Nov
|
Dec
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(19) |
Feb
(55) |
Mar
(54) |
Apr
(48) |
May
(41) |
Jun
(40) |
Jul
(156) |
Aug
(56) |
Sep
(90) |
Oct
(14) |
Nov
(41) |
Dec
(32) |
| 2004 |
Jan
(6) |
Feb
(57) |
Mar
(38) |
Apr
(23) |
May
(3) |
Jun
(40) |
Jul
(39) |
Aug
(82) |
Sep
(31) |
Oct
(14) |
Nov
|
Dec
(9) |
| 2005 |
Jan
|
Feb
(4) |
Mar
(13) |
Apr
|
May
(5) |
Jun
(2) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2006 |
Jan
(1) |
Feb
(1) |
Mar
(9) |
Apr
(1) |
May
|
Jun
(1) |
Jul
(5) |
Aug
|
Sep
(5) |
Oct
(1) |
Nov
|
Dec
|
| 2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(2) |
Nov
(1) |
Dec
|
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Mario R. <ma...@ru...> - 2003-12-04 09:43:31
|
Hi, two small questions that I do not remember/find the answer for... Can anyone remind me: - how to best incorporate a constraint that a (non-primary, string) attribute value should be unique ? - how to best handle enumeration attributes ? - how to best handle the single quote character when writing out string values ? (unescaped gives error for sqlite) Cheers, mario |
|
From: Mario R. <ma...@ru...> - 2003-12-04 05:59:33
|
> Mario Ruggier <ma...@ru...> wrote:
>> [...]
>> This reminds me of a problem that I meant to report though:
>> - I create an object with a date attribute (value for attribute set
>> with
>> mx.DateTime.now()), but without doing ec.saveChanges()
>> - then if I fetch the object with
>> ec.fetch('MyClass',
>> qualifier = 'createdate=="%s"' %(myObject.getDateattr()) )
>> the fetch does not return the newly created object.
>> This may be a bug, but I can confirm after playing with it further.
>
> This would help if you had a working test case, yes ;)
Fair enough ;)
I have made a simple object with just a DateTime attribute,
so in the pymodel it looks like :
Entity('MyObj',
properties=[
ADateTime('createdate',displayLabel='Date',isRequired=1),
]
)
Then I made the following test that uses it:
def test_0_FetchUnSavedDateTime(self):
ec = EditingContext()
o = MyObj()
test_datetime = mx.DateTime.now()
q = 'createdate=="%s"' %(test_datetime)
o.setCreatedate(test_datetime)
ec.insert(o)
ec.saveChanges()
print test_datetime,
print ec.fetch('MyObj',qualifier=q)[0]
o2 = MyObj()
test_datetime2 = mx.DateTime.now()
q2 = 'createdate=="%s"' %(test_datetime2)
o2.setCreatedate(test_datetime2)
ec.insert(o2)
#ec.saveChanges()
print test_datetime2,
print ec.fetch('MyObj',qualifier=q2)[0]
The first fetch is OK, the second is not.
This is with SQLite and Modleing CVS.
Cheers, mario
|
|
From: Sebastien B. <sbi...@us...> - 2003-12-02 17:16:14
|
Mario Ruggier <ma...@ru...> wrote:
> [...]
> This reminds me of a problem that I meant to report though:
> - I create an object with a date attribute (value for attribute set with
> mx.DateTime.now()), but without doing ec.saveChanges()
> - then if I fetch the object with
> ec.fetch('MyClass',
> qualifier =3D 'createdate=3D=3D"%s"' %(myObject.getDateattr()=
) )
> the fetch does not return the newly created object.
> This may be a bug, but I can confirm after playing with it further.
This would help if you had a working test case, yes ;)=20
-- S=E9bastien.
|
|
From: Sebastien B. <sbi...@us...> - 2003-12-02 17:13:10
|
Hi,
It was not clear to me why this was not working for you until I realized
that the following statement:
>>> ec.fetch('Writer', "birthday>1970-01-01 00:00:00.00")
leads exactly to what you describe (libpq.OperationalError:ERROR: bad
timestamp external representation '1970'). You've found a bug here, the
QualifierPaser has not detected that the qualifier string you passed to it
has a syntax error.
Those two are correct, however, and should work as you expect:
ec.fetch('Writer', 'birthday>"1970-01-01 00:00:00.00"')
ec.fetch('Writer', 'birthday>"%s"' % str(DateTime(1970,01,01)))
--and yes, this is a limitation of the parser, it only accepts double quo=
tes
around strings in qualifiers.
Hopefully this solves the problem. If you still have difficulties, please
tell. And thanks for reporting, I'll try to correct the bug in the parser f=
or
the next release.
-- S=E9bastien.
|
|
From: Mario R. <ma...@ru...> - 2003-12-01 17:16:32
|
Hi Lukasz,
not clear to me why you are concatenating the qualifer string the
way you are. Using mx.DateTime for date fields, I can then do this
in my qualifier to include a condition on the date value of the table
column "createdate" for the fetch:
q_part_whatever =3D ' ... '
q_date =3D 'createdate<"%s"' %(customObject.getCreatedate())
qualifier =3D ' AND '.join([ q_part_whatever, q_date])
This works. Not sure if there is a nicer way to do it though.
This reminds me of a problem that I meant to report though:
- I create an object with a date attribute (value for attribute set with
mx.DateTime.now()), but without doing ec.saveChanges()
- then if I fetch the object with
ec.fetch('MyClass',
qualifier =3D 'createdate=3D=3D"%s"' =
%(myObject.getDateattr()) )
the fetch does not return the newly created object.
This may be a bug, but I can confirm after playing with it further.
Cheers, mario
> Hi
>
> I've got some problem with conditions that using dates. The following
> examlple shows this.
>
> ERD:
> MaWychowawce
> Klasa|<<--------------->|Nauczyciel
> -----| |------------
> |attr: DataUrodzenia
>
> code:
> ---------------------------------------------------------------------
> warunek=3D'MaWychowawce.DataUrodzenia > '+str(DateTime(1970,1,1))
> print warunek
> klasy=3DEC.fetch('Klasa',qualifier=3Dwarunek)
> ---------------------------------------------------------------------
>
> Printed qualifier look like this: MaWychowawce.DataUrodzenia > =20
> 1970-01-01
> 00:00:00.00
> I've tried with: MaWychowawce.DataUrodzenia > '1970-01-01 00:00:00.00' =
=20
> but
> it also didn't work
> Conditions on another attributes in 'Nauczyciel' works perfectly.
>
> error
> ---------------------------------------
> Couldn't evaluate expression SELECT DISTINCT t0.KLASA_ID, t0.NAZWA,
> t0.PROFIL, t0.WYCHOWAWCA_ID FROM KLASA t0 INNER JOIN NAUCZYCIEL t1 ON
> t0.WYCHOWAWCA_ID=3Dt1.NAUCZYCIEL_ID WHERE t1.DATA_URODZENIA > '1970'. =20=
> Reason:
> libpq.OperationalError:ERROR: bad timestamp external representation =20=
> '1970'
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File "Baza.py", line 45, in PobierzDane
> klasy=3DEC.fetch('Klasa',qualifier=3Dwarunek)
> File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EditingContext.py", line =20=
> 1419, in
> fetch
> return self.objectsWithFetchSpecification(fs)
> File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EditingContext.py", line =20=
> 1302, in
> objectsWithFetchSpecification
> objects=3Dself.parentObjectStore().objectsWithFetchSpecification(fs,=
=20
> ec)
> File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\ObjectStoreCoordinator.py", =
=20
> line
> 434, in objectsWithFetchSpecification
> return store.objectsWithFetchSpecification(aFetchSpecification,
> anEditingContext)
> File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseContext.py", line =20=
> 1817,
> in objectsWithFetchSpecification
> anEditingContext)
> File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseChannel.py", line =20=
> 394, in
> selectObjectsWithFetchSpecification
> entity)
> File
> =
"C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseAdaptors\AbstractDBAPI2Adap=20=
> torLa
> yer\AbstractDBAPI2AdaptorChannel.py", line 297, in selectAttributes
> raise GeneralAdaptorException, msg
> Modeling.Adaptor.GeneralAdaptorException: Couldn't evaluate expression
> SELECT DISTINCT t0.KLASA_ID, t0.NAZWA, t0.PROFIL, t0.WYCHOWAWCA_ID =
FROM
> KLASA t0 INNER JO
> IN NAUCZYCIEL t1 ON t0.WYCHOWAWCA_ID=3Dt1.NAUCZYCIEL_ID WHERE
> t1.DATA_URODZENIA > '1970'. Reason: libpq.OperationalError:ERROR: Bad
> timestamp external representation '1970'
> ------------------------------------
>
> Is there any explanation?
>
>
> ****************************
> * =A3ukasz =A3akomy
> * luk...@po...
> ****************************
>
>
>
>
> -------------------------------------------------------
> This SF.net email is sponsored by: SF.net Giveback Program.
> Does SourceForge.net help you be more productive? Does it
> help you create better code? SHARE THE LOVE, and help us help
> YOU! Click Here: http://sourceforge.net/donate/
> _______________________________________________
> Modeling-users mailing list
> Mod...@li...
> https://lists.sourceforge.net/lists/listinfo/modeling-users
|
|
From: Sebastien B. <sbi...@us...> - 2003-12-01 17:10:41
|
Hi all,
Let me expose a bug in the framework that can cause data loss when
used w/ postgresql and psycopg (and maybe other adaptors as well, I
cannot be categorical).
There is a bug in the SQL generated for the database schema, involving
relationships to entities having subclasses: say you have classes A, B
and C, with A being the parent of B and B the parent of C.
Now if you design a relationship from A to B and you try to save two
objects 'a' and 'c' in relation, oracle and postgresql will fail
because the following constraint generated by
mdl_generate_DB_schema.py is wrong:
ALTER TABLE A ADD CONSTRAINT b FOREIGN KEY (FK_B) REFERENCES B(ID);
[in this case A.FK_B can reference either B(ID) or C(ID)]
Now the problem is that psycopg DISCARDS the error and does not raise
anything (in this case, an IntegrityError) --> nothing is actually
written in the database, but ec.saveChanges() returns successfully.
This problems happens w/ psycopg only, as far as I know. Other
adaptors will either fail (DCOracle2, pgdb, pypresql) with an
integrity error, or simply succeed because the underlying db does not
enforce the referential constraint (mysql, sqlite).
Immediate workaround: in your database schema, drop the constraints
coming from to-one relationships pointing to entities having subclasses.
Postgresql and Oracle:
ALTER TABLE A drop CONSTRAINT <constraint_name>;
This will ensure that your data are correctly saved w/ no "false"
integrity error, and additionally it will prevent data loss if you're
using postgresql and psycopg.
(You do not need this if you use sqlite or mysql, as far as I know)
-- S=E9bastien.
PS: the bug has been reported to the psycopg ml, you can find more
details here:
http://lists.initd.org/pipermail/psycopg/2003-December/002432.html
|
|
From: <luk...@po...> - 2003-12-01 08:42:33
|
Hi
I've got some problem with conditions that using dates. The following
examlple shows this.
ERD:
MaWychowawce
Klasa|<<--------------->|Nauczyciel
-----| |------------
|attr: DataUrodzenia
code:
---------------------------------------------------------------------
warunek=3D'MaWychowawce.DataUrodzenia > '+str(DateTime(1970,1,1))
print warunek
klasy=3DEC.fetch('Klasa',qualifier=3Dwarunek)
---------------------------------------------------------------------
Printed qualifier look like this: MaWychowawce.DataUrodzenia > 1970-01-01
00:00:00.00
I've tried with: MaWychowawce.DataUrodzenia > '1970-01-01 00:00:00.00' bu=
t
it also didn't work
Conditions on another attributes in 'Nauczyciel' works perfectly.
error
---------------------------------------
Couldn't evaluate expression SELECT DISTINCT t0.KLASA_ID, t0.NAZWA,
t0.PROFIL, t0.WYCHOWAWCA_ID FROM KLASA t0 INNER JOIN NAUCZYCIEL t1 ON
t0.WYCHOWAWCA_ID=3Dt1.NAUCZYCIEL_ID WHERE t1.DATA_URODZENIA > '1970'. Rea=
son:
libpq.OperationalError:ERROR: bad timestamp external representation '1970=
'
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "Baza.py", line 45, in PobierzDane
klasy=3DEC.fetch('Klasa',qualifier=3Dwarunek)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EditingContext.py", line 1419,=
in
fetch
return self.objectsWithFetchSpecification(fs)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EditingContext.py", line 1302,=
in
objectsWithFetchSpecification
objects=3Dself.parentObjectStore().objectsWithFetchSpecification(fs, =
ec)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\ObjectStoreCoordinator.py", li=
ne
434, in objectsWithFetchSpecification
return store.objectsWithFetchSpecification(aFetchSpecification,
anEditingContext)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseContext.py", line 1817=
,
in objectsWithFetchSpecification
anEditingContext)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseChannel.py", line 394,=
in
selectObjectsWithFetchSpecification
entity)
File
"C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseAdaptors\AbstractDBAPI2Adapto=
rLa
yer\AbstractDBAPI2AdaptorChannel.py", line 297, in selectAttributes
raise GeneralAdaptorException, msg
Modeling.Adaptor.GeneralAdaptorException: Couldn't evaluate expression
SELECT DISTINCT t0.KLASA_ID, t0.NAZWA, t0.PROFIL, t0.WYCHOWAWCA_ID FROM
KLASA t0 INNER JO
IN NAUCZYCIEL t1 ON t0.WYCHOWAWCA_ID=3Dt1.NAUCZYCIEL_ID WHERE
t1.DATA_URODZENIA > '1970'. Reason: libpq.OperationalError:ERROR: Bad
timestamp external representation '1970'
------------------------------------
Is there any explanation?
****************************
* =A3ukasz =A3akomy
* luk...@po...
****************************
|
|
From: <luk...@po...> - 2003-11-29 15:17:39
|
Hi
Thanks Sebastien for all advices. I use both optimization methods and there
are my results. They may be interesting. Given time is an average of 10
measurments
Fetching one table 'Mothers' with 100 records and three tables related with
it:
0. Fetching table in "pure" PostgreSQL by psql: 0.025 seconds
With Modeling:
1. Without any optimization: 14.20 seconds
2. Setting permanent DB connection: 1.31 seconds
3. Setting permanent DB connection and batchFetch 1.14 seconds
Now, its almost perfect
Code after optimization:
---------------------
# first optimization
import os
os.environ['MDL_PERMANENT_DB_CONNECTION']='1'
# second optimization
def databaseContext(entityName, ec):
from Modeling.FetchSpecification import FetchSpecification
fs=FetchSpecification(entityName)
return ec.rootObjectStore().objectStoreForFetchSpecification(fs)
EC=EditingContext()
mothers=EC.fetch('Mothers')
from Modeling.ModelSet import defaultModelSet
dbContext=databaseContext('Mothers', EC)
rel=defaultModelSet().entityNamed('Mothers').relationshipNamed('toProvince')
# Now fetch all provinces of mothers in a single fetch
dbContext.batchFetchRelationship(rel, mothers, EC)
for mother in mothers:
id=mother.getMothersId()
date=mother.getBirthDate()
province=mother.gettoProvince().getName()
---------------------
(It's Sebastien's code but he make some little mistakes.)
> I should probably add this feature to the framework, it's been
> regularly asked. Do we want this in the next release?
> [...]
> PS: as I said it previously when I sent the first version of the patch,
> this is not the definitive user-friendly interface ;) There will
> probably be a more convenient method at the EditingContext level,
> something like ec.batchFetch(mothers, 'toProvince') e.g.
It's a VERY good idea.
And a question about patches. How to include patch to the file. Now I just
copy the code from .patch file to .py file. It is propably some way to do it
automaticaly with WinCVS, but I dont know how.
****************************
* Lukasz Lakomy
* luk...@po...
****************************
|
|
From: John G. <ig...@do...> - 2003-11-28 10:44:03
|
Hi,
This is a patch to handle the differences between python 2.2 & 2.3
regarding converting boolean values. It uses the bool() built-in, so I
think it won't work for versions of python < 2.2.1
Boolean values such as isClassProperty & isAbstract are written as 0/1
in 2.2 and True/False in 2.3. The model loads fine with either 2.2/2.3
regardless of the version of python it was generated from.
I'm not familiar with the code base, so let me know if this breaks
something else.
cheers
john
diff -urN Modeling.orig/Attribute.py Modeling/Attribute.py
--- Modeling.orig/Attribute.py 2003-09-14 11:35:07.000000000 +0300
+++ Modeling/Attribute.py 2003-11-28 12:18:52.000000000 +0200
@@ -572,6 +572,13 @@
attrType=self.xmlAttributeType(attributeName)
set=self.xmlSetAttribute(attributeName)
if attrType=='string': value=unicodeToStr(value, encoding)
+ elif attrType=='number': value=int(value)
+ elif attrType=='bool':
+ if value=='False': value=False
+ else:
+ try: value=bool(int(value))
+ except ValueError: value=bool(value)
+
set(value)
def getXMLDOM(self, doc=None, parentNode=None, encoding='iso-8859-1'):
@@ -634,10 +641,10 @@
'externalType' : ('string',
self.setExternalType,
self.externalType),
- 'isClassProperty' : ('string',
+ 'isClassProperty' : ('bool',
self.setIsClassProperty,
self.isClassProperty),
- 'isRequired' : ('string',
+ 'isRequired' : ('bool',
self.setIsRequired,
self.isRequired),
# defaultValue must be loaded AFTER type is set, or we will get the
diff -urN Modeling.orig/Entity.py Modeling/Entity.py
--- Modeling.orig/Entity.py 2003-11-24 14:12:32.000000000 +0200
+++ Modeling/Entity.py 2003-11-28 12:15:11.000000000 +0200
@@ -1278,6 +1278,12 @@
attrType=self.xmlAttributeType(attributeName)
set=self.xmlSetAttribute(attributeName)
if attrType=='string': value=unicodeToStr(value, encoding)
+ elif attrType=='number': value=int(value)
+ elif attrType=='bool':
+ if value=='False': value=False
+ else:
+ try: value=bool(int(value))
+ except ValueError: value=bool(value)
set(value)
if phase==1:
@@ -1405,10 +1411,10 @@
'externalName': ( 'string',
self.setExternalName,
self.externalName ),
- 'isReadOnly': ( 'string',
+ 'isReadOnly': ( 'bool',
self.setReadOnly,
self.isReadOnly ),
- 'isAbstract': ( 'string',
+ 'isAbstract': ( 'bool',
self.setIsAbstract,
self.isAbstract ),
'moduleName': ( 'string',
diff -urN Modeling.orig/Relationship.py Modeling/Relationship.py
--- Modeling.orig/Relationship.py 2003-07-28 10:18:59.000000000 +0300
+++ Modeling/Relationship.py 2003-11-28 12:15:37.000000000 +0200
@@ -251,7 +251,12 @@
attrType=self.xmlAttributeType(attributeName)
set=self.xmlSetAttribute(attributeName)
if attrType=='string': value=unicodeToStr(value, encoding)
- if attrType=='number': value=int(value)
+ elif attrType=='number': value=int(value)
+ elif attrType=='bool':
+ if value=='False': value=False
+ else:
+ try: value=bool(int(value))
+ except ValueError: value=bool(value)
set(value)
return
@@ -303,7 +308,7 @@
'displayLabel' : ('string',
self.setDisplayLabel,
self.displayLabel),
- 'isClassProperty' : ('number',
+ 'isClassProperty' : ('bool',
self.setIsClassProperty,
self.isClassProperty),
'multiplicityLowerBound': ('number',
diff -urN Modeling.orig/utils.py Modeling/utils.py
--- Modeling.orig/utils.py 2003-11-24 14:12:38.000000000 +0200
+++ Modeling/utils.py 2003-11-27 21:36:56.000000000 +0200
@@ -81,11 +81,11 @@
def toBoolean(param):
"""
- If param is a string (or unicode) and equals to 0, returns 0 ; otherwise
+ If param is a string (or unicode) and equals to 0, returns False ; otherwise
returns 'not not param'.
"""
if type(param) in (types.StringType, types.UnicodeType):
- if param=='0': return 0
+ if param=='0': return False
return not not param
if sys.version_info < (2, 2):
|
|
From: Sebastien B. <sbi...@us...> - 2003-11-27 10:43:32
|
Hi,
<luk...@po...> wrote:
> I have some questions about modeling efficency. Lets consider the followi=
ng
> example:
>=20
> Model:
> (mother lives in one province, in one province lives many mothers)
> [ snipped model: Mother <<------> Province ]
>
> and python code (my orginal code translated from Polish to English:-):
>=20
> EC=3DEditingContext()
> mothers=3DEC.fetch('Mothers')
> for mother in mothers:
> id=3Dmother.getMothersId()
> date=3Dmother.getBirthDate()
>=20
> # efficency problematic code
> province=3Dmother.gettoProvince().getName()
>=20
> According to the manual everything is all right, and so it works. But... =
in
> database there is over 100 records. When I'm fetching the hole databse and
> get only Id and BirthDate it takes 0.0 seconds - good. But when I try to =
get
> the name of the province by toProvince realtion it takes about 0,5 sec for
> each row! So presenting this small database takes about minute.
>=20
> 1. Am I doing something wrong or this slow working is the feature of
> Modeling Framework?
You're not doing anything wrong. What happens here is that the province
is lazily fetched when needed, meaning that each iteration triggers a
fetch when the line=20
> province=3Dmother.gettoProvince().getName()
is hit. You can verify this by activating the mdl db-log (env. variable
MDL_ENABLE_DATABASE_LOGGING).
> 2. Is there any explanation for this or another way to get this data but
> much faster?
There are two ways of making this faster:
1. by default the framework opens a connection to the db, fetches, then
closes the connection; if you do not want that, set the env. variable=20
MDL_PERMANENT_DB_CONNECTION to "1" (see details at
http://modeling.sf.net/UserGuide/env-vars-core.html).
NB: the reason for this default behaviour originally was that there
were problems with psycopg in a MT environment and that seemed to
solve this --but the problem is now solved and there is no reason
for this to remain the default, we should probably change that.
2. Doing this, the fetch will probably be significantly faster, however
you still get one fetch per ietration, which is not that efficient
since you know that you'll need all of them anyway, so you probably
want to fetch them all.
We've discussed this some time ago with Yannick (see
https://sf.net/mailarchive/forum.php?thread_id=3D2766300&forum_id=3D10674)
and at that time I made a patch for DBContext working w/ to-many
relationships only. Since in your case you deal w/ to-one relationships
I've updated the patch:
https://sf.net/tracker/index.php?func=3Ddetail&aid=3D771009&group_id=3D5893=
5&atid=3D489337
so you can use it w/ to-one relationship as well. Then you can try it like
that:
------------------------------------------------------------------------
def databaseContext(entityName, ec):
from Modeling.FetchSpecification import FetchSpecification
fs=3DFetchSpecification(entityName)
return ec.rootObjectStore().objectStoreForFetchSpecification(fs)
=20=20
from Modeling.ModelSet import defaultModelSet
dbContext=3DdatabaseContext('Company', ec)
rel=3DdefaultModelSet().entityNamed('Mothers').relationshipNamed('toProvi=
nce')
EC=3DEditingContext()
mothers=3DEC.fetch('Mothers')
=20=20
# Now fetch all provinces of mothers in a single fetch
dbContext.batchFetchRelationship(rel, mothers, ec)
=20=20
for mother in mothers:
id=3Dmother.getMothersId()
date=3Dmother.getBirthDate()
=20=20
province=3Dmother.gettoProvince().getName()
------------------------------------------------------------------------
This makes the whole fetch even faster (because all the fetching is
done in a single roundtrip to the db).
BTW is there anyone here still using the original patch for toMany
relationships? (Yannick?)
I should probably add this feature to the framework, it's been
regularly asked. Do we want this in the next release?
-- S=E9bastien.
PS: as I said it previously when I sent the first version of the patch,
this is not the definitive user-friendly interface ;) There will
probably be a more convenient method at the EditingContext level,
something like ec.batchFetch(mothers, 'toProvince') e.g.
|
|
From: <luk...@po...> - 2003-11-25 12:06:30
|
Hi
I have some questions about modeling efficency. Lets consider the followi=
ng
example:
Model:
(mother lives in one province, in one province lives many mothers)
|------------| |--------------|
| Mothers | | Province |
|------------|* 1|--------------|
| MothersId |-----------| ProvinceId |
| BirthDate | | Name |
| ProvinceId | | |
|------------| |--------------|
and python code (my orginal code translated from Polish to English:-):
EC=3DEditingContext()
mothers=3DEC.fetch('Mothers')
for mother in mothers:
id=3Dmother.getMothersId()
date=3Dmother.getBirthDate()
# efficency problematic code
province=3Dmother.gettoProvince().getName()
According to the manual everything is all right, and so it works. But... =
in
database there is over 100 records. When I'm fetching the hole databse an=
d
get only Id and BirthDate it takes 0.0 seconds - good. But when I try to =
get
the name of the province by toProvince realtion it takes about 0,5 sec fo=
r
each row! So presenting this small database takes about minute.
1. Am I doing something wrong or this slow working is the feature of
Modeling Framework?
2. Is there any explanation for this or another way to get this data but
much faster?
****************************
* =A3ukasz =A3akomy
* luk...@po...
****************************
|
|
From: Mario R. <ma...@ru...> - 2003-11-23 08:22:47
|
Thanks S=E9bastien, that fixes the problem.
Running the tests after applying the patch I get the little
error below. Not sure if this is coming form this patch or not,
but must be a small typo introduced recently.
Cheers, mario
% python run.py
Traceback (most recent call last):
File "run.py", line 42, in ?
import test_PyModel
File "./test_PyModel.py", line 34, in ?
from Modeling.PyModel import *
File "<string>", line 528
<<<<<<< PyModel.py
^
IndentationError: expected an indented block
> Okay, please see ticket #847212 and the patch provided there:
> https://sourceforge.net/tracker/=20
> index.php?func=3Ddetail&aid=3D847212&group_id=3D58935&atid=3D489335
>
> Thanks for reporting, hopefully this should fix the problem (and =20
> fixes
> the very same problem for date, BTW).
>
> -- S=E9bastien.
>
> Mario Ruggier <ma...@ru...> wrote:
>> Hello!
>>
>> I am attempting to use the tempting IN operator, however, it doesn't =20=
>> like me
>> doing that ;)
>> The field I am using it on is a nothing-special string attribute:
>>
>> GeneralAdaptorException: Couldn't evaluate expression SELECT =20
>> COUNT(*) FROM
>> SomeTable t0 WHERE ((t0.CREATEDATE > '2003-11-22 09:29:15.65' AND =20
>> t0.ACTION IN
>> (one, two, three, four)) AND t0.USERNAME =3D 'john'). Reason:
>> _sqlite.DatabaseError:right-hand side of IN operator must be constant
>>
>> The qualifier that I pass to fetchCount() is:
>>
>> createdate>"2003-11-22 10:44:53.25" AND action IN =20
>> ["one","two","three","four"]
>> AND username=3D=3D"john"
>>
>> Am I misusing this, or is this a problem with the IN operator?
>>
>> Cheers, mario
>
|
|
From: Sebastien B. <sbi...@us...> - 2003-11-22 19:57:52
|
Hi,
<luk...@po...> wrote:
> Hi
>=20
> I notice a strange behavior. When I import this script showed below all is
> ok, Python finds the module "Matki" (sorry for strange names - ther are in
> Polish :-). But when I call function "PokazMatki()" I got this error.
> Interesting thing is that when I replace
> matki=3DEC.fetch('Matki')
> with
> matki=3DEC.fetch('Matki', rawRows=3D1)
> all is ok again. The package "BazaAdresowa" isn't in directory where is t=
his
> script. The package is in Python directory in subdirectory "GifExtensions=
".
> When I copy the package "BazaAdresowa" to the directory where the script =
is
> everything works fine again. Strange isn't it? Could you give me some
> explanation?
>=20
> #------
> from mx.DateTime import *
> from Modeling.EditingContext import EditingContext
> from GifExtensions.BazaAdresowa.Matki import Matki
>=20
> def PokazMatki():
> EC=3DEditingContext()
> matki=3DEC.fetch('Matki')
> #------
This happens because the framework is not able to find the class: I'm quite
sure that your model have packageName=3D"BazaAdresowa", with entity's
moduleName=3DMatki and className=3DMatki (whatever that means ;)
When you fetch, the framework tries to do the equivalent of:
"from <packageName>.<moduleName> import <className>",=20
in your case: "from BazaAdresowa.Matki import Matki".
But this does not work, because as your script shows it, package
BazaAdresowa is in GifExtensions, not in the python path. So the
solution is: either add BazaAdresowa in your python path, or change the
model so that its package name is "GifExtensions.BazaAdresowa".
In any case and as a general rule, wherever in the python code the
statement "from <packageName>.<moduleName> import <className>" fails,
the framework will equally fails. This is something that should probably
be put somewhere, I'll try not to forget and add that to the faq.
That's why the framework says:
> ImportError: Unable to locate class BazaAdresowa.Matki.Matki corresponding
> to entity 'Matki'.
> It is possible that the model's packageName, or the entity's moduleName or
> className do not correspond to where the module is installed --for exampl=
e,
> you might have moved it to a sub-package. You can solve this easily by
> updating your model so that 'packageName.moduleName.className' points to
> the exact location where the class is installed
>=20
> Original exception was: ImportError: No module named BazaAdresowa
Back on your other question:
> Interesting thing is that when I replace
> matki=3DEC.fetch('Matki')
> with
> matki=3DEC.fetch('Matki', rawRows=3D1)
> all is ok again.
fetch w/ rawRows does not try to instanciate any objects, it just
returns a dictionary from the db -> it does not try to import any class
in the process, and that's why it does not fail.
I hope I succedeed to make it clear, if not, you can keep picking on
me ;)
-- S=E9bastien.
|
|
From: <luk...@po...> - 2003-11-22 18:44:36
|
Hi
I notice a strange behavior. When I import this script showed below all i=
s
ok, Python finds the module "Matki" (sorry for strange names - ther are i=
n
Polish :-). But when I call function "PokazMatki()" I got this error.
Interesting thing is that when I replace
matki=3DEC.fetch('Matki')
with
matki=3DEC.fetch('Matki', rawRows=3D1)
all is ok again. The package "BazaAdresowa" isn't in directory where is t=
his
script. The package is in Python directory in subdirectory "GifExtensions=
".
When I copy the package "BazaAdresowa" to the directory where the script =
is
everything works fine again. Strange isn't it? Could you give me some
explanation?
#------
from mx.DateTime import *
from Modeling.EditingContext import EditingContext
from GifExtensions.BazaAdresowa.Matki import Matki
def PokazMatki():
EC=3DEditingContext()
matki=3DEC.fetch('Matki')
#------
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "PS_Baza.py", line 55, in PobierzMatki
matki=3DEC.fetch('Matki')
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EditingContext.py", line 1419,=
in
fetch
return self.objectsWithFetchSpecification(fs)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EditingContext.py", line 1302,=
in
objectsWithFetchSpecification
objects=3Dself.parentObjectStore().objectsWithFetchSpecification(fs, =
ec)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\ObjectStoreCoordinator.py", li=
ne
434, in objectsWithFetchSpecification
return store.objectsWithFetchSpecification(aFetchSpecification,
anEditingContext)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseContext.py", line 1765=
,
in objectsWithFetchSpecification
object=3Dchannel.fetchObject()
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\DatabaseChannel.py", line 269,=
in
fetchObject
object=3Dcd.createInstanceWithEditingContext(ec)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EntityClassDescription.py", li=
ne
177, in createInstanceWithEditingContext
theClass=3Dself.classForInstances()
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EntityClassDescription.py", li=
ne
161, in classForInstances
theClass=3DclassForEntity(self._entity)
File "C:\PROGRA~1\Zope2.6.2\bin\Modeling\EntityClassDescription.py", li=
ne
521, in classForEntity
raise ImportError, err_msg
ImportError: Unable to locate class BazaAdresowa.Matki.Matki correspondin=
g
to entity 'Matki'.
It is possible that the model's packageName, or the entity's moduleName o=
r
className do not correspond to where the module is installed --for exampl=
e,
you might have moved it to a sub-package. You can solve this easily by
updating your model so that 'packageName.moduleName.className' points to
the exact location where the class is installed
Original exception was: ImportError: No module named BazaAdresowa
****************************
* =A3ukasz =A3akomy
* luk...@po...
****************************
|
|
From: Sebastien B. <sbi...@us...> - 2003-11-22 13:30:28
|
Okay, please see ticket #847212 and the patch provided there: https://sourceforge.net/tracker/index.php?func=3Ddetail&aid=3D847212&group_= id=3D58935&atid=3D489335 Thanks for reporting, hopefully this should fix the problem (and fixes the very same problem for date, BTW). -- S=E9bastien. Mario Ruggier <ma...@ru...> wrote: > Hello! >=20 > I am attempting to use the tempting IN operator, however, it doesn't like= me > doing that ;) > The field I am using it on is a nothing-special string attribute: >=20 > GeneralAdaptorException: Couldn't evaluate expression SELECT COUNT(*) F= ROM > SomeTable t0 WHERE ((t0.CREATEDATE > '2003-11-22 09:29:15.65' AND t0.ACTI= ON IN > (one, two, three, four)) AND t0.USERNAME =3D 'john'). Reason: > _sqlite.DatabaseError:right-hand side of IN operator must be constant >=20 > The qualifier that I pass to fetchCount() is: >=20 > createdate>"2003-11-22 10:44:53.25" AND action IN ["one","two","three","f= our"] > AND username=3D=3D"john" >=20 > Am I misusing this, or is this a problem with the IN operator? >=20 > Cheers, mario |
|
From: Sebastien B. <sbi...@us...> - 2003-11-22 12:28:47
|
Hi, This is indeed a bug in the generation of the SQL statement --and a quick check confirms that this affects every adaptors, not only SQLite. I'm gonna look at that. -- S=E9bastien. Mario Ruggier <ma...@ru...> wrote: > Hello! >=20 > I am attempting to use the tempting IN operator, however, it doesn't like= me > doing that ;) > The field I am using it on is a nothing-special string attribute: >=20 > GeneralAdaptorException: Couldn't evaluate expression SELECT COUNT(*) F= ROM > SomeTable t0 WHERE ((t0.CREATEDATE > '2003-11-22 09:29:15.65' AND t0.ACTI= ON IN > (one, two, three, four)) AND t0.USERNAME =3D 'john'). Reason: > _sqlite.DatabaseError:right-hand side of IN operator must be constant >=20 > The qualifier that I pass to fetchCount() is: >=20 > createdate>"2003-11-22 10:44:53.25" AND action IN ["one","two","three","f= our"] > AND username=3D=3D"john" >=20 > Am I misusing this, or is this a problem with the IN operator? >=20 > Cheers, mario |
|
From: Mario R. <ma...@ru...> - 2003-11-22 10:04:52
|
Hello! I am attempting to use the tempting IN operator, however, it doesn't like me doing that ;) The field I am using it on is a nothing-special string attribute: GeneralAdaptorException: Couldn't evaluate expression SELECT COUNT(*) FROM SomeTable t0 WHERE ((t0.CREATEDATE > '2003-11-22 09:29:15.65' AND t0.ACTION IN (one, two, three, four)) AND t0.USERNAME = 'john'). Reason: _sqlite.DatabaseError:right-hand side of IN operator must be constant The qualifier that I pass to fetchCount() is: createdate>"2003-11-22 10:44:53.25" AND action IN ["one","two","three","four"] AND username=="john" Am I misusing this, or is this a problem with the IN operator? Cheers, mario |
|
From: Mario R. <ma...@ru...> - 2003-11-19 21:27:01
|
Hello! thanks for the reply! Oh, btw, the little reorganization changes you made on the public web site are a good improvement in my opinion... >> thanks for taking the time to clarify this issue... given that it >> seems that >> others are not often surprised by this, and that making this automatic >> will result in unnecessary overhead, I would be in favour of just >> clarifying >> when this may happen, and how to deal with it (also in the form of a >> nice faq...) > > Seems reasonable, esp. in the light of what follows... > >> Having said this, I still do not fully buy the performance overhead >> argument. See comments below... > [snipped] >> In this particular model, [containing just A and B] >> it is categoric that an A is related to a B (or, >> I guess, a sub-class of B, but not a super-class of B!). >> So, I still do not see why an A is returned, as this does not >> conform to the model -- thus I see this as incorrect behaviour. > > Okay... In fact, I realize that I did not explain the right thing > --what > I explained is more a reason on why the GlobalID for a fault is related > to the root entity, than a reason why the fault itself is an instance > of > the root class. Ah, OK. > I understand your point and agree that this can be seen as an > incorrect behaviour. I need to investigate on that, to see if fixing > this could be a problem in any way (incl. time overhead) --I dunno > for > now. Look forward to what you find out and the estimation for changing this. >>> Now if you clear the fault (b.willRead()), then b.getAs() works as >>> expected. >> >> Fine. At the moment, the (default) code that gets executed when >> a.getB() is called is something like: >> >> def getB(self): >> "Return the b relationship (toOne)" >> self.willRead() >> return self._b >> >> But, what's wrong with doing something like (only when an entity >> participates in an inheritance hierarchy) ? >> >> def getB(self): >> "Return the b relationship (toOne)" >> self.willRead() >> b = self._b >> b.willRead() >> return b >> >> This method is not called all the time b needs to be accessed (as in >> the examples you cite below, right?), so the performance hit >> (associated >> with the _getattr_ suggestion) is minimal. Or am I being too naive >> here? > > You're not ;) But why do you insist that we make it simple when we can > make it complex ?)) Because I'm just a simple guy... ( ... I live from day to day, A ray of sunshine melts my frown, and blows my blues away... ;) > [...] >> Other than the a.getB() explicit calls in client code, when is this >> method called within the framework? > > --> In fact you're absolutely right, and the framework will not call > this on its own: remember that the mdl. uses KeyValueCoding to > access properties, and only private methods (storedValueForKey), > so when obj._prop and obj.getProp() are defined, it always > accesses obj._prop and never calls obj.getProp(). > > Plus, your method is crystal-clear, and does not require any complex > inspection of subclasses or whatsoever... > > Sorry for having obfuscated rather than clarifying the > subject... Luckyly you were attentive on this one. Great. Nice to know that sometimes my gut feeling that things need not be complicated turns out to be correct ;) Unfortunately this is not always the case ;( Cheers, mario |
|
From: Sebastien B. <sbi...@us...> - 2003-11-17 13:45:21
|
Hi,
> thanks for taking the time to clarify this issue... given that it seems t=
hat
> others are not often surprised by this, and that making this automatic
> will result in unnecessary overhead, I would be in favour of just clarify=
ing
> when this may happen, and how to deal with it (also in the form of a
> nice faq...)
Seems reasonable, esp. in the light of what follows...
> Having said this, I still do not fully buy the performance overhead
> argument. See comments below...
[snipped]
> In this particular model, [containing just A and B]
> it is categoric that an A is related to a B (or,
> I guess, a sub-class of B, but not a super-class of B!).
> So, I still do not see why an A is returned, as this does not
> conform to the model -- thus I see this as incorrect behaviour.
Okay... In fact, I realize that I did not explain the right thing --what
I explained is more a reason on why the GlobalID for a fault is related
to the root entity, than a reason why the fault itself is an instance of
the root class.
I understand your point and agree that this can be seen as an
incorrect behaviour. I need to investigate on that, to see if fixing
this could be a problem in any way (incl. time overhead) --I dunno for
now.
> > Now if you clear the fault (b.willRead()), then b.getAs() works as
> > expected.
>=20
> Fine. At the moment, the (default) code that gets executed when
> a.getB() is called is something like:
>=20
> def getB(self):
> "Return the b relationship (toOne)"
> self.willRead()
> return self._b
>=20
> But, what's wrong with doing something like (only when an entity
> participates in an inheritance hierarchy) ?
>=20
> def getB(self):
> "Return the b relationship (toOne)"
> self.willRead()
> b =3D self._b
> b.willRead()
> return b
>=20
> This method is not called all the time b needs to be accessed (as in
> the examples you cite below, right?), so the performance hit (associated
> with the _getattr_ suggestion) is minimal. Or am I being too naive here?
You're not ;) But why do you insist that we make it simple when we can
make it complex ?))
[...]
> Other than the a.getB() explicit calls in client code, when is this
> method called within the framework?
--> In fact you're absolutely right, and the framework will not call
this on its own: remember that the mdl. uses KeyValueCoding to
access properties, and only private methods (storedValueForKey),
so when obj._prop and obj.getProp() are defined, it always
accesses obj._prop and never calls obj.getProp().
Plus, your method is crystal-clear, and does not require any complex
inspection of subclasses or whatsoever...
=20
Sorry for having obfuscated rather than clarifying the
subject... Luckyly you were attentive on this one.
-- S=E9bastien.
|
|
From: Mario R. <ma...@ru...> - 2003-11-16 23:15:28
|
Hi,
thanks for taking the time to clarify this issue... given that it seems=20=
that
others are not often surprised by this, and that making this automatic
will result in unnecessary overhead, I would be in favour of just=20
clarifying
when this may happen, and how to deal with it (also in the form of a
nice faq...)
Having said this, I still do not fully buy the performance overhead
argument. See comments below...
> Hi all,
>
> Back on the subject, now that the problem is identified. I think =
this
> can be interesting to anyone willing to understand faults and the way
> they are handled by the framework, so I'll try there to be as explicit
> as possible. This message concludes with... a question on how this=20
> could
> possibly be handled by the framework in the future, your opinion is
> appreciated.
>
> Remember we have a model: A <<----> B, with B inheriting from A, and =
we
> have an two instances 'a' and 'b' in relation to each other: a <<---->=20=
> b
>
> you fetch object 'a':
>
>>>> a=3Dec.fetch(..., isDeep=3D1)[0]
>>>> b=3Da.getB()
>
> Now, if we suppose that the fetch only fetched 'a' and *not* 'b' as=20
> well
> (which is possible since the fetch has isDeep=3D1), assuming =
furthermore
> that b has not been fetched before within 'ec', we have:
>
>>>> b.isFault()
> 1
>>>> b, b.__class__
> (<A.A instance at 0x820b24c>, <class A.A at 0x81d7f6c>)
>>>> b.getAs
> [...]
> AttributeError: A instance has no attribute 'getAs'
>
> --> b is a faulted object, and indeed, its class is A; like any fault,
> its class is the root entity's class. That is basically why you =
get
> an AttributeError when trying to send to this object a 'getAs()'
> message, to which only class B's instances can answer.
In this particular model, it is categoric that an A is related to a B=20
(or,
I guess, a sub-class of B, but not a super-class of B!).
So, I still do not see why an A is returned, as this does not
conform to the model -- thus I see this as incorrect behaviour.
> Now if you clear the fault (b.willRead()), then b.getAs() works as
> expected.
Fine. At the moment, the (default) code that gets executed when
a.getB() is called is something like:
def getB(self):
"Return the b relationship (toOne)"
self.willRead()
return self._b
But, what's wrong with doing something like (only when an entity
participates in an inheritance hierarchy) ?
def getB(self):
"Return the b relationship (toOne)"
self.willRead()
b =3D self._b
b.willRead()
return b
This method is not called all the time b needs to be accessed (as in
the examples you cite below, right?), so the performance hit (associated
with the _getattr_ suggestion) is minimal. Or am I being too naive here?
> I understand this can be surprising. The fact is that the model here
> is very simple, and that you expect to get a B instance, not an A. =
To
> understand why a fault is *always* an instance of the root entity=20
> when
> created, just imagine there is a third entity in the model such as:
>
> C <<-----> A <<----> B
>
> and an object 'c' such as: c <---> b <----> a
>
> If you fetch c first, then getA() returns 'b', a fault for an 'A',
> then you fetch 'a', and you expect to get the _same_ object 'b' when
> you ask for a.getB() --this is uniquing: the same row can only be
> represented by one, and only one, object in the editing context.
> As you can see here, even by examining the model there is no way to
> deduce from it that 'b' will be a 'B' when we ask for c.getA() --and
> I'm sure we do not want the fault's class to be checked and=20
> eventually
> changed when a is asked for getB(), or we'll experiment a real slow
> down in the process of uniquing & fetching objects.
Other than the a.getB() explicit calls in client code, when is this
method called within the framework?
> I hope I succeeded in making it clear /why/ faults are created w/ the
> rott entity's class. Now it can be also surprising that the fault is=20=
> not
> automatically cleared when it gets the 'getAs()' message. In fact, =
this
> is not a bug in itself, the fault is just not programmed to act like
> this.
>
> There would be a way to do this: define __getattr__() so that it=20
> calls
> willRead() on the object when it gets called. But this is not
> something I want to add to the default behaviour, I do not think =
this
> is a good thing to do, just because __getattr__ gets called in a lot
> of situations where you do want a fault to be actually triggered. =
For
> example, asking 'dir(b)' makes __getattr__ be asked for =
'__members__'
> and '__methods__', printing 'b' (in log e.g, or wherever) makes
> __getattr__ be asked for '__str__', then for '__repr__' (when none =
of
> them exists and before falling back to the default --clasic-style
> classes only), etc.
>
> --> I'm pretty sure that, if this is made the default, almost everyone
> will complain sooner or later about faults being triggered for
> choose-any-reason-here...
>
> That's the reason why this is not the default, and why the choice=20=
> is
> left to each developer there.
>
> Now, of course, __getattr__ could be designed so that it only calls
> willRead() if any of the class' subclasses methods are searched...
> Should we go that way? Or does anyone see an other possible =
approach?
> Or maybe is it enough to explicitely add this to the documentation?
Again, it seems that few fall into this surprise, so attempting a=20
possibly
bug-prone complex solution may not be worth the effort. I would be happy
just to be aware of what is happening, so I know how to deal with the
situation. If there is a simple way to unfault objects when needed, then
so much the better.
Cheers, mario
> -- S=E9bastien.
|
|
From: Sebastien B. <sbi...@us...> - 2003-11-16 18:28:47
|
Hi, I'd like to offer various useful dist. packages for the framework; that's why I've added the win32.exe installer. Now, studying new possibilities: 1. I've put the result of py-distutils 'bdist_rpm' at: http://modeling.sf.net/download/ModelingCore-0.9pre16-1.noarch.rpm http://modeling.sf.net/download/ModelingCore-0.9pre16-1.src.rpm=20=20=20= =20=20=20 If someone can confirm that one of these two or both are useful and working, I'll add them to the files distributed when a release is made. 2. I tried to use the debian/ directory that Guenther Starnberger offered at the beginning of september, but w/ no success. If someone has experiences on building .deb before I check the documentation for=20 'debian common build system' that would help a lot. As far as .deb and .rpm package are concerned, I'll probably not spend a lot of time on them unless this appears to be useful and I get feedback; I'm also looking for someone to maintain them and their configuration files, so if you feel like it, drop me a mail! -- S=E9bastien. |
|
From: Sebastien B. <sbi...@us...> - 2003-11-16 17:54:53
|
Hi all,
I'm pleased to announce that release 0.9pre16 is finally out. It only
contains fixes for bugs that have been detected on 0.9pre15 --as
usual, you'll find the complete changelog below.
The ZModeling is also repackaged but w/ no change of the shipped Zope
products, it's just that I removed from the tarball the products that
are out of sync and that are for debugging purposes only. Hence there is
no need to re-download it if you already installed 0.9pre15
ZModelizationTool & ZEditingContextSessioning products.
For the 1st time, I also included for the core a win32.exe installer,
since I got positive feedbacks from Vladimir Drobnjak (thank you!) for
0.9pre15 that the executable created by python-distutils is fully
functional (an installer.exe has also been added for the
NotificationFramework v0.6).
-- S=E9bastien.
------------------------------------------------------------------------
0.9-pre-16 (2003/11/16)
-----------------------
* Fixed bug #839231: python code generated in -B/--base mode made it
impossible to import a class having sub-classes at first (it was raising
because of circular imports).
* Fixed bug #842698: when a PyModel.Attribute property is set after
instanciation, its value was never propagated to the final Attribute at
build() time.
* Fixed bug #841315: PyModel associations do not set the multiplicity bou=
nds
e.g. a toOne relationship was always [0,1] regardless of what the
definition of the Association.
* RFE #812708: mdl_generate_db_schema.py now automatically adds a semi-co=
lon
(';') when option '-c' is enabled. A new option (-e/--end-with) is added
to control this behaviour. In particular, the old behaviour (no semi-co=
lon
at end of statements) can be still obtained by supplying an empty string
to option -e/--end-with (-e "" or --end-with "").
* Fixed bug #812671: utils.finalize_docstrings() disabled
* Fixed bug #814007: KeyValueCoding.storedValueForKey() unexpectedly
returned obj.key instead of obj._key when both exist.
* Fixed bug #785434: When mdl_generate_db_schema is run with an option wh=
ich
doesn't require the admin-dsn to be set, the script fails with a KeyErr=
or.
------------------------------------------------------------------------
|
|
From: Sebastien B. <sbi...@us...> - 2003-11-15 19:40:01
|
Hi all,
Back on the subject, now that the problem is identified. I think this
can be interesting to anyone willing to understand faults and the way
they are handled by the framework, so I'll try there to be as explicit
as possible. This message concludes with... a question on how this could
possibly be handled by the framework in the future, your opinion is
appreciated.
Remember we have a model: A <<----> B, with B inheriting from A, and we
have an two instances 'a' and 'b' in relation to each other: a <<----> b
you fetch object 'a':
>>> a=3Dec.fetch(..., isDeep=3D1)[0]
>>> b=3Da.getB()
Now, if we suppose that the fetch only fetched 'a' and *not* 'b' as well
(which is possible since the fetch has isDeep=3D1), assuming furthermore
that b has not been fetched before within 'ec', we have:
>>> b.isFault()
1
>>> b, b.__class__
(<A.A instance at 0x820b24c>, <class A.A at 0x81d7f6c>)
>>> b.getAs
[...]
AttributeError: A instance has no attribute 'getAs'
--> b is a faulted object, and indeed, its class is A; like any fault,
its class is the root entity's class. That is basically why you get
an AttributeError when trying to send to this object a 'getAs()'
message, to which only class B's instances can answer.
Now if you clear the fault (b.willRead()), then b.getAs() works as
expected.
I understand this can be surprising. The fact is that the model here
is very simple, and that you expect to get a B instance, not an A. To
understand why a fault is *always* an instance of the root entity when
created, just imagine there is a third entity in the model such as:
C <<-----> A <<----> B=20
and an object 'c' such as: c <---> b <----> a
If you fetch c first, then getA() returns 'b', a fault for an 'A',
then you fetch 'a', and you expect to get the _same_ object 'b' when
you ask for a.getB() --this is uniquing: the same row can only be
represented by one, and only one, object in the editing context.
As you can see here, even by examining the model there is no way to
deduce from it that 'b' will be a 'B' when we ask for c.getA() --and
I'm sure we do not want the fault's class to be checked and eventually
changed when a is asked for getB(), or we'll experiment a real slow
down in the process of uniquing & fetching objects.
I hope I succeeded in making it clear /why/ faults are created w/ the
rott entity's class. Now it can be also surprising that the fault is not
automatically cleared when it gets the 'getAs()' message. In fact, this
is not a bug in itself, the fault is just not programmed to act like
this.
There would be a way to do this: define __getattr__() so that it calls
willRead() on the object when it gets called. But this is not
something I want to add to the default behaviour, I do not think this
is a good thing to do, just because __getattr__ gets called in a lot
of situations where you do want a fault to be actually triggered. For
example, asking 'dir(b)' makes __getattr__ be asked for '__members__'
and '__methods__', printing 'b' (in log e.g, or wherever) makes
__getattr__ be asked for '__str__', then for '__repr__' (when none of
them exists and before falling back to the default --clasic-style
classes only), etc.
--> I'm pretty sure that, if this is made the default, almost everyone
will complain sooner or later about faults being triggered for
choose-any-reason-here...
That's the reason why this is not the default, and why the choice is
left to each developer there.
Now, of course, __getattr__ could be designed so that it only calls
willRead() if any of the class' subclasses methods are searched...
Should we go that way? Or does anyone see an other possible approach?
Or maybe is it enough to explicitely add this to the documentation?
-- S=E9bastien.
|
|
From: Sebastien B. <sbi...@us...> - 2003-11-15 13:17:21
|
Mario Ruggier <ma...@ru...> wrote: > I have installed this 2-in-1 patch, and confirm that the first > test (% python ./run.py) succeeds, and that the warnings > are not generated when I regenerate all from my model. Fine, thanks for reporting, it's now integrated into CVS, and will be in the next release. Please note that the fix that has been checked-in in slightly different with the previously posted one, you'll find it at https://sourceforge.net/tracker/index.php?func=3Ddetail&aid=3D841315&grou= p_id=3D58935&atid=3D489335 It fixes both bugs #841315 and #842698. -- S=E9bastien. |
|
From: Mario R. <ma...@ru...> - 2003-11-14 08:24:43
|
Hi, I have installed this 2-in-1 patch, and confirm that the first test (% python ./run.py) succeeds, and that the warnings are not generated when I regenerate all from my model. Thanks! mario >> thanks... Created bug 841315 for this: >> "Model associations do not set the multiplicity bounds" >> >> I have installed the patch, but there are some problems. >> >> First, the first installation test fails: >> % python ./run.py >> = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >> FAIL: [PyModel] unqualified_relationships_with_inverse >> = ---------------------------------------------------------------------- >> Traceback (most recent call last): >> File "test_PyModel.py", line 393, in >> test_08_qualified_relationships_with_inverse >> self.check_model(model) >> File "test_PyModel.py", line 92, in check_model >> =20 >> self.failIf(fkStore.isRequired()!=3DtoStore.multiplicityLowerBound()) >> File >> "/BinaryCache/python/python-3.root~193/usr/lib/python2.2/=20 >> unittest.py", line >> 258, in failIf >> if expr: raise self.failureException, msg >> AssertionError > [...] > > Okay, thanks for reporting. In fact the test is right --it checks that > the PyModel does what is expected, i.e. that the FK, when = automatically > created, is mandatory/required when the multiplicity's lower bound is > 1. Since this correlation was not coded but the multiplicity is now > correctly forwarded, the test now fails ;) I've attached to bug ticket > #841315 the corresponding patch (it is an extension of the one I = posted > earlier today). That's a 2-in-1 bugfix, cool. > >> Then, for my model, on validation I get a warning for each >> such relationship, e.g: >> >> Object: Relationship A.b >> ------------------------------- >> * Warning(s): >> - relationship is mandatory but source attribute A.fkBId is not = =20 >> required > > Yes, this warning is "normal" in the bug context, it is due to the = fact > that the FK is not marked as mandatory as it should (in particular, =20= > this > makes mdl_generate_DB_schema.py mark the FK as a NOT NULL column). It > will disappear w/ the new patch applied. > > Please note: this is not integrated into cvs yet, I still need to = add > test for the other discovered bug --but this will be in the next > release for sure. > > Thanks for the report, > > -- S=E9bastien. |