[Zope3-Users] sqlos - getting factory of NoneType

Christian Lück christian.lueck at ruhr-uni-bochum.de
Wed Jan 4 14:25:37 EST 2006


>> But when I`m trying to add an
>>
>> <browser:addMenuItem
>>     class="test.main.Person"
>>     title="Person"
>>     description="Person objects"
>>     view="addperson.html"
>>     permission="zope.ManageContent"
>>     />
>>
>> tag to my configure.zcml - zapi.getFactories() returns me factory of
>> NoneType (with name something like "BrowserAdd__test.main.Person"
> 
> No, the above code looks fine. The created factory name seems also ok. 
> 
>> Without mentioned addMenuItem tag - everything is OK.
> 
> Okay, so we call those configuration directives.
> 
>> So, the question is - how can i define "proper" factory?
> 
> You can create a factory using the <factory> directive by itself or inside the 
> <content> directive. There are plenty examples out there describing this.
> 

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.

further analysis:

>>> from zope.app.debug import Debugger
>>> debugger = Debugger('var/Data.fs', 'etc/site.zcml')
[snip]
>>> root = debugger.root()

My SQLObjectContainer is on the root folder an its name is 'resources':

>>> resources = root['resources']
>>> resources
<quotationtool.resourcedb.resourcedb.ResourceDB object at 0xb6e2002c>

Now lets check the registered factories:
We yust do the same like in the allowedFactories() method of
sqlos.container.SQLObjectContainer (first step to map the names)

>>> from zope.app import zapi
>>> from sqlos.interfaces import ISQLObject
>>> from zope.app.container.constraints import checkFactory
>>> for name, factory in zapi.getFactoriesFor(ISQLObject,
context=resources):
...     print "Name: %s ; Factory: %s" % (name, factory)
...     if checkFactory(resources, None, factory):
...             print "checkedOK"
...
Name: quotationtool.BookWithInitialValues ; Factory:
<quotationtool.resourcedb.book.BookFactory object at 0xb602236c>
checkedOK
Name: quotationtool.BookSQLObject ; Factory: <SQLObjectFactory for
<class 'quotationtool.resourcedb.book.Book'>>
checkedOK

*PROBLEM:* the non-sqlos factory certainly is not able do do any name
mapping. You see it, when you try do get the keys or items in the container:

>>> for key in resources.keys(): print key
...
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File
"/var/lib/zope3.1/instance/zope.test-3.2.0.b2.local/lib/python/sqlos/container.py",
line 93, in keys
    for name, obj in self.items(): yield name
  File
"/var/lib/zope3.1/instance/zope.test-3.2.0.b2.local/lib/python/sqlos/container.py",
line 109, in items
    factory = zapi.getUtility(IISQLObject, factoryName, context=self)
  File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/component/__init__.py",
line 257, in getUtility
    raise ComponentLookupError(interface, name)
zope.component.interfaces.ComponentLookupError: (<InterfaceClass
sqlos.interfaces.IISQLObject>, u'quotationtool.BookWithInitialValues')


maybe *SOLUTIONS*:
1) I tried a marker-interface which I called ISQLObjectFactory to
excpilitely mark the content class as the yust factory. Then I changed
the allowedFactories() method:
if ISQLObjectFactory.providedBy(factory): yield factory
But I didn't come along that way :(

2) I overwrote the allowedFactories() method in the implementation of
the container. I am really not happy with it, because checking for a
specific factory-name is not the style things should be wired together
in zope (not as elegant as 1) ).

class ResourceDB(SQLObjectContainer):
    """A ResourceDB object is the base-container for Books etc."""

    implements(IResourceDB)

    def allowedFactories(self):
        for name, factory in zapi.getFactoriesFor(ISQLObject, context=self):
            if name == "quotationtool.BookSQLObject":
                if checkFactory(self, None, factory):
                    yield name


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


*FACIT*:
sqlos really *****!

Regards
Christian


More information about the Zope3-users mailing list