|
45 | 45 | # Assumption made in _path_join() |
46 | 46 | assert all(len(sep) == 1 for sep in path_separators) |
47 | 47 | path_sep = path_separators[0] |
48 | | -path_sep_tuple = tuple(path_separators) |
49 | 48 | path_separators = ''.join(path_separators) |
50 | 49 | _pathseps_with_colon = {f':{s}' for s in path_separators} |
51 | 50 |
|
@@ -92,49 +91,22 @@ def _unpack_uint16(data): |
92 | 91 | return int.from_bytes(data, 'little') |
93 | 92 |
|
94 | 93 |
|
95 | | -if _MS_WINDOWS: |
96 | | - def _path_join(*path_parts): |
97 | | - """Replacement for os.path.join().""" |
98 | | - if not path_parts: |
99 | | - return "" |
100 | | - if len(path_parts) == 1: |
101 | | - return path_parts[0] |
102 | | - root = "" |
103 | | - path = [] |
104 | | - for new_root, tail in map(_os._path_splitroot, path_parts): |
105 | | - if new_root.startswith(path_sep_tuple) or new_root.endswith(path_sep_tuple): |
106 | | - root = new_root.rstrip(path_separators) or root |
107 | | - path = [path_sep + tail] |
108 | | - elif new_root.endswith(':'): |
109 | | - if root.casefold() != new_root.casefold(): |
110 | | - # Drive relative paths have to be resolved by the OS, so we reset the |
111 | | - # tail but do not add a path_sep prefix. |
112 | | - root = new_root |
113 | | - path = [tail] |
114 | | - else: |
115 | | - path.append(tail) |
116 | | - else: |
117 | | - root = new_root or root |
118 | | - path.append(tail) |
119 | | - path = [p.rstrip(path_separators) for p in path if p] |
120 | | - if len(path) == 1 and not path[0]: |
121 | | - # Avoid losing the root's trailing separator when joining with nothing |
122 | | - return root + path_sep |
123 | | - return root + path_sep.join(path) |
124 | | - |
125 | | -else: |
126 | | - def _path_join(*path_parts): |
127 | | - """Replacement for os.path.join().""" |
128 | | - return path_sep.join([part.rstrip(path_separators) |
129 | | - for part in path_parts if part]) |
| 94 | +def _path_join(*path_parts): |
| 95 | + """Replacement for os.path.join().""" |
| 96 | + return path_sep.join([part.rstrip(path_separators) |
| 97 | + for part in path_parts if part]) |
130 | 98 |
|
131 | 99 |
|
132 | 100 | def _path_split(path): |
133 | 101 | """Replacement for os.path.split().""" |
134 | | - i = max(path.rfind(p) for p in path_separators) |
135 | | - if i < 0: |
136 | | - return '', path |
137 | | - return path[:i], path[i + 1:] |
| 102 | + if len(path_separators) == 1: |
| 103 | + front, _, tail = path.rpartition(path_sep) |
| 104 | + return front, tail |
| 105 | + for x in reversed(path): |
| 106 | + if x in path_separators: |
| 107 | + front, tail = path.rsplit(x, maxsplit=1) |
| 108 | + return front, tail |
| 109 | + return '', path |
138 | 110 |
|
139 | 111 |
|
140 | 112 | def _path_stat(path): |
@@ -168,18 +140,13 @@ def _path_isdir(path): |
168 | 140 | return _path_is_mode_type(path, 0o040000) |
169 | 141 |
|
170 | 142 |
|
171 | | -if _MS_WINDOWS: |
172 | | - def _path_isabs(path): |
173 | | - """Replacement for os.path.isabs.""" |
174 | | - if not path: |
175 | | - return False |
176 | | - root = _os._path_splitroot(path)[0].replace('/', '\\') |
177 | | - return len(root) > 1 and (root.startswith('\\\\') or root.endswith('\\')) |
| 143 | +def _path_isabs(path): |
| 144 | + """Replacement for os.path.isabs. |
178 | 145 |
|
179 | | -else: |
180 | | - def _path_isabs(path): |
181 | | - """Replacement for os.path.isabs.""" |
182 | | - return path.startswith(path_separators) |
| 146 | + Considers a Windows drive-relative path (no drive, but starts with slash) to |
| 147 | + still be "absolute". |
| 148 | + """ |
| 149 | + return path.startswith(path_separators) or path[1:3] in _pathseps_with_colon |
183 | 150 |
|
184 | 151 |
|
185 | 152 | def _write_atomic(path, data, mode=0o666): |
@@ -743,11 +710,6 @@ def spec_from_file_location(name, location=None, *, loader=None, |
743 | 710 | pass |
744 | 711 | else: |
745 | 712 | location = _os.fspath(location) |
746 | | - if not _path_isabs(location): |
747 | | - try: |
748 | | - location = _path_join(_os.getcwd(), location) |
749 | | - except OSError: |
750 | | - pass |
751 | 713 |
|
752 | 714 | # If the location is on the filesystem, but doesn't actually exist, |
753 | 715 | # we could return None here, indicating that the location is not |
@@ -1492,8 +1454,6 @@ def __init__(self, path, *loader_details): |
1492 | 1454 | self._loaders = loaders |
1493 | 1455 | # Base (directory) path |
1494 | 1456 | self.path = path or '.' |
1495 | | - if not _path_isabs(self.path): |
1496 | | - self.path = _path_join(_os.getcwd(), self.path) |
1497 | 1457 | self._path_mtime = -1 |
1498 | 1458 | self._path_cache = set() |
1499 | 1459 | self._relaxed_path_cache = set() |
@@ -1559,10 +1519,7 @@ def find_spec(self, fullname, target=None): |
1559 | 1519 | is_namespace = _path_isdir(base_path) |
1560 | 1520 | # Check for a file w/ a proper suffix exists. |
1561 | 1521 | for suffix, loader_class in self._loaders: |
1562 | | - try: |
1563 | | - full_path = _path_join(self.path, tail_module + suffix) |
1564 | | - except ValueError: |
1565 | | - return None |
| 1522 | + full_path = _path_join(self.path, tail_module + suffix) |
1566 | 1523 | _bootstrap._verbose_message('trying {}', full_path, verbosity=2) |
1567 | 1524 | if cache_module + suffix in cache: |
1568 | 1525 | if _path_isfile(full_path): |
|
0 commit comments