Streamlined code in trace.Ignore and added unit tests.
diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py
index 33d7aa1..9c018b7 100644
--- a/Lib/test/test_trace.py
+++ b/Lib/test/test_trace.py
@@ -334,6 +334,20 @@
         self.assertIn(modname, coverage)
         self.assertEqual(coverage[modname], (5, 100))
 
+### 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.
+class Test_Ignore(unittest.TestCase):
+    def test_ignored(self):
+        ignore = trace.Ignore(['x', 'y.z'], ['/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('/foo/bar/baz.py', 'baz'))
+        self.assertFalse(ignore.names('bar/z.py', 'z'))
+        # Matched before.
+        self.assertTrue(ignore.names('bar/baz.py', 'baz'))
+
 
 def test_main():
     run_unittest(__name__)
diff --git a/Lib/trace.py b/Lib/trace.py
index d460cf2..8ea4b89 100644
--- a/Lib/trace.py
+++ b/Lib/trace.py
@@ -128,11 +128,10 @@
 rx_blank = re.compile(r'^\s*(#.*)?$')
 
 class Ignore:
-    def __init__(self, modules = None, dirs = None):
-        self._mods = modules or []
-        self._dirs = dirs or []
-
-        self._dirs = list(map(os.path.normpath, self._dirs))
+    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 = { '<string>': 1 }
 
     def names(self, filename, modulename):
@@ -140,24 +139,22 @@
             return self._ignore[modulename]
 
         # haven't seen this one before, so see if the module name is
-        # on the ignore list.  Need to take some care since ignoring
-        # "cmp" musn't mean ignoring "cmpcache" but ignoring
-        # "Spam" must also mean ignoring "Spam.Eggs".
+        # on the ignore list.
+        if modulename in self._mods:  # Identical names, so ignore
+            self._ignore[modulename] = 1
+            return 1
+
+        # check if the module is a proper submodule of something on
+        # the ignore list
         for mod in self._mods:
-            if mod == modulename:  # Identical names, so ignore
-                self._ignore[modulename] = 1
-                return 1
-            # check if the module is a proper submodule of something on
-            # the ignore list
-            n = len(mod)
-            # (will not overflow since if the first n characters are the
-            # same and the name has not already occurred, then the size
-            # of "name" is greater than that of "mod")
-            if mod == modulename[:n] and modulename[n] == '.':
+            # 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
 
-        # Now check that __file__ isn't in one of the directories
+        # 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