From 1334749ac1a0220076b91f335fb1b24ca6cb60be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milan=20Fale=C5=A1n=C3=ADk?= Date: Mon, 26 Jan 2015 14:47:38 +0100 Subject: [PATCH] Make the kwargifier work on methods too. The limitation here is that only existing methods can be used (eg. x = kwargify(y.z)) because if we wanted to decorate function to become a kwargified method, the kwarigfy class would have to be a descriptor. --- .travis.yml | 7 ++++-- README.md | 1 + kwargify.py | 6 ++++- setup.py | 2 +- test_kwargify.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 27284b9..1f18be2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,5 +5,8 @@ python: - "3.2" - "3.3" - "3.4" -install: "pip install -U pytest" -script: "py.test -v" \ No newline at end of file +install: + - "pip install -U pytest pytest-cov coveralls" +script: "py.test -v --cov kwargify" +after_success: + - coveralls \ No newline at end of file diff --git a/README.md b/README.md index ea7d750..463e200 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ python-kwargify =============== [![Build Status](https://travis-ci.org/mfalesni/python-kwargify.svg?branch=master)](https://travis-ci.org/mfalesni/python-kwargify) +[![Coverage Status](https://coveralls.io/repos/mfalesni/python-kwargify/badge.svg)](https://coveralls.io/r/mfalesni/python-kwargify) [![Downloads](https://pypip.in/download/kwargify/badge.svg?style=flat)](https://pypi.python.org/pypi/kwargify/) [![Latest version](https://pypip.in/version/kwargify/badge.svg?style=flat)](https://pypi.python.org/pypi/kwargify/) [![Supported Python versions](https://pypip.in/py_versions/kwargify/badge.svg?style=flat)](https://pypi.python.org/pypi/kwargify/) diff --git a/kwargify.py b/kwargify.py index e5c936e..c8effe7 100644 --- a/kwargify.py +++ b/kwargify.py @@ -4,11 +4,15 @@ class kwargify(object): def __init__(self, function): + self._method = hasattr(function, "im_func") or type(function).__name__ == "method" self._f = function self._defaults = {} self.func_defaults = tuple([]) argspec = inspect.getargspec(self._f) - self._args = argspec.args + if self._method: + self._args = argspec.args[1:] + else: + self._args = argspec.args f_defaults = argspec.defaults if f_defaults is not None: for key, value in zip(self._args[-len(f_defaults):], f_defaults): diff --git a/setup.py b/setup.py index 0f78297..f92b8b8 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="kwargify", - version="1.1.2", + version="1.2.0", author="Milan Falešník", author_email="milan@falesnik.net", description="Python function kwargifier", diff --git a/test_kwargify.py b/test_kwargify.py index e3bd4e5..f3601ef 100644 --- a/test_kwargify.py +++ b/test_kwargify.py @@ -73,3 +73,67 @@ def test_override_default_with_arg(self, function): def test_override_default_with_kwarg(self, function): assert function(1, b=2)["b"] == 2 + + +class TestKwargifyMethod(object): + class _TestClass(object): + def noargs(self): + return locals() + + def onlyargs(self, a, b): + return locals() + + def withdefault(self, a, b=None): + return locals() + + @pytest.fixture(scope="class") + def o(self): + return self._TestClass() + + # No args test + def test_no_args_given(self, o): + kwargify(o.noargs)() + + @pytest.mark.xfail + @pytest.mark.parametrize("n", range(1, 4)) + def test_args_given(self, o, n): + kwargify(o.noargs)(*range(n + 1)) + + def test_kwargs_passed(self, o): + kwargify(o.noargs)(foo="bar") + + # Only args + @pytest.mark.xfail + def test_no_args_given_fails(self, o): + kwargify(o.onlyargs)() + + @pytest.mark.xfail + def test_args_given_not_enough(self, o): + kwargify(o.onlyargs)(1) + + def test_args_given_enough(self, o): + kwargify(o.onlyargs)(1, 2) + + @pytest.mark.xfail + def test_only_kwargs_passed_wrong(self, o): + kwargify(o.onlyargs)(foo="bar") + + @pytest.mark.xfail + def test_only_kwargs_passed_not_enough(self, o): + kwargify(o.onlyargs)(a="bar") + + def test_only_kwargs_passed(self, o): + kwargify(o.onlyargs)(a=1, b=2) + + def test_both_passed(self, o): + kwargify(o.onlyargs)(1, b=2) + + # Default values + def test_pass_only_required(self, o): + assert kwargify(o.withdefault)(1)["b"] is None + + def test_override_default_with_arg(self, o): + assert kwargify(o.withdefault)(1, 2)["b"] == 2 + + def test_override_default_with_kwarg(self, o): + assert kwargify(o.withdefault)(1, b=2)["b"] == 2