11 import re |
11 import re |
12 import sys |
12 import sys |
13 |
13 |
14 from coverage import env |
14 from coverage import env |
15 from coverage.backward import unicode_class |
15 from coverage.backward import unicode_class |
16 from coverage.misc import CoverageException, join_regex |
16 from coverage.misc import contract, CoverageException, join_regex, isolate_module |
17 |
17 |
18 |
18 |
19 RELATIVE_DIR = None |
19 os = isolate_module(os) |
20 CANONICAL_FILENAME_CACHE = {} |
|
21 |
20 |
22 |
21 |
23 def set_relative_directory(): |
22 def set_relative_directory(): |
24 """Set the directory that `relative_filename` will be relative to.""" |
23 """Set the directory that `relative_filename` will be relative to.""" |
25 global RELATIVE_DIR, CANONICAL_FILENAME_CACHE |
24 global RELATIVE_DIR, CANONICAL_FILENAME_CACHE |
29 |
28 |
30 # Cache of results of calling the canonical_filename() method, to |
29 # Cache of results of calling the canonical_filename() method, to |
31 # avoid duplicating work. |
30 # avoid duplicating work. |
32 CANONICAL_FILENAME_CACHE = {} |
31 CANONICAL_FILENAME_CACHE = {} |
33 |
32 |
|
33 |
34 def relative_directory(): |
34 def relative_directory(): |
35 """Return the directory that `relative_filename` is relative to.""" |
35 """Return the directory that `relative_filename` is relative to.""" |
36 return RELATIVE_DIR |
36 return RELATIVE_DIR |
37 |
37 |
|
38 |
|
39 @contract(returns='unicode') |
38 def relative_filename(filename): |
40 def relative_filename(filename): |
39 """Return the relative form of `filename`. |
41 """Return the relative form of `filename`. |
40 |
42 |
41 The file name will be relative to the current directory when the |
43 The file name will be relative to the current directory when the |
42 `set_relative_directory` was called. |
44 `set_relative_directory` was called. |
43 |
45 |
44 """ |
46 """ |
45 fnorm = os.path.normcase(filename) |
47 fnorm = os.path.normcase(filename) |
46 if fnorm.startswith(RELATIVE_DIR): |
48 if fnorm.startswith(RELATIVE_DIR): |
47 filename = filename[len(RELATIVE_DIR):] |
49 filename = filename[len(RELATIVE_DIR):] |
48 return filename |
50 return unicode_filename(filename) |
49 |
51 |
|
52 |
|
53 @contract(returns='unicode') |
50 def canonical_filename(filename): |
54 def canonical_filename(filename): |
51 """Return a canonical file name for `filename`. |
55 """Return a canonical file name for `filename`. |
52 |
56 |
53 An absolute path with no redundant components and normalized case. |
57 An absolute path with no redundant components and normalized case. |
54 |
58 |
122 def actual_path(filename): |
126 def actual_path(filename): |
123 """The actual path for non-Windows platforms.""" |
127 """The actual path for non-Windows platforms.""" |
124 return filename |
128 return filename |
125 |
129 |
126 |
130 |
|
131 if env.PY2: |
|
132 @contract(returns='unicode') |
|
133 def unicode_filename(filename): |
|
134 """Return a Unicode version of `filename`.""" |
|
135 if isinstance(filename, str): |
|
136 encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() |
|
137 filename = filename.decode(encoding, "replace") |
|
138 return filename |
|
139 else: |
|
140 @contract(filename='unicode', returns='unicode') |
|
141 def unicode_filename(filename): |
|
142 """Return a Unicode version of `filename`.""" |
|
143 return filename |
|
144 |
|
145 |
|
146 @contract(returns='unicode') |
127 def abs_file(filename): |
147 def abs_file(filename): |
128 """Return the absolute normalized form of `filename`.""" |
148 """Return the absolute normalized form of `filename`.""" |
129 path = os.path.expandvars(os.path.expanduser(filename)) |
149 path = os.path.expandvars(os.path.expanduser(filename)) |
130 path = os.path.abspath(os.path.realpath(path)) |
150 path = os.path.abspath(os.path.realpath(path)) |
131 path = actual_path(path) |
151 path = actual_path(path) |
|
152 path = unicode_filename(path) |
132 return path |
153 return path |
|
154 |
|
155 |
|
156 RELATIVE_DIR = None |
|
157 CANONICAL_FILENAME_CACHE = None |
|
158 set_relative_directory() |
133 |
159 |
134 |
160 |
135 def isabs_anywhere(filename): |
161 def isabs_anywhere(filename): |
136 """Is `filename` an absolute path on any OS?""" |
162 """Is `filename` an absolute path on any OS?""" |
137 return ntpath.isabs(filename) or posixpath.isabs(filename) |
163 return ntpath.isabs(filename) or posixpath.isabs(filename) |