[Z3-sqlos] Re: [z3] [Fwd: Re: [Zope3-Users] sqlos - getting factory of NoneType]
Christian Lück
christian.lueck at ruhr-uni-bochum.de
Tue Jan 10 00:52:54 CET 2006
Brian Sutherland wrote:
> On Mon, Jan 09, 2006 at 07:52:38PM +0000, Christian Lück wrote:
>> Hi Brian!
>>
>> Brian Sutherland wrote:
>> > On Sat, Jan 07, 2006 at 06:26:19PM +0000, Christian L�ck wrote:
>> >> Hi
>> >>
>> >> The problem with sqlos seems: It does only work if ONE AND ONLY ONE
>> >> factory for the content component (interface) in question is registered.
>> >> And this one-and-only factory has to be registered with the
>> >> zcml-directive in a special sqlos namespace, ie.
>> >>
>> >> <sqlos:factory
>> >> id="quotationtool.BookSQLObject"
>> >> component=".book.Book"
>> >> title="BookSQLObject"
>> >> description="A book object for the sql resourcedb."
>> >> />
>> >>
>> >> When a second factory is registered for the same interface, ie.
>> >>
>> >> <factory
>> >> id="quotationtool.BookWithInitialValues"
>> >> component=".book.BookFactory"
>> >> title="BookWithInitialValues"
>> >> description="A factory for book object with initial values."
>> >> />
>> >>
>> >> sqlos fails to get the objects stored on the database (you get blank
>> >> browser pages).
>> >> The reason seems to be the implementation of
>> >> sqlos.container.SQLObjectContainer, which maps between sql-unique-keys
>> >> (SQLObject-names) and zope-object-names. The mapping mechanism makes use
>> >> of the factory.
>> >
>> > Yes, I have seen this problem before. You cannot mix sqlos:factory and
>> > factory and expect things to work.
>> >
>> > And yes, this is a _big_ problem which I think requires a re-think of
>> > how we do this. But that re-think is not yet thunk.
>> >
>> > So please try this patch (untested). If it works for you, I will add it
>> > to the source.
>> >
>> > Index: container.py
>> > ===================================================================
>> > --- container.py (revision 21506)
>> > +++ container.py (working copy)
>> > @@ -106,7 +106,9 @@
>> > (name, object) for the objects that appear in the folder.
>> > """
>> > for factoryName in self.allowedFactories():
>> > - factory = zapi.getUtility(IISQLObject, factoryName, context=self)
>> > + factory = zapi.queryUtility(IISQLObject, factoryName, context=self)
>> > + if factory is None:
>> > + continue
>> > for obj in factory.select():
>> > name = '%s.%s' % (factoryName, obj.id)
>> > yield (name, contained(obj, parent=self, name=name))
>> >
>>
>> No, this does not work for me.
>
> Why?
Well, as you can see from the debugging in my first email,
getFactoriesFor() does not return me a None type. I have registered a
factory with <zope:factory>. So in the list of returned factories there
is a
<quotationtool.resourcedb.book.BookFactory object at 0xb602236c> object.
The point is that a factory component has a getInterfaces() method, that
returns all interfaces implemented by an object which can be created by
this factory. See zope.component.interfaces.IFactory and p. 69.
That's why allowedFactories() as currently implemented returns a set
union of factories for components quontained in an SQLObjectContainer of
<sqlos:factory> AND <zope:factory>.
If you have the 'Person' example from README.txt as a tar ball, I would
beg you to send it to me. Then we could discuss a common example.
>
>> The problem with the "None type" was not
>> mine. I was answering to an other email. - I was facing the analgue
>> problem of several factories returned by the allowedFactories() method
>> which caused errors.
>>
>> Well I have found a solution now. See the diff I have attached.
>>
>> 1) First of all we define a marker Interface ISQLObjectFactory, see what
>> I added to interfaces.__init__.py.
>
> The problem I have with a marker interface is that it introduces a
> new concept, increasing the complexity of the code. If we can do the
> same without this concept, and with less lines of code, we should.
>
> It's a little concept, I know, but still something extra you need to
> understand when reading the code.
Ok, so lets formulate the problem:
We have to get allowedFactories() to know which factory to pick. That
means there has to be a information sticking on the right factory that
makes the difference.
Is it already there? Well, I don't know. Maybe, because of the
registration via the sqlos namespace. I did not dig deep into
metaconfiguration.
Now lets talk about possible implementations:
An argument for a marker interface would be, that it is a peace of
information that is as much independent from the implementation of the
factory as could be. It's a merely semantic concept. Marking makes a
difference.
(Maybe I like it because I'm a student of linguistics :)
>
>> 2) Then we implement this marker interface by factories registered by
>> the <sqlos:factory> directive. See what I added to metaconfigure.py.
>>
>> 3) Then we check for this marker interface in the allowedFactories()
>> method of SQLObjectContainer. Have a look at what I added to container.py
>> Well, in your diff you added the check for "None type" to the items()
>> method. I think one should rather check the factories in the
>> allowedFactories() method already.
>
> Yes, I agree, but I also know that there are people who use
> allowedFactories in their own code. So just changing the meaning of the
> function is a non flyer.
>
> So what I would like is to deprecate it and introduce a new function
> getAllowedIISQLObjectUtilities, which would return a generator of tuples
> (utility name, utility) and incorporate the check for None. All users of
> allowedFactories in the sqlos source can then be converted to this
> function.
>
> So instead of introducing a new concept, we can take away an old one and
> replace it with a new one.
>
I think that's a very good point. Well, I admit, that I haven't got
enough experience to decide such things.
> Also, perhaps the new function should be private?
>
Ok. Good!
>> For a) allowedFactories() could be
>> and in fact is called somewhere else and allways only our sqlos:factory
>> is an allowed factory for things relavat in SQLObjectContainer; b) the
>> allowedFactory() method is sqlos specific, it's not a common thing
>> specified in any zope interface.
>>
>> This way we achieve this:
>>
>> - sqlos gets more tyres on the standard zope3 highway: We can now
>> register <zope:factory> etc. besides <sqlos:factory> without getting errors.
>>
>> - Since all changes are sqlos internal sqlos applications keep running
>> without any changes -- provided zcml (the <sqlos:factory> - directive)
>> was used to wire things together.
>>
I have to correct myself: Even registration via phython works, because
the marker interface is implemented in the class.
>>
>>
>> >> This way it works, I see the sql-objects and can even edit them :) - But
>> >> works yust to run into the next bigger problem... (I can't create
>> >> objects due to rollback problems) :((((
>> >
>> > If you post a traceback here, there is a chance someone can give you a
>> > quick answer.
>> >
>>
>> Well, this was due to the incompatibility regarding the z3 standard two
>> step process of adding content. You already read about my solution...
>
> Yeah, but what I want to know is why the two step process works for me,
> but not for you.
>
Please send me your Person example.
>>
>> Kind Regards,
>> Christian
>>
>> PS. It was the first time I created a diff. I'm not sure if one can use
>> it at all, because of the filenames.
>
> Thanks for the diff it makes it very clear what you are talking about!
> And normally the filenames are no problem as one can use the -p argument
> to patch. Though it might be easier for you to generate them using 'svn
> diff'.
>
>> Do you know a good HOWTO, maybe zope specific?
>>
>> PS2. Maybe we should check for "None type", too.
>
>> diff -urN sqlos-21844/container.py sqlos-work/container.py
>> --- sqlos-21844/container.py 2006-01-09 18:13:45.000000000 +0000
>> +++ sqlos-work/container.py 2006-01-09 18:20:03.000000000 +0000
>> @@ -29,6 +29,7 @@
>> from sqlos.interfaces import ISQLObject, ISQLObjectIsolated, IISQLObject
>> from sqlos.interfaces.container import ISQLObjectContainer
>> from sqlos.interfaces.container import IIsolatedSQLContainer
>> +from sqlos.interfaces import ISQLObjectFactory
>>
>> def contained(obj, parent=None, name=None):
>> """An implementation of zope.app.container.contained.contained
>> @@ -84,7 +85,9 @@
>> def allowedFactories(self):
>> for name, factory in zapi.getFactoriesFor(ISQLObject, context=self):
>> if checkFactory(self, None, factory):
>> - yield name
>> + # check if registered with <sqlos:factory>
>> + if ISQLObjectFactory.providedBy(factory):
>> + yield name
>>
>> def keys(self):
>> """ Return a sequence-like object containing the names
>> diff -urN sqlos-21844/interfaces/__init__.py sqlos-work/interfaces/__init__.py
>> --- sqlos-21844/interfaces/__init__.py 2006-01-09 18:13:45.000000000 +0000
>> +++ sqlos-work/interfaces/__init__.py 2006-01-09 17:44:26.000000000 +0000
>> @@ -335,3 +335,9 @@
>>
>> def next():
>> """ Iterator """
>> +
>> +class ISQLObjectFactory(Interface):
>> + """This is a marker interface. A Factory which is registered
>> + by the <sqlos:factory> directive gets marked and can therefore
>> + be distinguished from other factories for a content component."""
>> + pass
>> diff -urN sqlos-21844/metaconfigure.py sqlos-work/metaconfigure.py
>> --- sqlos-21844/metaconfigure.py 2006-01-09 18:13:45.000000000 +0000
>> +++ sqlos-work/metaconfigure.py 2006-01-09 17:33:07.000000000 +0000
>> @@ -18,9 +18,10 @@
>> from zope.component.factory import Factory, IFactory
>> from sqlos.interfaces import IISQLObject, IConnectionName
>> from sqlos.interfaces import IReadSQLObjectClass, IWriteSQLObjectClass
>> +from sqlos.interfaces import ISQLObjectFactory
>>
>> class SQLObjectFactory(Factory):
>> - implements(IFactory)
>> + implements(IFactory, ISQLObjectFactory)
>
> Actually, we could probably get rid of SQLObjectFactory as well.
How would that look like? Don't we need it to make python/z3 objects
from rdb columns?
>
>>
>> def handler(_context, component, id, title=None, description=None):
>> if isinstance(component, basestring):
>
>
More information about the z3-sqlos
mailing list