[POS-commit] r1308 - in kiwi/trunk: . kiwi tests
Johan Dahlin
jdahlin at async.com.br
Fri Sep 30 11:50:38 BRT 2005
Author: jdahlin
Date: Fri Sep 30 11:50:37 2005
New Revision: 1308
Added:
kiwi/trunk/kiwi/argcheck.py
kiwi/trunk/tests/test_argcheck.py
Modified:
kiwi/trunk/ChangeLog
Log:
* tests/test_argcheck.py (ArgTest.testUserDefined): Add some basic
tests.
* kiwi/argcheck.py: Move in decorator from fiscalprinter.
Add some additional tests and support for checking default values.
Modified: kiwi/trunk/ChangeLog
==============================================================================
--- kiwi/trunk/ChangeLog (original)
+++ kiwi/trunk/ChangeLog Fri Sep 30 11:50:37 2005
@@ -1,3 +1,11 @@
+2005-09-30 Johan Dahlin <jdahlin at async.com.br>
+
+ * tests/test_argcheck.py (ArgTest.testUserDefined): Add some basic
+ tests.
+
+ * kiwi/argcheck.py: Move in decorator from fiscalprinter.
+ Add some additional tests and support for checking default values.
+
2005-09-28 Johan Dahlin <jdahlin at async.com.br>
* kiwi/ui/widgets/list.py:
Added: kiwi/trunk/kiwi/argcheck.py
==============================================================================
--- (empty file)
+++ kiwi/trunk/kiwi/argcheck.py Fri Sep 30 11:50:37 2005
@@ -0,0 +1,131 @@
+#
+# Kiwi: a Framework and Enhanced Widgets for Python
+#
+# Copyright (C) 2005 Async Open Source
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+#
+# Author(s): Johan Dahlin <jdahlin at async.com.br>
+#
+
+import inspect
+
+class CustomType(type):
+ @classmethod
+ def value_check(cls, name, value):
+ pass
+
+class number(CustomType):
+ type = int, float
+
+class percent(CustomType):
+ type = int, float
+ @classmethod
+ def value_check(cls, name, value):
+ if 0 > value < 100:
+ raise ValueError("%s must be between 0 and 100" % name)
+
+class argcheck(object):
+ __enabled__ = True
+
+ def __init__(self, *types):
+ for argtype in types:
+ if not isinstance(argtype, type):
+ raise TypeError("must be a type instance")
+ self.types = types
+
+ @classmethod
+ def enable(cls):
+ """
+ Enable argcheck globally
+ """
+ cls.__enabled__ = True
+
+ @classmethod
+ def disable(cls):
+ """
+ Disable argcheck globally
+ """
+ cls.__enabled__ = False
+
+ def __call__(self, func):
+ if not callable(func):
+ raise TypeError("%r must be callable" % func)
+
+ spec = inspect.getargspec(func)
+ arg_names, is_varargs, is_kwargs, default_values = spec
+ if is_kwargs and not is_varargs and self.types:
+ raise TypeError("argcheck cannot be used with only keywords")
+
+ types = self.types
+ defs = len(default_values or ())
+
+ kwarg_types = {}
+ for i, arg_name in enumerate(arg_names):
+ kwarg_types[arg_name] = types[i]
+
+ pos = defs - i
+ if defs and pos < defs:
+ value = default_values[pos]
+ arg_type = types[pos]
+ try:
+ self._type_check(value, arg_type, arg_name)
+ except TypeError:
+ raise TypeError("default value for %s must be of type %s "
+ "and not %s" % (arg_name,
+ arg_type.__name__,
+ type(value).__name__))
+ if not is_varargs:
+ if len(types) != len(arg_names):
+ raise TypeError("%s has wrong number of arguments, "
+ "%d specified in decorator, "
+ "but function has %d" %
+ (func.__name__,
+ len(types),
+ len(arg_names)))
+
+ def wrapper(*args, **kwargs):
+ if self.__enabled__:
+ # Positional arguments
+ for arg, type, name in zip(args, types, arg_names):
+ self._type_check(arg, type, name)
+
+ # Keyword arguments
+ for name, arg in kwargs.items():
+ self._type_check(arg, kwarg_types[name], name)
+
+ return func(*args, **kwargs)
+ wrapper.__name__ = func.__name__
+ return wrapper
+
+ def _type_check(self, value, argument_type, name):
+ if issubclass(argument_type, CustomType):
+ custom = True
+ check_type = argument_type.type
+ else:
+ custom = False
+ check_type = argument_type
+
+ type_name = argument_type.__name__
+
+ if not isinstance(value, check_type):
+ raise TypeError(
+ "%s must be %s, not %s" % (name, type_name,
+ type(value).__name__))
+ if custom:
+ argument_type.value_check(name, value)
+
+
Added: kiwi/trunk/tests/test_argcheck.py
==============================================================================
--- (empty file)
+++ kiwi/trunk/tests/test_argcheck.py Fri Sep 30 11:50:37 2005
@@ -0,0 +1,51 @@
+import unittest
+
+from kiwi.argcheck import argcheck, number, percent
+
+class ArgTest(unittest.TestCase):
+ def testOneArg(self):
+ f = argcheck(str)(lambda s: None)
+ f('str')
+ self.assertRaises(TypeError, f, None)
+ self.assertRaises(TypeError, f, 1)
+
+ def testTwoArgs(self):
+ f = argcheck(str, int)(lambda s, i: None)
+ f('str', 1)
+ self.assertRaises(TypeError, f, 1, 1) # first incorret
+ self.assertRaises(TypeError, f, 'str', 'str') # second incorrect
+ self.assertRaises(TypeError, f, 1, 'str') # swapped
+ self.assertRaises(TypeError, f, 1) # too few
+ self.assertRaises(TypeError, f, 'str', 1, 1) # too many
+
+ def testVarArgs(self):
+ f = argcheck(int)(lambda *v: None)
+ f(1)
+ f(1, 'str')
+ f(1, 2, 3)
+ #self.assertRaises(TypeError, f, 'str')
+
+ def testDefault(self):
+ f1 = lambda a, b=1: None
+ d1 = argcheck(int, int)(f1)
+ self.assertRaises(TypeError, d1, 'f')
+
+ f2 = lambda a, b='str': None
+ self.assertRaises(TypeError, argcheck, f2)
+
+ def testKwargs(self):
+ self.assertRaises(TypeError, argcheck, lambda **kw: None)
+
+ def testUserDefined(self):
+ class Payment(object):
+ pass
+
+ @argcheck(Payment, str)
+ def pay(payment, description):
+ pass
+ pay(Payment(), 'foo')
+ self.assertRaises(TypeError, 'bar', 'bar')
+ self.assertRaises(TypeError, Payment(), Payment())
+
+if __name__ == '__main__':
+ unittest.main()
More information about the POS-commit
mailing list