Cornices/cornice

Remove the @resource feature?

Closed this issue · 5 comments

A while ago, we discussed with @almet the possibility to get rid of the @resource decorator feature.

Among the things I remember there were:

  • relying on decorators can lead to weird errors and limitations (eg. depth argument, or inability to subclass resources)
  • the usage of schema for the resource does not really makes sense (eg. GET has no body and PATCH is likely to accept a simple mapping to be merged on the existing instance)
  • the service.definitions content is not the same as a usual service (#259)

The intend of resources was to define groups of views for REST resources.

In kinto.core we implemented that same idea using the notion of viewsets. Instead of having a @resource decorator that introspect the class, we have an explicit viewset object which describes the expected views and their parameters in a simple python object. I believe our resulting API is relatively overkill and I wouldn't defend it blindly.

But what if we design a new resource API where everything is made explicit via a descriptive object?

Something like this (rough idea):

    class ViewSet(object):

        service_args = {'factory': my_factory}
        default_view_args = {'renderer': 'custom_json'}

        methods = [
            ('GET', {}, 'get'),
            ('PUT', {'schema': UserSchema()}, 'put'),
            ('PATCH', {}, 'patch'),
            ('PATCH', {
                'schema': JsonMerge(),
                'content_type': 'application/json-merge+json'
             }, 'patch_merge'),
            ('DELETE', {}, 'delete'),
        ]

        collection_methods = [
            ('GET', {}, 'get_list')
        ]

    @register(ViewSet(), path='/users/{id}', collection_path='/users')
    class Users(object):
        def __init__(self, request, context):
            pass
        def patch_merge(self):
            # ...
        # ...

We could provide a basic viewset that matches the current behaviour of cornice.resource.

We want to be able to define several methods based on different predicates (for
example Json-Merge and Json-Patch for PATCH etc.).

Ideally, we'd want to be able to register custom content-types and renderers
imperatively (for example, a GeoJSON plugin could enhance an existing resource
with a specific renderer)

If you have idea or suggestions, or good arguments in favor of the existing approach,
please speak up :)

Related #68 #120

Natim commented

I feel like telling people to have a look at kinto.core would be a good idea but as you said it comes with a storage so one might need something in between.

However I feel that it would be more stable for people to use them than writing yet another approach that we wouldn't dogfood.

it comes with a storage

IMO the main problem of our viewsets in kinto.core is that they provide many many ways to achieve the same result. Although it may seem super powerful and flexible, it ends up being confusing. Plus, they don't allow to have several methods for the same verb, which is annoying when you want to handle JSONMerge and JSONPatch content types for example.

it would be more stable for people to use them than writing yet another approach that we wouldn't dogfood.

We would definitely move kinto.core to the new system. And it will also help validating the design :)

Natim commented

We would definitely move kinto.core to the new system.

Oh ok I didn't get that.

+1 for keeping the something like the @resource decorator; we use it in our production code and I like it because I think it gives the true REST feeling to programming services. After all we are trying to expose resources.

+1 (although "acl per HTTP method" would be nice /issues/322)