Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(42715)

Side by Side Diff: Lib/posixpath.py

Issue 10395: new os.path function to extract common prefix based on path components
Patch Set: Created 5 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/ntpath.py ('k') | Lib/test/test_ntpath.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 """Common operations on Posix pathnames. 1 """Common operations on Posix pathnames.
2 2
3 Instead of importing this module directly, import os and refer to 3 Instead of importing this module directly, import os and refer to
4 this module as os.path. The "os.path" name is an alias for this 4 this module as os.path. The "os.path" name is an alias for this
5 module on Posix systems; on other systems (e.g. Mac, Windows), 5 module on Posix systems; on other systems (e.g. Mac, Windows),
6 os.path provides the same operations in a manner specific to that 6 os.path provides the same operations in a manner specific to that
7 platform, and is an alias to another module (e.g. macpath, ntpath). 7 platform, and is an alias to another module (e.g. macpath, ntpath).
8 8
9 Some of this can actually be useful on non-Posix systems too, e.g. 9 Some of this can actually be useful on non-Posix systems too, e.g.
10 for manipulation of the pathname component of URLs. 10 for manipulation of the pathname component of URLs.
11 """ 11 """
12 12
13 import os 13 import os
14 import sys 14 import sys
15 import stat 15 import stat
16 import genericpath 16 import genericpath
17 from genericpath import * 17 from genericpath import *
18 18
19 __all__ = ["normcase","isabs","join","splitdrive","split","splitext", 19 __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
20 "basename","dirname","commonprefix","getsize","getmtime", 20 "basename","dirname","commonprefix","getsize","getmtime",
21 "getatime","getctime","islink","exists","lexists","isdir","isfile", 21 "getatime","getctime","islink","exists","lexists","isdir","isfile",
22 "ismount", "expanduser","expandvars","normpath","abspath", 22 "ismount", "expanduser","expandvars","normpath","abspath",
23 "samefile","sameopenfile","samestat", 23 "samefile","sameopenfile","samestat",
24 "curdir","pardir","sep","pathsep","defpath","altsep","extsep", 24 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
25 "devnull","realpath","supports_unicode_filenames","relpath"] 25 "devnull","realpath","supports_unicode_filenames","relpath",
26 "commonpath"]
26 27
27 # Strings representing various path-related bits and pieces. 28 # Strings representing various path-related bits and pieces.
28 # These are primarily for export; internally, they are hardcoded. 29 # These are primarily for export; internally, they are hardcoded.
29 curdir = '.' 30 curdir = '.'
30 pardir = '..' 31 pardir = '..'
31 extsep = '.' 32 extsep = '.'
32 sep = '/' 33 sep = '/'
33 pathsep = ':' 34 pathsep = ':'
34 defpath = ':/bin:/usr/bin' 35 defpath = ':/bin:/usr/bin'
35 altsep = None 36 altsep = None
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 start_list = [x for x in abspath(start).split(sep) if x] 451 start_list = [x for x in abspath(start).split(sep) if x]
451 path_list = [x for x in abspath(path).split(sep) if x] 452 path_list = [x for x in abspath(path).split(sep) if x]
452 453
453 # Work out how much of the filepath is shared by start and path. 454 # Work out how much of the filepath is shared by start and path.
454 i = len(commonprefix([start_list, path_list])) 455 i = len(commonprefix([start_list, path_list]))
455 456
456 rel_list = [pardir] * (len(start_list)-i) + path_list[i:] 457 rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
457 if not rel_list: 458 if not rel_list:
458 return curdir 459 return curdir
459 return join(*rel_list) 460 return join(*rel_list)
461
462
463 # Return the longest common sub-path of the sequence of paths given as input.
464 # The paths are not normalized before comparing them (this is the
465 # responsibility of the caller). Any trailing separator is stripped from the
466 # returned path.
467
468 def commonpath(paths):
469 """Given a sequence of path names, returns the longest common sub-path."""
470
471 if not paths:
472 raise ValueError('commonpath() arg is an empty sequence')
473
474 if isinstance(paths[0], bytes):
475 sep = b'/'
476 curdir = b'.'
477 else:
478 sep = '/'
479 curdir = '.'
480
481 try:
482 split_paths = [path.split(sep) for path in paths]
483 except TypeError:
484 valid_types = all(isinstance(p, (str, bytes)) for p in paths)
485 if valid_types:
486 # Must have a mixture of text and binary data
487 raise TypeError("Can't mix strings and bytes in paths") from None
488 raise
489
490 if len(set(p[:1] == sep for p in paths)) != 1:
491 raise ValueError("Can't mix absolute and relative paths")
492
493 split_paths = [[c for c in s if c and c != curdir] for s in split_paths]
494 s1 = min(split_paths)
495 s2 = max(split_paths)
496 common = s1
497 for i, c in enumerate(s1):
498 if c != s2[i]:
499 common = s1[:i]
500 break
501
502 prefix = sep if isabs(paths[0]) else sep[:0]
503 if not common:
504 return prefix
505 else:
506 return prefix + sep.join(common)
OLDNEW
« no previous file with comments | « Lib/ntpath.py ('k') | Lib/test/test_ntpath.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+