From e81e569328e454baba03355df473182d73b88428 Mon Sep 17 00:00:00 2001 From: Le Van Vuong Date: Sun, 13 Jun 2021 12:46:19 +0700 Subject: [PATCH 1/6] Fixed invalid methods error in falcon 3 --- falcon_apispec/falcon_plugin.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/falcon_apispec/falcon_plugin.py b/falcon_apispec/falcon_plugin.py index 9583a93..91ae954 100644 --- a/falcon_apispec/falcon_plugin.py +++ b/falcon_apispec/falcon_plugin.py @@ -2,6 +2,7 @@ import re from apispec import BasePlugin, yaml_utils from apispec.exceptions import APISpecError +from apispec.core import VALID_METHODS class FalconPlugin(BasePlugin): @@ -11,8 +12,14 @@ def __init__(self, app): super(FalconPlugin, self).__init__() self._app = app - @staticmethod - def _generate_resource_uri_mapping(app): + def init_spec(self, spec): + self._spec = spec + + def _get_valid_methods(self): + return set(VALID_METHODS[self._spec.openapi_version.major]) + + def _generate_resource_uri_mapping(self, app): + valid_methods = self._get_valid_methods() routes_to_check = copy.copy(app._router._roots) mapping = {} @@ -28,6 +35,8 @@ def _generate_resource_uri_mapping(app): for method_name, method_handler in route.method_map.items(): if method_handler.__dict__.get("__module__") == "falcon.responders": continue + if method_name.lower() not in valid_methods: + continue mapping[resource]["methods"][method_name.lower()] = method_handler routes_to_check.extend(route.children) From e45d1bc169c3ce20119d3294373f8c18e7860941 Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 30 Dec 2021 12:46:31 -0600 Subject: [PATCH 2/6] Apply changes to support falcon3 --- falcon_apispec/falcon_plugin.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/falcon_apispec/falcon_plugin.py b/falcon_apispec/falcon_plugin.py index 9583a93..3511680 100644 --- a/falcon_apispec/falcon_plugin.py +++ b/falcon_apispec/falcon_plugin.py @@ -2,7 +2,7 @@ import re from apispec import BasePlugin, yaml_utils from apispec.exceptions import APISpecError - +from apispec.core import VALID_METHODS class FalconPlugin(BasePlugin): """APISpec plugin for Falcon""" @@ -11,8 +11,14 @@ def __init__(self, app): super(FalconPlugin, self).__init__() self._app = app - @staticmethod - def _generate_resource_uri_mapping(app): + def init_spec(self, spec): + self._spec = spec + + def _get_valid_methods(self): + return set(VALID_METHODS[self._spec.openapi_version.major]) + + def _generate_resource_uri_mapping(self, app): + valid_methods = self._get_valid_methods() routes_to_check = copy.copy(app._router._roots) mapping = {} @@ -26,7 +32,9 @@ def _generate_resource_uri_mapping(app): if route.method_map: for method_name, method_handler in route.method_map.items(): - if method_handler.__dict__.get("__module__") == "falcon.responders": + if method_handler.__module__ == "falcon.responders": + continue + if method_name.lower() not in valid_methods: continue mapping[resource]["methods"][method_name.lower()] = method_handler From 869998eedcb5802ae8fdc8ab2ce94a33faa13551 Mon Sep 17 00:00:00 2001 From: Javier Lopez Lopez Date: Thu, 30 Dec 2021 12:56:15 -0600 Subject: [PATCH 3/6] Update version.py --- falcon_apispec/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/falcon_apispec/version.py b/falcon_apispec/version.py index 6a9beea..3d26edf 100644 --- a/falcon_apispec/version.py +++ b/falcon_apispec/version.py @@ -1 +1 @@ -__version__ = "0.4.0" +__version__ = "0.4.1" From beedaf843ac21ebc178fe20235b15d6788d5f995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Santos?= Date: Thu, 8 Dec 2022 02:50:29 +0000 Subject: [PATCH 4/6] Use falcon.routing.map_http_methods to get list of methods - Get route for specific resource instead of creating a mapping for all resources using filter - Get uri from route - Get methods from resource with falcon.routing.map_http_methods instead of getting methods from route.method_map. NOTE: The main difference is that route.method_map returns all methods ["GET", "POST", "PUT", ...] regardless if the resource is implementing that method. Using falcon.routing.map_http_methods only implemented methods are listed. This allows for a much cleaner API Spec that doesn't list unsupported methods. --- falcon_apispec/falcon_plugin.py | 87 +++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/falcon_apispec/falcon_plugin.py b/falcon_apispec/falcon_plugin.py index 427fb54..987eba1 100644 --- a/falcon_apispec/falcon_plugin.py +++ b/falcon_apispec/falcon_plugin.py @@ -3,7 +3,7 @@ from apispec import BasePlugin, yaml_utils from apispec.exceptions import APISpecError from apispec.core import VALID_METHODS - +from falcon.routing import map_http_methods class FalconPlugin(BasePlugin): """APISpec plugin for Falcon""" @@ -18,41 +18,67 @@ def init_spec(self, spec): def _get_valid_methods(self): return set(VALID_METHODS[self._spec.openapi_version.major]) - def _generate_resource_uri_mapping(self, app): + # def _generate_resource_uri_mapping(self, app, resource): + # valid_methods = self._get_valid_methods() + # routes_to_check = copy.copy(app._router._roots) + + # mapping = {} + # for route in routes_to_check: + # uri = route.uri_template + # resource = route.resource + # mapping[resource] = { + # "uri": uri, + # "methods": {} + # } + + # if route.method_map: + # for method_name, method_handler in route.method_map.items(): + # if method_handler.__module__ == "falcon.responders": + # continue + # if method_name.lower() not in valid_methods: + # continue + # if method_name.lower() not in valid_methods: + # continue + # mapping[resource]["methods"][method_name.lower()] = method_handler + + # routes_to_check.extend(route.children) + # return mapping + + def _generate_resource_uri(self, resource): valid_methods = self._get_valid_methods() - routes_to_check = copy.copy(app._router._roots) - - mapping = {} - for route in routes_to_check: - uri = route.uri_template - resource = route.resource - mapping[resource] = { - "uri": uri, - "methods": {} - } - - if route.method_map: - for method_name, method_handler in route.method_map.items(): - if method_handler.__module__ == "falcon.responders": - continue - if method_name.lower() not in valid_methods: - continue - if method_name.lower() not in valid_methods: - continue - mapping[resource]["methods"][method_name.lower()] = method_handler - - routes_to_check.extend(route.children) - return mapping + routes_to_check = copy.copy(self._app._router._roots) + + route = next(filter(lambda r: r.resource == resource, routes_to_check), None) + resource_methods = map_http_methods(resource) + + uri = route.uri_template + methods = {} + if resource_methods: + for method_name, method_handler in resource_methods: + if method_handler.__module__ == "falcon.responders": + continue + if method_name.lower() not in valid_methods: + continue + if method_name.lower() not in valid_methods: + continue + methods[method_name.lower()] = method_handler + + return { + "uri": uri, + "methods": methods + } def path_helper(self, operations, resource, base_path=None, **kwargs): """Path helper that allows passing a Falcon resource instance.""" - resource_uri_mapping = self._generate_resource_uri_mapping(self._app) - - if resource not in resource_uri_mapping: + #resource_uri_mapping = self._generate_resource_uri_mapping(self._app, resource) + resource_uri = self._generate_resource_uri(resource) + #if resource not in resource_uri_mapping: + if not resource_uri: raise APISpecError("Could not find endpoint for resource {0}".format(resource)) operations.update(yaml_utils.load_operations_from_docstring(resource.__doc__) or {}) - path = resource_uri_mapping[resource]["uri"] + #path = resource_uri_mapping[resource]["uri"] + path = resource_uri["uri"] if base_path is not None: # make sure base_path accept either with or without leading slash @@ -60,7 +86,8 @@ def path_helper(self, operations, resource, base_path=None, **kwargs): base_path = '/' + base_path.strip('/') path = re.sub(base_path, "", path, 1) - methods = resource_uri_mapping[resource]["methods"] + #methods = resource_uri_mapping[resource]["methods"] + methods = resource_uri["methods"] for method_name, method_handler in methods.items(): docstring_yaml = yaml_utils.load_yaml_from_docstring(method_handler.__doc__) From ada896ef2e5b2d40434d191eda3e67b0bdff0c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Santos?= Date: Thu, 8 Dec 2022 02:50:44 +0000 Subject: [PATCH 5/6] Fix BREAKING BUG in for :facepalm --- falcon_apispec/falcon_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/falcon_apispec/falcon_plugin.py b/falcon_apispec/falcon_plugin.py index 987eba1..b189a29 100644 --- a/falcon_apispec/falcon_plugin.py +++ b/falcon_apispec/falcon_plugin.py @@ -54,7 +54,7 @@ def _generate_resource_uri(self, resource): uri = route.uri_template methods = {} if resource_methods: - for method_name, method_handler in resource_methods: + for method_name, method_handler in resource_methods.items(): if method_handler.__module__ == "falcon.responders": continue if method_name.lower() not in valid_methods: From da172c90710e8af64e0f6c76c9683ad46fe0170c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Santos?= Date: Thu, 8 Dec 2022 02:50:50 +0000 Subject: [PATCH 6/6] Remove commented code --- falcon_apispec/falcon_plugin.py | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/falcon_apispec/falcon_plugin.py b/falcon_apispec/falcon_plugin.py index b189a29..361714b 100644 --- a/falcon_apispec/falcon_plugin.py +++ b/falcon_apispec/falcon_plugin.py @@ -18,32 +18,6 @@ def init_spec(self, spec): def _get_valid_methods(self): return set(VALID_METHODS[self._spec.openapi_version.major]) - # def _generate_resource_uri_mapping(self, app, resource): - # valid_methods = self._get_valid_methods() - # routes_to_check = copy.copy(app._router._roots) - - # mapping = {} - # for route in routes_to_check: - # uri = route.uri_template - # resource = route.resource - # mapping[resource] = { - # "uri": uri, - # "methods": {} - # } - - # if route.method_map: - # for method_name, method_handler in route.method_map.items(): - # if method_handler.__module__ == "falcon.responders": - # continue - # if method_name.lower() not in valid_methods: - # continue - # if method_name.lower() not in valid_methods: - # continue - # mapping[resource]["methods"][method_name.lower()] = method_handler - - # routes_to_check.extend(route.children) - # return mapping - def _generate_resource_uri(self, resource): valid_methods = self._get_valid_methods() routes_to_check = copy.copy(self._app._router._roots) @@ -70,14 +44,11 @@ def _generate_resource_uri(self, resource): def path_helper(self, operations, resource, base_path=None, **kwargs): """Path helper that allows passing a Falcon resource instance.""" - #resource_uri_mapping = self._generate_resource_uri_mapping(self._app, resource) resource_uri = self._generate_resource_uri(resource) - #if resource not in resource_uri_mapping: if not resource_uri: raise APISpecError("Could not find endpoint for resource {0}".format(resource)) operations.update(yaml_utils.load_operations_from_docstring(resource.__doc__) or {}) - #path = resource_uri_mapping[resource]["uri"] path = resource_uri["uri"] if base_path is not None: @@ -86,7 +57,6 @@ def path_helper(self, operations, resource, base_path=None, **kwargs): base_path = '/' + base_path.strip('/') path = re.sub(base_path, "", path, 1) - #methods = resource_uri_mapping[resource]["methods"] methods = resource_uri["methods"] for method_name, method_handler in methods.items():