1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
"""Code unit (module) handling for coverage.py"""
import glob, os, types
def code_unit_factory(morfs, file_locator, omit_prefixes=None):
"""Construct a list of CodeUnits from polymorphic inputs.
`morfs` is a module or a filename, or a list of same.
`file_locator` is a FileLocator that can help resolve filenames.
`omit_prefixes` is a list of prefixes. CodeUnits that match those prefixes
will be omitted from the list.
Returns a list of CodeUnit objects.
"""
# Be sure we have a list.
if not isinstance(morfs, types.ListType):
morfs = [morfs]
# On Windows, the shell doesn't expand wildcards. Do it here.
globbed = []
for morf in morfs:
if isinstance(morf, basestring) and ('?' in morf or '*' in morf):
globbed.extend(glob.glob(morf))
else:
globbed.append(morf)
morfs = globbed
code_units = [CodeUnit(morf, file_locator) for morf in morfs]
if omit_prefixes:
prefixes = [file_locator.abs_file(p) for p in omit_prefixes]
filtered = []
for cu in code_units:
for prefix in prefixes:
if cu.name.startswith(prefix):
break
else:
filtered.append(cu)
code_units = filtered
return code_units
class CodeUnit:
"""Code unit: a filename or module.
Instance attributes:
`name` is a human-readable name for this code unit.
`filename` is the os path from which we can read the source.
`relative` is a boolean.
"""
def __init__(self, morf, file_locator):
if hasattr(morf, '__file__'):
f = morf.__file__
else:
f = morf
# .pyc files should always refer to a .py instead.
if f.endswith('.pyc'):
f = f[:-1]
self.filename = file_locator.canonical_filename(f)
if hasattr(morf, '__name__'):
n = morf.__name__
self.relative = True
else:
n = os.path.splitext(morf)[0]
rel = file_locator.relative_filename(n)
self.relative = (rel != n)
n = rel
self.name = n
def __cmp__(self, other):
return cmp(self.name, other.name)
def flat_rootname(self):
"""A base for a flat filename to correspond to this code unit.
Useful for writing files about the code where you want all the files in
the same directory, but need to differentiate same-named files from
different directories.
For example, the file a/b/c.py might return 'a_b_c'
"""
root = os.path.splitdrive(os.path.splitext(self.name)[0])[1]
return root.replace('\\', '_').replace('/', '_')
|