Index: Lib/test/test_trace.py =================================================================== --- Lib/test/test_trace.py (revision 88001) +++ Lib/test/test_trace.py (working copy) @@ -337,19 +337,54 @@ ### Tests that don't mess with sys.settrace and can be traced ### themselves TODO: Skip tests that do mess with sys.settrace when ### regrtest is invoked with -T option. +jn = os.path.join + class Test_Ignore(unittest.TestCase): def test_ignored(self): - jn = os.path.join ignore = trace._Ignore(['x', 'y.z'], [jn('foo', 'bar')]) self.assertTrue(ignore.names('x.py', 'x')) self.assertFalse(ignore.names('xy.py', 'xy')) self.assertFalse(ignore.names('y.py', 'y')) self.assertTrue(ignore.names(jn('foo', 'bar', 'baz.py'), 'baz')) self.assertFalse(ignore.names(jn('bar', 'z.py'), 'z')) + self.assertTrue(ignore.names(None, 'zz')) # Matched before. self.assertTrue(ignore.names(jn('bar', 'baz.py'), 'baz')) + self.assertFalse(ignore.names('xyz.py', 'z')) + self.assertTrue(ignore.names('xyz.py', 'zz')) + self.assertEqual(ignore._mods, {'x', 'y.z'}) + self.assertEqual(ignore._dirs, (jn('foo', 'bar'),)) + self.assertEqual(ignore._ignore, {'': True, 'x': True, + 'xy':False, 'y': False, 'baz': True, 'z': False, 'zz': True}) + def test_no_ignored(self): + ignore = trace._Ignore() + self.assertFalse(ignore.names('x.py', 'x')) + self.assertFalse(ignore.names('xy.py', 'xy')) + self.assertFalse(ignore.names('y.py', 'y')) + self.assertFalse(ignore.names(jn('foo', 'bar', 'baz.py'), 'baz')) + self.assertFalse(ignore.names(jn('bar', 'z.py'), 'z')) + self.assertTrue(ignore.names(None, 'zz')) + # Matched before. + self.assertFalse(ignore.names(jn('bar', 'baz.py'), 'baz')) + self.assertFalse(ignore.names('xyz.py', 'z')) + self.assertTrue(ignore.names('xyz.py', 'zz')) + self.assertEqual(ignore._mods, set()) + self.assertEqual(ignore._dirs, tuple()) + self.assertEqual(ignore._ignore, {'': True, 'x': False, + 'xy':False, 'y': False, 'baz': False, 'z': False, 'zz': True}) + def test_multiple_dirs(self): + ignore = trace._Ignore(dirs=(r'C:\Program Files\Python31', + r'c:\Program Files\Python31', + r'c:\Program Files\Python31', + r'c:\program files\Python31', + r'c:\program files\python31')) + if os.name == 'win': + self.assertEqual(len(ignore._dirs), 1) + else: + self.assertEqual(len(ignore._dirs), 4) + def test_main(): run_unittest(__name__) Index: Lib/trace.py =================================================================== --- Lib/trace.py (revision 88001) +++ Lib/trace.py (working copy) @@ -131,53 +131,24 @@ class _Ignore: def __init__(self, modules=None, dirs=None): self._mods = set() if not modules else set(modules) - self._dirs = [] if not dirs else [os.path.normpath(d) - for d in dirs] - self._ignore = { '': 1 } + self._sub_mods = tuple(mod + '.' for mod in self._mods) + self._dirs = () if not dirs else tuple(set(dirs)) + self._ignore = { '': True } def names(self, filename, modulename): if modulename in self._ignore: return self._ignore[modulename] - # haven't seen this one before, so see if the module name is - # on the ignore list. - if modulename in self._mods: # Identical names, so ignore - self._ignore[modulename] = 1 - return 1 + if (modulename in self._mods or + modulename.startswith(self._sub_mods) or + filename is None or + os.path.dirname(filename).startswith(self._dirs)): + self._ignore[modulename] = True + return True - # check if the module is a proper submodule of something on - # the ignore list - for mod in self._mods: - # Need to take some care since ignoring - # "cmp" mustn't mean ignoring "cmpcache" but ignoring - # "Spam" must also mean ignoring "Spam.Eggs". - if modulename.startswith(mod + '.'): - self._ignore[modulename] = 1 - return 1 + self._ignore[modulename] = False + return False - # Now check that filename isn't in one of the directories - if filename is None: - # must be a built-in, so we must ignore - self._ignore[modulename] = 1 - return 1 - - # Ignore a file when it contains one of the ignorable paths - for d in self._dirs: - # The '+ os.sep' is to ensure that d is a parent directory, - # as compared to cases like: - # d = "/usr/local" - # filename = "/usr/local.py" - # or - # d = "/usr/local.py" - # filename = "/usr/local.py" - if filename.startswith(d + os.sep): - self._ignore[modulename] = 1 - return 1 - - # Tried the different ways, so we don't ignore this module - self._ignore[modulename] = 0 - return 0 - def _modname(path): """Return a plausible module name for the patch.""" @@ -597,6 +568,7 @@ # the ignore support won't work right for packages modulename = _modname(filename) if modulename is not None: + filename = os.path.normcase(filename) ignore_it = self.ignore.names(filename, modulename) if not ignore_it: if self.trace: @@ -652,6 +624,14 @@ sys.stderr.write("%s: %s\n" % (sys.argv[0], msg)) sys.exit(1) +def _process_dir(s): + s = os.path.expandvars(s.strip()) + s = s.replace("$prefix", os.path.join(sys.prefix, "lib", + "python" + sys.version[:3])) + s = s.replace("$exec_prefix", os.path.join(sys.exec_prefix, "lib", + "python" + sys.version[:3])) + return os.path.normcase(os.path.normpath(s)) + def main(argv=None): import getopt @@ -740,23 +720,11 @@ continue if opt == "--ignore-module": - for mod in val.split(","): - ignore_modules.append(mod.strip()) + ignore_modules = [mod.strip() for mod in val.split(',')] continue if opt == "--ignore-dir": - for s in val.split(os.pathsep): - s = os.path.expandvars(s) - # should I also call expanduser? (after all, could use $HOME) - - s = s.replace("$prefix", - os.path.join(sys.prefix, "lib", - "python" + sys.version[:3])) - s = s.replace("$exec_prefix", - os.path.join(sys.exec_prefix, "lib", - "python" + sys.version[:3])) - s = os.path.normpath(s) - ignore_dirs.append(s) + ignore_dirs = [_process_dir(s) for s in val.split(os.pathsep)] continue assert 0, "Should never get here"