ROA Technical Summary

class fantastico.roa.resource_decorator.Resource(name, url, version=1.0, subresources=None, validator=None, user_dependent=False)[source]
../../_images/roa_classes.png

This class provides the main way for defining resources. Below you can find a very simple example for defining new resources:

@Resource(name="app-setting", url="/app-settings")
class AppSetting(BASEMODEL):
    id = Column("id", Integer, primary_key=True, autoincrement=True)
    name = Column("name", String(50), unique=True, nullable=False)
    value = Column("value", Text, nullable=False)

    def __init__(self, name=None, value=None):
       self.name = name
       self.value = value

Starting from Fantastico version 0.6 ROA resources support OAuth2 authorization. Because of this, resources can now be user dependent or user independent. In order for authorization to work as expected for resources which are available only to certain users you can use the following code snippet:

@Resource(name="app-setting", url="/app-settings", user_dependent=True)
class AppSetting(BASEMODEL):
    id = Column("id", Integer, primary_key=True, autoincrement=True)
    name = Column("name", String(50), unique=True, nullable=False)
    value = Column("value", Text, nullable=False)
    user_id = Column("user_id", Integer, nullable=False)

    def __init__(self, name=None, value=None, user_id=None):
       self.name = name
       self.value = value
       self.user_id = user_id

If you do not define a user_id property for user dependent resources a runtime exception is raised. In order to find out more about OAuth2 authorization implemented into fantastico please read: OAUTH2.

model[source]

This read only property holds the model of the resource.

name[source]

This read only property holds the name of the resource.

subresources[source]

This read only property holds the subresources of this resource. A resource can identify a subresource by one or multiple (composite uniquely identified resources) resource attributes.

@Resource(name="person", url="/persons", version=1.0,
          subresources={"bill_address": ["bill_address_id"],
                        "mail_address": ["mail_address_id"],
                        "ship_address:" ["ship_address_id"])
class Person(BASEMODEL):
    id = Column("id", Integer, primary_key=True, autoincrement=True)
    first_name = Column("first_name", String(80))
    last_name = Column("last_name", String(50))
    bill_address_id = Column("bill_address_id", ForeignKey("addresses.id"))
    bill_address = relationship(Address, primaryjoin=bill_address_id == Address.id)
    ship_address_id = Column("ship_address_id", ForeignKey("addresses.id"))
    ship_address = relationship(Address, primaryjoin=ship_address_id == Address.id)
    mail_address_id = Column("ship_address_id", ForeignKey("addresses.id"))
    ship_address = relationship(Address, primaryjoin=mail_address_id == Address.id)
url[source]

This read only property holds the url of the resource.

user_dependent[source]

This read only property returns True if user is owned only by one resource and False otherwise. It is really important to understand the impact of the property when set to True:

  1. Every GET on resource root url will also receive a filter user_id from access_token == resource.model.user_id

  2. Every GET on a specific resource id will be validated also on user_id field.

  3. Every POST for creating a new resource will automatically assign resource to user_id found in access_token. There is an

    exception when the resource does not require create scopes.

  4. Every PUT on a specific resource id will also check to ensure the user from the access_token owns the resource.

  5. Every DELETE on a specific resource id will also check to ensure the user from the access_token owns the resource.

validator[source]

This property returns the validator type which must be used for this resource for creating / updating it. You can read more about it on fantastico.roa.resource_validator.ResourceValidator.

version[source]

This read only property holds the version of the resource.

class fantastico.roa.resources_registry.ResourcesRegistry[source]

This class provide the methods for registering resources into Fantastico framework and locating them by url or name and version. As a Developer you will not usually need access to this class.

all_resources()[source]

This method returns a list of all registered resources order by name and version. It is extremely useful for introspecting Fantastico ROA platform.

available_resources[source]

This readonly property returns the indexed resources by name.

available_url_resources[source]

This readonly property returns the indexed resources by urk.

find_by_name(name, version='latest')[source]

This method returns a registered resource under the given name and version.

Parameters:
  • name (string) – The resource name.
  • version (string) – The numeric version of the resource or latest.
Returns:

The resource found or None.

Return type:

fantastico.roa.resource_decorator.Resource

find_by_url(url, version='latest')[source]

This method returns a registered resource under the given url and version.

Parameters:
  • name (string) – The resource name.
  • version (string) – The numeric version of the resource or latest.
Returns:

The resource found or None.

Return type:

fantastico.roa.resource_decorator.Resource

register_resource(resource)[source]

This method register a new resource into Fantastico framework. It first checks against name, url and version collision in order to detect as early as possible errors with the current defined resources.

Parameters:resource (fantastico.roa.resource_decorator.Resource) – The resource instance we want to register into Fantastico ROA registry.
Raises fantastico.roa.roa_exceptions.FantasticoRoaDuplicateError:
 This exception is raised when:
  • resource name and version already registered.
  • resource url already registered.
unregister_resource(name, version)[source]

This method unregister a resource version. If the given resource is not found no exception is raised. Once a resource is unregistered latest version is recalculated. The resource is completely removed from AVAILABLE_RESOURCES and AVAILABLE_URLS dictionaries.

Parameters:
  • name (string) – Resource name.
  • version (float) – Resource version. If you specify latest it will have no effect.
class fantastico.roa.resources_registrator.ResourcesRegistrator(settings_facade, file_patterns=None, folder_pattern=None)[source]

This class provides the algorithm for registering all defined resources. Resources discovered by this class are decorated by fantastico.roa.resource_decorator.Resource. In the constructor of this class you can define special naming convention for discovered resources (through regex). Default behavior is to scan only in models folder / subfolders in all available files.

In addition this class is also designed to be a route provider. This guarantees that at start time, all resources will be registered correctly.

load_routes()[source]

This method simple triggers resources registration and returns empty routes. Using this mechanism guarantees that routing engine will also discover ROA resources.

register_resources(path)[source]

This method scans all files and folders from the given path, match the filenames against registered file patterns and import all ROA resources.

class fantastico.contrib.roa_discovery.discovery_controller.RoaDiscoveryController(settings_facade, registry_cls=None)[source]

This class provides the routes for introspecting Fantastico registered resources through ROA. It is extremely useful to surf using your browser and to not be required to hardcode links in your code. Typically, you will want to code your client side applications against resources name and you are going to use this controller to find the location of those records.

By default, all ROA resources are mapped on /api/ relative to current project root. You can easily change this behavior by modifying the settings of your application (fantastico.settings.BasicSettings - property roa_api_url)

handle_list_resources_options(*args, **kwargs)[source]

This method handles all OPTIONS cors requests coming for resources registry listing.

list_registered_resources(*args, **kwargs)[source]

This method list all registered resources as well as a link to their entry point.

// ROA api is mapped on a subdomain: roa.fantasticoproject.com
// listing is done by GET http://fantasticoproject.com/roa/resources HTTP/1.1

{
    "Person": {1.0 : "http://roa.fantasticoproject.com/1.0/persons",
               "latest": "http://roa.fantasticoproject.com/latest/persons"},
    "Address": {1.0 : "http://roa.fantasticoproject.com/1.0/addresses",
                2.0 : "http://roa.fantasticoproject.com/2.0/addresses",
                "latest": "http://roa.fantasticoproject.com/latest/addresses"}
}
// ROA api is mapped on a relative path of the project: http://fantasticoproject.com/api/
// listing is done by GET http://fantasticoproject.com/roa/resources HTTP/1.1

{
    "Person": {1.0 : "http://fantasticoproject.com/api/1.0/persons",
               "latest": "http://roa.fantasticoproject.com/api/latest/persons"},
    "Address": {1.0 : "http://roa.fantasticoproject.com/api/1.0/addresses",
                2.0 : "http://roa.fantasticoproject.com/api/2.0/addresses",
                "latest": "http://roa.fantasticoproject.com/api/latest/addresses"}
}
class fantastico.roa.query_parser.QueryParser[source]

This class provides ROA query parser functionality. It provides methods for transforming filter and sorting expressions (REST API standard) into mvc filters (Model View Controller).

parse_filter(filter_expr, model)[source]

This method transform the given filter expression into mvc filters.

Parameters:
  • filter_expr – The filter string expression we want to convert to query objects.
  • model – The model used to describe the resource on which the requests are done.
Returns:

The newly created mvc query object.

Return type:

fantastico.mvc.models.model_filter.ModelFilterAbstract

parse_sort(sort_expr, model)[source]

This method transform the given sort expression into mvc sort filter.

Parameters:
  • filter_expr – The filter string expression we want to convert to query objects.
  • model – The model used to describe the resource on which the requests are done.
Returns:

The newly created mvc query object.

Return type:

fantastico.mvc.models.model_sort.ModelSort

class fantastico.roa.query_parser_operations.QueryParserOperation(parser)[source]

This class defines the contract for a query parser operation.

add_argument(argument)[source]

This method add a new argument to the parser operation.

build_filter(model)[source]

This method builds the model filter (fantastico.mvc.models.model_filter.ModelFilter).

get_filter(model)[source]

This method validates the current operation and build the filter.

get_grammar_rules()[source]

This method returns the rules required to interpret this operation.

return {
            "(": [(self.TERM, "("), (self.RULE, self.REGEX_TEXT), (self.RULE, ","), (self.RULE, self.REGEX_TEXT),
                  (self.RULE, ")")],
       }

Grammar rules simply describe the tokens which come after operator + symbol. For instance, eq( is followed by two comma separated arguments.

get_grammar_table(new_mixin)[source]

This method returns a dictionary describing the operator + symbol rule and action.

return {
            "(": ("eq", "(", lambda: new_mixin(QueryParserOperationBinaryEq)),
            ")": None
       }
Parameters:new_mixin (function) – New mixin described a factory method required to correctly pass current operation to parser.
Returns:A dictionary describing the grammar table for this operator.
get_token()[source]

This method returns the token which maps on this operation.

validate(model)[source]

This method validates the given operation and argument in order to ensure a filter can be built.

Raises fantastico.roa.query_parser_exceptions.QueryParserOperationInvalidError:
 Whenever the current operation attributes are invalid.
class fantastico.roa.query_parser_operations.QueryParserOperationBinary(parser)[source]

This class provides the validation / build logic for binary operations.

build_filter(model)[source]

This method builds a binary filter.

get_grammar_rules()[source]

This method returns the grammar rules supported by binary operators.

get_grammar_table(new_mixin)[source]

The grammar table supported by binary operators.

validate(model)[source]

This method ensures that three arguments were passed.

class fantastico.roa.query_parser_operations.QueryParserOperationBinaryEq(parser)[source]

This class provides the eq operator which can compare two arguments for equality.

get_token()[source]

This method returns the equality token supported by ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationBinaryGt(parser)[source]

This class provides the gt operator which can compare two arguments for greater than relation.

get_token()[source]

This method returns the greater than token supported by ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationBinaryGe(parser)[source]

This class provides the ge operator which can compare two arguments for greater or equal than relation.

get_token()[source]

This method returns the greater equals token supported by ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationBinaryLt(parser)[source]

This class provides the lt operator which can compare two arguments for less than relation.

get_token()[source]

This method returns the less than token supported by ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationBinaryLe(parser)[source]

This class provides the le operator which can compare two arguments for less or equal than relation.

get_token()[source]

This method returns the less equal than token supported by ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationBinaryIn(parser)[source]

This class provides the in operator which can compare a value with a possible list of values.

get_token()[source]

This method returns in token supported by ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationBinaryLike(parser)[source]

This class provides the like operator which can compare two arguments for similarity.

get_token()[source]

This method returns like token supported by ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationCompound(parser, compound_filter_cls=None)[source]

This class provides the parser for compound filter or. It will recursively parse each argument and in the end will return a compatible fantastico.mvc.model_filter_compound.ModelFilterCompound. Each concrete class must specify the compound filter type to use.

build_filter(model)[source]

This method builds the compound filter based on the parsed arguments of this operation.

get_grammar_rules()[source]

This method returns the grammar rules supported by binary operators.

get_grammar_table(new_mixin)[source]

The grammar table supported by binary operators.

validate(model)[source]

This method validates all arguments passed to this compound filter.

class fantastico.roa.query_parser_operations.QueryParserOperationOr(parser)[source]

This class provides a query parser for or compound filtering.

get_token()[source]

This method returns or compound token for ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationAnd(parser)[source]

This class provides a query parser for and compound filtering.

get_token()[source]

This method returns and compound token for ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationSort(parser, sort_dir=None)[source]

This class provides base support for sort operations: asc / desc.

build_filter(model)[source]

This method builds the sorting model.

get_grammar_rules()[source]

This method returns the grammar rules supported by binary operators.

get_grammar_table(new_mixin)[source]

The grammar table supported by binary operators.

validate(model)[source]

This method validates sorting argument passed to this operation.

class fantastico.roa.query_parser_operations.QueryParserOperationSortAsc(parser)[source]

This class provides asc sort operation.

get_token()[source]

This method returns asc sort token for ROA query language.

class fantastico.roa.query_parser_operations.QueryParserOperationSortDesc(parser)[source]

This class provides desc sort operation.

get_token()[source]

This method returns desc sort token for ROA query language.

class fantastico.roa.resource_json_serializer.ResourceJsonSerializer(resource_ref)[source]

This class provides the methods for serializing a given resource into a dictionary and deserializing a dictionary into a resource.

# serialize / deserialize a resource without subresources
json_serializer = ResourceJsonSerializer(AppSetting)
resource_json = json_serializer.serialize(AppSetting("simple-setting", "0.19"))
resource = json_serializer.deserialize(resource)
deserialize(body)[source]

This method converts the given body into a concrete model (if possible).

Parameters:body (dict) – A JSON object we want to convert to the model compatible with this serializer.
Returns:A model instance initiated with attributes from the given dictionary.
Raises fantastico.roa.resource_json_serializer_exceptions.ResourceJsonSerializerError:
 Whenever given body contains entries which are not supported by resource underlining model.
serialize(model, fields=None)[source]

This method serialize the given model into a json object.

Parameters:
  • model – The model we want to convert to JSON object.
  • fields (str) – A list of fields we want to include in result. Read more on Partial object representation
Returns:

A dictionary containing all required attributes.

Return type:

dict

Raises fantastico.roa.resource_json_serializer_exceptions.ResourceJsonSerializerError:
 

Whenever requested fields for serialization are not found in model attributes.

Exceptions

class fantastico.roa.roa_exceptions.FantasticoRoaError(msg, http_code=400)[source]

This class provides the core error used within Fantastico ROA layer. Usually, more concrete exceptions are raised by ROA layers.

class fantastico.roa.roa_exceptions.FantasticoRoaDuplicateError(msg, http_code=400)[source]

This concrete exception is used to notify user that multiple resources with same name and version or url and version can not be registered multiple times.

class fantastico.roa.query_parser_exceptions.QueryParserOperationInvalidError(msg, http_code=400)[source]

This exception notifies the query parser that something is wrong with the current operation arguments.

class fantastico.roa.resource_json_serializer_exceptions.ResourceJsonSerializerError(msg, http_code=400)[source]

This class provides a concrete exception used when serializing / deserializing resource models.

API generic controller

class fantastico.roa.resource_validator.ResourceValidator[source]

This class provides the base for all validators which can be used for resources.

class AppSettingValidator(ResourceValidator):
    def validate(self, resource, request, existing_resource_id=None):
        errors = []

        if resource.name == "unsupported":
            errors.append("Invalid setting name: %s" % resource.name)

        if len(resource.value) == 0:
            errors.append("Setting %s value can not be empty. %s" % resource.name)

        if len(errors) == 0:
            return

        raise FantasticoRoaError(errors)

    def format_collection(self, resources, request):
        # we can safely retrieve the full collection of resources so nothing has to be done here.

    def format_resource(self, resource, request):
        # we can safely retrieve the resource so nothing has to be done here.
    
    def on_post_create(self, resource, request):
        # override this only if you want to trigger additional actions after a resource creation.
    
    def on_post_update(self, resource, request):
        # override this only if you want to trigger additional actions after a resource update.
    
    def on_post_delete(self, resource, requesT):
        # override this only if you want to trigger addition actions after a resource delete.

Every method from validator receives the current http request in order to give access to resource validators to security context and other contexts which might be necessary.

format_collection(resources, request)[source]

This method must be overriden by each subclass in order to provide custom logic which must be executed after a collection is fetched from database. By default, this method simply iterates over the list of available resources and invoke format_resource.

Usually you will want to override this method in order to suppress sensitive data to be sent to clients.

format_resource(resource, request)[source]

This method must be overriden by each subclass in order to provide custom logic which must be executed after a resource is fetched.

Usually you will want to override this method in order to suppress sensitive data to be sent to clients.

on_post_create(resource, request)[source]

This method must be overriden by each subclass which wants to receive notifications after a resource has been successfully created.

on_post_delete(resource, request)[source]

This method must be overriden by each subclass which wants to receive notifications after a resource has been successfully deleted.

on_post_update(resource, request)[source]

This method must be overriden by each subclass which wants to receive notifications after a resource has been successfully updated.

on_pre_create(resource, request)[source]

This method must be overriden by each subclass which wants to receive notifications about a pending create resource operation.

on_pre_delete(resource, request)[source]

This method must be overriden by each subclass which wants to receive notifications about a pending delete resource operation.

on_pre_update(resource, request)[source]

This method must be overriden by each subclass which wants to receive notifications about a pending update resource operation.

validate(resource, request, existing_resource_id=None)[source]

This method must be overriden by each subclass in order to provide the validation logic required for the given resource. The resource received as an argument represents an instance of the model used to describe the resource. This method can raise unexpected exceptions. It is recommended to use fantastico.roa.roa_exceptions.FantasticoRoaError

Moreover, there are special cases when you need the existing resource id. The easiest way to achieve this is to look at existing_resource_id argument..

validate_missing_attr(resource, attr_name)[source]

This method provides a simple validation for ensuring given attr_name exists and it’s not empty into the specified resource.

class fantastico.contrib.roa_discovery.roa_controller.RoaController(settings_facade, resources_registry_cls=<class 'fantastico.roa.resources_registry.ResourcesRegistry'>, model_facade_cls=<class 'fantastico.mvc.model_facade.ModelFacade'>, conn_manager=<module 'fantastico.mvc' from '/mnt/jenkins_ebs/continous_integration/fantastico_doc_workspace/fantastico/mvc/__init__.py'>, json_serializer_cls=<class 'fantastico.roa.resource_json_serializer.ResourceJsonSerializer'>, query_parser_cls=<class 'fantastico.roa.query_parser.QueryParser'>)[source]

This class provides dynamic routes for ROA registered resources. All CRUD operations are supported out of the box. In addition error handling is automatically provided by this controller.

create_item(*args, **kwargs)[source]

This method provides the route for adding new resources into an existing collection. The API is json only and invoke the validator as described in ROA spec. Usually, when a resource is created successfully a similar answer is returned to the client:

201 Created
Content-Type: application/json
Content-Length: 0
Location: /api/2.0/app-settings/123

Below you can find all error response codes which might be returned when creating a new resource:

  • 10000 - Whenever we try to create a resource with unknown type. (Not registered to ROA).
  • 10010 - Whenever we try to create a resource which fails validation.
  • 10020 - Whenever we try to create a resource without passing a valid body.
  • 10030 - Whenever we try to create a resource and an unexpected database exception occurs.

You can find more information about typical REST ROA APIs response on REST Responses.

create_item_latest(*args, **kwargs)[source]

This method provides create item latest API version.

delete_item(*args, **kwargs)[source]

This method provides the route for deleting existing resources from an existing collection. The API is json only. Usually, when a resource is deleted successfully a similar answer is returned to the client:

204 No Content
Content-Type: application/json
Content-Length: 0

Below you can find all error response codes which might be returned when creating a new resource:

  • 10000 - Whenever we try to delete a resource with unknown type. (Not registered to ROA).
  • 10030 - Whenever we try to delete a resource and an unexpected database exception occurs.
  • 10040 - Whenever we try to delete a resource which does not exist.

You can find more information about typical REST ROA APIs response on REST Responses.

delete_item_latest(*args, **kwargs)[source]

This method provides the functionality for delete item latest version api route.

get_collection(*args, **kwargs)[source]

This method provides the route for accessing a resource collection. REST API standard for collections are enabled by this method. The typical response format is presented below:

var response = {"items": [
                    // resources represented as json objects.
                ],
                "totalItems": 100}

If a resource is not found or the resource version does not exist the following response is returned:

{"error_code": 10000,
 "error_description": "Resource %s version %s does not exist.",
 "error_details": "http://rcosnita.github.io/fantastico/html/features/roa/errors/error_10000.html"}
get_collection_latest(*args, **kwargs)[source]

This method retrieves a resource collection using the latest version of the api.

get_item(*args, **kwargs)[source]

This method provides the API for retrieving a single item from a collection. The item is uniquely identified by resource_id. Below you can find a success response example:

GET - /api/1.0/simple-resources/1 HTTP/1.1

200 OK
Content-Type: application/json
Content-Length: ...

{
    "id": 1,
    "name": "Test resource",
    "description": "Simple description"
}

Of course there are cases when exceptions might occur. Below, you can find a list of error response retrieved from get_item API:

  • 10000 - Whenever we try to retrieve a resource with unknown type. (Not registered to ROA).
  • 10030 - Whenever we try to retrieve a resource and an unexpected database exception occurs.
  • 10040 - Whenever we try to retrieve a resource which does not exist.
get_item_latest(*args, **kwargs)[source]

This method provides the latest get_item route for ROA api.

handle_resource_options(*args, **kwargs)[source]

This method enables support for http ajax CORS requests. This is mandatory if we want to host apis on different domains than project host.

handle_resource_options_latest(*args, **kwargs)[source]

This method handles OPTIONS http requests for ROA api latest versions.

update_item(*args, **kwargs)[source]

This method provides the route for updating existing resources from an existing collection. The API is json only and invokes the validator as described in ROA spec. Usually, when a resource is update successfully a similar answer is returned to the client:

204 No Content
Content-Type: application/json
Content-Length: 0

Below you can find all error response codes which might be returned when creating a new resource:

  • 10000 - Whenever we try to update a resource with unknown type. (Not registered to ROA).
  • 10010 - Whenever we try to update a resource which fails validation.
  • 10020 - Whenever we try to update a resource without passing a valid body.
  • 10030 - Whenever we try to update a resource and an unexpected database exception occurs.
  • 10040 - Whenever we try to update a resource which does not exist.

You can find more information about typical REST ROA APIs response on REST Responses.

update_item_latest(*args, **kwargs)[source]

This is the route handler for latest update existing item api.

validate_security_context(request, attr_scope)[source]

This method triggers security context validation and converts unexpected exceptions to OAuth2UnauthorizedError. If everything is fine this method return the access_token from security context.