DebugClients/Python3/coverage/codeunit.py

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

eric ide

mercurial