Thread: [SQLObject] Problems with validators and connectionFromURI
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Cyril E. <cy...@de...> - 2004-08-30 07:34:30
|
Hello, We have found the following two problems: If someone modify a property and then read it back the 'toPython' validator's method is _not_ called. In our case we are using a 'UnicaodeValidator' to store Unicode strings in UTF8 into a Postgres database, code follows: class UnicodeValidator(sqlobject.include.validators.Validator): def toPython(self, value, state=None): if value is None: return None return unicode(value,"utf8") def fromPython(self, value, state=None): if value is None: return None return value.encode("utf8") Reading an object from the database from the first time correctly calls the validator 'toPython' method , but not after a write. Is somebody else having this problem? It arises even when disabling the cache. The 'fromPython' method _seems_ to be called every time. My second concern is with the parsing of the 'query' part in connectionFromURI; the values are assigned to properties as String and are not evaluated, for Boolean values (like enableing and disabling the cache) it ask for problems as setting cache=False always make a True value. A simple solution is to use eval before assigning the property inside the code of the method, but it may raise security problems. Again is somebody else having this problem? If I do a patch what is the procedure to post it and make it reviewed? All in all the library is quite impressive and I must thank the author for his work. Cyril Elkaim |
From: Ian B. <ia...@co...> - 2004-08-31 03:43:48
|
Cyril Elkaim wrote: > Hello, > > We have found the following two problems: > > If someone modify a property and then read it back the 'toPython' > validator's method is _not_ called. In our case we are using a > 'UnicaodeValidator' to store Unicode strings in UTF8 into a Postgres > database, code follows: > > > class UnicodeValidator(sqlobject.include.validators.Validator): > > def toPython(self, value, state=None): > if value is None: > return None > > return unicode(value,"utf8") > > def fromPython(self, value, state=None): > if value is None: > return None > > return value.encode("utf8") I think there's a shortcut, so if you assign an attribute it goes through fromPython to the database, but we keep the original value in an instance variable. So when you later access the attribute, it's not toPython(fromPython(originalValue)), but just the original value. This might be noticeable because validators normalize values. Is this what you are encountering? Is it causing a problem? > Reading an object from the database from the first time correctly calls > the validator 'toPython' method , but not after a write. Is somebody > else having this problem? It arises even when disabling the cache. The > 'fromPython' method _seems_ to be called every time. > > My second concern is with the parsing of the 'query' part in > connectionFromURI; the values are assigned to properties as String and > are not evaluated, for Boolean values (like enableing and disabling the > cache) it ask for problems as setting cache=False always make a True > value. A simple solution is to use eval before assigning the property > inside the code of the method, but it may raise security problems. Again > is somebody else having this problem? Yeah, the query part isn't fully thought out. It works for booleans, though -- the empty string is a false value, any non-empty string is true. Some safe evaluator might be nice at some point, that knows how to parse integers and some booleans (true/false, yes/no, etc). > If I do a patch what is the procedure to post it and make it reviewed? I guess mail it to the list. Bugs should go to the bug tracker on sf.net. There's also a place for patches there, though I'm fine for a patch going to either location. > All in all the library is quite impressive and I must thank the author > for his work. Thanks. -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Cyril E. <cy...@de...> - 2004-09-02 16:33:13
|
Hello, here is a patch that should correct the problem with validators. In fact the method _SO_setValues does the job correctly so I just copy its code to set(): --- /home/cyril/src/SQLObject/sqlobject/main.py Tue Aug 31 10:49:27 2004 +++ main.py Thu Sep 2 18:26:55 2004 @@ -760,10 +760,14 @@ for name, value in kw.items(): fromPython = getattr(self, '_SO_fromPython_%s' % name, None) if fromPython: - value = fromPython(value, self._SO_validatorState) - toUpdate[name] = value + dbValue = fromPython(value, self._SO_validatorState) + else: + dbValue = value + + toUpdate[name] = dbValue if self._cacheValues: - setattr(self, instanceName(name), value) + setattr(self, instanceName(name), value) + for name, value in extra.items(): setattr(self, name, value) Cyril Elkaim |
From: Ian B. <ia...@co...> - 2004-09-03 15:58:02
|
Cyril Elkaim wrote: > --- /home/cyril/src/SQLObject/sqlobject/main.py Tue Aug 31 10:49:27 2004 > +++ main.py Thu Sep 2 18:26:55 2004 > @@ -760,10 +760,14 @@ > for name, value in kw.items(): > fromPython = getattr(self, '_SO_fromPython_%s' % name, > None) > if fromPython: > - value = fromPython(value, self._SO_validatorState) > - toUpdate[name] = value > + dbValue = fromPython(value, self._SO_validatorState) > + else: > + dbValue = value > + > + toUpdate[name] = dbValue I don't see how this code changes anything...? -- Ian Bicking / ia...@co... / http://blog.ianbicking.org |
From: Cyril E. <cy...@de...> - 2004-09-03 16:41:14
|
That changes everything :-) if fact in your code you assign to value and put back this _modified_ value in the object, with the correction the value in memory is never changed. I repeat it's simply what you are doing in the SO_setValue method, I think that you just forgot to do that. the difference are the first two letters in 'dbValue' :-) Cyril Elkaim Ian Bicking wrote: > Cyril Elkaim wrote: > >> --- /home/cyril/src/SQLObject/sqlobject/main.py Tue Aug 31 10:49:27 2004 >> +++ main.py Thu Sep 2 18:26:55 2004 >> @@ -760,10 +760,14 @@ >> for name, value in kw.items(): >> fromPython = getattr(self, '_SO_fromPython_%s' % >> name, None) >> if fromPython: >> - value = fromPython(value, self._SO_validatorState) >> - toUpdate[name] = value >> + dbValue = fromPython(value, self._SO_validatorState) >> + else: >> + dbValue = value >> + >> + toUpdate[name] = dbValue > > > I don't see how this code changes anything...? > |
From: Ian B. <ia...@co...> - 2004-09-03 16:58:01
|
Cyril Elkaim wrote: > That changes everything :-) > > if fact in your code you assign to value and put back this _modified_ > value in the object, with the correction the value in memory is never > changed. I repeat it's simply what you are doing in the SO_setValue > method, I think that you just forgot to do that. > > the difference are the first two letters in 'dbValue' :-) Oh, wait, now I see it. It's only an important change because of the line *right after* the line you change. OK, applied. |