1# -*- coding: utf-8 -*- 2# Copyright (c) 2015 Spotify AB 3 4from __future__ import absolute_import, division, print_function 5 6import attr 7from six.moves import BaseHTTPServer as httpserver # NOQA 8 9from .parameters import Content 10from .validate import * # NOQA 11 12HTTP_RESP_CODES = httpserver.BaseHTTPRequestHandler.responses.keys() 13AVAILABLE_METHODS = [ 14 "get", "post", "put", "delete", "patch", "head", "options", 15 "trace", "connect" 16] 17 18METHOD_PROPERTIES = [ 19 "headers", "body", "responses", "query_params", "form_params" 20] 21 22 23@attr.s 24class RootNode(object): 25 """ 26 API Root Node 27 28 :param dict raw: dict of loaded RAML data 29 :param str version: API version 30 :param str base_uri: API's base URI 31 :param list base_uri_params: parameters for base URI, or ``None``. \ 32 The order of ``base_uri_params`` will follow the order \ 33 defined in the :py:obj:`.RootNode.base_uri`. 34 :param list uri_params: URI parameters that can apply to all resources, \ 35 or ``None``. The order of ``uri_params`` will follow the order \ 36 defined in the :py:obj:`.RootNode.base_uri`. 37 :param list protocols: API-supported protocols, defaults to protocol \ 38 in ``base_uri`` 39 :param str title: API Title 40 :param list docs: list of :py:class:`parameters.Documentation` objects, \ 41 or ``None`` 42 :param list schemas: list of dictionaries, or ``None`` 43 :param str media_type: default accepted request/response media type, \ 44 or ``None`` 45 :param list resource_types: list of :py:class:`ResourceTypeNode`, \ 46 or ``None`` 47 :param list traits: list of :py:class:`TraitNode`, or ``None`` 48 :param list security_schemes: list of \ 49 :py:class:`parameters.SecurityScheme` objects, or ``None`` 50 :param list resources: list of :py:class:`ResourceNode` objects, \ 51 or ``None`` 52 :param raml_obj: loaded :py:class:`raml.RAMLDict` object 53 """ 54 raw = attr.ib(repr=False) 55 version = attr.ib(repr=False, validator=root_version) 56 base_uri = attr.ib(repr=False, validator=root_base_uri) 57 base_uri_params = attr.ib(repr=False, 58 validator=root_base_uri_params) 59 uri_params = attr.ib(repr=False, validator=root_uri_params) 60 protocols = attr.ib(repr=False, validator=root_protocols) 61 title = attr.ib(validator=root_title) 62 documentation = attr.ib(repr=False, validator=root_docs) 63 schemas = attr.ib(repr=False, validator=root_schemas) 64 media_type = attr.ib(repr=False, validator=root_media_type) 65 secured_by = attr.ib(repr=False, validator=root_secured_by) 66 resource_types = attr.ib(repr=False, init=False) 67 traits = attr.ib(repr=False, init=False) 68 security_schemes = attr.ib(repr=False, init=False) 69 resources = attr.ib(repr=False, init=False, 70 validator=root_resources) 71 raml_obj = attr.ib(repr=False) 72 config = attr.ib(repr=False, 73 validator=attr.validators.instance_of(dict)) 74 errors = attr.ib(repr=False) 75 76 77@attr.s 78class BaseNode(object): 79 """ 80 :param dict raw: The raw data parsed from the RAML file 81 :param RootNode root: Back reference to the node's API root 82 :param list headers: List of node's :py:class:`parameters.Header` \ 83 objects, or ``None`` 84 :param list body: List of node's :py:class:`parameters.Body` objects, \ 85 or ``None`` 86 :param list responses: List of node's :py:class:`parameters.Response`\ 87 objects, or ``None`` 88 :param list uri_params: List of node's :py:class:`parameters.URIParameter`\ 89 objects, or ``None``. The order of ``uri_params`` will follow the \ 90 order defined in the \ 91 :py:obj:`.ResourceNode.absolute_uri`. 92 :param list base_uri_params: List of node's base \ 93 :py:obj:`parameters.URIParameter` objects, or ``None``. The order of \ 94 ``base_uri_params`` will follow the order defined in the \ 95 :py:attribute:`.ResourceNode.absolute_uri`. 96 :param list query_params: List of node's \ 97 :py:obj:`parameters.QueryParameter` objects, or ``None`` 98 :param list form_params: List of node's \ 99 :py:class:`parameters.FormParameter` objects, or ``None`` 100 :param str media_type: Supported request MIME media type. Defaults to \ 101 :py:class:`RootNode`'s ``media_type``. 102 :param str description: Description of node. 103 :param list protocols: List of ``str`` 's of supported protocols. \ 104 Defaults to :py:class:`RootNode`'s ``protocols``. 105 """ 106 root = attr.ib(repr=False) 107 headers = attr.ib(repr=False) 108 body = attr.ib(repr=False) 109 responses = attr.ib(repr=False) 110 uri_params = attr.ib(repr=False) 111 base_uri_params = attr.ib(repr=False) 112 query_params = attr.ib(repr=False) 113 form_params = attr.ib(repr=False) 114 media_type = attr.ib(repr=False) 115 desc = attr.ib(repr=False) 116 protocols = attr.ib(repr=False) 117 errors = attr.ib(repr=False) 118 119 @property 120 def description(self): 121 return Content(self.desc) 122 123 124@attr.s 125class TraitNode(BaseNode): 126 """ 127 RAML Trait object 128 129 :param str name: Name of trait 130 :param str usage: Usage of trait 131 """ 132 name = attr.ib() 133 raw = attr.ib(repr=False, validator=defined_trait) 134 usage = attr.ib(repr=False) 135 136 137@attr.s 138class ResourceTypeNode(BaseNode): 139 """ 140 RAML Resource Type object 141 142 :param str name: Name of resource type 143 :param str type: Name of inherited :py:class:`ResourceTypeNode` object, 144 or ``None``. 145 :param str method: Supported method. If ends in ``?``, parameters will \ 146 only be applied to assigned resource if resource implements this \ 147 method. Else, resource must implement the method. 148 :param str usage: Usage of resource type, or ``None`` 149 :param bool optional: Inherited if resource defines method. 150 :param list is\_: List of assigned trait names, or ``None`` 151 :param list traits: List of assigned :py:class:`TraitNode` objects, \ 152 or ``None`` 153 :param str secured_by: List of ``str`` s or ``dict`` s of assigned \ 154 security scheme, or ``None``. If a ``str``, the name of the security \ 155 scheme. If a ``dict``, the key is the name of the scheme, the values \ 156 are the parameters assigned (e.g. relevant OAuth 2 scopes). 157 :param list security_schemes: A list of assigned \ 158 :py:class:`parameters.SecurityScheme` objects, or ``None``. 159 :param str display_name: User-friendly name of resource; \ 160 defaults to ``name`` 161 162 """ 163 name = attr.ib() 164 raw = attr.ib(repr=False, validator=defined_resource_type) 165 type = attr.ib(repr=False, validator=assigned_res_type) 166 method = attr.ib(repr=False) 167 usage = attr.ib(repr=False) 168 optional = attr.ib(repr=False) 169 is_ = attr.ib(repr=False, validator=assigned_traits) 170 traits = attr.ib(repr=False) 171 secured_by = attr.ib(repr=False) 172 security_schemes = attr.ib(repr=False) 173 display_name = attr.ib(repr=False) 174 175 176@attr.s 177class ResourceNode(BaseNode): 178 """ 179 Supported API-endpoint (“resource”) 180 181 :param str name: Resource name 182 :param ResourceNode parent: parent node object if any, or ``None`` 183 :param str method: HTTP method for resource, or ``None`` 184 :param str display_name: User-friendly name of resource; \ 185 defaults to ``name`` 186 :param str path: relative path of resource 187 :param str absolute_uri: Absolute URI of resource: \ 188 :py:class:`RootNode`'s ``base_uri`` + ``path`` 189 :param list is\_: A list of ``str`` s or ``dict`` s of resource-assigned \ 190 traits, or ``None`` 191 :param list traits: A list of assigned :py:class:`TraitNode` objects, \ 192 or ``None`` 193 :param str type: The name of the assigned resource type, or ``None`` 194 :param ResourceTypeNode resource_type: The assigned \ 195 :py:class:`ResourceTypeNode` object 196 :param list secured_by: A list of ``str`` s or ``dict`` s of resource-\ 197 assigned security schemes, or ``None``. If a ``str``, the name of the \ 198 security scheme. If a ``dict``, the key is the name of the scheme, \ 199 the values are the parameters assigned (e.g. relevant OAuth 2 scopes). 200 :param list security_schemes: A list of assigned \ 201 :py:class:`parameters.SecurityScheme` objects, or ``None``. 202 """ 203 name = attr.ib(repr=False) 204 raw = attr.ib(repr=False) 205 parent = attr.ib(repr=False) 206 method = attr.ib() 207 display_name = attr.ib(repr=False) 208 path = attr.ib() 209 absolute_uri = attr.ib(repr=False) 210 is_ = attr.ib(repr=False, validator=assigned_traits) 211 traits = attr.ib(repr=False) 212 type = attr.ib(repr=False, validator=assigned_res_type) 213 resource_type = attr.ib(repr=False) 214 secured_by = attr.ib(repr=False) 215 security_schemes = attr.ib(repr=False) 216 217 def _inherit_type(self): 218 for p in METHOD_PROPERTIES: 219 inherited_prop = getattr(self.resource_type, p) 220 resource_prop = getattr(self, p) 221 if resource_prop and inherited_prop: 222 for r in resource_prop: 223 r._inherit_type_properties(inherited_prop) 224