diff options
author | Sylvain Thenault <sylvain.thenault@logilab.fr> | 2008-10-16 07:54:34 +0200 |
---|---|---|
committer | Sylvain Thenault <sylvain.thenault@logilab.fr> | 2008-10-16 07:54:34 +0200 |
commit | caeb6e6bfce040fc4939a1b28f52a27054ff378d (patch) | |
tree | 0efa868760c9b90497ae870de0ae463fc5f42d0e | |
parent | dcbe0edcda83d5480596d2e4316d191bcbac5101 (diff) | |
parent | 361640698cf03f9447c487ec9f38628bef9b72fd (diff) | |
download | logilab-common-caeb6e6bfce040fc4939a1b28f52a27054ff378d.tar.gz |
merge
-rw-r--r-- | decorators.py | 39 | ||||
-rw-r--r-- | logging_ext.py | 11 | ||||
-rw-r--r-- | test/unittest_decorators.py | 74 | ||||
-rw-r--r-- | testlib.py | 28 |
4 files changed, 144 insertions, 8 deletions
diff --git a/decorators.py b/decorators.py index 2c2834d..64b5e08 100644 --- a/decorators.py +++ b/decorators.py @@ -8,6 +8,7 @@ __docformat__ = "restructuredtext en" from types import MethodType from time import clock +import sys, re # XXX rewrite so we can use the decorator syntax when keyarg has to be specified @@ -143,3 +144,41 @@ def locked(acquire, release): return wrapper return decorator +def require_version(version): + """ Compare version of python interpretor to the given one. Skip the test + if older. + """ + def check_require_version(f): + version_elements = version.split('.') + try: + compare = tuple([int(v) for v in version_elements]) + except ValueError: + raise ValueError('%s is not a correct version : should be X.Y[.Z].' % version) + current = sys.version_info[:3] + #print 'comp', current, compare + if current < compare: + #print 'version too old' + def new_f(self, *args, **kwargs): + self.skip('Need at least %s version of python. Current version is %s.' % (version, '.'.join([str(element) for element in current]))) + new_f.__name__ = f.__name__ + return new_f + else: + #print 'version young enough' + return f + return check_require_version + +def require_module(module): + """ Check if the given module is loaded. Skip the test if not. + """ + def check_require_module(f): + try: + __import__(module) + #print module, 'imported' + return f + except ImportError: + #print module, 'can not be imported' + def new_f(self, *args, **kwargs): + self.skip('%s can not be imported.' % module) + new_f.__name__ = f.__name__ + return new_f + return check_require_module diff --git a/logging_ext.py b/logging_ext.py index 0012f0b..b788c00 100644 --- a/logging_ext.py +++ b/logging_ext.py @@ -20,8 +20,8 @@ class ColorFormatter(logging.Formatter): """ A color Formatter for the logging standard module. - By default, colorize CRITICAL and ERROR in red, WARNING in orange - and INFO in yellow. + By default, colorize CRITICAL and ERROR in red, WARNING in orange, INFO in + green and DEBUG in yellow. self.colors is customizable via the 'color' constructor argument (dictionnary). @@ -35,12 +35,13 @@ class ColorFormatter(logging.Formatter): self.colors = {'CRITICAL': 'red', 'ERROR': 'red', 'WARNING': 'magenta', - 'INFO': 'yellow', + 'INFO': 'green', + 'DEBUG': 'yellow', } if colors is not None: assert isinstance(colors, dict) - self.colors.update(colors) - + self.colors.update(colors) + def format(self, record): msg = logging.Formatter.format(self, record) if record.levelname in self.colors: diff --git a/test/unittest_decorators.py b/test/unittest_decorators.py new file mode 100644 index 0000000..855f242 --- /dev/null +++ b/test/unittest_decorators.py @@ -0,0 +1,74 @@ +import sys +from logilab.common.testlib import TestCase, unittest_main, TestSuite +from logilab.common.decorators import require_version, require_module + +class DecoratorsTC(TestCase): + def test_require_version_good(self): + """ should return the same function + """ + def func() : + pass + sys.version_info = (2, 5, 5, 'final', 4) + current = sys.version_info[:3] + compare = ('2.4', '2.5', '2.5.4', '2.5.5') + for version in compare: + decorator = require_version(version) + self.assertEquals(func, decorator(func), '%s =< %s : function \ + return by the decorator should be the same.' % (version, + '.'.join([str(element) for element in current]))) + + def test_require_version_bad(self): + """ should return a different function : skipping test + """ + def func() : + pass + sys.version_info = (2, 5, 5, 'final', 4) + current = sys.version_info[:3] + compare = ('2.5.6', '2.6', '2.6.5') + for version in compare: + decorator = require_version(version) + self.assertNotEquals(func, decorator(func), '%s >= %s : function \ + return by the decorator should NOT be the same.' + % ('.'.join([str(element) for element in current]), version)) + + def test_require_version_exception(self): + """ should throw a ValueError exception + """ + def func() : + pass + compare = ('2.5.a', '2.a', 'azerty') + for version in compare: + decorator = require_version(version) + self.assertRaises(ValueError, decorator, func) + + def test_require_module_good(self): + """ should return the same function + """ + def func() : + pass + module = 'sys' + decorator = require_module(module) + self.assertEquals(func, decorator(func), 'module %s exists : function \ + return by the decorator should be the same.' % module) + + def test_require_module_bad(self): + """ should return a different function : skipping test + """ + def func() : + pass + modules = ('bla', 'blo', 'bli') + for module in modules: + try: + __import__(module) + pass + except ImportError: + decorator = require_module(module) + self.assertNotEquals(func, decorator(func), 'module %s does \ + not exist : function return by the decorator should \ + NOT be the same.' % module) + return + print 'all modules in %s exist. Could not test %s' % (', '.join(modules), + sys._getframe().f_code.co_name) + +if __name__ == '__main__': + unittest_main() @@ -55,6 +55,13 @@ except ImportError: pass test_support = TestSupport() +try: + from pygments import highlight, lexers, formatters + # only print in color if executed from a terminal + PYGMENTS_FOUND = True +except ImportError: + PYGMENTS_FOUND = False + from logilab.common.deprecation import class_renamed, deprecated_function, \ obsolete # pylint: disable-msg=W0622 @@ -63,6 +70,7 @@ from logilab.common.compat import set, enumerate, any from logilab.common.modutils import load_module_from_name from logilab.common.debugger import Debugger from logilab.common.decorators import cached +from logilab.common import textutils __all__ = ['main', 'unittest_main', 'find_tests', 'run_test', 'spawn'] @@ -401,8 +409,16 @@ class SkipAwareTestResult(unittest._TextTestResult): def printErrorList(self, flavour, errors): for (_, descr), (test, err) in zip(self.descrs_for(flavour), errors): + if PYGMENTS_FOUND and os.isatty(self.stream.fileno()): + err = highlight(err, lexers.PythonLexer(), + formatters.terminal.TerminalFormatter()) self.stream.writeln(self.separator1) - self.stream.writeln("%s: %s" % (flavour, descr)) + if os.isatty(self.stream.fileno()): + self.stream.writeln("%s: %s" % ( + textutils.colorize_ansi(flavour, color='red'), descr)) + else: + self.stream.writeln("%s: %s" % (flavour, descr)) + self.stream.writeln(self.separator2) self.stream.writeln("%s" % err) try: @@ -537,9 +553,15 @@ class SkipAwareTextTestRunner(unittest.TextTestRunner): (run, run != 1 and "s" or "", timeTaken)) self.stream.writeln() if not result.wasSuccessful(): - self.stream.write("FAILED") + if os.isatty(self.stream.fileno()): + self.stream.write(textutils.colorize_ansi("FAILED", color='red')) + else: + self.stream.write("FAILED") else: - self.stream.write("OK") + if os.isatty(self.stream.fileno()): + self.stream.write(textutils.colorize_ansi("OK", color='green')) + else: + self.stream.write("OK") failed, errored, skipped = map(len, (result.failures, result.errors, result.skipped)) |