def path_from_view(spec, app, view, **kwargs): """Path helper that allows passing a Chalice view function.""" kwarg_ops = kwargs.get('operations') kwarg_ops = set() if not kwarg_ops else set(kwarg_ops) uri, methods = _route_for_view(app, view, path=kwargs.get('path', Path()), operations=kwarg_ops) operations = load_operations_from_docstring(view.__doc__) if not operations: operations = {} # check that the operations in the docstring match those of the actual route decorator path = Path(path=uri, operations={ method: op for method, op in iteritems(operations) if method in methods }) # add methods from route decorator that were not in docstring for op in methods: path.operations.setdefault(op, {}) return path
def _update_paths(self, data: dict, method, url_path): operations = copy.deepcopy(data) operations.pop('docked', None) if method in PATHS: self.spec.add_path( Path(path=url_path, operations={method: operations}))
def path_from_router(spec, view, operations, **kwargs): """Path helper that allows passing a bottle view function.""" operations = utils.load_operations_from_docstring(view.__doc__) app = kwargs.get('app', _default_app) route = _route_for_view(app, view) bottle_path = bottle_path_to_swagger(route.rule) return Path(path=bottle_path, operations=operations)
def path_from_view(spec, view, rule, **kwargs): """Path helper that allows passing a Werkzeug view function.""" path = werkzeugpath2swagger(rule.rule) path = urllib.parse.urljoin('/', path.lstrip('/')) operations = utils.load_operations_from_docstring(view.__doc__) path = Path(path=path, operations=operations) return path
def path_from_view(spec, view, operations, **kwargs): """Path helper that allows passing a Flask view function.""" rule = _rule_for_view(view) path = flaskpath2swagger(rule.rule) operations = utils.load_operations_from_docstring(view.__doc__) path = Path(path=path, operations=operations) return path
def test_add_path_accepts_path(self, spec): route = '/pet/{petId}' route_spec = self.paths[route] path = Path(path=route, operations={'get': route_spec['get']}) spec.add_path(path) p = spec._paths[path.path] assert p == path.operations assert 'get' in p
def path_from_view(spec, view, **kwargs): """Path helper that allows passing a Flask view function.""" rule = _rule_for_view(view) path = flaskpath2swagger(rule.rule) app_root = current_app.config['APPLICATION_ROOT'] or '/' path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/')) operations = utils.load_operations_from_docstring(view.__doc__) path = Path(path=path, operations=operations) return path
def _update_paths(self, data: dict, method: str, url_path: str): if method in PATHS: existing = [ p['name'] for p in data['parameters'] if p['in'] == 'path' ] data["parameters"].extend({ "in": "path", "name": path_key, "required": True, "type": "string" } for path_key in get_path_keys(url_path) if path_key not in existing) operations = copy.deepcopy(data) self.spec.add_path( Path(path=url_path, operations={method: operations}))
def path_from_route(spec, route, operations, **kwargs): """Path helper that allows passing a webapp2 Route or tuple.""" if not isinstance(route, BaseRoute): route = Route(*route) if operations is None: operations = {} for operation in _operations_from_methods(route.handler): operations.update(operation) if not operations: raise APISpecError( 'Could not find endpoint for route {0}'.format(route)) params_method = getattr(route.handler, list(operations.keys())[0]) path = webapp2_path_to_swagger(route, params_method) extensions = _extensions_from_handler(route.handler) operations.update(extensions) return Path(path=path, operations=operations)
def path_from_urlspec(spec, urlspec, operations, **kwargs): """Path helper that allows passing a Tornado URLSpec or tuple.""" if not isinstance(urlspec, URLSpec): urlspec = URLSpec(*urlspec) if operations is None: operations = {} for operation in _operations_from_methods(urlspec.handler_class): operations.update(operation) if not operations: raise APISpecError( 'Could not find endpoint for urlspec {0}'.format(urlspec)) params_method = getattr(urlspec.handler_class, list(operations.keys())[0]) path = tornadopath2swagger(urlspec, params_method) extensions = _extensions_from_handler(urlspec.handler_class) operations.update(extensions) return Path(path=path, operations=operations)
def path_helper(self, app, rule, operations=None, **kwargs): """Make Path from flask Rule""" path = self.flaskpath2openapi(rule.rule) app_root = app.config['APPLICATION_ROOT'] or '/' path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/')) if operations: # Get path parameters path_parameters = self.rule_to_params(rule) if path_parameters: for operation in operations.values(): parameters = operation.setdefault('parameters', []) # Add path parameters to documentation for path_p in path_parameters: parameters.append(path_p) return Path(path=path, operations=operations)
def path_from_view(spec, view, **kwargs): """Path helper that allows passing a Flask view function.""" rule = _rule_for_view(view) path = flaskpath2swagger(rule.rule) app_root = current_app.config['APPLICATION_ROOT'] or '/' path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/')) operations = utils.load_operations_from_docstring(view.__doc__) path = Path(path=path, operations=operations) if hasattr(view, 'view_class') and issubclass(view.view_class, MethodView): operations = {} for method in view.methods: method_name = method.lower() method = getattr(view.view_class, method_name) docstring_yaml = utils.load_yaml_from_docstring(method.__doc__) operations[method_name] = docstring_yaml or dict() path.operations.update(operations) return path
def path_helper(self, rule, operations=None, **kwargs): """Get path from flask Rule and set path parameters in operations""" path = self.flaskpath2openapi(rule.rule) if operations: # Get path parameters path_parameters = self.rule_to_params(rule) if path_parameters: for operation in operations.values(): parameters = operation.setdefault('parameters', []) # Add path parameters to documentation for path_p in path_parameters: parameters.append(path_p) if APISPEC_VERSION_MAJOR == 0: return Path(path=path, operations=operations) return path
def path_helper(_spec, **kwargs): """Extracts swagger spec from `flask-restful` methods.""" try: resource = kwargs.pop('resource') path = deduce_path(resource, **kwargs) # normalize path path = re.sub(r'<(?:[^:<>]+:)?([^<>]+)>', r'{\1}', path) operations = parse_operations(resource) return Path(path=path, operations=operations) except Exception as exc: logging.getLogger(__name__).exception("Exception parsing APISpec %s", exc) raise
def flask_path_helper(spec, app, rule, operations=None, **kwargs): path = flaskpath2swagger(rule.rule) app_root = app.config['APPLICATION_ROOT'] or '/' path = urljoin(app_root.rstrip('/') + '/', path.lstrip('/')) if operations: # Get path parameters path_parameters = rule_to_params(rule) if path_parameters: for operation in operations.values(): parameters = operation.setdefault('parameters', list()) # Add path parameters to documentation # If a parameter is already in the doc (because it appears in # the parameters schema), merge properties rather than # duplicate or replace for path_p in path_parameters: op_p = next((x for x in parameters if x['name'] == path_p['name']), None) if op_p is not None: op_p.update(path_p) else: parameters.append(path_p) # Translate Marshmallow Schema for operation in operations.values(): for response in operation.get('responses', {}).values(): if 'schema' in response: # If the API returns a list, # the schema is specfied as [schema] if isinstance(response['schema'], list): response['schema'] = [ resolve_schema_dict(spec, response['schema'][0]) ] else: response['schema'] = resolve_schema_dict( spec, response['schema']) for parameter in operation.get('parameters', []): if 'schema' in parameter: parameter['schema'] = resolve_schema_dict( spec, parameter['schema']) return Path(path=path, operations=operations)
def _route_for_view(current_app, view, path=Path(), operations=set()): view_funcs = current_app.routes for uri, endpoint in iteritems(view_funcs): methods = set() for method, route_entry in iteritems(endpoint): method = method.lower() if route_entry.view_function == view and (not operations or method in operations): if path.path and not path.path == uri: break else: methods.add(method) else: if methods: return uri, methods raise APISpecError( 'Could not find endpoint for view {0} and path {1}'.format( view, getattr(path, 'path', None)))
def path_from_urlspec(spec, route, operations, **kwargs): if not isinstance(route, ResourceRoute): raise Exception('Route is not ResourceRoute instance %s' % type(route)) extensions = extensions_from_handler(route.handler) if operations is None: operations = {} for operation in operations_from_methods(route.handler, extensions): operations.update(operation) if not operations: raise APISpecError( 'Could not find endpoint for route {0}'.format(route)) if isinstance(route.resource, DynamicResource): path = route.get_info()['formatter'] if isinstance(route.resource, PlainResource): path = route.get_info()['path'] return Path(path=path, operations=operations)
def path_helper(self, rule=None, operations=None, **kwargs): """Get path from flask Rule and set path parameters in operations""" if rule is None: raise PluginMethodNotImplementedError for path_p in self.rule_to_params(rule): for operation in operations.values(): parameters = operation.setdefault("parameters", []) # If a parameter with same name and location is already # documented, update. Otherwise, append as new parameter. p_doc = next((p for p in parameters if p["in"] == "path" and p["name"] == path_p["name"]), None) if p_doc is not None: # If parameter already documented, mutate to update doc # Ensure manual doc overwrites auto doc p_doc.update({**path_p, **p_doc}) else: parameters.append(path_p) path = self.flaskpath2openapi(rule.rule) if APISPEC_VERSION_MAJOR == 0: return Path(path=path, operations=operations) return path
def path_helper(_spec, **kwargs): """Extracts swagger spec from `flask-restful` methods.""" try: resource = kwargs.pop('resource') except KeyError: # Skip when resource isn't provided. This allows other extensions # to process this path. raise TypeError try: path = deduce_path(resource, **kwargs) # normalize path path = re.sub(r'<(?:[^:<>]+:)?([^<>]+)>', r'{\1}', path) operations = parse_operations(resource) return Path(path=path, operations=operations) except Exception as exc: logging.getLogger(__name__).exception("Exception parsing APISpec %s", exc) raise
def path_helper(self, rule, operations=None, **kwargs): """Get path from flask Rule and set path parameters in operations""" path = self.flaskpath2openapi(rule.rule) if operations: # Get path parameters path_parameters = self.rule_to_params(rule) if path_parameters: for operation in operations.values(): parameters = operation.setdefault('parameters', []) # Add path parameters to documentation, updating if the name already exists for path_p in path_parameters: updated = False for existing in parameters: if getattr(existing, "name", None) == path_p["name"]: existing = deepupdate(path_p, existing) updated = True if not updated: parameters.append(path_p) if APISPEC_VERSION_MAJOR == 0: return Path(path=path, operations=operations) return path
def path_helper(self, path, **kwargs): if path.path == '/path_1': return Path( path='/path_1_modified', operations={'get': {'responses': {'200': {}}}}, )
def path_helper(spec, view_func, **kwargs): return Path(path=view_func['path'])
def helper2(spec, eggs, **kwargs): return Path(path='/foo/bar')
def helper1(spec, spam, **kwargs): return Path(path='/foo/bar')
def test_add_path_strips_path_base_path(self, spec): spec.options['basePath'] = '/v1' path = Path(path='/v1/pets') spec.add_path(path) assert '/pets' in spec._paths assert '/v1/pets' not in spec._paths
def path_helper(self, view=None, **kwargs): """Path helper that allows passing a Schema as a response. Responses can be defined in a view's docstring. :: from pprint import pprint from my_app import Users, UserSchema class UserHandler: def get(self, user_id): '''Get a user endpoint. --- description: Get a user responses: 200: description: A user schema: UserSchema ''' user = Users.get(id=user_id) schema = UserSchema() return schema.dumps(user) urlspec = (r'/users/{user_id}', UserHandler) spec.add_path(urlspec=urlspec) pprint(spec.to_dict()['paths']) # {'/users/{user_id}': {'get': {'description': 'Get a user', # 'responses': {200: {'description': 'A user', # 'schema': {'$ref': '#/definitions/User'}}}}}} :: from pprint import pprint from my_app import Users, UserSchema class UsersHandler: def get(self): '''Get users endpoint. --- description: Get a list of users responses: 200: description: A list of user schema: type: array items: UserSchema ''' users = Users.all() schema = UserSchema(many=True) return schema.dumps(users) urlspec = (r'/users', UsersHandler) spec.add_path(urlspec=urlspec) pprint(spec.to_dict()['paths']) # {'/users': {'get': {'description': 'Get a list of users', # 'responses': {200: {'description': 'A list of users', # 'schema': {'type': 'array', # 'items': {'$ref': '#/definitions/User'}}}}}}} """ operations = (kwargs.get('operations') or (view and utils.load_operations_from_docstring(view.__doc__))) if not operations: return None operations = operations.copy() return Path(operations=operations)
def path_helper(spec, view_func, **kwargs): return Path(path=view_func['path'], method='get')
def resource_path_helper(spec, path, resource): """Provides path when given a FlaskRestful resource""" operations = utils.load_operations_from_docstring(resource.__doc__) return Path(path=path, operations=operations)
def docstring_path_helper(spec, path, router, func, **kwargs): operations = load_operations_from_docstring(func.__doc__) cp_config = func._cp_config if operations is not None: for method, data in operations.items(): if cp_config.get('tools.authentication.on', True): data['security'] = [{'Bearer': []}] if 'tools.model_in.cls' in cp_config: model_cls = cp_config['tools.model_in.cls'] spec.definition(model_cls.__name__, **parse_model(spec, model_cls)) data['requestBody']['required'] = True data['requestBody']['content'] = { 'application/json': { 'schema': { '$ref': '#/components/schemas/' + model_cls.__name__ } } } if 'tools.model_params.cls' in cp_config: model_cls = cp_config['tools.model_params.cls'] data['parameters'] = data.get('parameters', []) # In query vs in path for key, obj in model_cls.__dict__.items(): inn = 'query' if '{' + key + '}' in path.path: inn = 'path' if isinstance(obj, FieldDescriptor): data['parameters'].append({ 'name': key, 'in': inn, 'required': model_cls._fields[key].required, 'schema': parse_model_type(spec, model_cls._fields[key]) }) if 'tools.model_out.cls' in cp_config: model_cls = cp_config['tools.model_out.cls'] spec.definition(model_cls.__name__, **parse_model(spec, model_cls)) data['responses'][200]['content'] = { 'application/json': { 'schema': { '$ref': '#/components/schemas/' + model_cls.__name__ } } } if 'tools.model_out_pagination.cls' in cp_config: model_cls = cp_config['tools.model_out_pagination.cls'] spec.definition(model_cls.__name__, **parse_model(spec, model_cls)) data['responses'][200]['content'] = { 'application/json': { 'schema': { 'type': 'array', 'items': { '$ref': '#/components/schemas/' + model_cls.__name__ } } } } if isinstance(router, SandwichProjectRouter): data['parameters'] = data.get('parameters', []) data['parameters'].append({ 'name': 'project_name', 'in': 'path', 'required': True, 'schema': { 'type': 'string' } }) if 'tools.enforce_permission.permission_name' in cp_config: data['x-required-permission'] = cp_config[ 'tools.enforce_permission.permission_name'] return Path(path=path.path, operations=operations)
def _update_paths(self, data: dict, method: str, url_path: str): operations = copy.deepcopy(data) if method in PATHS: self.spec.add_path(Path(path=url_path, operations={method: operations}))