Skip to content

Commit 85cdf6b

Browse files
author
Matt Wright
committed
Adjust factory method to follow Flask extension guidelines
1 parent b8bf69e commit 85cdf6b

File tree

1 file changed

+28
-17
lines changed

1 file changed

+28
-17
lines changed

flask_restful/__init__.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import difflib
22
from functools import wraps, partial
33
import re
4-
from flask import request, Response, url_for
4+
from flask import request, Response, url_for, current_app
55
from flask import abort as original_flask_abort
66
from flask.views import MethodView
77
from flask.signals import got_request_exception
@@ -69,11 +69,14 @@ def __init__(self, app=None, prefix='',
6969
self.default_mediatype = default_mediatype
7070
self.decorators = decorators if decorators else []
7171
self.catch_all_404s = catch_all_404s
72+
self.endpoints = set()
73+
self.resources = []
74+
self.app = None
7275

7376
if app is not None:
77+
self.app = app
7478
self.init_app(app)
75-
else:
76-
self.app = None
79+
7780

7881
def init_app(self, app):
7982
"""Initialize this class with the given :class:`flask.Flask`
@@ -89,11 +92,13 @@ def init_app(self, app):
8992
api.add_resource(...)
9093
9194
"""
92-
self.app = app
93-
self.endpoints = set()
9495
app.handle_exception = partial(self.error_router, app.handle_exception)
9596
app.handle_user_exception = partial(self.error_router, app.handle_user_exception)
9697

98+
if len(self.resources) > 0:
99+
for resource, urls, kwargs in self.resources:
100+
self._register_view(app, resource, *urls, **kwargs)
101+
97102

98103
def _should_use_fr_error_handler(self):
99104
""" Determine if error should be handled with FR or default Flask
@@ -104,7 +109,7 @@ def _should_use_fr_error_handler(self):
104109
105110
:return: bool
106111
"""
107-
adapter = self.app.create_url_adapter(request)
112+
adapter = current_app.create_url_adapter(request)
108113

109114
try:
110115
adapter.match()
@@ -152,9 +157,9 @@ def handle_error(self, e):
152157
:type e: Exception
153158
154159
"""
155-
got_request_exception.send(self.app, exception=e)
160+
got_request_exception.send(current_app._get_current_object(), exception=e)
156161

157-
if not hasattr(e, 'code') and self.app.propagate_exceptions:
162+
if not hasattr(e, 'code') and current_app.propagate_exceptions:
158163
exc_type, exc_value, tb = sys.exc_info()
159164
if exc_value is e:
160165
exc = exc_type(exc_value)
@@ -171,14 +176,14 @@ def handle_error(self, e):
171176
# There's currently a bug in Python3 that disallows calling
172177
# logging.exception() when an exception hasn't actually be raised
173178
if sys.exc_info() == (None, None, None):
174-
self.app.logger.error("Internal Error")
179+
current_app.logger.error("Internal Error")
175180
else:
176-
self.app.logger.exception("Internal Error")
181+
current_app.logger.exception("Internal Error")
177182

178183
if code == 404 and ('message' not in data or
179184
data['message'] == HTTP_STATUS_CODES[404]):
180185
rules = dict([(re.sub('(<.*>)', '', rule.rule), rule.rule)
181-
for rule in self.app.url_map.iter_rules()])
186+
for rule in current_app.url_map.iter_rules()])
182187
close_matches = difflib.get_close_matches(request.path, rules.keys())
183188
if close_matches:
184189
# If we already have a message, add punctuation and continue it.
@@ -196,7 +201,7 @@ def handle_error(self, e):
196201

197202
if code == 401:
198203
resp = unauthorized(resp,
199-
self.app.config.get("HTTP_BASIC_AUTH_REALM", "flask-restful"))
204+
current_app.config.get("HTTP_BASIC_AUTH_REALM", "flask-restful"))
200205

201206
return resp
202207

@@ -229,11 +234,18 @@ def add_resource(self, resource, *urls, **kwargs):
229234
api.add_resource(FooSpecial, '/special/foo', endpoint="foo")
230235
231236
"""
237+
238+
if self.app is not None:
239+
self._register_view(self.app, resource, *urls, **kwargs)
240+
else:
241+
self.resources.append((resource, urls, kwargs))
242+
243+
def _register_view(self, app, resource, *urls, **kwargs):
232244
endpoint = kwargs.pop('endpoint', None) or resource.__name__.lower()
233245
self.endpoints.add(endpoint)
234246

235-
if endpoint in self.app.view_functions.keys():
236-
previous_view_class = self.app.view_functions[endpoint].__dict__['view_class']
247+
if endpoint in app.view_functions.keys():
248+
previous_view_class = app.view_functions[endpoint].__dict__['view_class']
237249

238250
# if you override the endpoint with a different class, avoid the collision by raising an exception
239251
if previous_view_class != resource:
@@ -246,9 +258,8 @@ def add_resource(self, resource, *urls, **kwargs):
246258
for decorator in self.decorators:
247259
resource_func = decorator(resource_func)
248260

249-
250261
for url in urls:
251-
self.app.add_url_rule(self.prefix + url, view_func=resource_func, **kwargs)
262+
app.add_url_rule(self.prefix + url, view_func=resource_func, **kwargs)
252263

253264
def output(self, resource):
254265
"""Wraps a resource (as a flask view function), for cases where the
@@ -268,7 +279,7 @@ def wrapper(*args, **kwargs):
268279
def url_for(self, resource, **values):
269280
"""Generates a URL to the given resource."""
270281
return url_for(resource.endpoint, **values)
271-
282+
272283
def make_response(self, data, *args, **kwargs):
273284
"""Looks up the representation transformer for the requested media
274285
type, invoking the transformer to create a response object. This

0 commit comments

Comments
 (0)