Fix call_view_method warnings for view classes
parent
2bc9addc99
commit
b8512bda8e
|
|
@ -1,3 +1,5 @@
|
||||||
|
import six
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
@ -12,21 +14,44 @@ NotHandled = object()
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def is_callable_method(cls_or_instance, method_name):
|
||||||
|
method = getattr(cls_or_instance, method_name)
|
||||||
|
if inspect.ismethod(method) and getattr(method, '__self__', None):
|
||||||
|
# bound classmethod or instance method
|
||||||
|
return method, True
|
||||||
|
|
||||||
|
try:
|
||||||
|
# inspect.getattr_static was added in python 3.2
|
||||||
|
from inspect import getattr_static
|
||||||
|
|
||||||
|
# on python 3, both unbound instance methods (i.e. getattr(cls, mth)) and static methods are plain functions
|
||||||
|
# getattr_static allows us to check the type of the method descriptor; for `@staticmethod` this is staticmethod
|
||||||
|
return method, isinstance(getattr_static(cls_or_instance, method_name, None), staticmethod)
|
||||||
|
except ImportError:
|
||||||
|
# python 2 still has unbound methods, so ismethod <=> !staticmethod TODO: remove when dropping python 2.7
|
||||||
|
return method, not inspect.ismethod(method)
|
||||||
|
|
||||||
|
|
||||||
def call_view_method(view, method_name, fallback_attr=None, default=None):
|
def call_view_method(view, method_name, fallback_attr=None, default=None):
|
||||||
"""Call a view method which might throw an exception. If an exception is thrown, log an informative error message
|
"""Call a view method which might throw an exception. If an exception is thrown, log an informative error message
|
||||||
and return the value of fallback_attr, or default if not present.
|
and return the value of fallback_attr, or default if not present. The method must be callable without any arguments
|
||||||
|
except cls or self.
|
||||||
|
|
||||||
:param rest_framework.views.APIView view:
|
:param view: view class or instance; if a class is passed, instance methods won't be called
|
||||||
|
:type view: rest_framework.views.APIView or type[rest_framework.views.APIView]
|
||||||
:param str method_name: name of a method on the view
|
:param str method_name: name of a method on the view
|
||||||
:param str fallback_attr: name of an attribute on the view to fall back on, if calling the method fails
|
:param str fallback_attr: name of an attribute on the view to fall back on, if calling the method fails
|
||||||
:param default: default value if all else fails
|
:param default: default value if all else fails
|
||||||
:return: view method's return value, or value of view's fallback_attr, or default
|
:return: view method's return value, or value of view's fallback_attr, or default
|
||||||
|
:rtype: any or None
|
||||||
"""
|
"""
|
||||||
if hasattr(view, method_name):
|
if hasattr(view, method_name):
|
||||||
try:
|
try:
|
||||||
return getattr(view, method_name)()
|
view_method, is_callabale = is_callable_method(view, method_name)
|
||||||
|
if is_callabale:
|
||||||
|
return view_method()
|
||||||
except Exception: # pragma: no cover
|
except Exception: # pragma: no cover
|
||||||
logger.warning("view's %s.get_parsers raised exception during schema generation; use "
|
logger.warning("view's %s raised exception during schema generation; use "
|
||||||
"`getattr(self, 'swagger_fake_view', False)` to detect and short-circuit this",
|
"`getattr(self, 'swagger_fake_view', False)` to detect and short-circuit this",
|
||||||
type(view).__name__, exc_info=True)
|
type(view).__name__, exc_info=True)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@ def get_queryset_from_view(view, serializer=None):
|
||||||
:return: queryset or ``None``
|
:return: queryset or ``None``
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
queryset = call_view_method(view, 'get_queryset', 'queryset', None)
|
queryset = call_view_method(view, 'get_queryset', 'queryset')
|
||||||
|
|
||||||
if queryset is not None and serializer is not None:
|
if queryset is not None and serializer is not None:
|
||||||
# make sure the view is actually using *this* serializer
|
# make sure the view is actually using *this* serializer
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue