On Wed 2007-05-30 17:14:13 Tres Seaver wrote:
Peter Sabaini wrote:
Hi list,
I am clearly doing something wrong here.
I try to use an Adapter from zope.app.session with an HTTPRequest object, but the Adapterregistry doesnt quite cooperate.
Specifically, I try to adapt a HTTPRequest object to zope.app.session.interfaces.IClientId via the Adapter zope.app.session.session.ClientId
A short demo:
% ./zopectl debug [ ... ]
Import stuff: >>> from ZPublisher.HTTPRequest import * >>> from StringIO import StringIO >>> from zope.app.session.session import ClientId >>> from zope.app.session.interfaces import IClientId >>> from zope import component >>> from zope.interface import *
Create ourselves a faux request object: >>> env = {'SERVER_NAME': '', 'SERVER_PORT' : ''} >>> request = HTTPRequest(StringIO(), env, None)
ClientId implements IClientId: >>> list(implementedBy(ClientId))
[<InterfaceClass zope.app.session.interfaces.IClientId>]
It seems ClientId is an Adapter for IRequest: >>> component.adaptedBy(ClientId)
(<InterfaceClass zope.publisher.interfaces.IRequest>,)
request implements IBrowserRequest, which is a subclass of IRequest: >>> list(providedBy(request))
[<InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>]
>>> issubclass(list(providedBy(request))[0], >>> component.adaptedBy(ClientId)
[0]) True
...so I'd expect to get ClientId as an Adapter for IClientId(request), but I
dont: >>> IClientId(request)
Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: ('Could not adapt', <HTTPRequest, URL=http://:>, <InterfaceClass zope.app.session.interfaces.IClientId>)
Shouldnt this work? Obviously I am missing something here. This is on Zope 2.10.2 with the built-in Five, and Python 2.4.4
Any help greatly appreciated!
You have verified that 'ClientID' is a suitable candidate for adapting 'IRequest' to 'IClientID', but not that it has been actually registered as the factory for that adaptaion.
Ah, I see. I thought component.adaptedBy() checked the actual registration...
Does adding the following help?
from zope.component import provideAdapter provideAdapter(ClientID)
Nope, I still get the "Could not adapt ... " error. Besides, zope/app/session/configure.zcml has the following: <adapter factory=".session.ClientId" permission="zope.Public" /> and ClientId has: class ClientId(str): implements(IClientId) adapts(IRequest) Does that take care of registration? I wonder if I need to do some special Five incantation to make the global registration work? This, on the other hand, works quite well (lifted from some unit tests): >>> from cStringIO import StringIO >>> from zope.app.testing import ztapi, placelesssetup >>> from zope.app.session.interfaces import IClientId, IClientIdManager >>> from zope.app.session.session import ClientId >>> from zope.app.session.http import CookieClientIdManager >>> from zope.publisher.interfaces import IRequest >>> from zope.publisher.http import HTTPRequest >>> >>> placelesssetup.setUp() >>> ztapi.provideAdapter(IRequest, IClientId, ClientId) >>> ztapi.provideUtility(IClientIdManager, CookieClientIdManager()) >>> request = HTTPRequest(StringIO(), {}, None) >>> IClientId(request) 'WiKfis240zXEVZ0UWM6H6AsWc6kYwJyviHNXhGqd835xsnZhKlzfjc' The difference: zope.publisher.http.HTTPRequest is a new-style class (is that required?), and placelesssetup.setUp() is executed (what does it do?)
Also, at the point where the lookup fails, you can try:
import pdb; pdb.pm()
and be in a "postmortem" traceback of the failed component tookup.
I'm afraid I'm not sure what I should be looking for... Thanks a lot, peter.
Tres.