[Zope] zope3, browser:addMenuItem, ZCML factory => ForbiddenAttribute: ('__call__', <...>)

KLEIN Stéphane stephane at harobed.org
Sat Sep 20 18:04:28 EDT 2008


Le Fri, 19 Sep 2008 23:30:21 +0000, KLEIN Stéphane a écrit :

> Now, I've some comment and question about it :
>
> * I think this tip isn't "developer friendly", what is the good method ?
>
> * Philipp von Weitershausen's book (Web Component Development with Zope 
> 3) give first version of my example (without __Security_checker__ tip) 
> and its example didn't working with zope 3.4 (zopeproject use). Why 
this 
> compatibility breaking ?

Well, I've this problem with zope.component 3.5.1, it's unstable version. 
It's a
answer to "Why this compatibility breaking". I think it's a bug.

I know what revision bring the issue : http://svn.zope.org/zope.component/
trunk/src/zope/component/zcml.py?rev=88794&view=rev

Before the utility function in zope/component/zcml.py is :

def utility(_context, provides=None, component=None, factory=None,
            permission=None, name=''):
    if factory:
        if component:
            raise TypeError("Can't specify factory and component.")
        component = factory()

    if provides is None:
        if factory:
            provides = list(zope.interface.implementedBy(factory))
        else:
            provides = list(zope.interface.providedBy(component))
        if len(provides) == 1:
            provides = provides[0]
        else:
            raise TypeError("Missing 'provides' attribute")

    if permission is not None:
        if permission == PublicPermission:
            permission = CheckerPublic
        checker = InterfaceChecker(provides, permission)

        component = proxify(component, checker)

    _context.action(
        discriminator = ('utility', provides, name),
        callable = handler,
        args = ('registerUtility', component, provides, name)
        )
    _context.action(
        discriminator = None,
        callable = provideInterface,
        args = (provides.__module__ + '.' + provides.getName(), provides)
        )

now it's :

def utility(_context, provides=None, component=None, factory=None,
            permission=None, name=''):
    if factory and component:
        raise TypeError("Can't specify factory and component.")

    if provides is None:
        if factory:
            provides = list(zope.interface.implementedBy(factory))
        else:
            provides = list(zope.interface.providedBy(component))
        if len(provides) == 1:
            provides = provides[0]
        else:
            raise TypeError("Missing 'provides' attribute")

    if permission is not None:
        if permission == PublicPermission:
            permission = CheckerPublic
        checker = InterfaceChecker(provides, permission)

        component = proxify(component, checker)

    _context.action(
        discriminator = ('utility', provides, name),
        callable = handler,
        args = ('registerUtility', component, provides, name),
        kw = dict(factory=factory),
        )
    _context.action(
        discriminator = None,
        callable = provideInterface,
        args = (provides.__module__ + '.' + provides.getName(), provides)
        )

So, in new version, if factory is given then permission isn't used because
component is None. Before, component was builded with factory and 
permission was
applied on this component and this ZCML declaration worked perfeclty with
"browser:addMenuItem".

Now, I don't know how can I fix this issue with new Utility ZMCL design.

I've reported this bug here : https://bugs.launchpad.net/zope3/+bug/272595

Regards,
Stephane



More information about the Zope mailing list