diff --git a/business_rules/__init__.py b/business_rules/__init__.py index dfea36f9..54e87a48 100644 --- a/business_rules/__init__.py +++ b/business_rules/__init__.py @@ -1,4 +1,4 @@ -__version__ = '1.4.1' +__version__ = '1.4.2' from .engine import run_all, check_conditions_recursively from .utils import export_rule_data, validate_rule_data diff --git a/business_rules/engine.py b/business_rules/engine.py index 09cc3ca2..9b4c4810 100644 --- a/business_rules/engine.py +++ b/business_rules/engine.py @@ -6,6 +6,7 @@ from .fields import FIELD_NO_INPUT from .models import ConditionResult from .util import method_type +from .util.compat import getfullargspec logger = logging.getLogger(__name__) @@ -230,7 +231,7 @@ def _build_variable_parameters(method, parameters, rule): def _build_parameters(method, parameters, extra_parameters): - if inspect.getargspec(method).keywords is not None: + if getfullargspec(method).varkw is not None: method_params = extra_parameters else: method_params = {} diff --git a/business_rules/util/compat.py b/business_rules/util/compat.py new file mode 100644 index 00000000..0caba58f --- /dev/null +++ b/business_rules/util/compat.py @@ -0,0 +1,33 @@ +from __future__ import absolute_import, unicode_literals + +import sys +from collections import namedtuple + +PY2 = sys.version_info[0] == 2 + +# Taken from https://github.com/HypothesisWorks/hypothesis/pull/625/files#diff-e84a85b835af44101e1986c47ba39630R264 +if PY2: + FullArgSpec = namedtuple('FullArgSpec', 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations') + + def getfullargspec(func): + import inspect + args, varargs, varkw, defaults = inspect.getargspec(func) + return FullArgSpec(args, varargs, varkw, defaults, [], None, {}) +else: + from inspect import getfullargspec + + if sys.version_info[:2] == (3, 5): + # silence deprecation warnings on Python 3.5 + # (un-deprecated in 3.6 to allow single-source 2/3 code like this) + def silence_warnings(func): + import warnings + import functools + + @functools.wraps(func) + def inner(*args, **kwargs): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + return func(*args, **kwargs) + return inner + + getfullargspec = silence_warnings(getfullargspec) diff --git a/tests/test_engine_logic.py b/tests/test_engine_logic.py index 2386eec3..2ee8d6f7 100644 --- a/tests/test_engine_logic.py +++ b/tests/test_engine_logic.py @@ -195,8 +195,8 @@ def test_check_operator_comparison(self): # ##################################### # def test_do_actions(self): function_params_mock = MagicMock() - function_params_mock.keywords = None - with patch('inspect.getargspec', return_value=function_params_mock): + function_params_mock.varkw = None + with patch('business_rules.engine.getfullargspec', return_value=function_params_mock): rule_actions = [ { 'name': 'action1' @@ -232,8 +232,8 @@ def test_do_actions(self): def test_do_actions_with_injected_parameters(self): function_params_mock = MagicMock() - function_params_mock.keywords = True - with patch('inspect.getargspec', return_value=function_params_mock): + function_params_mock.varkw = True + with patch('business_rules.engine.getfullargspec', return_value=function_params_mock): rule_actions = [ { 'name': 'action1'