[Z3-sqlos] Re: [z3] [Fwd: Re: [Zope3-Users] sqlos - getting factory of NoneType]

Brian Sutherland jinty at web.de
Tue Jan 10 02:30:33 CET 2006


Hi Christian,

I have implemented the changes I have been talking about on a branch,
you can see the checkins, starting from this post:

http://codespeak.net/pipermail/z3-checkins/2006q1/001908.html

Does anyone else have any comments on this?

On Mon, Jan 09, 2006 at 11:52:54PM +0000, Christian Lück wrote:
> 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>.

Exactly.

Then queryUtility(IISQLObject, factoryName) will return None for
everything registered with <zope:factory> and an object implementing
IISQLObject for everything registered with <sqlos:factory>. So filtering
these for None will give you only the set of objects registered with
<sqlos: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.

Have a look at the source in sqlos/testing/sampleperson.py and
sqlos/ftesting.zcml. The add and edit views are tested in
ftests/adding.txt.

That is our functional testing infrastructure and is actually a
mini-application in it's own right.

> > 
> >> 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 :)

Heh;) I am an engineer, which means I generally throw a brick at it if
it doesn't work.

But how about this, the information needed to tell whether a factory is
a good one to pick is already there. If there was no corresponding
registration of an IISQLObject utility, then the factory is not one that
we want. queryUtility tells us this by returning None.

The key here is that <sqlos:factory> registers an IISQLObject utility
and and then does whatever <zope:factory> does.

By adding a marker interface you can make that very explicit, but I am
not convinced it is necessary.

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

Well, Factory already implements IFactory, so we could just delete
SQLObjectFactory and replace it with factory wherever it was used.

I doubt we will need to deprecate this first.

see: http://codespeak.net/pipermail/z3-checkins/2006q1/001911.html

> > 
> >>  
> >>  def handler(_context, component, id, title=None, description=None):
> >>      if isinstance(component, basestring):

-- 
Brian Sutherland

Metropolis - "it's the first movie with a robot. And she's a woman.
              And she's EVIL!!"



More information about the z3-sqlos mailing list