Table Of Contents

Previous topic

Glossary

Next topic

Upgrade Notes

This Page

API Documentation

Resources

class yarhp.resource.Resource(config, member_name='', collection_name='', parent=None, uid='', children=None, model=None)[source]

Class providing the core functionality.

m = Resource(config)
pa = m.add('parent', 'parents')
pa.add('child', 'children')
add(member_name, collection_name='', parent=None, uid='', **kwargs)[source]
Parameters:
  • member_name – singular name of the resource. It should be the appropriate singular version of the resource given your locale and used with members of the collection.
  • collection_name – plural name of the resource. It will be used to refer to the resource collection methods and should be a plural version of the member_name argument. Note: if collection_name is empty, it means resource is singular
  • parent – parent resource name or object.
  • uid – unique name for the resource
  • kwargs

    view: custom view to overwrite the default one. model: custom model class to override the default one used in default view.

    the rest of the keyward arguments are passed to add_resource call.

Returns:

ResourceMap object

add_from(resource)[source]

add a resource with its all children resources to the current resource

ancestors

Returns the list of ancestor resources.

get_ancestors()[source]

Returns the list of ancestor resources.

yarhp.resource.add_resource(config, view, member_name, collection_name, **kwargs)[source]

view is a dotted name of (or direct reference to) a Python view class, e.g. 'my.package.views.MyView'.

member_name should be the appropriate singular version of the resource given your locale and used with members of the collection.

collection_name will be used to refer to the resource collection methods and should be a plural version of the member_name argument.

All keyword arguments are optional.

path_prefix
Prepends the URL path for the Route with the path_prefix given. This is most useful for cases where you want to mix resources or relations between resources.
name_prefix

Perpends the route names that are generated with the name_prefix given. Combined with the path_prefix option, it’s easy to generate route names and paths that represent resources that are in relations.

Example:

config.add_resource('myproject.views:CategoryView', 'message', 'messages',
    path_prefix='/category/:category_id',
    name_prefix="category_")

# GET /category/7/messages/1
# has named route "category_message"
yarhp.resource.adjust_actions(kwargs)[source]

Returns the adjusted list of actions based on kwargs.

yarhp.resource.default_model(resource)[source]

Returns a dotted path to the default model class.

yarhp.resource.default_view(resource)[source]

Returns the dotted path to the default view class.

yarhp.resource.get_root_resource(config)[source]

Returns the root resource.

yarhp.resource.resource_factory(request)[source]

Permits to associate a request with the concerned resource.

Views

Yarhp provides 3 view classes to help you to reduce lots of repetitive code in your views.
  • BaseView
  • SQLAView
  • DynamoDBView

Last two are derived from BaseView.

class yarhp.view.BaseView(context, request)[source]

Base class for yarhp views. This class holds some common objects used by the derived SQLAView and DynamoDBView classes. Those are:

_default_actions

__model_class__

__validation_schema__

_default_actions are those for which the derived view can omit the implementation for and it will be handled by the parent class.

class MyView(SQLAView):
    def index(self):
        ...

In this example we have MyView derived from SQLAView and it defines only the index action. The rest of the actions will by default handled by SQLAView. In case the particular view does not need a certain action, it should declare it so when adding the resource:

root.add('user', 'users', include=['index'])

Here the resource user defines only the index action.

__model_class__ is a class object or dotted path to it which is associated with this view. By default yarhp expects the model to be defined in your_project.model.<resource_member_name>.<Resource>View.py

There are two ways to override this default:

root.add('user', 'users', model='path.to.my.model.ClassView')
root.add('whatever',model='yarhp.NoModel') #redefine it to NoModel

or

class MyView(BaseView):
    __model_class__ = ResourceView
__validation_schema__ is a dict of dicts in the form of:
{field_name1:
    {'type':<python type>, 
    'required':<bool>},
field_name2:{...}
    ...}

This is bare minimum that is checked by validators to make sure that request.params correspond to the model’s requirements.

If you want to supply custom validation schema, you should override the validate_schema method of your view, which must return the dict in the format above.

default_action(name)[source]

default_index, default_create, etc must be defined in the child class. See SQLAView or DynamoDBView for examples. also _default_actions is by default empty. It must be defined by the derived view class.

edit(**kw)[source]

by default edit is not allowed, unless its redefined in the child view

new(**kw)[source]

by default new is not allowed, unless its redefined in the child view

scan_action_decorators()[source]

Iterates over actions and appends decorated wrappers for before and after calls to the corresponding before or after dict

setup_default_wrappers()[source]

Add all the default before and after calls. before calls are validate_types and validate_required which are called with the validation schema returned by validation_schema method. This allows any subclass to change validation schema.

after calls are those that modify the result returned by the actions:

pager : paginates the results, if the result is a sequence. obj2dict: if result is an python object, it calls to_dict on it.

if its a list of objects, it enumerates and calls to_dict on each element.

wrap_in_dict: if action result is a list, it wraps it into a dict. add_pagination_links: if the result was paginated, it appends pagination links

validation_schema()[source]

Override this method in your own view to provide custom validation schema

class yarhp.view.NoModel[source]

No-op model class to use when defining a resource who doesnt have a model

class yarhp.view.ViewMapper(**kwargs)[source]

Custom mapper class for BaseView

class yarhp.view.ViewNotImplemented(*args, **kwargs)[source]

Use this view for the routes that raise HTTPMethodNotAllowed for any action

class yarhp.sqla.SQLAView(context, request)[source]

Yarhp view used to serve SQLAlchemy objects. ``SQLAView implements the following logic:

default behaviour for all actions validation agaisnt the sqla model’s schema
default_create(**kw)[source]

default for create action. Raises HTTPConflict if there is an integrity error in DB. Returns HTTPCreated on success.

default_delete(**kw)[source]

default for delete action. Raises HTTPNotFound if the row is not found. Returns HTTPOk on success.

default_index(**kw)[source]

default for index action. Returns sqla query object which is passed to the pager to paginate the results.

default_show(**kw)[source]

default for show action. Raises HTTPNotFound if the row is not found. Returns the resouce as python dict.

default_update(**kw)[source]

default for update action. Raises HTTPNotFound if the resource being updated is not found. Returns HTTPOk on success.

validation_schema()[source]

Returns the validation schema dict

yarhp.sqla.get_model_schema(model)[source]

Returns a validation schema for the model the schema is a dict of dicts in the form of:

{field_name1:{
    'type':<python type>,
    'required':<bool>,
    'length':<int>}
field_name2:{
    ...
}
...

}

class yarhp.dynamo.DynamoDBView(context, request)[source]

Simple REST view used to serve dymamodb-mapper objects at the top level.

For hash_key-indexed classes, subclass this and fill in the __model_class__ attribute with the class you want to serve. That’s it! The default __model_class__ value is “your_project.model.resource_name.ResourceName”

Example usage:

class UserView(DynamoDBView):
    #__model_class__ = 'your_project.model.user.User'
    pass
default_create(**kw)[source]

POST /items: create a new item.

default_delete(**kw)[source]

DELETE /items/hash_key: delete a single item.

default_index(**kw)[source]

GET /items: list all items in the collection.

Warning: Uses the scan operation. Please avoid calling this on large collections.

default_show(**kw)[source]

GET /items/hash_key: get a single item.

default_update(**kw)[source]

PUT /items/hash_key: update an existing item.

Utilities

class yarhp.renderers.YarhpJsonRendererFactory(info)[source]

Yarhp specific json renderer which will apply all after_calls(filters) to the result.

Default filters are:
pager, obj2dict, add_parent_links, wrap_in_dict, add_pagination_links
yarhp.utils.camel2snake(text)[source]

turn the camel case to snake: CamelSname -> camel_snake

yarhp.utils.maybe_dotted(modul, throw=True)[source]

if modul is a dotted string pointing to the modul, imports and returns the modul object.

yarhp.utils.snake2camel(text)[source]

turn the snake case to camel case: snake_camel -> SnakeCamel

Wrappers

Add links to the result dict to the resouce itself.

class yarhp.wrappers.callable_base(**kwargs)[source]

Base class for all before and after calls. __eq__ method is overloaded in order to prevent duplicate callables of the same type. For example, you could have a before call pager which is called in the base class and also decorate the action with paginate. __eq__ declares all same type callables to be the same.

class yarhp.wrappers.check_ancestors[source]

Decorator which adds a wrapper to check the ancestors.

yarhp.wrappers.obj2dict(**kwargs)[source]

converts objects in result into dicts

class yarhp.wrappers.pager(**kwargs)[source]

kwargs are passed down to webhelpers.paginate.Page

some of the usefull kw args with defaults are: - items_per_page=20: how many items per page - item_count=None: total count if known, otherwise DB will be queried. - presliced_list=False: if collection was alredy sliced fitting into a page

For more see http://sluggo.scrapping.cc/python/WebHelpers/modules/paginate.html

class yarhp.wrappers.paginate(**kwargs)[source]

Decorator used to paginate the results. Its an after-call

if result has “links”, update it with new_links if result has “link”, change it to “links” and add values from new_links if not empty if result has neither, create “link” or “links” depending len(new_links)

class yarhp.wrappers.validate_ancestors(**kwargs)[source]

Validates that all ancestor resources of the given resource exist

class yarhp.wrappers.validate_base(**kwargs)[source]

Base class for validation callables.

class yarhp.wrappers.validate_required(**kwargs)[source]

Validates that fields in request.params are present according to kwargs argument passed to ``__call__. Raises ValidationError in case of the mismatch

class yarhp.wrappers.validate_types(**kwargs)[source]

Validates the field types in request.params match the types declared in kwargs. Raises ValidationError if there is mismatch.

class yarhp.wrappers.validator(**kwargs)[source]

Decorator that validates the type and required fields in request params against the supplied kwargs

class MyView():
    @validator(first_name={'type':int, 'required':True})
    def index(self):
        return response
yarhp.wrappers.wrap_in_dict(**kwargs)[source]

if result is a list then wrap it in the dict

class yarhp.wrappers.wrap_me(before=None, after=None)[source]

Base class for decorators used to add before and after calls. The callables are appended to the before or after lists, which are in turn injected into the method object being decorated. Method is returned without any side effects.

Validators

Validators are implemented as wrappers that are before-calls. Essentially they ‘wrap’ your action (or any method really) and are called before the action is called.

There are two ways how validators can be involved:

  • Decorator
  • Subclassing from one of yarhp’s base view classes
  • The Chuck Norris way

Decorator

@validator(name={'type': str, 'required': True},
            age={'type': int, 'required': True},
            birthdate={'type': date, 'required': False})
def create(self):
    pass

Keyword arguments passed to the validator are the validation schema that is used to check request.params validity.

Subclassing

Yarhp provides 2 base classes one could derive from to have automated validation in the views. SQLAView and DynamoDBView. The essential difference between those two is what kind of information about the underlaying schema yarhp is able to collect. In case of SQL for example it gets the type, required and also length of the field.

class MyView(SQLAView):
    def create(self):
        pass

In the example above the create action is automatically gets validated by yarhp: the type and the required field. So you dont have to do anything. The way it does this magic is pulling the metadata (schema) from SQLA and comparing with request.params. If you wish to override any default behavior, you could do:

class MyView(SQLAView):
    @validator(name={'type':str, required=False})
    def create(self):
        ...

Here we change the required to False, thus overriding the metadata coming from the DB schema where name was required. This is obviously not recommended and should be done with care, understanding the side effects. In this case it might raise DB error since name could be NULL, but DB requires it.

The Chuck Norris way

Now what if you write a common validator and you want to apply it to all of your actions? One way is to decorate them all. But another is “Chuck Norris way” !

Stay tuned for more..

The add_resource method

config.add_resource(member_name, collection_name, **kwargs)

defines a new resource, its named routes:

config.add_resource("user", "users")

view to find : UsersView

URL route name HTTP verb action name
/users users GET index
/users users POST create
/users/:id user GET show
/users/:id user PUT update
/users/:id user DELETE delete
/users/:id/edit edit_user GET edit
/users/new new_user GET new

These last two are non-standard CRUD actions.

config.add_resource("transaction", "transactions", parent="user")

view to find: UserTransactionsView model: user_transaction.UserTransaction

URL route name HTTP verb action name
/users/:user_id/transactions user_transactions GET index
/users/:user_id/transactions user_transactions POST create
/users/:user_id/transactions/:id user_transaction GET show
/users/:user_id/transactions/:id user_transaction PUT update
/users/:user_id/transactions/:id user_transaction DELETE delete
/users/1/transactions/edit user_edit_transaction GET edit
/users/1/transactions/new user_new_transaction GET new

These last two are non-standard CRUD actions.

singular resource:

config.add_resource('detail', parent='transaction')

view to find: UserTransactionDetailView

URL route name HTTP verb action
/users/:user_id/transactions/:transaction_id/detail user_transaction_detail GET show
/users/:user_id/transactions/:transaction_id/detail user_transaction_detail POST create
/users/:user_id/transactions/:transaction_id/detail user_transaction_detail PUT update
/users/:user_id/transactions/:transaction_id/detail user_transaction_detail DELETE delete
/users/:user_id/transactions/:transaction_id/detail/edit user_transaction_edit_detail GET edit
/users/:user_id/transactions/:transaction_id/detail/new user_transaction_new_detail GET new