← Back to team overview

lazr-users team mailing list archive

Re: Using lazr.restful with a zope3 app

 

2010/6/23 Gustavo Rahal <gustavorahal@xxxxxxxxx>

>
>
> 2010/6/22 Gustavo Rahal <gustavorahal@xxxxxxxxx>
>
>
>>
>> 2010/6/22 Gary Poster <gary.poster@xxxxxxxxxxxxx>
>>
>>
>>> On Jun 22, 2010, at 10:15 AM, Gustavo Rahal wrote:
>>>
>>> > 2010/6/21 Gary Poster <gary.poster@xxxxxxxxxxxxx>
>>> >
>>> > On Jun 21, 2010, at 2:42 PM, Gustavo Rahal wrote:
>>> >
>>> > > The problem was really the __repr__ of z3c.form. I fixed it and
>>> things worked fine. Will contact z3c.form owner for a permanent fix
>>> >
>>> > Great.
>>> >
>>> > > Now zope.app.publication and z3c.form need fixes...
>>> > >
>>> > > So, one step closer but still not there. At least now it seems i'm
>>> really on lazr.restful space. I'm having problems with the following:
>>> > >
>>> > >    lazr/restful/_resource.py(1887)toDataForJSON()
>>> > >    1886         for link_name, publication in publications.items():
>>> > > -> 1887             data_for_json[link_name] =
>>> absoluteURL(publication,
>>> > >    1888
>>>  self.request)
>>> > >
>>> > > absoluteURL call fails with TypeError: There isn't enough context to
>>> get URL information
>>> > > Here is what the various objects look like:
>>> > >
>>> > > ipdb> publications
>>> > > Out[0]: {'systems_collection_link':
>>> <tp4.portal.restful.resources.SystemSet object at 0xaf14d6c>}
>>> > > ipdb> publication
>>> > > Out[0]: <tp4.portal.restful.resources.SystemSet object at 0xaf14d6c>
>>> > > ipdb> self.request
>>> > > Out[0]: <lazr.restful.simple.Request instance URL=
>>> http://localhost:8080/api/1.0>
>>> > >
>>> > > My RootResource is:
>>> > >
>>> > > class WebServiceRootResource(RootResource):
>>> > >     """The root resource for a web service."""
>>> > >
>>> > >     def _build_top_level_objects(self):
>>> > >         systemset = SystemSet()
>>> > >         systemset.systems = [
>>> > >             System(systemset, "foo", "bar"),
>>> > >             System(systemset, "1", "2")
>>> > >             ]
>>> > >         collections = dict(systems=(ISystem, systemset))
>>> > >         return collections, {}
>>> > >
>>> > > Configuration:
>>> > >
>>> > > class WebServiceConfiguration(BaseWebServiceConfiguration):
>>> > >     code_revision = '1'
>>> > >     active_versions = ['1.0',]
>>> > >     use_https = False
>>> > >     last_version_with_mutator_named_operations = None
>>> > >     view_permission = 'zope.Public'
>>> > >     service_root_uri_prefix = "api/"
>>> > >     hostname = "localhost"
>>> > >     port = "8080"
>>> > >
>>> > >
>>> > > Thoughts?
>>> >
>>> > It sounds like you need to define your own IAbsoluteURL implementation
>>> for the root object.
>>> >
>>> > It might be sufficient to add this to your zcml:
>>> >
>>> > <adapter factory="lazr.restful.simple.RootResourceAbsoluteURL" />
>>> >
>>> > If you are curious what is going on here, see
>>> lazr/restful/docs/absoluteurl.txt
>>> >
>>> >
>>> > This is already done
>>> >
>>> > Look what happens in lazr/restful/_resource.py(1887)toDataForJSON() :
>>> >
>>> > ipdb> self.request
>>> > Out[0]: <lazr.restful.simple.Request instance URL=
>>> http://localhost:8080/api/1.0>
>>> > ipdb> publication
>>> > Out[0]: <tp4.portal.restful.resources.SystemSet object at 0xb0db04c>
>>> > ipdb> getMultiAdapter((publication, self.request), IAbsoluteURL)
>>> > Out[0]: <tp4.portal.restful.root.BelowRootAbsoluteURL object at
>>> 0xac00b6c>
>>> > ipdb> self
>>> > Out[0]: <tp4.portal.restful.root.WebServiceRootResource object at
>>> 0xe324b0c>
>>> > ipdb> getMultiAdapter((self, self.request), IAbsoluteURL)
>>> > Out[0]: <tp4.portal.restful.root.RootAbsoluteURL object at 0xb44d50c>
>>> >
>>> > This works fine:
>>> > ipdb> adapter_root = getMultiAdapter((self, self.request),
>>> IAbsoluteURL)
>>> > ipdb> adapter_root()
>>> > Out[0]: 'http://localhost:8080/api/1.0/'
>>> >
>>> > But then:
>>> >
>>> > ipdb> adapter = getMultiAdapter((publication, self.request),
>>> IAbsoluteURL)
>>> > ipdb> adapter()
>>> > *** TypeError: There isn't enough context to get URL information. This
>>> is probably due to a bug in setting up location information.
>>>
>>> More guessing:
>>>
>>> - Does SystemSet declare that it implements
>>> zope.location.interfaces.ILocation, either by a direct declaration or by
>>> ISystemSet inherting from ILocation?
>>> - Does SystemSet actually implement ILocation?
>>>
>>> See PairSet at the bottom of lazr/restful/example/wsgi/resources.py for
>>> an example.
>>>
>>> Gary
>>>
>>>
>> ipdb> ILocation.providedBy(publication)
>> Out[0]: True
>> ipdb> publication.__parent__
>> Out[0]: <tp4.portal.restful.root.WebServiceRootResource object at
>> 0xe773c0c>
>> ipdb> publication.__name__
>> Out[0]: 'systems'
>>
>> I tested WSGI example setting "service_root_uri_prefix = "api/"" to the
>> WSGI WebServiceConfiguration and it also worked fine. This was mostly the
>> only difference compared to what I have.
>>
>> I have not shown what I did to customize the request. Just to double
>> check:
>>
>> from lazr.restful.directives import publication_class, request_class
>>
>> class TP4WSFactory:
>>     implements(IRequestPublicationFactory)
>>
>>     def canHandle(self, environment):
>>         ws_config = getUtility(IWebServiceConfiguration)
>>         if environment["REQUEST_URI"].startswith("/" +
>> ws_config.path_override):
>>             return True
>>         else:
>>             return False
>>
>>     def __call__(self):
>>         return request_class.default, publication_class.default
>>
>> ZCML:
>>
>>   <publisher
>>       name="LAZRWS"
>>       factory=".root.TP4WSFactory"
>>       methods="GET POST HEAD DELETE"
>>       mimetypes="*"
>>       priority="5"
>>       />
>>
>>
>>
> Does this rings a bell?
>
> ipdb> getMultiAdapter((self, self.request), name='absolute_url')
> Out[0]: <zope.app.publisher.browser.viewmeta.AbsoluteURL object at
> 0xab9f92c>
> ipdb> from zope.traversing.browser.interfaces import IAbsoluteURL
>
> ipdb> getMultiAdapter((self, self.request), IAbsoluteURL)
> Out[0]: <tp4.portal.restful.root.RootAbsoluteURL object at 0xaccc76c>
>
> Things are failing here:
>
> >
> /home/grahal/.buildout/eggs/zope.traversing-3.4.1-py2.5.egg/zope/traversing/browser/absoluteurl.py(57)__str__()
>      56
> ---> 57         url = str(zope.component.getMultiAdapter((container,
> request),
>      58
> name='absolute_url'))
>
>
> Continuing investigation...
>
>
Nice
3.5.3 (2009-03-10)

   - Use applySkin from new location. zope.publisher.skinnable instead of
   zope.publisher.browser.
   - Use IAbsoluteURL lookup instead of the "absolute_url" view in the
   recursive AbsoluteURL adapters (LP: #338101).

Follow ups

References