Given an iterable of path names, returns the longest common sub-path.
(paths)
| 799 | # stripped from the returned path. |
| 800 | |
| 801 | def commonpath(paths): |
| 802 | """Given an iterable of path names, returns the longest common sub-path.""" |
| 803 | paths = tuple(map(os.fspath, paths)) |
| 804 | if not paths: |
| 805 | raise ValueError('commonpath() arg is an empty iterable') |
| 806 | |
| 807 | if isinstance(paths[0], bytes): |
| 808 | sep = b'\\' |
| 809 | altsep = b'/' |
| 810 | curdir = b'.' |
| 811 | else: |
| 812 | sep = '\\' |
| 813 | altsep = '/' |
| 814 | curdir = '.' |
| 815 | |
| 816 | try: |
| 817 | drivesplits = [splitroot(p.replace(altsep, sep).lower()) for p in paths] |
| 818 | split_paths = [p.split(sep) for d, r, p in drivesplits] |
| 819 | |
| 820 | # Check that all drive letters or UNC paths match. The check is made only |
| 821 | # now otherwise type errors for mixing strings and bytes would not be |
| 822 | # caught. |
| 823 | if len({d for d, r, p in drivesplits}) != 1: |
| 824 | raise ValueError("Paths don't have the same drive") |
| 825 | |
| 826 | drive, root, path = splitroot(paths[0].replace(altsep, sep)) |
| 827 | if len({r for d, r, p in drivesplits}) != 1: |
| 828 | if drive: |
| 829 | raise ValueError("Can't mix absolute and relative paths") |
| 830 | else: |
| 831 | raise ValueError("Can't mix rooted and not-rooted paths") |
| 832 | |
| 833 | common = path.split(sep) |
| 834 | common = [c for c in common if c and c != curdir] |
| 835 | |
| 836 | split_paths = [[c for c in s if c and c != curdir] for s in split_paths] |
| 837 | s1 = min(split_paths) |
| 838 | s2 = max(split_paths) |
| 839 | for i, c in enumerate(s1): |
| 840 | if c != s2[i]: |
| 841 | common = common[:i] |
| 842 | break |
| 843 | else: |
| 844 | common = common[:len(s1)] |
| 845 | |
| 846 | return drive + root + sep.join(common) |
| 847 | except (TypeError, AttributeError): |
| 848 | genericpath._check_arg_types('commonpath', *paths) |
| 849 | raise |
| 850 | |
| 851 | |
| 852 | try: |