API Guide

SpanAPI

class SpanAPI(debug=False, title=None, description=None, version=None, auto_escape=True, openapi=None, docs_route=None, allowed_hosts=None, **kwargs)[source]

responder.API extension for data-driven micro-services

The is_test param is added to SpanAPI.__init__(), and can be accessed through SpanAPI.IS_TEST for flagging that an API is being run as a test.

add_route(route, endpoint, *, default=False, static=False, check_existing=True, websocket=False, before_request=False)[source]

Adds a route to the API.

Parameters
  • route (str) – A string representation of the route.

  • endpoint (Callable) – The endpoint for the route – can be a callable, or a class.

  • default (bool) – If True, all unknown requests will route to this view.

  • static (bool) – If True, and no endpoint was passed, render “static/index.html”, and it will become a default route.

Return type

None

openapi_save(path)[source]

Save openapi.yaml file to path

Return type

None

static paged(*, limit, default_offset=0)[source]

Decorator to handle paging for SpanRoute method.

Parameters

limit (int) – max items a user can request

Assumes the possibility of paging-offset and paging-limit url params. Passes Paging object into request and response paging attributes``.

Paging information, including urls for the next / previous page are added to the response headers for all decorated routes.

If paging.total_items must be set inside the route, all other paging attributes will be automatically generated based on the total item count.

Raises

APILimitError – If requested paging-limit url param is above limit.

Return type

Callable

redoc_save(path_openapi, path_redoc)[source]

Save openapi.yaml file to path then generate ReDoc bundled api at path_redoc.

Return type

None

register_mimetype(mimetype, encoder, decoder)[source]

Registers encoder and decoder function for a given mimetype.

Parameters
  • mimetype (Union[MimeType, str, None]) – to register for ex: 'text/csv'.

  • encoder (Callable[[Any], bytes]) – Encodes mimetype data to binary.

  • decoder (Callable[[bytes], Any]) – Decodes mimetype data to binary.

Return type

None

Returns

use_schema(*, req=None, req_name=None, req_load=<LoadOptions.VALIDATE_AND_LOAD: 1>, resp=None, resp_name=None, resp_dump=<DumpOptions.DUMP_ONLY: 1>)[source]

Decorator for SpanRoute methods to automatically validate incoming request data based on a given model.

Parameters
  • req (Union[Type[Schema], Schema, MimeType, None]) – schema for request json data.

  • req_name (Optional[str]) – name for request schema.

  • req_load (LoadOptions) –

    loading options for req schema.

    • VALIDATE_AND_LOAD: Default. Loads and validates incoming data using the schema’s loads method.

    • VALIDATE_ONLY: Validates incoming data, but passes raw dict to data param in route method.

    • PASS_THROUGH: Passes json data into data param of route, but does not validate or load it.

    • IGNORE: Uses req schema for documentation, but does nothing with incoming data at runtime – default responder behavior.

  • resp (Union[Type[Schema], Schema, MimeType, None]) – schema for response json data.

  • resp_name (Optional[str]) – name for response schema.

  • resp_dump (DumpOptions) –

    loading options for req schema

    • DUMP_ONLY: Default. Dumps data using the schema’s dump method. Only minimal validation is done during this process. See Marshmallow’s documentation for details.

    • VALIDATE_ONLY: Validates outgoing data but does not dump it.

    • VALIDATE_AND_DUMP: Validates outdoing data, then dumps it.

    • IGNORE: Uses resp schema for documentation, but does nothing with outgoing data at runtime – default responder behavior.

A data param can be added to the decorated method which data from req.media() will be passed into based on the req_load option above.

Using spanreed.flag.TEXT as the response or request schema indicates that data will be loaded or sent back from req.text rather than req.media, and openapi documentation will be tweaked accordingly.

Return type

Callable

SpanRoute

class SpanRoute[source]

Base class for class-view based routing with SpanAPI See responder’s documentation for more information on class-based routing.

Request and Response

class Request(*args, **kwargs)[source]
async media()[source]

Replacement for request’s Request.media(). Can handle bson with no special modification, and loads through schema when desired.

Return type

Optional[~MediaType]

async media_loaded()[source]

Returns Request.media() data loaded through route schema.

Return type

Optional[~LoadedType]

property mimetype

Mimetype pulled from 'Content-Type' request header.

Return type

Union[str, MimeType]

property paging

Returns paging data pulled from url params.

Return type

PagingReq

property projection

Return a str, int dict of which fields to project into the response. 1 means send field, 0 means remove field.

Projection specification is passed via query params. A url with: '?project.id=1&project.data1=1' would return a payload with ONLY the id and data1 fields.

'?project.id=1&project.data1=0' would send back all fields except data1.

Return type

Dict[str, int]

class Response(*args, **kwargs)[source]
property paging

Response paging information for response headers. Only total_items must be set for all other fields to be included in response.

Return type

PagingResp

Options Enums

class LoadOptions[source]

An enumeration.

class DumpOptions[source]

An enumeration.

MimeType

MimeType

class MimeType[source]

An enumeration.

Enum class for the default supported Content-Types / Mimetypes for decoding and encoding.

Enum Attr

Text Value

JSON

application/json

YAML

application/yaml

BSON

application/bson

TEXT

text/plain

classmethod is_mimetype(value, mimetype)[source]

Checks if string or enum is equivalent to a given mimetype enum value. Similar to isinstance() or issubclass().

Parameters
  • value (Union[MimeType, str, None]) – to check

  • mimetype (MimeType) – to check against.

Return type

bool

Returns

True: is equivalent. False: is not Equivalent.

Does some cleaning (such as resolving case and removing ‘x-‘ from type).

For instance, all of the following will pass equivalence for MimeType.YAML:

  • ‘application/yaml’

  • ‘application/YAML’

  • ‘application/x-yaml’

  • ‘yaml’

  • ‘x-yaml’

classmethod from_name(value)[source]

Returns enum for given name. Does some cleaning (such as resolving case and removing ‘x-‘ from type.)

Parameters

value (Union[MimeType, str, None]) – Value to convert to enum.

Raises

ValueError – No MimeType enum for value.

Return type

MimeType

classmethod to_string(value)[source]

Get string value for given enum or string mimetype.

Parameters

value (Union[MimeType, str, None]) – Incoming value

Return type

str

Returns

String representation.

Raises

ValueError – If mimetype is None.

static add_to_headers(headers, mimetype)[source]

Add ‘Content-Type’ header for mimetype.

Parameters
  • headers (MutableMapping[str, str]) – headers obj

  • mimetype (Union[MimeType, str, None]) – to add

Return type

None

Returns

classmethod from_headers(headers)[source]

Get mimetype from ‘Content-Type’ value of headers.

Parameters

headers (Mapping[str, str]) – to fetch from.

Return type

Union[MimeType, str, None]

Returns

mimetype.

If known mimetype, enum value will be returned. If ‘Content-Type’ is not in headers, None is returned.

MimeTypeTolerant

Typing alias for Union[MimeType, str, None].

Models

class PagingReq(offset: int, limit: int)[source]

Paging info for requests.

serialized url param example:

{
  "paging-limit": 50,
  "paging-offset": 0
}
classmethod from_params(params, default_offset=None, default_limit=None)[source]

Creates PagingReq object from mapping of request url params.

Parameters
  • params (MutableMapping[str, str]) –

  • default_offset (Optional[int]) – offset to use if None is supplied

  • default_limit (Optional[int]) – limit to use if None is supplied

Return type

PagingReq

Returns

Raises

KeyError – If offset or limit is not supplied and no default is given.

limit: int = None

Limit sent to params of request.

offset: int = None

Offset sent to params of request.

to_params(params)[source]

Adds paging info to URL params for request.

Parameters

params (MutableMapping[str, str]) –

Return type

None

Returns

All values are converted to strings before being added.

All param names are prefixed with "paging-" and underscores are replaces with hyphens.

class PagingResp(offset: int, limit: int, total_items: Optional[int], current_page: int, previous: Optional[str], next: Optional[str], total_pages: Optional[int])[source]

Paging info for responses.

serialized header example:

{
   "paging-limit": 50,
   "paging-offset": 150,
   "paging-previous": "https://www.api.com/items?limit=50&offset=200",
   "paging-next": "https://www.api.com/items?limit=50&offset=100",
   "paging-total-items": 234,
   "paging-current-page": 4
   "paging-total-pages": 5
}
current_page: int = None

Current page index (starting at one).

classmethod from_headers(headers)[source]

Creates PagingResp object from mapping of response headers.

Parameters

headers (Mapping[str, str]) –

Return type

PagingResp

Returns

next: Optional[str] = None

Next page url

previous: Optional[str] = None

Previous page url.

to_headers(headers)[source]

Adds paging info to request headers in-place.

Parameters

headers (MutableMapping[str, str]) –

Return type

None

Returns

All values are converted to strings before being added. Optional fields whose values are None are skipped.

All header keys are prefixed with "paging-" and underscores are replaces with hyphens.

total_items: Optional[int] = None

Total number of returnable items.

total_pages: Optional[int] = None

Number of total pages.

class Error(name: str, message: str, code: int, data: Optional[dict] = None, id: uuid.UUID = <factory>)[source]

Model for error information.

serialized example:

{
    "content-type": "application/json",
    "error-name": "RequestValidationError",
    "error-message": "Request data does not match schema.",
    "error-id": "3a7b504b-19f0-473f-a3b0-3dfa5dd128ce",
    "error-code": "1003",
    "error-data": "{\"title\": [\"Missing data for required field.\"]}",
    "content-length": "4"
}
code: int = None

API error code. NOT the http code.

data: Optional[dict] = None

Arbitrary data dict with information about the error.

  • default: None

classmethod from_exception(exc)[source]

Creates Error object from mapping of response headers, and handles generation of APIError from Non-APIError exceptions.

Parameters

exc (BaseException) – Instance of an BaseException

Return type

Tuple[Error, APIError]

Returns

If exc does not inherit from APIError, a general APIError will be generated and returned alongside the Error dataclass.

If exc does inherit from APIError, it will be passed through.

classmethod from_headers(headers)[source]

Creates Error object from mapping of response headers.

Parameters

headers (Mapping[str, str]) –

Return type

Error

Returns

id: uuid.UUID = None

UUID for specific instance of raised error for bug fixing.

  • default factory: uuid.uuid4

message: str = None

Description of error.

name: str = None

Name of error class.

to_exception(errors_additional=None)[source]

Generate APIError object for given error information.

Parameters

errors_additional (Optional[Dict[int, Type[APIError]]]) – Additional custom APIError classes for possible raise.

Return type

APIError

Returns

BaseException instance with message, .api_code, .error_data and .error_id

Raises

InvalidErrorCodeError – when error class with correct api_code not supplied.

to_headers(headers)[source]

Adds error info to response headers in-place.

Parameters

headers (MutableMapping) –

Return type

None

Returns

All values are converted to strings before being added. Optional fields whose values are None are skipped.

All header keys are prefixed with "error-".

Documentation Tools

class DocInfo(req_example: Union[Any, NoneType] = None, req_params: List[spanserver._openapi.ParamInfo] = <factory>, responses: Dict[int, spanserver._openapi.DocRespInfo] = <factory>, tags: List[str] = <factory>)[source]
req_example: Optional[Any] = None

Example request body data.

  • default: None

req_params: List[ParamInfo] = None

Request parameter details.

  • default factory: builtins.list

responses: Dict[int, DocRespInfo] = None

Response codes and details.

  • default factory: builtins.dict

tags: List[str] = None

Tags for this method.

  • default factory: builtins.list

class DocRespInfo(description: Optional[str] = None, example: Optional[Any] = None, params: List[spanserver._openapi.ParamInfo] = <factory>)[source]

Documentation information about method responses.

description: Optional[str] = None

Description of the response code.

  • default: None

example: Optional[Any] = None

Example of response payload.

  • default: None

params: List[ParamInfo] = None

Response Headers Details.

  • default factory: builtins.list

class ParamInfo(param_type: spanserver._openapi.ParamTypes, name: str, decode_types: Sequence[type], description: Optional[str] = None, required: bool = True, default: Optional[Any] = None, max: Optional[float] = None, min: Optional[float] = None)[source]

Parameter detail.

decode_types: Sequence[type] = None

Python types for decoding from string.

default: Optional[Any] = None

Default value used if the parameter is not passed.

  • default: None

description: Optional[str] = None

Description of parameter.

  • default: None

max: Optional[float] = None

Maximum allowed value of the parameter.

  • default: None

min: Optional[float] = None

Minimum allowed value of the parameter.

  • default: None

name: str = None

Name of parameter.

param_type: ParamTypes = None

Type of parameter.

required: bool = True

Whether the parameter is required.

  • default: True

class ParamTypes[source]

An enumeration.

Typing Aliases

RecordType = typing.Mapping[str, typing.Any]

The central part of internal API.

This represents a generic version of type ‘origin’ with type arguments ‘params’. There are two kind of these aliases: user defined and special. The special ones are wrappers around builtin collections and ABCs in collections.abc. These must have ‘name’ always set. If ‘inst’ is False, then the alias can’t be instantiated, this is used by e.g. typing.List and typing.Dict.

Type alias to be used for Mapping-based objects in Req bodies.

API Errors

These errors will be automatically returned in response headers if raised within a route method.

exception APIError(message, error_data=None, error_id=None, send_media=False)

Base error returned by SpanAPI in http responses. Must have a unique code.

http code: 501

api code: 1000

Returned when any exception not inherited from APIError is raised from a SpanRoute method.

Init Values / Attributes
  • message: str: error message passed back in response

  • error_data: Optional[dict]: error data to be passed back in response

  • send_data: bool: send regular response data as well as error. If False: 'data' object of response is set to None

exception InvalidMethodError(message, error_data=None, error_id=None, send_media=False)

Invalid method requested from endpoint

http code: 405

api code: 1001

Returned when SpanRoute does not support request method (POST/DELETE/GET/etc.).

exception NothingToReturnError(message, error_data=None, error_id=None, send_media=False)

No Data to Return

http code: 400

api code: 1002

Returned when response schema is specified but resp.media is None, an empty list, or an empty dict.

exception RequestValidationError(message, error_data=None, error_id=None, send_media=False)

Request Data Does not match schema

http code: 400

api code: 1003

Returned when request.media() does not match schema for model supplied by SpanAPI.use_model()

exception APILimitError(message, error_data=None, error_id=None, send_media=False)

Too many items for batch request

http code: 400

api code: 1004

Request param exceeds limit

exception ResponseValidationError(message, error_data=None, error_id=None, send_media=False)

Server encountered error while validating response.

http code: 400

api code: 1005

Returned when route method with SpanAPI.use_schema() has data that fails validation.

Testing Utilities

validate_error(response, error_type)[source]

Validates response contains correct error info, prints response and headers for test logs.

Parameters
  • response (Response) – from test client.

  • error_type (Type[APIError]) – APIError class that returned error should correspond to.

Raises
Return type

Error

Returns

error data model.

Response status code and data are printed to stdout for log capture.

All exceptions are inherited from ResponseValidationError

validate_response(response, valid_status_codes=200, data_schema=None, text_value=None, expected_headers=None, expected_paging=None, paging_urls=True)[source]

Validate response object from test client. For use when writing tests.

Parameters
  • response (Response) – from test client.

  • valid_status_codes (Union[int, Tuple[int, …]]) – Status code(s) expected.

  • data_schema (Optional[Schema]) – used for loading data.

  • text_value (Optional[str]) – if text return expected, the expected text value.

  • expected_headers (Optional[Dict[str, str]]) – dict of expected headers.

  • expected_paging (Optional[PagingResp]) – Paging object with expected values.

  • paging_urls (bool) – Whether to check the URLs of the paging object. Default is True.

Return type

Optional[Any]

Returns

Loaded Data.

Raises
  • StatusMismatchError – Response http code does not match valid_status_codes.

  • TextValidationError – Response.text does not match text_value.

  • DataLoadError – Content could not be loaded as dict / bson.

  • DataValidationError – Loaded data does not match schema.

  • HeadersMismatchError – Response header values missing / different from expected_headers. Additional values are allowed. Only passed values are checked.

This function tests that:

  • Status code comes back as expected.

  • Data can be loaded by passed schema.

  • Header values match expected.

  • Text data matches expected value.

Response status code and data are printed to stdout for log capture.

All exceptions are inherited from ResponseValidationError

Testing Errors

exception ContentDecodeError[source]

Could not load data type.

exception ContentEncodeError[source]

Could not load data type.

exception NoErrorReturnedError[source]

No Error in Headers

exception ResponseValidationError[source]

Base Error for Exceptions Thrown by mismatched Responses.

exception StatusMismatchError[source]

Response status does not match expectations.

exception WrongExceptionError[source]

Error in headers does not match expected exception.

exception DataValidationError[source]

Response data does not match schema.

exception DataTypeValidationError[source]

Response data does not match schema.

exception TextValidationError[source]

Response text does not match supplied value.

exception HeadersMismatchError[source]

Headers do not match expected values.

exception ParamsMismatchError[source]

Headers do not match expected values.

exception PagingMismatchError[source]

Paging does not match expected values.

exception URLMismatchError[source]

Request URL does not match expected url.