diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2010-08-30 23:08:39 -0400 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2010-08-30 23:08:39 -0400 |
commit | b8a9e1e21d728e4dd783a4aaecba81dc4f0b11f3 (patch) | |
tree | ced71b31e8b9d3fc238ef0fd9e76fdcefd21d664 | |
parent | 95b6988b7728fca012cc1469587f7316c80b4d78 (diff) | |
download | python-coveragepy-git-b8a9e1e21d728e4dd783a4aaecba81dc4f0b11f3.tar.gz |
Some prep work for finding completely uncovered files.
-rw-r--r-- | coverage/data.py | 5 | ||||
-rw-r--r-- | coverage/files.py | 14 | ||||
-rw-r--r-- | test/coveragetest.py | 6 | ||||
-rw-r--r-- | test/modules/pkg1/p1c.py | 3 | ||||
-rw-r--r-- | test/modules/pkg1/sub/__init__.py | 0 | ||||
-rw-r--r-- | test/modules/pkg1/sub/ps1a.py | 3 | ||||
-rw-r--r-- | test/test_api.py | 1 | ||||
-rw-r--r-- | test/test_files.py | 24 |
8 files changed, 55 insertions, 1 deletions
diff --git a/coverage/data.py b/coverage/data.py index fe076bef..6d49f710 100644 --- a/coverage/data.py +++ b/coverage/data.py @@ -52,7 +52,10 @@ class CoverageData(object): # A map from canonical Python source file name to a dictionary with an # entry for each pair of line numbers forming an arc: # - # { filename: { (l1,l2): None, ... }, ...} + # { + # 'filename1.py': { (12,14): None, (47,48): None, ... }, + # ... + # } # self.arcs = {} diff --git a/coverage/files.py b/coverage/files.py index 741b456f..9a8ac564 100644 --- a/coverage/files.py +++ b/coverage/files.py @@ -102,6 +102,7 @@ class TreeMatcher(object): return True return False + class FnmatchMatcher(object): """A matcher for files by filename pattern.""" def __init__(self, pats): @@ -116,3 +117,16 @@ class FnmatchMatcher(object): if fnmatch.fnmatch(fpath, pat): return True return False + + +def find_python_files(dirname): + """Yield all of the importable Python files in `dirname`, recursively.""" + for dirpath, dirnames, filenames in os.walk(dirname, topdown=True): + if '__init__.py' not in filenames: + # If a directory doesn't have __init__.py, then it isn't + # importable and neither are its files + del dirnames[:] + continue + for filename in filenames: + if fnmatch.fnmatch(filename, "*.py"): + yield os.path.join(dirpath, filename) diff --git a/test/coveragetest.py b/test/coveragetest.py index bdee9185..53f0ef0b 100644 --- a/test/coveragetest.py +++ b/test/coveragetest.py @@ -327,6 +327,12 @@ class CoverageTest(TestCase): fname = os.path.join(*fparts) return os.path.normcase(os.path.abspath(os.path.realpath(fname))) + def assert_same_files(self, flist1, flist2): + """Assert that `flist1` and `flist2` are the same set of file names.""" + flist1_nice = [self.nice_file(f) for f in flist1] + flist2_nice = [self.nice_file(f) for f in flist2] + self.assertSameElements(flist1_nice, flist2_nice) + def command_line(self, args, ret=OK, _covpkg=None): """Run `args` through the command line. diff --git a/test/modules/pkg1/p1c.py b/test/modules/pkg1/p1c.py new file mode 100644 index 00000000..a9aeef04 --- /dev/null +++ b/test/modules/pkg1/p1c.py @@ -0,0 +1,3 @@ +a = 1 +b = 2 +c = 3 diff --git a/test/modules/pkg1/sub/__init__.py b/test/modules/pkg1/sub/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/modules/pkg1/sub/__init__.py diff --git a/test/modules/pkg1/sub/ps1a.py b/test/modules/pkg1/sub/ps1a.py new file mode 100644 index 00000000..4b6a15cc --- /dev/null +++ b/test/modules/pkg1/sub/ps1a.py @@ -0,0 +1,3 @@ +d = 1 +e = 2 +f = 3 diff --git a/test/test_api.py b/test/test_api.py index f64ad44d..aa6f42cd 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -324,6 +324,7 @@ class SourceOmitIncludeTest(CoverageTest): self.assertEqual(lines['p1b.py'], 3) self.assertEqual(lines['p2a.py'], 3) self.assertEqual(lines['p2b.py'], 3) + self.assert_('p1c.py' not in lines) def test_source_package(self): lines = self.coverage_usepkgs_summary(source=["pkg1"]) diff --git a/test/test_files.py b/test/test_files.py index db835e5e..ecb2a750 100644 --- a/test/test_files.py +++ b/test/test_files.py @@ -3,6 +3,7 @@ import os, sys from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher +from coverage.files import find_python_files sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k from coveragetest import CoverageTest @@ -34,6 +35,10 @@ class FileLocatorTest(CoverageTest): self.assertEqual(fl.relative_filename(a1), "file1.py") self.assertEqual(fl.relative_filename(a2), a2) + +class MatcherTest(CoverageTest): + """Tests of file matchers.""" + def test_tree_matcher(self): file1 = self.make_file("sub/file1.py") file2 = self.make_file("sub/file2.c") @@ -64,3 +69,22 @@ class FileLocatorTest(CoverageTest): self.assertTrue(fnm.match(fl.canonical_filename(file3))) self.assertTrue(fnm.match(fl.canonical_filename(file4))) self.assertFalse(fnm.match(fl.canonical_filename(file5))) + + +class FindPythonFilesTest(CoverageTest): + """Tests of `find_python_files`.""" + + def test_find_python_files(self): + self.make_file("sub/a.py") + self.make_file("sub/b.py") + self.make_file("sub/__init__.py") + self.make_file("sub/x.c") # nope: not .py + self.make_file("sub/ssub/__init__.py") + self.make_file("sub/ssub/s.py") + self.make_file("sub/lab/exp.py") # nope: no __init__.py + py_files = set(find_python_files("sub")) + self.assert_same_files(py_files, [ + "sub/__init__.py", "sub/a.py", "sub/b.py", + "sub/ssub/__init__.py", "sub/ssub/s.py", + ]) + |