| 105 | |
| 106 | # Join two (or more) paths. |
| 107 | def join(path, *paths): |
| 108 | path = os.fspath(path) |
| 109 | if isinstance(path, bytes): |
| 110 | sep = b'\\' |
| 111 | seps = b'\\/' |
| 112 | colon = b':' |
| 113 | else: |
| 114 | sep = '\\' |
| 115 | seps = '\\/' |
| 116 | colon = ':' |
| 117 | try: |
| 118 | if not paths: |
| 119 | path[:0] + sep #23780: Ensure compatible data type even if p is null. |
| 120 | result_drive, result_path = splitdrive(path) |
| 121 | for p in map(os.fspath, paths): |
| 122 | p_drive, p_path = splitdrive(p) |
| 123 | if p_path and p_path[0] in seps: |
| 124 | # Second path is absolute |
| 125 | if p_drive or not result_drive: |
| 126 | result_drive = p_drive |
| 127 | result_path = p_path |
| 128 | continue |
| 129 | elif p_drive and p_drive != result_drive: |
| 130 | if p_drive.lower() != result_drive.lower(): |
| 131 | # Different drives => ignore the first path entirely |
| 132 | result_drive = p_drive |
| 133 | result_path = p_path |
| 134 | continue |
| 135 | # Same drive in different case |
| 136 | result_drive = p_drive |
| 137 | # Second path is relative to the first |
| 138 | if result_path and result_path[-1] not in seps: |
| 139 | result_path = result_path + sep |
| 140 | result_path = result_path + p_path |
| 141 | ## add separator between UNC and non-absolute path |
| 142 | if (result_path and result_path[0] not in seps and |
| 143 | result_drive and result_drive[-1:] != colon): |
| 144 | return result_drive + sep + result_path |
| 145 | return result_drive + result_path |
| 146 | except (TypeError, AttributeError, BytesWarning): |
| 147 | genericpath._check_arg_types('join', path, *paths) |
| 148 | raise |
| 149 | |
| 150 | |
| 151 | # Split a path in a drive specification (a drive letter followed by a |