diff options
author | Sylvain Th?nault <sylvain.thenault@logilab.fr> | 2009-11-23 14:45:11 +0100 |
---|---|---|
committer | Sylvain Th?nault <sylvain.thenault@logilab.fr> | 2009-11-23 14:45:11 +0100 |
commit | 57b10e1b76dd3bd3c834bacd338076de6e35cabe (patch) | |
tree | 3f59f0a76e5bcb0bd760b37edac7b2fe906a2473 | |
parent | b7e84e3fc5418641041f95a80f08fe053c004c27 (diff) | |
parent | 1b4d12cbd2ab6e6e586743df592648faa42fa26e (diff) | |
download | logilab-common-57b10e1b76dd3bd3c834bacd338076de6e35cabe.tar.gz |
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | db.py | 35 | ||||
-rw-r--r-- | debugger.py | 9 | ||||
-rw-r--r-- | graph.py | 6 | ||||
-rw-r--r-- | pyro_ext.py | 3 | ||||
-rw-r--r-- | pytest.py | 13 | ||||
-rw-r--r-- | shellutils.py | 15 | ||||
-rw-r--r-- | test/unittest_db.py | 11 | ||||
-rw-r--r-- | test/unittest_graph.py | 18 | ||||
-rw-r--r-- | test/unittest_testlib.py | 57 | ||||
-rw-r--r-- | testlib.py | 9 |
11 files changed, 144 insertions, 34 deletions
@@ -6,6 +6,8 @@ ChangeLog for logilab.common - proper bytes and time option types support - make Method usable as 'callback' value - fix #8849 Using plugins, options and .pylintrc crashes PyLint + * graph: fix has_path returned value to include the destination node, else we get + an empty list which makes think there is no path (test added) 2009-08-26 -- 0.45.0 * added function for parsing XML processing instructions @@ -410,14 +410,45 @@ class _PySqlite2Adapter(DBAPIAdapter): sqlite.register_converter('time', convert_mxtime) # else use datetime.datetime else: - from datetime import time + from datetime import time, timedelta + # datetime.time def adapt_time(data): return data.strftime('%H:%M:%S') sqlite.register_adapter(time, adapt_time) def convert_time(data): return time(*[int(i) for i in data.split(':')]) sqlite.register_converter('time', convert_time) - + # datetime.timedelta + def adapt_timedelta(data): + '''the sign in the result only refers to the number of days. day + fractions always indicate a positive offset. this may seem strange, + but it is the same that is done by the default __str__ method. we + redefine it here anyways (instead of simply doing "str") because we + do not want any "days," string within the representation. + ''' + days = data.days + frac = data - timedelta(days) + return "%d %s" % (data.days, frac) + sqlite.register_adapter(timedelta, adapt_timedelta) + def convert_timedelta(data): + parts = data.split(" ") + if len(parts) == 2: + daypart, timepart = parts + days = int(daypart) + else: + days = 0 + timepart = parts[-1] + timepart_full = timepart.split(".") + hours, minutes, seconds = map(int, timepart_full[0].split(":")) + if len(timepart_full) == 2: + microseconds = int(float("0." + timepart_full[1]) * 1000000) + else: + microseconds = 0 + data = timedelta(days, + hours*3600 + minutes*60 + seconds, + microseconds) + return data + sqlite.register_converter('interval', convert_timedelta) def connect(self, host='', database='', user='', password='', port=None): diff --git a/debugger.py b/debugger.py index 53a7bd9..96e6a52 100644 --- a/debugger.py +++ b/debugger.py @@ -74,11 +74,12 @@ class Debugger(Pdb): - overrides list command to search for current block instead of using 5 lines of context """ - def __init__(self, tcbk): + def __init__(self, tcbk=None): Pdb.__init__(self) self.reset() - while tcbk.tb_next is not None: - tcbk = tcbk.tb_next + if tcbk: + while tcbk.tb_next is not None: + tcbk = tcbk.tb_next self._tcbk = tcbk self._histfile = osp.join(os.environ["HOME"], ".pdbhist") @@ -187,3 +188,5 @@ def pm(): dbg = Debugger(sys.last_traceback) dbg.start() +def set_trace(): + Debugger().set_trace(sys._getframe().f_back) @@ -189,16 +189,16 @@ def has_path(graph_dict, fromnode, tonode, path=None): node has key associated to a list of nodes directly reachable from it. Return None if no path exists to go from `fromnode` to `tonode`, else the - first path found + first path found (as a list including the destination node at last) """ if path is None: path = [] elif fromnode in path: - return False + return None path.append(fromnode) for destnode in graph_dict[fromnode]: if destnode == tonode or has_path(graph_dict, destnode, tonode, path): - return path[1:] + return path[1:] + [tonode] path.pop() return None diff --git a/pyro_ext.py b/pyro_ext.py index a531188..e7915c6 100644 --- a/pyro_ext.py +++ b/pyro_ext.py @@ -14,12 +14,15 @@ Main functions available: __docformat__ = "restructuredtext en" import logging +import tempfile from Pyro import core, naming, errors, util, config _LOGGER = logging.getLogger('pyro') _MARKER = object() +config.PYRO_STORAGE = tempfile.gettempdir() + def ns_group_and_id(idstr, defaultnsgroup=_MARKER): try: nsgroup, nsid = idstr.rsplit('.', 1) @@ -725,17 +725,10 @@ def run(): import traceback traceback.print_exc() finally: - tester.show_report() if covermode: cvg.stop() cvg.save() - here = osp.abspath(os.getcwd()) - if this_is_a_testdir(here): - morfdir = osp.normpath(osp.join(here, '..')) - else: - morfdir = here - print "computing code coverage (%s), this might take some time" % \ - morfdir - cvg.annotate([morfdir]) - cvg.report([morfdir], False) + tester.show_report() + if covermode: + print 'coverage information stored, use it with pycoverage -ra' sys.exit(tester.errcode) diff --git a/shellutils.py b/shellutils.py index b9f6253..ed5d23f 100644 --- a/shellutils.py +++ b/shellutils.py @@ -42,7 +42,7 @@ def chown(path, login=None, group=None): try: uid = int(login) except ValueError: - import pwd + import pwd # Platforms: Unix uid = pwd.getpwnam(login).pw_uid if group is None: gid = -1 @@ -285,6 +285,7 @@ def confirm(question, default_is_yes=True): """ask for confirmation and return true on positive answer""" return RawInput().confirm(question, default_is_yes) + class RawInput(object): def __init__(self, input=None, printer=None): @@ -331,3 +332,15 @@ class RawInput(object): return answer == 'y' ASK = RawInput() + + +def getlogin(): + """avoid using os.getlogin() because of strange tty / stdin problems + (man 3 getlogin) + Another solution would be to use $LOGNAME, $USER or $USERNAME + """ + import pwd # Platforms: Unix + return pwd.getpwuid(os.getuid())[0] + + + diff --git a/test/unittest_db.py b/test/unittest_db.py index 0f818ec..af288ff 100644 --- a/test/unittest_db.py +++ b/test/unittest_db.py @@ -1,12 +1,10 @@ """ unit tests for module logilab.common.db """ - -import os -import pwd import socket from logilab.common.testlib import TestCase, unittest_main +from logilab.common.shellutils import getlogin from logilab.common.db import * from logilab.common.db import PREFERED_DRIVERS from logilab.common.adbh import (_GenericAdvFuncHelper, _SqliteAdvFuncHelper, @@ -15,13 +13,6 @@ from logilab.common.adbh import (_GenericAdvFuncHelper, _SqliteAdvFuncHelper, auto_register_function) -def getlogin(): - """avoid usinng os.getlogin() because of strange tty / stdin problems - (man 3 getlogin) - Another solution would be to use $LOGNAME, $USER or $USERNAME - """ - return pwd.getpwuid(os.getuid())[0] - class PreferedDriverTC(TestCase): def setUp(self): self.drivers = {"pg":[('foo', None), ('bar', None)]} diff --git a/test/unittest_graph.py b/test/unittest_graph.py index b8f5394..ce272e5 100644 --- a/test/unittest_graph.py +++ b/test/unittest_graph.py @@ -1,9 +1,9 @@ # unit tests for the cache module from logilab.common.testlib import TestCase, unittest_main -from logilab.common.graph import get_cycles +from logilab.common.graph import get_cycles, has_path -class getCycleTestCase(TestCase): +class getCyclesTC(TestCase): def test_known0(self): self.assertEqual(get_cycles({1:[2], 2:[3], 3:[1]}), [[1, 2, 3]]) @@ -15,5 +15,19 @@ class getCycleTestCase(TestCase): self.assertEqual(get_cycles({1:[2], 2:[3], 3:[0], 0:[]}), []) +class hasPathTC(TestCase): + + def test_direct_connection(self): + self.assertEquals(has_path({'A': ['B'], 'B': ['A']}, 'A', 'B'), ['B']) + + def test_indirect_connection(self): + self.assertEquals(has_path({'A': ['B'], 'B': ['A', 'C'], 'C': ['B']}, 'A', 'C'), ['B', 'C']) + + def test_no_connection(self): + self.assertEquals(has_path({'A': ['B'], 'B': ['A']}, 'A', 'C'), None) + + def test_cycle(self): + self.assertEquals(has_path({'A': ['A']}, 'A', 'B'), None) + if __name__ == "__main__": unittest_main() diff --git a/test/unittest_testlib.py b/test/unittest_testlib.py index 1bf5123..5e37cf0 100644 --- a/test/unittest_testlib.py +++ b/test/unittest_testlib.py @@ -20,7 +20,7 @@ except NameError: from unittest import TestSuite -from logilab.common.testlib import TestCase, SkipAwareTextTestRunner +from logilab.common.testlib import TestCase, SkipAwareTextTestRunner, Tags from logilab.common.testlib import mock_object, NonStrictTestLoader, create_files from logilab.common.testlib import capture_stdout, unittest_main, InnerTest from logilab.common.testlib import with_tempdir, tag @@ -776,6 +776,21 @@ class TagTC(TestCase): self.func = bob + class TagTestTC(TestCase): + tags = Tags(('one', 'two')) + + def test_one(self): + self.assertTrue(True) + + @tag('two', 'three') + def test_two(self): + self.assertTrue(True) + + @tag('three') + def test_three(self): + self.assertTrue(True) + self.cls = TagTestTC + def test_tag_decorator(self): bob = self.func @@ -804,5 +819,45 @@ class TagTC(TestCase): self.assertTrue(tags.match('not other or (testing and bibi)')) self.assertTrue(tags.match('other or (testing and bob)')) + def test_tagged_class(self): + def options(tags): + class Options(object): + tags_pattern = tags + return Options() + + cls = self.cls + + runner = SkipAwareTextTestRunner() + self.assertTrue(runner.does_match_tags(cls.test_one)) + self.assertTrue(runner.does_match_tags(cls.test_two)) + self.assertTrue(runner.does_match_tags(cls.test_three)) + + runner = SkipAwareTextTestRunner(options=options('one')) + self.assertTrue(runner.does_match_tags(cls.test_one)) + self.assertFalse(runner.does_match_tags(cls.test_two)) + self.assertFalse(runner.does_match_tags(cls.test_three)) + + runner = SkipAwareTextTestRunner(options=options('two')) + self.assertTrue(runner.does_match_tags(cls.test_one)) + self.assertTrue(runner.does_match_tags(cls.test_two)) + self.assertFalse(runner.does_match_tags(cls.test_three)) + + runner = SkipAwareTextTestRunner(options=options('three')) + self.assertFalse(runner.does_match_tags(cls.test_one)) + self.assertTrue(runner.does_match_tags(cls.test_two)) + self.assertTrue(runner.does_match_tags(cls.test_three)) + + runner = SkipAwareTextTestRunner(options=options('two or three')) + self.assertTrue(runner.does_match_tags(cls.test_one)) + self.assertTrue(runner.does_match_tags(cls.test_two)) + self.assertTrue(runner.does_match_tags(cls.test_three)) + + runner = SkipAwareTextTestRunner(options=options('two and three')) + self.assertFalse(runner.does_match_tags(cls.test_one)) + self.assertTrue(runner.does_match_tags(cls.test_two)) + self.assertFalse(runner.does_match_tags(cls.test_three)) + + + if __name__ == '__main__': unittest_main() @@ -466,8 +466,13 @@ class SkipAwareTextTestRunner(unittest.TextTestRunner): if self.options is not None: tags_pattern = getattr(self.options, 'tags_pattern', None) if tags_pattern is not None: - tags = getattr(test, 'tags', Tags()) - return tags.match(tags_pattern) + tags = getattr(test, 'tags', None) + if tags is not None: + return tags.match(tags_pattern) + if isinstance(test, types.MethodType): + tags = getattr(test.im_class, 'tags', Tags()) + return tags.match(tags_pattern) + return False return True # no pattern def _makeResult(self): |