Skip to content

Commit

Permalink
Merge pull request #111 from druids/FixUtilHelpers
Browse files Browse the repository at this point in the history
Fixed class method utils
  • Loading branch information
matllubos committed Mar 19, 2021
2 parents f1c2ddd + 6a33d93 commit c5b64f3
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 deletions.
31 changes: 24 additions & 7 deletions chamber/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
from django.utils.text import normalize_newlines


class InvalidFunctionArguments(Exception):
pass


def remove_accent(string_with_diacritics):
"""
Removes a diacritics from a given string"
Expand All @@ -28,7 +32,7 @@ def get_class_method(cls_or_inst, method_name):
meth = meth.fget
elif isinstance(meth, cached_property):
meth = meth.func
return meth
return meth if callable(meth) else None


def keep_spacing(value, autoescape=True):
Expand All @@ -43,15 +47,28 @@ def keep_spacing(value, autoescape=True):
return mark_safe(value.replace(' ', ' &nbsp;').replace('\n', '<br />'))


def call_method_with_unknown_input(method, **fun_kwargs):
method_kwargs_names = inspect.getargspec(method)[0][1:]
def call_function_with_unknown_input(function, **kwargs):
"""
Call function and use kwargs from input if function requires them.
:param function: function to call.
:param kwargs: function input kwargs or extra kwargs which will not be used.
:return: function result or raised InvalidFunctionArguments exception.
"""
function_kwargs_names = set(inspect.signature(function).parameters.keys())

method_kwargs = {arg_name: fun_kwargs[arg_name] for arg_name in method_kwargs_names if arg_name in fun_kwargs}
required_function_kwargs_names = set(
k for k, v in inspect.signature(function).parameters.items() if v.default is v.empty
)

if len(method_kwargs_names) == len(method_kwargs):
return method(**method_kwargs)
function_kwargs = {k: v for k, v in kwargs.items() if k in function_kwargs_names}
if required_function_kwargs_names <= set(function_kwargs.keys()):
return function(**function_kwargs)
else:
raise RuntimeError('Invalid method parameters')
raise InvalidFunctionArguments(
'Function {} missing required arguments {}'.format(
function, ', '.join(required_function_kwargs_names - set(function_kwargs.keys()))
)
)


def generate_container_app_config(name,):
Expand Down
5 changes: 2 additions & 3 deletions example/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SETTINGS = settings
DJANGO_SETTINGS_MODULE = $(DJANGO_DIR).settings.$(SETTINGS)
DJANGO_POSTFIX = --settings=$(DJANGO_SETTINGS_MODULE) --pythonpath=$(PYTHONPATH)
PYTHON_BIN = $(VIRTUAL_ENV)/bin
PYTHON = python3.7
PYTHON = python3
PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1)))
PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL}).$(word 2,${PYTHON_VERSION_FULL})
TYPE = dev
Expand All @@ -40,8 +40,7 @@ pip:
$(PYTHON_BIN)/pip install -r requirements.txt

initvirtualenv:
virtualenv -p $(PYTHON) --no-site-packages $(VIRTUAL_ENV)
$(PYTHON_BIN)/pip install setuptools --upgrade
virtualenv -p $(PYTHON) $(VIRTUAL_ENV)

bootstrap: initvirtualenv pip

Expand Down
37 changes: 35 additions & 2 deletions example/dj/apps/test_chamber/tests/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
from django.test import TestCase
from django.utils.functional import cached_property
from django.utils.safestring import SafeData, mark_safe
from django.utils.functional import cached_property

from chamber.utils import get_class_method, keep_spacing, remove_accent
from chamber.utils import (
get_class_method, keep_spacing, remove_accent, call_function_with_unknown_input, InvalidFunctionArguments
)

from germanium.decorators import data_provider # pylint: disable=E0401
from germanium.tools import assert_equal, assert_true # pylint: disable=E0401
Expand All @@ -26,6 +29,8 @@ def property_method(self):
def cached_property_method(self):
pass

attribute = 'attribute'


class UtilsTestCase(TestCase):

Expand All @@ -49,10 +54,14 @@ def test_should_remove_accent_from_string_when_unicode_error(self):
[TestClass.property_method.fget, TestClass(), 'property_method'],
[TestClass.cached_property_method.func, TestClass, 'cached_property_method'],
[TestClass.cached_property_method.func, TestClass(), 'cached_property_method'],
[None, TestClass, 'attribute'],
[None, TestClass(), 'attribute'],
[None, TestClass, 'invalid'],
[None, TestClass(), 'invalid'],
]

@data_provider(classes_and_method_names)
def test_should_return_class_method(self, expected_method, cls_or_inst, method_name):
def test_get_class_method_should_return_right_class_method_or_none(self, expected_method, cls_or_inst, method_name):
assert_equal(expected_method, get_class_method(cls_or_inst, method_name))

values_for_keep_spacing = [
Expand All @@ -68,3 +77,27 @@ def test_should_keep_spacing(self, expected, value, autoescape):
escaped_value = keep_spacing(value, autoescape)
assert_equal(expected, escaped_value)
assert_true(isinstance(escaped_value, SafeData))

def test_call_function_with_unknown_input_should_return_right_response_or_exception(self):
def test_function(a, b, c):
assert_equal(a, 3)
assert_equal(b, 2)
assert_equal(c, 1)

call_function_with_unknown_input(test_function, a=3, b=2, c=1)
call_function_with_unknown_input(test_function, c=1, a=3, b=2)
call_function_with_unknown_input(test_function, c=1, a=3, b=2, d=8, e=9)

with assert_raises(InvalidFunctionArguments):
call_function_with_unknown_input(test_function, a=3, b=2)

def test_call_function_with_default_values_and_unknown_input_should_return_right_response_or_exception(self):
def test_function(a, b=5, c=6):
return a, b, c

assert_equal(call_function_with_unknown_input(test_function, a=1), (1, 5, 6))
assert_equal(call_function_with_unknown_input(test_function, c=1, a=2), (2, 5, 1))
assert_equal(call_function_with_unknown_input(test_function, b=1, a=2), (2, 1, 6))

with assert_raises(InvalidFunctionArguments):
call_function_with_unknown_input(test_function, b=2, c=1)
Empty file modified example/manage.py
100644 → 100755
Empty file.

0 comments on commit c5b64f3

Please sign in to comment.