Edit on GitHub

gpath

1__version__ = '0.4.4'
2
3from . import platform, render
4from ._gpath import GPath, GPathLike
5
6__all__ = ('GPath', 'GPathLike', 'platform', 'render')
class GPath(Hashable, Sized, Iterable, render.Renderable):
  86class GPath(Hashable, Sized, Iterable, render.Renderable):
  87	"""
  88		An immutable generalised abstract file path that has no dependency on any real filesystem.
  89
  90		The path can be manipulated on a system that is different from where it originated, notably including systems with a different operating system, and it can represent file paths on a system other than local. Examples where this is useful include remote management of servers and when cross-compiling source code for a different platform.
  91
  92		Since GPath objects are immutable, all operations return a new instance. The path is always stored in a normalised state, and is always treated as case sensitive.
  93
  94		The path can be rendered as a string using <code>str(<var>g</var>)</code>, which will use `/` as the path separator if possible to maximise cross-platform compatibility.
  95	"""
  96
  97	__slots__ = (
  98		'_parts',
  99		'_root',
 100		'_drive',
 101		'_parent_level',
 102		'_platform',
 103		'_encoding',
 104	)
 105
 106
 107	def __init__(self,
 108		path: Union[str, bytes, os.PathLike, GPath, None]="",
 109		platform: Optional[Union[str, Platform]]=None,
 110		encoding: Optional[str]=None,
 111	):
 112		"""
 113			Initialise a normalised and generalised abstract file path, possibly by copying an existing GPath object.
 114
 115			Parameters
 116			----------
 117			`path`
 118			: path-like object representing a (possibly unnormalised) file path, or a GPath object to be copied
 119
 120			`​platform`
 121			: interpret `path` as originating from a specific platform. This is usually not required for normal file paths on Windows, Linux or macOS, and is needed only for edge cases (see [compatibility](https://github.com/yushiyangk/gpath#compatibility) in the readme). If `path` is a GPath, this argument has no effect. The platform name should be one of the keys in `gpath.platform.platform_names`. If specified, the platform will propagate to new GPaths returned by operations on this GPath; for binary operations of two GPaths, the platform specified by the left operand will be propagated. See also the `from_*()` static methods.
 122
 123			`​encoding`
 124			: the text encoding that should be used to decode paths given as bytes-like objects; if not specified, `'utf_8'` will be used by default. The encoding name should be one of the standard Python text encodings, as listed in the `codecs` module of the standard library. If specified, the encoding will propagate to new GPaths returned by operations on this GPath; for binary operations of two GPaths, the encoding specified by the left operand will be propagated.
 125
 126			Raises
 127			------
 128			`ValueError` if `other` is an invalid GPath
 129
 130			Examples
 131			--------
 132			```python
 133			GPath("/")
 134			GPath("/usr/bin")
 135			GPath("C:/Program Files")
 136			```
 137		"""
 138
 139		self._parts: tuple[str, ...] = tuple()  # root- or parent- relative path
 140		self._root: bool = False
 141		self._drive: str = ""
 142		self._parent_level: int = 0
 143
 144		self._platform: Optional[Platform] = Platform.from_str(platform) if isinstance(platform, str) else platform
 145		self._encoding: Optional[str] = encoding
 146
 147		if isinstance(path, GPath):
 148			path._validate()
 149			self._parts = path._parts
 150			self._root = path._root
 151			self._drive = path._drive
 152			self._parent_level = path._parent_level
 153
 154			self._platform = path._platform if self._platform is None else self._platform
 155			self._encoding = path._encoding if self._encoding is None else self._encoding
 156			return
 157
 158		if path is None or path == "":
 159			return
 160
 161		path = os.fspath(path)
 162
 163		if isinstance(path, bytes):
 164			if self._encoding is None:
 165				path = path.decode(DEFAULT_ENCODING)
 166			else:
 167				path = path.decode(self._encoding)
 168
 169		# path is a str
 170
 171		if self._platform is None:
 172			platform = Platform.GENERIC
 173		else:
 174			platform = self._platform
 175
 176		if platform == Platform.POSIX:
 177			for root in _rules.posix_rules.roots:
 178				if path.startswith(root):
 179					self._root = True
 180					break
 181
 182			if self._root:
 183				rootless_path = path[1:]
 184			else:
 185				rootless_path = path
 186
 187			parts = _split_relative(rootless_path, delimiters=_rules.posix_rules.separators)
 188
 189		elif platform == Platform.WINDOWS:
 190			if len(path) >= 2 and path[1] in _rules.windows_rules.drive_postfixes:
 191				self._drive = path[0]
 192				driveless_path = path[2:]
 193			else:
 194				driveless_path = path
 195
 196			for root in _rules.windows_rules.roots:
 197				if driveless_path.startswith(root):
 198					self._root = True
 199					break
 200
 201			if self._root:
 202				rootless_path = driveless_path[1:]
 203			else:
 204				rootless_path = driveless_path
 205
 206			parts = _split_relative(rootless_path, delimiters=_rules.windows_rules.separators)
 207
 208		else:
 209			if len(path) >= 2 and path[1] in _rules.generic_rules.drive_postfixes:
 210				self._drive = path[0]
 211				driveless_path = path[2:]
 212			else:
 213				driveless_path = path
 214
 215			for root in _rules.generic_rules.roots:
 216				if driveless_path.startswith(root):
 217					self._root = True
 218					break
 219
 220			if self._root:
 221				rootless_path = driveless_path[1:]
 222			else:
 223				rootless_path = driveless_path
 224
 225			parts = _split_relative(rootless_path, delimiters=_rules.generic_rules.separators)
 226
 227
 228		parts = _normalise_relative(parts)
 229		parent_level = 0
 230		while parent_level < len(parts) and parts[parent_level] in _rules.generic_rules.parent_indicators:
 231			parent_level += 1
 232		self._parts = tuple(parts[parent_level:])
 233		if self._root == False:
 234			self._parent_level = parent_level
 235
 236
 237	@property
 238	def named_parts(self) -> list[str]:
 239		"""
 240			Read-only named components of the path, not including the filesystem root, drive name, or any parent directories
 241
 242			Examples
 243			--------
 244			```python
 245			GPath("usr/local/bin").named_parts     # ["usr", "local", "bin"]
 246			GPath("../../Documents").named_parts   # ["Documents"]
 247			GPath("/usr/bin").named_parts          # ["usr", "bin"]
 248			GPath("C:/Program Files").named_parts  # ["Program Files"]
 249			```
 250		"""
 251		return list(self._parts)
 252
 253	@property
 254	def relative_parts(self) -> list[str]:
 255		"""
 256			Read-only relative components of the path, not including the filesystem root or drive name, including one item for each level of parent directory
 257
 258			Examples
 259			--------
 260			```python
 261			GPath("usr/local/bin").relative_parts     # ["usr", "local", "bin"]
 262			GPath("../../Documents").relative_parts   # ["..", "..", "Documents"]
 263			GPath("/usr/bin").relative_parts          # ["usr", "bin"]
 264			GPath("C:/Program Files").relative_parts  # ["Program Files"]
 265			```
 266		"""
 267		return self.parent_parts + list(self._parts)
 268
 269	@property
 270	def absolute(self) -> bool:
 271		"""
 272			Read-only flag for whether the path is an absolute path
 273
 274			Examples
 275			--------
 276			```python
 277			GPath("/").absolute                # True
 278			GPath("C:/Windows").absolute       # True
 279			GPath("local/bin").absolute        # False
 280			GPath("../../Documents").absolute  # False
 281			```
 282		"""
 283		return self._root
 284
 285	@property
 286	def root(self) -> bool:
 287		"""
 288			Read-only flag for whether the path is exactly the root of the filesystem
 289
 290			Examples
 291			--------
 292			```python
 293			GPath("/").root                # True
 294			GPath("C:/").root              # True
 295			GPath("/usr/bin").root         # False
 296			GPath("C:/Windows").root       # False
 297			GPath("../../Documents").root  # False
 298			```
 299		"""
 300		return self._root and len(self._parts) == 0
 301
 302	@property
 303	def drive(self) -> str:
 304		"""
 305			Read-only drive name
 306
 307			Examples
 308			--------
 309			```python
 310			GPath("C:/Windows").drive       # "C:"
 311			GPath("/usr/bin").drive         # ""
 312			GPath("../../Documents").drive  # ""
 313			```
 314		"""
 315		return self._drive
 316
 317	@property
 318	def parent_level(self) -> int:
 319		"""
 320			Read-only number of levels of parent directories that the path is relative to, which may be 0
 321
 322			Examples
 323			--------
 324			```python
 325			GPath("../../Documents").parent_level  # 2
 326			GPath("usr/local/bin").parent_level    # 0
 327			```
 328		"""
 329		return self._parent_level
 330
 331	@property
 332	def parent_parts(self) -> list[str]:
 333		"""
 334			Read-only path components representing a parent directory that it is relative to, if any, with one item for each level of parent directory
 335
 336			Examples
 337			--------
 338			```python
 339			GPath("../../Documents").parent_parts  # ["..", ".."]
 340			GPath("usr/local/bin").parent_parts    # []
 341			```
 342		"""
 343		return [_rules.generic_rules.parent_indicators[0] for i in range(self._parent_level)]
 344
 345	@property
 346	def encoding(self) -> Union[str, None]:
 347		"""
 348			Read-only encoding used to decode other paths that are given as bytes-like objects, or None if the default should be used
 349		"""
 350		return self._encoding
 351
 352	@property
 353	def platform(self) -> Union[str, None]:
 354		"""
 355			Read-only platform that other non-GPath operands should be interepreted as, or None if the default should be used
 356		"""
 357		return str(self._platform) if self._platform is not None else None
 358
 359
 360	@staticmethod
 361	def from_posix(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
 362		"""
 363			Initialise a GPath that originates from a POSIX-like operating system, or copy a GPath such that any future non-GPath operands would be interpreted as originating from a POSIX-like operating system.
 364
 365			See `__init__()` for details.
 366
 367			Equivalent to `GPath(path, platform='posix')`
 368			```
 369		"""
 370		return GPath(path, platform=Platform.POSIX, encoding=encoding)
 371
 372	@staticmethod
 373	def from_linux(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
 374		"""
 375			Alias of `from_posix()`
 376		"""
 377		return GPath.from_posix(path, encoding=encoding)
 378
 379	@staticmethod
 380	def from_macos(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
 381		"""
 382			Alias of `from_posix()`
 383		"""
 384		return GPath.from_posix(path, encoding=encoding)
 385
 386
 387	@staticmethod
 388	def from_windows(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
 389		"""
 390			Initialise a GPath that originates from a Windows operating system, or copy a GPath such that any future non-GPath operands would be interpreted as originating from a Windows operating system.
 391
 392			See `__init__()` for details.
 393
 394			Equivalent to `GPath(path, platform='windows')`
 395			```
 396		"""
 397		return GPath(path, platform=Platform.WINDOWS, encoding=encoding)
 398
 399
 400	#@overload
 401	#@staticmethod
 402	#def partition(paths: Iterable[GPathLike], /, *, allow_current, allow_parents, platform, encoding) -> dict[GPath, list[GPath]]:
 403	#	...
 404	#@overload
 405	#@staticmethod
 406	#def partition(*paths: GPathLike, allow_current, allow_parents, platform, encoding) -> dict[GPath, list[GPath]]:
 407	#	...
 408	@staticmethod
 409	def partition(
 410		*paths,
 411		allow_current: bool=True,
 412		allow_parents: bool=True,
 413		platform: Optional[Union[str, Platform]]=None,
 414		encoding: Optional[str]=None,
 415	) -> dict[GPath, list[GPath]]:
 416		"""
 417			Partition a collection of paths based on shared common base paths such that each path belongs to one partition.
 418
 419			For each partition, return a list of relative paths from the base path of that partition to each corresponding input path within that partition, unless `allow_parents` is True (see below). If the input collection is ordered, the output order is preserved within each partition. If the input collection contains duplicates, the corresponding output lists will as well.
 420
 421			The number of partitions is minimised by merging partitions as much as possible, so that each partition represents the highest possible level base path. Two partitions can no longer be merged when there is no common base path between them, as determined by `common_with()`. This method takes the same optional arguments as `common_with()`, with the same default values.
 422
 423			Parameters
 424			----------
 425			`paths: Iterable[GPath | str | bytes | os.PathLike]` or `*paths: GPath | str | bytes | os.PathLike`
 426			: the paths to be partitioned, which can be given as either a list-like object or as variadic arguments
 427
 428			`allow_current`
 429			: whether non-parent relative paths with no shared components should be considered to have a common base path (see `common_with()`)
 430
 431			`allow_parents`
 432			: whether paths that are relative to different levels of parent directories should be considered to have a common base path (see `common_with()`). **Warning**: when set to True, the output lists for each partition are invalidated, and explicitly set to empty. This is because it is not possible in general to obtain a relative path from the base path to its members if the base path is a parent directory of a higher level than the member (see `relpath_from()`). This  option should be True if and only if the list of members in each partition are not of interest; in most cases False is more appropriate.
 433
 434			`​platform`
 435			: the originating platform that should be assumed when interpreting non-GPath objects in `paths`, if any (see `__init__()`).
 436
 437			`​encoding`
 438			: the text encoding that should be used to decode bytes-like objects in `paths`, if any (see `__init__()`).
 439
 440			Returns
 441			-------
 442			a dictionary that maps the common base path of each partition to a list of relative paths
 443
 444			Raises
 445			------
 446			  `ValueError`
 447			  if any of the GPaths are invalid
 448
 449			Examples
 450			--------
 451			```python
 452			GPath.partition("/usr/bin", "/usr/local/bin", "../../doc", "C:/Windows", "C:/Program Files")
 453
 454			assert partitions == {
 455				GPath("/usr")      : [GPath("bin"), GPath("local")],
 456				GPath("../../doc") : [GPath("")],
 457				GPath("C:/")       : [GPath("Windows"), GPath("Program Files")],
 458			}
 459			```
 460		"""
 461		flattened_paths: list[GPathLike] = []
 462		for path_or_list in paths:
 463			if _is_gpathlike(path_or_list):
 464				flattened_paths.append(path_or_list)
 465			else:
 466				flattened_paths.extend(path_or_list)
 467		gpaths = [path if isinstance(path, GPath) else GPath(path, encoding=encoding, platform=platform) for path in flattened_paths]
 468
 469		partition_map = {}
 470		if len(gpaths) > 0:
 471			if allow_parents == True:
 472				partition_map[gpaths[0]] = []
 473			else:
 474				partition_map[gpaths[0]] = [gpaths[0]]
 475
 476		for path in gpaths[1:]:
 477			partition_found = False
 478			for partition in partition_map:
 479				candidate_common = partition.common_with(path, allow_current=allow_current, allow_parents=allow_parents)
 480				if candidate_common is not None:
 481					partition_found = True
 482					if candidate_common != partition:
 483						partition_map[candidate_common] = partition_map[partition]
 484						del partition_map[partition]
 485					if allow_parents == False:
 486						partition_map[candidate_common].append(path)
 487					break
 488			if not partition_found:
 489				if allow_parents == True:
 490					partition_map[path] = []
 491				else:
 492					partition_map[path] = [path]
 493
 494		for partition, path_list in partition_map.items():
 495			partition_map[partition] = [path.subpath_from(partition) for path in path_list]
 496
 497		return partition_map
 498
 499
 500	#@overload
 501	#@staticmethod
 502	#def join(paths: Iterable[GPathLike], /, *, platform, encoding) -> GPath:
 503	#	...
 504	#@overload
 505	#@staticmethod
 506	#def join(*paths: GPathLike, platform, encoding) -> GPath:
 507	#	...
 508	@staticmethod
 509	def join(*paths, platform: Optional[Union[str, Platform]]=None, encoding: Optional[str]=None) -> GPath:
 510		"""
 511			Join a sequence of paths into a single path. Apart from the first item in the sequence, all subsequent paths should be relative paths and any absolute paths will be ignored.
 512
 513			Parameters
 514			----------
 515			`paths`: `Sequence[GPath | str | bytes | os.PathLike]` or `*paths: GPath | str | bytes | os.PathLike`
 516			: the paths to be combined, which can be given as either a list-like object or as variadic arguments
 517
 518			`​platform`
 519			: the originating platform that should be assumed when interpreting non-GPath objects in `paths`, if any (see `__init__()`).
 520
 521			`​encoding`
 522			: the text encoding that should be used to decode bytes-like objects in `paths`, if any (see `__init__()`).
 523
 524			Returns
 525			-------
 526			the combined path
 527
 528			Raises
 529			------
 530			`ValueError` if any of the GPaths are invalid
 531
 532			Examples
 533			--------
 534			```python
 535			GPath.join("usr", "local", "bin")          # GPath("usr/local/bin")
 536			GPath.join("/usr/local/bin", "../../bin")  # GPath("/usr/bin")
 537			GPath.join("C:/", "Windows")               # GPath("C:/Windows")
 538			```
 539		"""
 540		flattened_paths: list[GPathLike] = []
 541		for path_or_list in paths:
 542			if _is_gpathlike(path_or_list):
 543				flattened_paths.append(path_or_list)
 544			else:
 545				flattened_paths.extend(path_or_list)
 546
 547		if len(flattened_paths) == 0:
 548			return GPath(encoding=encoding, platform=platform)
 549
 550		combined_path = flattened_paths[0]
 551		if not isinstance(combined_path, GPath):
 552			combined_path = GPath(combined_path, encoding=encoding, platform=platform)
 553		for path in flattened_paths[1:]:
 554			combined_path = combined_path + path
 555
 556		return combined_path
 557
 558
 559	def as_relative(self, parent_level: Optional[int]=None) -> GPath:
 560		"""
 561			Convert the path to a relative path and return a new copy.
 562
 563			Parameters
 564			----------
 565			`​parent_level`
 566			: the number of levels of parent directories that the returned path should be relative to, which may be 0. If set to None, the returned path will have the same parent level as the current path if it is currently a relative path, or have no parent level (i.e. 0) otherwise.
 567
 568			Raises
 569			------
 570			`TypeError` if `​parent_level` is not a valid type
 571
 572			Examples
 573			--------
 574			```python
 575			GPath("/usr/bin").as_relative()      # GPath("usr/bin")
 576			GPath("C:/Windows").as_relative()    # GPath("C:Windows")
 577			GPath("../Documents").as_relative()  # GPath("../Documents")
 578			```
 579		"""
 580
 581		new_path = GPath(self)
 582		new_path._root = False
 583		if parent_level is None:
 584			pass
 585		elif isinstance(parent_level, int):
 586			new_path._parent_level = parent_level
 587		else:
 588			raise TypeError(f"parent_level must be an int: {parent_level} ({type(parent_level)})")
 589
 590		return new_path
 591
 592
 593	def as_absolute(self) -> GPath:
 594		"""
 595			Convert the path to an absolute path and return a new copy.
 596
 597			Any parent directory that the path is relative to will be removed. If the path is already absolute, an identical copy is returned.
 598
 599			Examples
 600			--------
 601			```python
 602			GPath("usr/bin").as_absolute()       # GPath("/usr/bin")
 603			GPath("../Documents").as_absolute()  # GPath("/Documents")
 604			GPath("C:Windows").as_absolute()     # GPath("C:/Windows")
 605			```
 606		"""
 607		new_path = GPath(self)
 608		new_path._root = True
 609		new_path._parent_level = 0
 610		return new_path
 611
 612
 613	def with_drive(self, drive: Union[str, bytes, None]=None) -> GPath:
 614		"""
 615			Return a new copy of the path with the drive set to `​drive`.
 616
 617			If `​drive` is `""` or None, this would be equivalent to `without_drive()`.
 618
 619			Parameters
 620			----------
 621			`​drive`
 622			: the drive for the returned path, or either `""` or None if the returned path should have no drive
 623
 624			Returns
 625			-------
 626			`GPath`
 627			: a new path with the given drive
 628
 629			Raises
 630			------
 631			- `TypeError` if `​drive` is not a valid type
 632			- `ValueError` if `​drive` has more than one character
 633
 634			Examples
 635			--------
 636			```python
 637			GPath("C:/Windows").with_drive()      # GPath("/Windows")
 638			GPath("C:/Windows").with_drive("D")   # GPath("D:/Windows")
 639			GPath("/Windows").with_drive("C")     # GPath("C:/Windows")
 640			```
 641		"""
 642		if drive is None:
 643			drive = ""
 644		elif isinstance(drive, bytes):
 645			if self._encoding is None:
 646				drive = drive.decode(DEFAULT_ENCODING)
 647			else:
 648				drive = drive.decode(self._encoding)
 649		elif isinstance(drive, str):
 650			pass
 651		else:
 652			raise TypeError(f"drive must be a str or bytes object: {drive} ({type(drive)})")
 653
 654		if len(drive) > 1:
 655			raise ValueError(f"drive can only be a single character, an empty string or None: {drive}")
 656
 657		new_path = GPath(self)
 658		new_path._drive = drive
 659		return new_path
 660
 661
 662	def without_drive(self) -> GPath:
 663		"""
 664			Return a new copy of the path without a drive.
 665
 666			Equivalent to `with_drive("")` or `with_drive(None)`.
 667
 668			Returns
 669			-------
 670			`GPath`
 671			: a new path without a drive
 672
 673			Examples
 674			--------
 675			```python
 676			GPath("C:/Windows").without_drive()      # GPath("/Windows")
 677			```
 678		"""
 679		return self.with_drive(None)
 680
 681
 682	def common_with(self, other: GPathLike, allow_current: bool=True, allow_parents: bool=False) -> Optional[GPath]:
 683		"""
 684			Find the longest common base path shared between `self` and `other`, or return None if no such path exists.
 685
 686			A common base path might not exist if one path is an absolute path while the other is a relative path, or if the two paths are in different filesystems (with different drive names), or in other cases as controlled by the `allow_current` and `allow_parents` options.
 687
 688			If using the default options of `allow_current=True` and `allow_parent=False`, the binary operator for bitwise-and can be used: `__and__()` (usage: <code><var>g1</var> & <var>g2</var></code>).
 689
 690			Parameters
 691			----------
 692			`other`
 693			: the path to compare with
 694
 695			`allow_current`
 696			: whether two non-parent relative paths that do not share any components should be considered to have a common base path, namely the imaginary current working directory. For instance, `GPath("some/rel/path").find_common("another/rel/path")` will return `GPath("")` if set to True, or return None if set to False.
 697
 698			`allow_parents`
 699			: whether two relative paths that are relative to different levels of parent directories should be considered to have a common base path, which is the highest level of parent directory between the two paths. For instance, `GPath("../rel/to/parent").find_common("../../rel/to/grandparent")` will return `GPath("../..")` if set to True, or return None if set to False. **Warning**: when set to True, given a higher level of parent directory as output, it may not be possible to find the relative path to one of the inputs (see `relpath_from()`); in most cases False is more appropriate.
 700
 701			Returns
 702			-------
 703			`GPath`
 704			: the longest common base path, which may be empty, if it exists
 705
 706			`None`
 707			: otherwise
 708
 709			Raises
 710			------
 711			`ValueError` if either `self` or `other` is an invalid GPath
 712
 713			Examples
 714			--------
 715			```python
 716			GPath("/usr/bin").find_common("/usr/local/bin")               # GPath("/usr")
 717			GPath("C:/Windows/System32").find_common("C:/Program Files")  # GPath("C:/")
 718			GPath("../Documents").find_common("../Pictures")              # GPath("..")
 719			```
 720		"""
 721		self._validate()
 722		if isinstance(other, GPath):
 723			other._validate()
 724		else:
 725			other = GPath(other, encoding=self._encoding)
 726
 727		if self._drive != other._drive:
 728			return None
 729		if self._root != other._root:
 730			return None
 731
 732		if allow_parents:
 733			allow_current = True
 734
 735		parts = []
 736		if self._root:
 737			common_path = GPath(self)
 738			for part1, part2 in zip(self._parts, other._parts):
 739				if part1 == part2:
 740					parts.append(part1)
 741		else:
 742			if self._parent_level != other._parent_level:
 743				if not allow_parents:
 744					return None
 745
 746				common_path = GPath(self)
 747				common_path._parent_level = max(self._parent_level, other._parent_level)
 748			else:
 749				common_path = GPath(self)
 750				for part1, part2 in zip(self._parts, other._parts):
 751					if part1 == part2:
 752						parts.append(part1)
 753
 754		common_path._parts = tuple(parts)
 755
 756		if not allow_current and not bool(common_path):
 757			if common_path != self or common_path != other:
 758				return None
 759		return common_path
 760
 761
 762	def subpath_from(self, base: GPathLike) -> Optional[GPath]:
 763		"""
 764			Find the relative subpath from `base` to `self` if possible and if `base` contains `self`, or return None otherwise.
 765
 766			None will also be returned if there are unknown components in the subpath from `base` to `self`. For instance, if `self` is relative to the parent directory while `base` is relative to the grandparent directory, the path from the grandparent directory `../..` to the parent directory `..` cannot be known.
 767
 768			Similar to `relpath_from()`, but `self` must be a descendent of `base`.
 769
 770			Parameters
 771			----------
 772			`base`
 773			: the base path that the relative subpath should start from
 774
 775			Returns
 776			-------
 777			`GPath`
 778			: relative subpath from `base` to `self`, which may be empty, if it exists
 779
 780			`None`
 781			: otherwise
 782
 783			Raises
 784			------
 785			`ValueError` if either `self` or `base` is an invalid GPath
 786
 787			Examples
 788			--------
 789			```python
 790			GPath("/usr/local/bin").subpath_from("/usr")      # GPath("local/bin")
 791			GPath("/usr/bin").subpath_from("/usr/local/bin")  # None
 792			GPath("/usr/bin").subpath_from("../Documents")    # None
 793			```
 794		"""
 795		if not isinstance(base, GPath):
 796			base = GPath(base, encoding=self._encoding)
 797
 798		if self.common_with(base, allow_current=True, allow_parents=False) is not None and self in base:
 799			# If self._parent_level > base._parent_level, self is not in base, whereas if self._parent_level < base._parent_level, path from base to self's parent cannot be known
 800			base_length = len(base._parts)
 801			new_path = GPath(self)
 802			new_path._parts = self._parts[base_length:]  # () when self == base
 803			new_path._drive = ""
 804			new_path._root = False
 805			new_path._parent_level = 0
 806			return new_path
 807		else:
 808			return None
 809
 810
 811	def relpath_from(self, origin: GPathLike) -> Optional[GPath]:
 812		"""
 813			Find the relative path from `origin` to `self` if possible, or return None otherwise.
 814
 815			None will also be returned if there are unknown components in the relative path from `origin` to `self`. For instance, if `self` is relative to the parent directory while `base` base is relative to the grandparent directory, the path from the grandparent directory `../..` to the parent directory `..` cannot be known.
 816
 817			Similar to `subpath_from()`, but `self` does not need to be a descendent of `origin`.
 818
 819			Parameters
 820			----------
 821			`origin`
 822			: the origin that the relative path should start from
 823
 824			Returns
 825			-------
 826			`GPath`
 827			: relative path from `origin` to `self`, which may be empty, if it exists
 828
 829			`None`
 830			: otherwise
 831
 832			Raises
 833			------
 834			`ValueError` if either `self` or `origin` is an invalid GPath
 835
 836			Examples
 837			--------
 838			```python
 839			GPath("/usr/local/bin").subpath_from("/usr")      # GPath("local/bin")
 840			GPath("/usr/bin").subpath_from("/usr/local/bin")  # GPath("../../bin")
 841			GPath("/usr/bin").subpath_from("../Documents")    # None
 842			```
 843		"""
 844		self._validate()
 845		if not isinstance(origin, GPath):
 846			origin = GPath(origin, encoding=self._encoding)
 847
 848		if origin._root:
 849			common = self.common_with(origin)
 850			if common is None:
 851				return None
 852
 853			new_path = GPath(self)
 854			new_path._parent_level = len(origin) - len(common)
 855			new_path._parts = self._parts[len(common):]
 856			new_path._drive = ""
 857			new_path._root = False
 858			return new_path
 859
 860		else:
 861			common = self.common_with(origin, allow_current=True, allow_parents=True)
 862			if common is None:
 863				return None
 864			if common._parent_level > self._parent_level:
 865				return None  # Path from common to self's parent cannot be known
 866
 867			# common._dotdot == self._dotdot
 868			# origin._dotdot <= self._dotdot
 869
 870			new_path = GPath(self)
 871			new_path._drive = ""
 872			new_path._root = False
 873			if len(common) == 0:
 874				if origin._parent_level == self._parent_level:
 875					new_path._parent_level = len(origin)
 876				else:
 877					new_path._parent_level = (common._parent_level - origin._parent_level) + len(origin)
 878				new_path._parts = self._parts
 879			else:
 880				new_path._parent_level = len(origin) - len(common)
 881				new_path._parts = self._parts[len(common):]
 882
 883			return new_path
 884
 885
 886	def render(self, platform: Union[str, Platform, None]) -> render.RenderedPath:
 887		"""
 888			Convert the path to a RenderedPath for printing in a specific target operating system.
 889
 890			This will convert, and coerce if necessary, the generalised abstract GPath into a platform-specific path which can then be converted to a printable string using <code>str(<var>renderred_path</var>)</code>. The resulting string will be in the format preferred by the target platform.
 891
 892			If the GPath contains features that the target platform does not support (such as drive name when the target platform is POSIX), and if there are no analogous features in the target platform, they will be dropped in the rendered path.
 893
 894			The rendered path also implements total ordering with binary comparisons, e.g. <code><var>r1</var> < <var>r2</var></code>, making it useful for sorting and collation. This ordering is done with platform-specific semantics, unlike GPath which does not have meaningful order.
 895
 896			Parameters
 897			----------
 898			`platform`
 899			: the target platform where the path is to be used
 900
 901			Returns
 902			-------
 903			`RenderedPath`
 904			: platform-specific path ready for sorting or output
 905
 906			Examples
 907			--------
 908			```python
 909			# Print examples
 910			print(GPath("/usr/bin").render('linux'))      # /usr/bin
 911			print(GPath("/usr/bin").render('windows'))    # \\usr\\bin
 912			print(GPath("C:/Windows").render('linux'))    # /Windows
 913			print(GPath("C:/Windows").render('windows'))  # C:\\Windows
 914
 915			# Ordering examples
 916			GPath("").render('linux') < GPath("abc").render('linux')       # True
 917			GPath("abc").render('linux') < GPath("..").render('linux')     # True
 918			GPath("..").render('linux') < GPath("../..").render('linux')   # True
 919			GPath("../..").render('linux') < GPath("/").render('linux')    # True
 920			GPath("/").render('linux') < GPath("C:/").render('linux')      # False
 921			GPath("/").render('linux') <= GPath("C:/").render('linux')     # True
 922			GPath("/").render('windows') < GPath("C:/").render('windows')  # True
 923			```
 924		"""
 925		if platform is None:
 926			platform = DEFAULT_PLATFORM
 927		elif isinstance(platform, str):
 928			platform = Platform.from_str(platform)
 929		return render.get_type(platform)(self)
 930
 931
 932	def __hash__(self) -> int:
 933		"""
 934			Calculate hash of the GPath object.
 935
 936			Usage: <code>hash(<var>g</var>)</code>
 937		"""
 938		return hash(self._tuple)
 939
 940
 941	def __eq__(self, other: GPathLike) -> bool:
 942		"""
 943			Check if two GPaths are completely identical.
 944
 945			Always return False if `other` is not a GPath object, even if it is a GPath-like object.
 946
 947			Usage: <code><var>g1</var> == <var>g2</var></code>
 948
 949			Examples
 950			--------
 951			```python
 952			GPath("/usr/bin") == GPath("/usr/bin")  # True
 953			GPath("/usr/bin") == GPath("usr/bin")   # False
 954			GPath("C:/") == GPath("D:/")            # False
 955			```
 956		"""
 957		if not isinstance(other, GPath):
 958			other = GPath(other, encoding=self._encoding)
 959		return self._tuple == other._tuple
 960
 961
 962	def __bool__(self) -> bool:
 963		"""
 964			False if `self` is a relative path without any relative components and without a drive, and True otherwise.
 965
 966			Usage: <code>bool(<var>g</var>)</code>, <code>not <var>g</var></code>, or <code>if <var>g</var>:</code>
 967
 968			Examples
 969			--------
 970			```python
 971			bool(GPath("/"))    # True
 972			bool(GPath(".."))   # True
 973			bool(GPath("doc"))  # True
 974			bool(GPath(""))     # False
 975			```
 976		"""
 977		return self._root or self._drive != "" or self._parent_level != 0 or len(self._parts) > 0
 978
 979
 980	def __str__(self) -> str:
 981		"""
 982			Return a platform-independent string representation of the path.
 983
 984			Usage: <code>str(<var>g</var>)</code>
 985		"""
 986		return str(self.render(Platform.GENERIC))
 987
 988
 989	def __repr__(self) -> str:
 990		"""
 991			Return a string that, when printed, gives the Python code associated with instantiating the GPath object.
 992
 993			Usage: <code>repr(<var>g</var>)</code>
 994		"""
 995		if self._platform is None:
 996			platform_repr = ""
 997		else:
 998			platform_repr = f", platform={repr(self._platform)}"
 999
1000		if self._encoding is None:
1001			encoding_repr = ""
1002		else:
1003			encoding_repr = f", encoding={repr(self._encoding)}"
1004
1005		if bool(self):
1006			return f"GPath({repr(str(self))}{platform_repr}{encoding_repr})"
1007		else:
1008			return f"GPath({repr('')}{platform_repr}{encoding_repr})"
1009
1010
1011	def __len__(self) -> int:
1012		"""
1013			Get the number of named path components, excluding any drive name or parent directories.
1014
1015			Usage: <code>len(<var>g</var>)</code>
1016
1017			Examples
1018			--------
1019			```python
1020			len(GPath("/usr/bin"))    # 2
1021			len(GPath("/"))           # 0
1022			len(GPath("C:/Windows"))  # 0
1023			len(GPath("C:/"))         # 0
1024			```
1025		"""
1026		return len(self._parts)
1027
1028
1029	def __getitem__(self, index: Union[int, slice]) -> Union[str, list[str]]:
1030		"""
1031			Get a 0-indexed named path component, or a slice of path components, excluding any drive name or parent directories.
1032
1033			Usage: <code><var>g</var>[<var>n</var>]</code>, <code><var>g</var>[<var>start</var>:<var>end</var>]</code>, <code><var>g</var>[<var>start</var>:<var>end</var>:<var>step</var>]</code>, etc.
1034
1035			Examples
1036			--------
1037			```python
1038			GPath("/usr/local/bin")[1]    # "local"
1039			GPath("/usr/local/bin")[-1]   # "bin"
1040			GPath("/usr/local/bin")[1:]   # ["local", "bin"]
1041			GPath("/usr/local/bin")[::2]  # ["usr", "bin"]
1042			```
1043		"""
1044		if isinstance(index, int):
1045			return self._parts[index]
1046		elif isinstance(index, slice):
1047			return list(self._parts[index])
1048
1049
1050	def __iter__(self) -> Iterator[str]:
1051		"""
1052			Get an iterator through the named path components, excluding any drive name or parent directories.
1053
1054			Usage: <code>iter(<var>g</var>)</code> or <code>for <var>p</var> in <var>g</var>:</code>
1055		"""
1056		return iter(self._parts)
1057
1058
1059	def __contains__(self, other: GPathLike) -> bool:
1060		"""
1061			Check if the path represented by `self` contains the path represented by `other`; i.e. check if `self` is a parent directory of `other`.
1062
1063			Usage: <code><var>other</var> in <var>self</var></code>
1064
1065			Raises `ValueError` if either GPath is invalid
1066
1067			Examples
1068			--------
1069			```python
1070			GPath("/usr/local/bin") in GPath("/usr")  # True
1071			GPath("/usr/local/bin") in GPath("/bin")  # False
1072			GPath("..") in GPath("../..")             # True
1073			GPath("..") in GPath("C:/")               # False
1074			```
1075		"""
1076		if not isinstance(other, GPath):
1077			other = GPath(other, encoding=self._encoding)
1078
1079		common_path = self.common_with(other, allow_current=True, allow_parents=True)
1080		return common_path is not None and common_path == self
1081
1082
1083	def __add__(self, other: GPathLike) -> GPath:
1084		"""
1085			Add (concatenate) `other` to the end of `self`, and return a new copy.
1086
1087			If `other` is an absolute path, the returned path will be an absolute path that matches `other`, apart from the drive name.
1088
1089			If `other` has a drive, the returned path will have the same drive as `other`. Otherwise, the returned path will have the same drive as `self`. If neither has a drive, the returned path will not have a drive as well.
1090
1091			Alias: `__truediv__()`
1092
1093			Usage: <code><var>self</var> + <var>other</var></code> or <code><var>self</var> / <var>other</var></code>
1094
1095			Raises `ValueError` if either GPath is invalid
1096
1097			Examples
1098			--------
1099			```python
1100			GPath("/usr") + GPath("local/bin")                   # GPath("/usr/local/bin")
1101			GPath("C:/Windows/System32") + GPath("../SysWOW64")  # GPath("C:/Windows/SysWOW64")
1102			GPath("C:/Windows/System32") + GPath("/usr/bin")     # GPath("C:/usr/bin")
1103			GPath("..") + GPath("../..")                         # GPath("../../..")
1104			GPath("..") / GPath("../..")                         # GPath("../../..")
1105			```
1106		"""
1107		if isinstance(other, GPath):
1108			other._validate
1109		else:
1110			other = GPath(other, encoding=self._encoding)
1111
1112		new_path = GPath(self)
1113		if other._root:
1114			new_path._parts = other._parts
1115			new_path._root = other._root
1116			new_path._parent_level = other._parent_level
1117		else:
1118			new_parts = [part for part in self._parts]
1119			for i in range(other._parent_level):
1120				if len(new_parts) > 0:
1121					new_parts.pop()
1122				elif not new_path._root:
1123					new_path._parent_level += 1
1124				else:
1125					pass  # parent of directory of root is still root
1126
1127			new_parts.extend(other._parts)
1128			new_path._parts = tuple(new_parts)
1129
1130		if other._drive != "":
1131			new_path._drive = other._drive
1132
1133		return new_path
1134
1135
1136	def __sub__(self, n: int) -> GPath:
1137		"""
1138			Remove `n` components from the end of the path and return a new copy.
1139
1140			Usage: <code><var>self</var> - <var>n</var></code>
1141
1142			Raises `ValueError` if `self` is an invalid GPath or if `n` is negative
1143
1144			Examples
1145			--------
1146			```python
1147			GPath("C:/Windows/System32") - 1  # GPath("C:/Windows")
1148			GPath("/usr/bin") - 2             # GPath("/")
1149			GPath("Documents") - 3            # GPath("..")
1150			GPath("/") - 1                    # GPath("/")
1151			```
1152		"""
1153		if n < 0:
1154			raise ValueError("cannot subtract a negative number of components from the path: {n}; use __add__() instead")
1155
1156		new_path = GPath(self)
1157		new_parts = [part for part in self._parts]
1158		for i in range(n):
1159			if len(new_parts) > 0:
1160				new_parts.pop()
1161			elif not new_path._root:
1162				new_path._parent_level += 1
1163			else:
1164				pass  # removing components from root should still give root
1165		new_path._parts = tuple(new_parts)
1166		return new_path
1167
1168
1169	def __mul__(self, n: int) -> GPath:
1170		"""
1171			Duplicate the named components of `self` `n` times and return a new path with the duplicated components.
1172
1173			Named components will be duplicated separately from the components representing a parent directory. If `self` is an absolute path, only the relative components will be duplicated.
1174
1175			If `n` is 0, the result is an empty path (either relative or absolute).
1176
1177			Usage: <code><var>self</var> * <var>n</var></code>
1178
1179			Raises `ValueError` if `self` is an invalid GPath or if `n` is negative.
1180
1181			Examples
1182			--------
1183			```python
1184			GPath("/usr/bin") * 2    # GPath("/usr/bin/usr/bin")
1185			GPath("../docs") * 2     # GPath("../../docs/docs")
1186			GPath("C:/Windows") * 0  # GPath("C:/")
1187			```
1188		"""
1189		if n < 0:
1190			raise ValueError("cannot multiply path by a negative integer: {n}")
1191		new_path = GPath(self)
1192		new_path._parent_level = self._parent_level * n
1193		new_path._parts = self._parts * n
1194		return new_path
1195
1196
1197	def __truediv__(self, other: GPathLike) -> GPath:
1198		"""
1199			Alias of `__add__()`.
1200
1201			Usage: <code><var>self</var> + <var>other</var></code> or <code><var>self</var> / <var>other</var></code>
1202		"""
1203		return self.__add__(other)
1204
1205
1206	def __and__(self, other: GPathLike) -> Union[GPath, None]:
1207		"""
1208			Equivalent to `self.common_with(other)`, using the default options of `common_with()`.
1209
1210			Usage: <code><var>g1</var> & <var>g2</var></code>
1211		"""
1212		return self.common_with(other)
1213
1214
1215	def __lshift__(self, n: int) -> GPath:
1216		"""
1217			Move the imaginary current working directory `n` steps up the filesystem tree.
1218
1219			If `self` is a relative path, remove up to `n` levels of parent directories from the start of the path and return a copy. If it is an absolute path, return a copy of `self` unchanged.
1220
1221			If `n` is negative, this is equivalent to `__rshift__(-n)`.
1222
1223			Usage: <code><var>self</var> << <var>n</var></code>
1224
1225			Raises `ValueError` if `self` is an invalid GPath.
1226
1227			Examples
1228			--------
1229			```python
1230			GPath("../SysWOW64/drivers") << 1  # GPath("SysWOW64/drivers")
1231			GPath("../doc") << 2               # GPath("doc")
1232			GPath("/usr/bin") << 2             # GPath("/usr/bin")
1233			```
1234		"""
1235		if n < 0:
1236			return self.__rshift__(-1 * n)
1237		new_path = GPath(self)
1238		if not new_path._root:
1239			new_path._parent_level = max(new_path._parent_level - n, 0)
1240		return new_path
1241
1242
1243	def __rshift__(self, n: int) -> GPath:
1244		"""
1245			Move the imaginary current working directory `n` steps down the filesystem tree.
1246
1247			If `self` is a relative path, add `n` levels of parent directories to the start of the path and return a copy. If it is an absolute path, return a copy of `self` unchanged.
1248
1249			If `n` is negative, this is equivalent to `__lshift__(-n)`.
1250
1251			Usage: <code><var>self</var> >> <var>n</var></code>
1252
1253			Raises `ValueError` if `self` is an invalid GPath
1254
1255			Examples
1256			--------
1257			```python
1258			GPath("../SysWOW64/drivers") >> 1  # GPath("../../SysWOW64/drivers")
1259			GPath("/usr/bin") >> 2             # GPath("/usr/bin")
1260			```
1261		"""
1262		if n < 0:
1263			return self.__lshift__(-1 * n)
1264		new_path = GPath(self)
1265		if not new_path._root:
1266			new_path._parent_level += n
1267		return new_path
1268
1269
1270	@property
1271	def _tuple(self) -> tuple:
1272		# Get a tuple of all fields
1273		return (
1274			self._root,
1275			self._drive,
1276			self._parent_level,
1277			self._parts,
1278			self._platform,
1279			self._encoding,
1280		)
1281
1282
1283	def _validate(self) -> bool:
1284		# Check if self is in a valid state
1285		if self._parent_level < 0:
1286			raise ValueError(f"invalid GPath, _parent cannot be negative: {repr(self)}")
1287		if self._root:
1288			if self._parent_level != 0:
1289				raise ValueError(f"invalid GPath, _parent must be 0 when root is True: {repr(self)}")
1290		return True

An immutable generalised abstract file path that has no dependency on any real filesystem.

The path can be manipulated on a system that is different from where it originated, notably including systems with a different operating system, and it can represent file paths on a system other than local. Examples where this is useful include remote management of servers and when cross-compiling source code for a different platform.

Since GPath objects are immutable, all operations return a new instance. The path is always stored in a normalised state, and is always treated as case sensitive.

The path can be rendered as a string using str(g), which will use / as the path separator if possible to maximise cross-platform compatibility.

GPath( path: Union[str, bytes, os.PathLike, GPath, NoneType] = '', platform: Union[str, platform.Platform, NoneType] = None, encoding: Optional[str] = None)
107	def __init__(self,
108		path: Union[str, bytes, os.PathLike, GPath, None]="",
109		platform: Optional[Union[str, Platform]]=None,
110		encoding: Optional[str]=None,
111	):
112		"""
113			Initialise a normalised and generalised abstract file path, possibly by copying an existing GPath object.
114
115			Parameters
116			----------
117			`path`
118			: path-like object representing a (possibly unnormalised) file path, or a GPath object to be copied
119
120			`​platform`
121			: interpret `path` as originating from a specific platform. This is usually not required for normal file paths on Windows, Linux or macOS, and is needed only for edge cases (see [compatibility](https://github.com/yushiyangk/gpath#compatibility) in the readme). If `path` is a GPath, this argument has no effect. The platform name should be one of the keys in `gpath.platform.platform_names`. If specified, the platform will propagate to new GPaths returned by operations on this GPath; for binary operations of two GPaths, the platform specified by the left operand will be propagated. See also the `from_*()` static methods.
122
123			`​encoding`
124			: the text encoding that should be used to decode paths given as bytes-like objects; if not specified, `'utf_8'` will be used by default. The encoding name should be one of the standard Python text encodings, as listed in the `codecs` module of the standard library. If specified, the encoding will propagate to new GPaths returned by operations on this GPath; for binary operations of two GPaths, the encoding specified by the left operand will be propagated.
125
126			Raises
127			------
128			`ValueError` if `other` is an invalid GPath
129
130			Examples
131			--------
132			```python
133			GPath("/")
134			GPath("/usr/bin")
135			GPath("C:/Program Files")
136			```
137		"""
138
139		self._parts: tuple[str, ...] = tuple()  # root- or parent- relative path
140		self._root: bool = False
141		self._drive: str = ""
142		self._parent_level: int = 0
143
144		self._platform: Optional[Platform] = Platform.from_str(platform) if isinstance(platform, str) else platform
145		self._encoding: Optional[str] = encoding
146
147		if isinstance(path, GPath):
148			path._validate()
149			self._parts = path._parts
150			self._root = path._root
151			self._drive = path._drive
152			self._parent_level = path._parent_level
153
154			self._platform = path._platform if self._platform is None else self._platform
155			self._encoding = path._encoding if self._encoding is None else self._encoding
156			return
157
158		if path is None or path == "":
159			return
160
161		path = os.fspath(path)
162
163		if isinstance(path, bytes):
164			if self._encoding is None:
165				path = path.decode(DEFAULT_ENCODING)
166			else:
167				path = path.decode(self._encoding)
168
169		# path is a str
170
171		if self._platform is None:
172			platform = Platform.GENERIC
173		else:
174			platform = self._platform
175
176		if platform == Platform.POSIX:
177			for root in _rules.posix_rules.roots:
178				if path.startswith(root):
179					self._root = True
180					break
181
182			if self._root:
183				rootless_path = path[1:]
184			else:
185				rootless_path = path
186
187			parts = _split_relative(rootless_path, delimiters=_rules.posix_rules.separators)
188
189		elif platform == Platform.WINDOWS:
190			if len(path) >= 2 and path[1] in _rules.windows_rules.drive_postfixes:
191				self._drive = path[0]
192				driveless_path = path[2:]
193			else:
194				driveless_path = path
195
196			for root in _rules.windows_rules.roots:
197				if driveless_path.startswith(root):
198					self._root = True
199					break
200
201			if self._root:
202				rootless_path = driveless_path[1:]
203			else:
204				rootless_path = driveless_path
205
206			parts = _split_relative(rootless_path, delimiters=_rules.windows_rules.separators)
207
208		else:
209			if len(path) >= 2 and path[1] in _rules.generic_rules.drive_postfixes:
210				self._drive = path[0]
211				driveless_path = path[2:]
212			else:
213				driveless_path = path
214
215			for root in _rules.generic_rules.roots:
216				if driveless_path.startswith(root):
217					self._root = True
218					break
219
220			if self._root:
221				rootless_path = driveless_path[1:]
222			else:
223				rootless_path = driveless_path
224
225			parts = _split_relative(rootless_path, delimiters=_rules.generic_rules.separators)
226
227
228		parts = _normalise_relative(parts)
229		parent_level = 0
230		while parent_level < len(parts) and parts[parent_level] in _rules.generic_rules.parent_indicators:
231			parent_level += 1
232		self._parts = tuple(parts[parent_level:])
233		if self._root == False:
234			self._parent_level = parent_level

Initialise a normalised and generalised abstract file path, possibly by copying an existing GPath object.

Parameters

path : path-like object representing a (possibly unnormalised) file path, or a GPath object to be copied

​platform : interpret path as originating from a specific platform. This is usually not required for normal file paths on Windows, Linux or macOS, and is needed only for edge cases (see compatibility in the readme). If path is a GPath, this argument has no effect. The platform name should be one of the keys in gpath.platform.platform_names. If specified, the platform will propagate to new GPaths returned by operations on this GPath; for binary operations of two GPaths, the platform specified by the left operand will be propagated. See also the from_*() static methods.

​encoding : the text encoding that should be used to decode paths given as bytes-like objects; if not specified, 'utf_8' will be used by default. The encoding name should be one of the standard Python text encodings, as listed in the codecs module of the standard library. If specified, the encoding will propagate to new GPaths returned by operations on this GPath; for binary operations of two GPaths, the encoding specified by the left operand will be propagated.

Raises

ValueError if other is an invalid GPath

Examples

GPath("/")
GPath("/usr/bin")
GPath("C:/Program Files")
named_parts: list[str]

Read-only named components of the path, not including the filesystem root, drive name, or any parent directories

Examples

GPath("usr/local/bin").named_parts     # ["usr", "local", "bin"]
GPath("../../Documents").named_parts   # ["Documents"]
GPath("/usr/bin").named_parts          # ["usr", "bin"]
GPath("C:/Program Files").named_parts  # ["Program Files"]
relative_parts: list[str]

Read-only relative components of the path, not including the filesystem root or drive name, including one item for each level of parent directory

Examples

GPath("usr/local/bin").relative_parts     # ["usr", "local", "bin"]
GPath("../../Documents").relative_parts   # ["..", "..", "Documents"]
GPath("/usr/bin").relative_parts          # ["usr", "bin"]
GPath("C:/Program Files").relative_parts  # ["Program Files"]
absolute: bool

Read-only flag for whether the path is an absolute path

Examples

GPath("/").absolute                # True
GPath("C:/Windows").absolute       # True
GPath("local/bin").absolute        # False
GPath("../../Documents").absolute  # False
root: bool

Read-only flag for whether the path is exactly the root of the filesystem

Examples

GPath("/").root                # True
GPath("C:/").root              # True
GPath("/usr/bin").root         # False
GPath("C:/Windows").root       # False
GPath("../../Documents").root  # False
drive: str

Read-only drive name

Examples

GPath("C:/Windows").drive       # "C:"
GPath("/usr/bin").drive         # ""
GPath("../../Documents").drive  # ""
parent_level: int

Read-only number of levels of parent directories that the path is relative to, which may be 0

Examples

GPath("../../Documents").parent_level  # 2
GPath("usr/local/bin").parent_level    # 0
parent_parts: list[str]

Read-only path components representing a parent directory that it is relative to, if any, with one item for each level of parent directory

Examples

GPath("../../Documents").parent_parts  # ["..", ".."]
GPath("usr/local/bin").parent_parts    # []
encoding: Optional[str]

Read-only encoding used to decode other paths that are given as bytes-like objects, or None if the default should be used

platform: Optional[str]

Read-only platform that other non-GPath operands should be interepreted as, or None if the default should be used

@staticmethod
def from_posix( path: Union[str, bytes, os.PathLike, GPath, NoneType] = '', encoding: Optional[str] = None) -> GPath:
360	@staticmethod
361	def from_posix(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
362		"""
363			Initialise a GPath that originates from a POSIX-like operating system, or copy a GPath such that any future non-GPath operands would be interpreted as originating from a POSIX-like operating system.
364
365			See `__init__()` for details.
366
367			Equivalent to `GPath(path, platform='posix')`
368			```
369		"""
370		return GPath(path, platform=Platform.POSIX, encoding=encoding)

Initialise a GPath that originates from a POSIX-like operating system, or copy a GPath such that any future non-GPath operands would be interpreted as originating from a POSIX-like operating system.

See __init__() for details.

Equivalent to GPath(path, platform='posix') ```

@staticmethod
def from_linux( path: Union[str, bytes, os.PathLike, GPath, NoneType] = '', encoding: Optional[str] = None) -> GPath:
372	@staticmethod
373	def from_linux(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
374		"""
375			Alias of `from_posix()`
376		"""
377		return GPath.from_posix(path, encoding=encoding)

Alias of from_posix()

@staticmethod
def from_macos( path: Union[str, bytes, os.PathLike, GPath, NoneType] = '', encoding: Optional[str] = None) -> GPath:
379	@staticmethod
380	def from_macos(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
381		"""
382			Alias of `from_posix()`
383		"""
384		return GPath.from_posix(path, encoding=encoding)

Alias of from_posix()

@staticmethod
def from_windows( path: Union[str, bytes, os.PathLike, GPath, NoneType] = '', encoding: Optional[str] = None) -> GPath:
387	@staticmethod
388	def from_windows(path: Union[str, bytes, os.PathLike, GPath, None]="", encoding: Optional[str]=None) -> GPath:
389		"""
390			Initialise a GPath that originates from a Windows operating system, or copy a GPath such that any future non-GPath operands would be interpreted as originating from a Windows operating system.
391
392			See `__init__()` for details.
393
394			Equivalent to `GPath(path, platform='windows')`
395			```
396		"""
397		return GPath(path, platform=Platform.WINDOWS, encoding=encoding)

Initialise a GPath that originates from a Windows operating system, or copy a GPath such that any future non-GPath operands would be interpreted as originating from a Windows operating system.

See __init__() for details.

Equivalent to GPath(path, platform='windows') ```

@staticmethod
def partition( *paths, allow_current: bool = True, allow_parents: bool = True, platform: Union[str, platform.Platform, NoneType] = None, encoding: Optional[str] = None) -> dict[GPath, list[GPath]]:
408	@staticmethod
409	def partition(
410		*paths,
411		allow_current: bool=True,
412		allow_parents: bool=True,
413		platform: Optional[Union[str, Platform]]=None,
414		encoding: Optional[str]=None,
415	) -> dict[GPath, list[GPath]]:
416		"""
417			Partition a collection of paths based on shared common base paths such that each path belongs to one partition.
418
419			For each partition, return a list of relative paths from the base path of that partition to each corresponding input path within that partition, unless `allow_parents` is True (see below). If the input collection is ordered, the output order is preserved within each partition. If the input collection contains duplicates, the corresponding output lists will as well.
420
421			The number of partitions is minimised by merging partitions as much as possible, so that each partition represents the highest possible level base path. Two partitions can no longer be merged when there is no common base path between them, as determined by `common_with()`. This method takes the same optional arguments as `common_with()`, with the same default values.
422
423			Parameters
424			----------
425			`paths: Iterable[GPath | str | bytes | os.PathLike]` or `*paths: GPath | str | bytes | os.PathLike`
426			: the paths to be partitioned, which can be given as either a list-like object or as variadic arguments
427
428			`allow_current`
429			: whether non-parent relative paths with no shared components should be considered to have a common base path (see `common_with()`)
430
431			`allow_parents`
432			: whether paths that are relative to different levels of parent directories should be considered to have a common base path (see `common_with()`). **Warning**: when set to True, the output lists for each partition are invalidated, and explicitly set to empty. This is because it is not possible in general to obtain a relative path from the base path to its members if the base path is a parent directory of a higher level than the member (see `relpath_from()`). This  option should be True if and only if the list of members in each partition are not of interest; in most cases False is more appropriate.
433
434			`​platform`
435			: the originating platform that should be assumed when interpreting non-GPath objects in `paths`, if any (see `__init__()`).
436
437			`​encoding`
438			: the text encoding that should be used to decode bytes-like objects in `paths`, if any (see `__init__()`).
439
440			Returns
441			-------
442			a dictionary that maps the common base path of each partition to a list of relative paths
443
444			Raises
445			------
446			  `ValueError`
447			  if any of the GPaths are invalid
448
449			Examples
450			--------
451			```python
452			GPath.partition("/usr/bin", "/usr/local/bin", "../../doc", "C:/Windows", "C:/Program Files")
453
454			assert partitions == {
455				GPath("/usr")      : [GPath("bin"), GPath("local")],
456				GPath("../../doc") : [GPath("")],
457				GPath("C:/")       : [GPath("Windows"), GPath("Program Files")],
458			}
459			```
460		"""
461		flattened_paths: list[GPathLike] = []
462		for path_or_list in paths:
463			if _is_gpathlike(path_or_list):
464				flattened_paths.append(path_or_list)
465			else:
466				flattened_paths.extend(path_or_list)
467		gpaths = [path if isinstance(path, GPath) else GPath(path, encoding=encoding, platform=platform) for path in flattened_paths]
468
469		partition_map = {}
470		if len(gpaths) > 0:
471			if allow_parents == True:
472				partition_map[gpaths[0]] = []
473			else:
474				partition_map[gpaths[0]] = [gpaths[0]]
475
476		for path in gpaths[1:]:
477			partition_found = False
478			for partition in partition_map:
479				candidate_common = partition.common_with(path, allow_current=allow_current, allow_parents=allow_parents)
480				if candidate_common is not None:
481					partition_found = True
482					if candidate_common != partition:
483						partition_map[candidate_common] = partition_map[partition]
484						del partition_map[partition]
485					if allow_parents == False:
486						partition_map[candidate_common].append(path)
487					break
488			if not partition_found:
489				if allow_parents == True:
490					partition_map[path] = []
491				else:
492					partition_map[path] = [path]
493
494		for partition, path_list in partition_map.items():
495			partition_map[partition] = [path.subpath_from(partition) for path in path_list]
496
497		return partition_map

Partition a collection of paths based on shared common base paths such that each path belongs to one partition.

For each partition, return a list of relative paths from the base path of that partition to each corresponding input path within that partition, unless allow_parents is True (see below). If the input collection is ordered, the output order is preserved within each partition. If the input collection contains duplicates, the corresponding output lists will as well.

The number of partitions is minimised by merging partitions as much as possible, so that each partition represents the highest possible level base path. Two partitions can no longer be merged when there is no common base path between them, as determined by common_with(). This method takes the same optional arguments as common_with(), with the same default values.

Parameters

paths: Iterable[GPath | str | bytes | os.PathLike] or *paths: GPath | str | bytes | os.PathLike : the paths to be partitioned, which can be given as either a list-like object or as variadic arguments

allow_current : whether non-parent relative paths with no shared components should be considered to have a common base path (see common_with())

allow_parents : whether paths that are relative to different levels of parent directories should be considered to have a common base path (see common_with()). Warning: when set to True, the output lists for each partition are invalidated, and explicitly set to empty. This is because it is not possible in general to obtain a relative path from the base path to its members if the base path is a parent directory of a higher level than the member (see relpath_from()). This option should be True if and only if the list of members in each partition are not of interest; in most cases False is more appropriate.

​platform : the originating platform that should be assumed when interpreting non-GPath objects in paths, if any (see __init__()).

​encoding : the text encoding that should be used to decode bytes-like objects in paths, if any (see __init__()).

Returns

a dictionary that maps the common base path of each partition to a list of relative paths

Raises

ValueError if any of the GPaths are invalid

Examples

GPath.partition("/usr/bin", "/usr/local/bin", "../../doc", "C:/Windows", "C:/Program Files")

assert partitions == {
	GPath("/usr")      : [GPath("bin"), GPath("local")],
	GPath("../../doc") : [GPath("")],
	GPath("C:/")       : [GPath("Windows"), GPath("Program Files")],
}
@staticmethod
def join( *paths, platform: Union[str, platform.Platform, NoneType] = None, encoding: Optional[str] = None) -> GPath:
508	@staticmethod
509	def join(*paths, platform: Optional[Union[str, Platform]]=None, encoding: Optional[str]=None) -> GPath:
510		"""
511			Join a sequence of paths into a single path. Apart from the first item in the sequence, all subsequent paths should be relative paths and any absolute paths will be ignored.
512
513			Parameters
514			----------
515			`paths`: `Sequence[GPath | str | bytes | os.PathLike]` or `*paths: GPath | str | bytes | os.PathLike`
516			: the paths to be combined, which can be given as either a list-like object or as variadic arguments
517
518			`​platform`
519			: the originating platform that should be assumed when interpreting non-GPath objects in `paths`, if any (see `__init__()`).
520
521			`​encoding`
522			: the text encoding that should be used to decode bytes-like objects in `paths`, if any (see `__init__()`).
523
524			Returns
525			-------
526			the combined path
527
528			Raises
529			------
530			`ValueError` if any of the GPaths are invalid
531
532			Examples
533			--------
534			```python
535			GPath.join("usr", "local", "bin")          # GPath("usr/local/bin")
536			GPath.join("/usr/local/bin", "../../bin")  # GPath("/usr/bin")
537			GPath.join("C:/", "Windows")               # GPath("C:/Windows")
538			```
539		"""
540		flattened_paths: list[GPathLike] = []
541		for path_or_list in paths:
542			if _is_gpathlike(path_or_list):
543				flattened_paths.append(path_or_list)
544			else:
545				flattened_paths.extend(path_or_list)
546
547		if len(flattened_paths) == 0:
548			return GPath(encoding=encoding, platform=platform)
549
550		combined_path = flattened_paths[0]
551		if not isinstance(combined_path, GPath):
552			combined_path = GPath(combined_path, encoding=encoding, platform=platform)
553		for path in flattened_paths[1:]:
554			combined_path = combined_path + path
555
556		return combined_path

Join a sequence of paths into a single path. Apart from the first item in the sequence, all subsequent paths should be relative paths and any absolute paths will be ignored.

Parameters

paths: Sequence[GPath | str | bytes | os.PathLike] or *paths: GPath | str | bytes | os.PathLike : the paths to be combined, which can be given as either a list-like object or as variadic arguments

​platform : the originating platform that should be assumed when interpreting non-GPath objects in paths, if any (see __init__()).

​encoding : the text encoding that should be used to decode bytes-like objects in paths, if any (see __init__()).

Returns

the combined path

Raises

ValueError if any of the GPaths are invalid

Examples

GPath.join("usr", "local", "bin")          # GPath("usr/local/bin")
GPath.join("/usr/local/bin", "../../bin")  # GPath("/usr/bin")
GPath.join("C:/", "Windows")               # GPath("C:/Windows")
def as_relative(self, parent_level: Optional[int] = None) -> GPath:
559	def as_relative(self, parent_level: Optional[int]=None) -> GPath:
560		"""
561			Convert the path to a relative path and return a new copy.
562
563			Parameters
564			----------
565			`​parent_level`
566			: the number of levels of parent directories that the returned path should be relative to, which may be 0. If set to None, the returned path will have the same parent level as the current path if it is currently a relative path, or have no parent level (i.e. 0) otherwise.
567
568			Raises
569			------
570			`TypeError` if `​parent_level` is not a valid type
571
572			Examples
573			--------
574			```python
575			GPath("/usr/bin").as_relative()      # GPath("usr/bin")
576			GPath("C:/Windows").as_relative()    # GPath("C:Windows")
577			GPath("../Documents").as_relative()  # GPath("../Documents")
578			```
579		"""
580
581		new_path = GPath(self)
582		new_path._root = False
583		if parent_level is None:
584			pass
585		elif isinstance(parent_level, int):
586			new_path._parent_level = parent_level
587		else:
588			raise TypeError(f"parent_level must be an int: {parent_level} ({type(parent_level)})")
589
590		return new_path

Convert the path to a relative path and return a new copy.

Parameters

​parent_level : the number of levels of parent directories that the returned path should be relative to, which may be 0. If set to None, the returned path will have the same parent level as the current path if it is currently a relative path, or have no parent level (i.e. 0) otherwise.

Raises

TypeError if ​parent_level is not a valid type

Examples

GPath("/usr/bin").as_relative()      # GPath("usr/bin")
GPath("C:/Windows").as_relative()    # GPath("C:Windows")
GPath("../Documents").as_relative()  # GPath("../Documents")
def as_absolute(self) -> GPath:
593	def as_absolute(self) -> GPath:
594		"""
595			Convert the path to an absolute path and return a new copy.
596
597			Any parent directory that the path is relative to will be removed. If the path is already absolute, an identical copy is returned.
598
599			Examples
600			--------
601			```python
602			GPath("usr/bin").as_absolute()       # GPath("/usr/bin")
603			GPath("../Documents").as_absolute()  # GPath("/Documents")
604			GPath("C:Windows").as_absolute()     # GPath("C:/Windows")
605			```
606		"""
607		new_path = GPath(self)
608		new_path._root = True
609		new_path._parent_level = 0
610		return new_path

Convert the path to an absolute path and return a new copy.

Any parent directory that the path is relative to will be removed. If the path is already absolute, an identical copy is returned.

Examples

GPath("usr/bin").as_absolute()       # GPath("/usr/bin")
GPath("../Documents").as_absolute()  # GPath("/Documents")
GPath("C:Windows").as_absolute()     # GPath("C:/Windows")
def with_drive(self, drive: Union[str, bytes, NoneType] = None) -> GPath:
613	def with_drive(self, drive: Union[str, bytes, None]=None) -> GPath:
614		"""
615			Return a new copy of the path with the drive set to `​drive`.
616
617			If `​drive` is `""` or None, this would be equivalent to `without_drive()`.
618
619			Parameters
620			----------
621			`​drive`
622			: the drive for the returned path, or either `""` or None if the returned path should have no drive
623
624			Returns
625			-------
626			`GPath`
627			: a new path with the given drive
628
629			Raises
630			------
631			- `TypeError` if `​drive` is not a valid type
632			- `ValueError` if `​drive` has more than one character
633
634			Examples
635			--------
636			```python
637			GPath("C:/Windows").with_drive()      # GPath("/Windows")
638			GPath("C:/Windows").with_drive("D")   # GPath("D:/Windows")
639			GPath("/Windows").with_drive("C")     # GPath("C:/Windows")
640			```
641		"""
642		if drive is None:
643			drive = ""
644		elif isinstance(drive, bytes):
645			if self._encoding is None:
646				drive = drive.decode(DEFAULT_ENCODING)
647			else:
648				drive = drive.decode(self._encoding)
649		elif isinstance(drive, str):
650			pass
651		else:
652			raise TypeError(f"drive must be a str or bytes object: {drive} ({type(drive)})")
653
654		if len(drive) > 1:
655			raise ValueError(f"drive can only be a single character, an empty string or None: {drive}")
656
657		new_path = GPath(self)
658		new_path._drive = drive
659		return new_path

Return a new copy of the path with the drive set to ​drive.

If ​drive is "" or None, this would be equivalent to without_drive().

Parameters

​drive : the drive for the returned path, or either "" or None if the returned path should have no drive

Returns

GPath : a new path with the given drive

Raises

  • TypeError if ​drive is not a valid type
  • ValueError if ​drive has more than one character

Examples

GPath("C:/Windows").with_drive()      # GPath("/Windows")
GPath("C:/Windows").with_drive("D")   # GPath("D:/Windows")
GPath("/Windows").with_drive("C")     # GPath("C:/Windows")
def without_drive(self) -> GPath:
662	def without_drive(self) -> GPath:
663		"""
664			Return a new copy of the path without a drive.
665
666			Equivalent to `with_drive("")` or `with_drive(None)`.
667
668			Returns
669			-------
670			`GPath`
671			: a new path without a drive
672
673			Examples
674			--------
675			```python
676			GPath("C:/Windows").without_drive()      # GPath("/Windows")
677			```
678		"""
679		return self.with_drive(None)

Return a new copy of the path without a drive.

Equivalent to with_drive("") or with_drive(None).

Returns

GPath : a new path without a drive

Examples

GPath("C:/Windows").without_drive()      # GPath("/Windows")
def common_with( self, other: Union[GPath, str, bytes, os.PathLike], allow_current: bool = True, allow_parents: bool = False) -> Optional[GPath]:
682	def common_with(self, other: GPathLike, allow_current: bool=True, allow_parents: bool=False) -> Optional[GPath]:
683		"""
684			Find the longest common base path shared between `self` and `other`, or return None if no such path exists.
685
686			A common base path might not exist if one path is an absolute path while the other is a relative path, or if the two paths are in different filesystems (with different drive names), or in other cases as controlled by the `allow_current` and `allow_parents` options.
687
688			If using the default options of `allow_current=True` and `allow_parent=False`, the binary operator for bitwise-and can be used: `__and__()` (usage: <code><var>g1</var> & <var>g2</var></code>).
689
690			Parameters
691			----------
692			`other`
693			: the path to compare with
694
695			`allow_current`
696			: whether two non-parent relative paths that do not share any components should be considered to have a common base path, namely the imaginary current working directory. For instance, `GPath("some/rel/path").find_common("another/rel/path")` will return `GPath("")` if set to True, or return None if set to False.
697
698			`allow_parents`
699			: whether two relative paths that are relative to different levels of parent directories should be considered to have a common base path, which is the highest level of parent directory between the two paths. For instance, `GPath("../rel/to/parent").find_common("../../rel/to/grandparent")` will return `GPath("../..")` if set to True, or return None if set to False. **Warning**: when set to True, given a higher level of parent directory as output, it may not be possible to find the relative path to one of the inputs (see `relpath_from()`); in most cases False is more appropriate.
700
701			Returns
702			-------
703			`GPath`
704			: the longest common base path, which may be empty, if it exists
705
706			`None`
707			: otherwise
708
709			Raises
710			------
711			`ValueError` if either `self` or `other` is an invalid GPath
712
713			Examples
714			--------
715			```python
716			GPath("/usr/bin").find_common("/usr/local/bin")               # GPath("/usr")
717			GPath("C:/Windows/System32").find_common("C:/Program Files")  # GPath("C:/")
718			GPath("../Documents").find_common("../Pictures")              # GPath("..")
719			```
720		"""
721		self._validate()
722		if isinstance(other, GPath):
723			other._validate()
724		else:
725			other = GPath(other, encoding=self._encoding)
726
727		if self._drive != other._drive:
728			return None
729		if self._root != other._root:
730			return None
731
732		if allow_parents:
733			allow_current = True
734
735		parts = []
736		if self._root:
737			common_path = GPath(self)
738			for part1, part2 in zip(self._parts, other._parts):
739				if part1 == part2:
740					parts.append(part1)
741		else:
742			if self._parent_level != other._parent_level:
743				if not allow_parents:
744					return None
745
746				common_path = GPath(self)
747				common_path._parent_level = max(self._parent_level, other._parent_level)
748			else:
749				common_path = GPath(self)
750				for part1, part2 in zip(self._parts, other._parts):
751					if part1 == part2:
752						parts.append(part1)
753
754		common_path._parts = tuple(parts)
755
756		if not allow_current and not bool(common_path):
757			if common_path != self or common_path != other:
758				return None
759		return common_path

Find the longest common base path shared between self and other, or return None if no such path exists.

A common base path might not exist if one path is an absolute path while the other is a relative path, or if the two paths are in different filesystems (with different drive names), or in other cases as controlled by the allow_current and allow_parents options.

If using the default options of allow_current=True and allow_parent=False, the binary operator for bitwise-and can be used: __and__() (usage: g1 & g2).

Parameters

other : the path to compare with

allow_current : whether two non-parent relative paths that do not share any components should be considered to have a common base path, namely the imaginary current working directory. For instance, GPath("some/rel/path").find_common("another/rel/path") will return GPath("") if set to True, or return None if set to False.

allow_parents : whether two relative paths that are relative to different levels of parent directories should be considered to have a common base path, which is the highest level of parent directory between the two paths. For instance, GPath("../rel/to/parent").find_common("../../rel/to/grandparent") will return GPath("../..") if set to True, or return None if set to False. Warning: when set to True, given a higher level of parent directory as output, it may not be possible to find the relative path to one of the inputs (see relpath_from()); in most cases False is more appropriate.

Returns

GPath : the longest common base path, which may be empty, if it exists

None : otherwise

Raises

ValueError if either self or other is an invalid GPath

Examples

GPath("/usr/bin").find_common("/usr/local/bin")               # GPath("/usr")
GPath("C:/Windows/System32").find_common("C:/Program Files")  # GPath("C:/")
GPath("../Documents").find_common("../Pictures")              # GPath("..")
def subpath_from( self, base: Union[GPath, str, bytes, os.PathLike]) -> Optional[GPath]:
762	def subpath_from(self, base: GPathLike) -> Optional[GPath]:
763		"""
764			Find the relative subpath from `base` to `self` if possible and if `base` contains `self`, or return None otherwise.
765
766			None will also be returned if there are unknown components in the subpath from `base` to `self`. For instance, if `self` is relative to the parent directory while `base` is relative to the grandparent directory, the path from the grandparent directory `../..` to the parent directory `..` cannot be known.
767
768			Similar to `relpath_from()`, but `self` must be a descendent of `base`.
769
770			Parameters
771			----------
772			`base`
773			: the base path that the relative subpath should start from
774
775			Returns
776			-------
777			`GPath`
778			: relative subpath from `base` to `self`, which may be empty, if it exists
779
780			`None`
781			: otherwise
782
783			Raises
784			------
785			`ValueError` if either `self` or `base` is an invalid GPath
786
787			Examples
788			--------
789			```python
790			GPath("/usr/local/bin").subpath_from("/usr")      # GPath("local/bin")
791			GPath("/usr/bin").subpath_from("/usr/local/bin")  # None
792			GPath("/usr/bin").subpath_from("../Documents")    # None
793			```
794		"""
795		if not isinstance(base, GPath):
796			base = GPath(base, encoding=self._encoding)
797
798		if self.common_with(base, allow_current=True, allow_parents=False) is not None and self in base:
799			# If self._parent_level > base._parent_level, self is not in base, whereas if self._parent_level < base._parent_level, path from base to self's parent cannot be known
800			base_length = len(base._parts)
801			new_path = GPath(self)
802			new_path._parts = self._parts[base_length:]  # () when self == base
803			new_path._drive = ""
804			new_path._root = False
805			new_path._parent_level = 0
806			return new_path
807		else:
808			return None

Find the relative subpath from base to self if possible and if base contains self, or return None otherwise.

None will also be returned if there are unknown components in the subpath from base to self. For instance, if self is relative to the parent directory while base is relative to the grandparent directory, the path from the grandparent directory ../.. to the parent directory .. cannot be known.

Similar to relpath_from(), but self must be a descendent of base.

Parameters

base : the base path that the relative subpath should start from

Returns

GPath : relative subpath from base to self, which may be empty, if it exists

None : otherwise

Raises

ValueError if either self or base is an invalid GPath

Examples

GPath("/usr/local/bin").subpath_from("/usr")      # GPath("local/bin")
GPath("/usr/bin").subpath_from("/usr/local/bin")  # None
GPath("/usr/bin").subpath_from("../Documents")    # None
def relpath_from( self, origin: Union[GPath, str, bytes, os.PathLike]) -> Optional[GPath]:
811	def relpath_from(self, origin: GPathLike) -> Optional[GPath]:
812		"""
813			Find the relative path from `origin` to `self` if possible, or return None otherwise.
814
815			None will also be returned if there are unknown components in the relative path from `origin` to `self`. For instance, if `self` is relative to the parent directory while `base` base is relative to the grandparent directory, the path from the grandparent directory `../..` to the parent directory `..` cannot be known.
816
817			Similar to `subpath_from()`, but `self` does not need to be a descendent of `origin`.
818
819			Parameters
820			----------
821			`origin`
822			: the origin that the relative path should start from
823
824			Returns
825			-------
826			`GPath`
827			: relative path from `origin` to `self`, which may be empty, if it exists
828
829			`None`
830			: otherwise
831
832			Raises
833			------
834			`ValueError` if either `self` or `origin` is an invalid GPath
835
836			Examples
837			--------
838			```python
839			GPath("/usr/local/bin").subpath_from("/usr")      # GPath("local/bin")
840			GPath("/usr/bin").subpath_from("/usr/local/bin")  # GPath("../../bin")
841			GPath("/usr/bin").subpath_from("../Documents")    # None
842			```
843		"""
844		self._validate()
845		if not isinstance(origin, GPath):
846			origin = GPath(origin, encoding=self._encoding)
847
848		if origin._root:
849			common = self.common_with(origin)
850			if common is None:
851				return None
852
853			new_path = GPath(self)
854			new_path._parent_level = len(origin) - len(common)
855			new_path._parts = self._parts[len(common):]
856			new_path._drive = ""
857			new_path._root = False
858			return new_path
859
860		else:
861			common = self.common_with(origin, allow_current=True, allow_parents=True)
862			if common is None:
863				return None
864			if common._parent_level > self._parent_level:
865				return None  # Path from common to self's parent cannot be known
866
867			# common._dotdot == self._dotdot
868			# origin._dotdot <= self._dotdot
869
870			new_path = GPath(self)
871			new_path._drive = ""
872			new_path._root = False
873			if len(common) == 0:
874				if origin._parent_level == self._parent_level:
875					new_path._parent_level = len(origin)
876				else:
877					new_path._parent_level = (common._parent_level - origin._parent_level) + len(origin)
878				new_path._parts = self._parts
879			else:
880				new_path._parent_level = len(origin) - len(common)
881				new_path._parts = self._parts[len(common):]
882
883			return new_path

Find the relative path from origin to self if possible, or return None otherwise.

None will also be returned if there are unknown components in the relative path from origin to self. For instance, if self is relative to the parent directory while base base is relative to the grandparent directory, the path from the grandparent directory ../.. to the parent directory .. cannot be known.

Similar to subpath_from(), but self does not need to be a descendent of origin.

Parameters

origin : the origin that the relative path should start from

Returns

GPath : relative path from origin to self, which may be empty, if it exists

None : otherwise

Raises

ValueError if either self or origin is an invalid GPath

Examples

GPath("/usr/local/bin").subpath_from("/usr")      # GPath("local/bin")
GPath("/usr/bin").subpath_from("/usr/local/bin")  # GPath("../../bin")
GPath("/usr/bin").subpath_from("../Documents")    # None
def render( self, platform: Union[str, platform.Platform, NoneType]) -> render.RenderedPath:
886	def render(self, platform: Union[str, Platform, None]) -> render.RenderedPath:
887		"""
888			Convert the path to a RenderedPath for printing in a specific target operating system.
889
890			This will convert, and coerce if necessary, the generalised abstract GPath into a platform-specific path which can then be converted to a printable string using <code>str(<var>renderred_path</var>)</code>. The resulting string will be in the format preferred by the target platform.
891
892			If the GPath contains features that the target platform does not support (such as drive name when the target platform is POSIX), and if there are no analogous features in the target platform, they will be dropped in the rendered path.
893
894			The rendered path also implements total ordering with binary comparisons, e.g. <code><var>r1</var> < <var>r2</var></code>, making it useful for sorting and collation. This ordering is done with platform-specific semantics, unlike GPath which does not have meaningful order.
895
896			Parameters
897			----------
898			`platform`
899			: the target platform where the path is to be used
900
901			Returns
902			-------
903			`RenderedPath`
904			: platform-specific path ready for sorting or output
905
906			Examples
907			--------
908			```python
909			# Print examples
910			print(GPath("/usr/bin").render('linux'))      # /usr/bin
911			print(GPath("/usr/bin").render('windows'))    # \\usr\\bin
912			print(GPath("C:/Windows").render('linux'))    # /Windows
913			print(GPath("C:/Windows").render('windows'))  # C:\\Windows
914
915			# Ordering examples
916			GPath("").render('linux') < GPath("abc").render('linux')       # True
917			GPath("abc").render('linux') < GPath("..").render('linux')     # True
918			GPath("..").render('linux') < GPath("../..").render('linux')   # True
919			GPath("../..").render('linux') < GPath("/").render('linux')    # True
920			GPath("/").render('linux') < GPath("C:/").render('linux')      # False
921			GPath("/").render('linux') <= GPath("C:/").render('linux')     # True
922			GPath("/").render('windows') < GPath("C:/").render('windows')  # True
923			```
924		"""
925		if platform is None:
926			platform = DEFAULT_PLATFORM
927		elif isinstance(platform, str):
928			platform = Platform.from_str(platform)
929		return render.get_type(platform)(self)

Convert the path to a RenderedPath for printing in a specific target operating system.

This will convert, and coerce if necessary, the generalised abstract GPath into a platform-specific path which can then be converted to a printable string using str(renderred_path). The resulting string will be in the format preferred by the target platform.

If the GPath contains features that the target platform does not support (such as drive name when the target platform is POSIX), and if there are no analogous features in the target platform, they will be dropped in the rendered path.

The rendered path also implements total ordering with binary comparisons, e.g. r1 < r2, making it useful for sorting and collation. This ordering is done with platform-specific semantics, unlike GPath which does not have meaningful order.

Parameters

platform : the target platform where the path is to be used

Returns

RenderedPath : platform-specific path ready for sorting or output

Examples

# Print examples
print(GPath("/usr/bin").render('linux'))      # /usr/bin
print(GPath("/usr/bin").render('windows'))    # \usr\bin
print(GPath("C:/Windows").render('linux'))    # /Windows
print(GPath("C:/Windows").render('windows'))  # C:\Windows

# Ordering examples
GPath("").render('linux') < GPath("abc").render('linux')       # True
GPath("abc").render('linux') < GPath("..").render('linux')     # True
GPath("..").render('linux') < GPath("../..").render('linux')   # True
GPath("../..").render('linux') < GPath("/").render('linux')    # True
GPath("/").render('linux') < GPath("C:/").render('linux')      # False
GPath("/").render('linux') <= GPath("C:/").render('linux')     # True
GPath("/").render('windows') < GPath("C:/").render('windows')  # True
def __hash__(self) -> int:
932	def __hash__(self) -> int:
933		"""
934			Calculate hash of the GPath object.
935
936			Usage: <code>hash(<var>g</var>)</code>
937		"""
938		return hash(self._tuple)

Calculate hash of the GPath object.

Usage: hash(g)

def __eq__(self, other: Union[GPath, str, bytes, os.PathLike]) -> bool:
941	def __eq__(self, other: GPathLike) -> bool:
942		"""
943			Check if two GPaths are completely identical.
944
945			Always return False if `other` is not a GPath object, even if it is a GPath-like object.
946
947			Usage: <code><var>g1</var> == <var>g2</var></code>
948
949			Examples
950			--------
951			```python
952			GPath("/usr/bin") == GPath("/usr/bin")  # True
953			GPath("/usr/bin") == GPath("usr/bin")   # False
954			GPath("C:/") == GPath("D:/")            # False
955			```
956		"""
957		if not isinstance(other, GPath):
958			other = GPath(other, encoding=self._encoding)
959		return self._tuple == other._tuple

Check if two GPaths are completely identical.

Always return False if other is not a GPath object, even if it is a GPath-like object.

Usage: g1 == g2

Examples

GPath("/usr/bin") == GPath("/usr/bin")  # True
GPath("/usr/bin") == GPath("usr/bin")   # False
GPath("C:/") == GPath("D:/")            # False
def __bool__(self) -> bool:
962	def __bool__(self) -> bool:
963		"""
964			False if `self` is a relative path without any relative components and without a drive, and True otherwise.
965
966			Usage: <code>bool(<var>g</var>)</code>, <code>not <var>g</var></code>, or <code>if <var>g</var>:</code>
967
968			Examples
969			--------
970			```python
971			bool(GPath("/"))    # True
972			bool(GPath(".."))   # True
973			bool(GPath("doc"))  # True
974			bool(GPath(""))     # False
975			```
976		"""
977		return self._root or self._drive != "" or self._parent_level != 0 or len(self._parts) > 0

False if self is a relative path without any relative components and without a drive, and True otherwise.

Usage: bool(g), not g, or if g:

Examples

bool(GPath("/"))    # True
bool(GPath(".."))   # True
bool(GPath("doc"))  # True
bool(GPath(""))     # False
def __str__(self) -> str:
980	def __str__(self) -> str:
981		"""
982			Return a platform-independent string representation of the path.
983
984			Usage: <code>str(<var>g</var>)</code>
985		"""
986		return str(self.render(Platform.GENERIC))

Return a platform-independent string representation of the path.

Usage: str(g)

def __repr__(self) -> str:
 989	def __repr__(self) -> str:
 990		"""
 991			Return a string that, when printed, gives the Python code associated with instantiating the GPath object.
 992
 993			Usage: <code>repr(<var>g</var>)</code>
 994		"""
 995		if self._platform is None:
 996			platform_repr = ""
 997		else:
 998			platform_repr = f", platform={repr(self._platform)}"
 999
1000		if self._encoding is None:
1001			encoding_repr = ""
1002		else:
1003			encoding_repr = f", encoding={repr(self._encoding)}"
1004
1005		if bool(self):
1006			return f"GPath({repr(str(self))}{platform_repr}{encoding_repr})"
1007		else:
1008			return f"GPath({repr('')}{platform_repr}{encoding_repr})"

Return a string that, when printed, gives the Python code associated with instantiating the GPath object.

Usage: repr(g)

def __len__(self) -> int:
1011	def __len__(self) -> int:
1012		"""
1013			Get the number of named path components, excluding any drive name or parent directories.
1014
1015			Usage: <code>len(<var>g</var>)</code>
1016
1017			Examples
1018			--------
1019			```python
1020			len(GPath("/usr/bin"))    # 2
1021			len(GPath("/"))           # 0
1022			len(GPath("C:/Windows"))  # 0
1023			len(GPath("C:/"))         # 0
1024			```
1025		"""
1026		return len(self._parts)

Get the number of named path components, excluding any drive name or parent directories.

Usage: len(g)

Examples

len(GPath("/usr/bin"))    # 2
len(GPath("/"))           # 0
len(GPath("C:/Windows"))  # 0
len(GPath("C:/"))         # 0
def __getitem__(self, index: Union[int, slice]) -> Union[str, list[str]]:
1029	def __getitem__(self, index: Union[int, slice]) -> Union[str, list[str]]:
1030		"""
1031			Get a 0-indexed named path component, or a slice of path components, excluding any drive name or parent directories.
1032
1033			Usage: <code><var>g</var>[<var>n</var>]</code>, <code><var>g</var>[<var>start</var>:<var>end</var>]</code>, <code><var>g</var>[<var>start</var>:<var>end</var>:<var>step</var>]</code>, etc.
1034
1035			Examples
1036			--------
1037			```python
1038			GPath("/usr/local/bin")[1]    # "local"
1039			GPath("/usr/local/bin")[-1]   # "bin"
1040			GPath("/usr/local/bin")[1:]   # ["local", "bin"]
1041			GPath("/usr/local/bin")[::2]  # ["usr", "bin"]
1042			```
1043		"""
1044		if isinstance(index, int):
1045			return self._parts[index]
1046		elif isinstance(index, slice):
1047			return list(self._parts[index])

Get a 0-indexed named path component, or a slice of path components, excluding any drive name or parent directories.

Usage: g[n], g[start:end], g[start:end:step], etc.

Examples

GPath("/usr/local/bin")[1]    # "local"
GPath("/usr/local/bin")[-1]   # "bin"
GPath("/usr/local/bin")[1:]   # ["local", "bin"]
GPath("/usr/local/bin")[::2]  # ["usr", "bin"]
def __iter__(self) -> Iterator[str]:
1050	def __iter__(self) -> Iterator[str]:
1051		"""
1052			Get an iterator through the named path components, excluding any drive name or parent directories.
1053
1054			Usage: <code>iter(<var>g</var>)</code> or <code>for <var>p</var> in <var>g</var>:</code>
1055		"""
1056		return iter(self._parts)

Get an iterator through the named path components, excluding any drive name or parent directories.

Usage: iter(g) or for p in g:

def __contains__(self, other: Union[GPath, str, bytes, os.PathLike]) -> bool:
1059	def __contains__(self, other: GPathLike) -> bool:
1060		"""
1061			Check if the path represented by `self` contains the path represented by `other`; i.e. check if `self` is a parent directory of `other`.
1062
1063			Usage: <code><var>other</var> in <var>self</var></code>
1064
1065			Raises `ValueError` if either GPath is invalid
1066
1067			Examples
1068			--------
1069			```python
1070			GPath("/usr/local/bin") in GPath("/usr")  # True
1071			GPath("/usr/local/bin") in GPath("/bin")  # False
1072			GPath("..") in GPath("../..")             # True
1073			GPath("..") in GPath("C:/")               # False
1074			```
1075		"""
1076		if not isinstance(other, GPath):
1077			other = GPath(other, encoding=self._encoding)
1078
1079		common_path = self.common_with(other, allow_current=True, allow_parents=True)
1080		return common_path is not None and common_path == self

Check if the path represented by self contains the path represented by other; i.e. check if self is a parent directory of other.

Usage: other in self

Raises ValueError if either GPath is invalid

Examples

GPath("/usr/local/bin") in GPath("/usr")  # True
GPath("/usr/local/bin") in GPath("/bin")  # False
GPath("..") in GPath("../..")             # True
GPath("..") in GPath("C:/")               # False
def __add__( self, other: Union[GPath, str, bytes, os.PathLike]) -> GPath:
1083	def __add__(self, other: GPathLike) -> GPath:
1084		"""
1085			Add (concatenate) `other` to the end of `self`, and return a new copy.
1086
1087			If `other` is an absolute path, the returned path will be an absolute path that matches `other`, apart from the drive name.
1088
1089			If `other` has a drive, the returned path will have the same drive as `other`. Otherwise, the returned path will have the same drive as `self`. If neither has a drive, the returned path will not have a drive as well.
1090
1091			Alias: `__truediv__()`
1092
1093			Usage: <code><var>self</var> + <var>other</var></code> or <code><var>self</var> / <var>other</var></code>
1094
1095			Raises `ValueError` if either GPath is invalid
1096
1097			Examples
1098			--------
1099			```python
1100			GPath("/usr") + GPath("local/bin")                   # GPath("/usr/local/bin")
1101			GPath("C:/Windows/System32") + GPath("../SysWOW64")  # GPath("C:/Windows/SysWOW64")
1102			GPath("C:/Windows/System32") + GPath("/usr/bin")     # GPath("C:/usr/bin")
1103			GPath("..") + GPath("../..")                         # GPath("../../..")
1104			GPath("..") / GPath("../..")                         # GPath("../../..")
1105			```
1106		"""
1107		if isinstance(other, GPath):
1108			other._validate
1109		else:
1110			other = GPath(other, encoding=self._encoding)
1111
1112		new_path = GPath(self)
1113		if other._root:
1114			new_path._parts = other._parts
1115			new_path._root = other._root
1116			new_path._parent_level = other._parent_level
1117		else:
1118			new_parts = [part for part in self._parts]
1119			for i in range(other._parent_level):
1120				if len(new_parts) > 0:
1121					new_parts.pop()
1122				elif not new_path._root:
1123					new_path._parent_level += 1
1124				else:
1125					pass  # parent of directory of root is still root
1126
1127			new_parts.extend(other._parts)
1128			new_path._parts = tuple(new_parts)
1129
1130		if other._drive != "":
1131			new_path._drive = other._drive
1132
1133		return new_path

Add (concatenate) other to the end of self, and return a new copy.

If other is an absolute path, the returned path will be an absolute path that matches other, apart from the drive name.

If other has a drive, the returned path will have the same drive as other. Otherwise, the returned path will have the same drive as self. If neither has a drive, the returned path will not have a drive as well.

Alias: __truediv__()

Usage: self + other or self / other

Raises ValueError if either GPath is invalid

Examples

GPath("/usr") + GPath("local/bin")                   # GPath("/usr/local/bin")
GPath("C:/Windows/System32") + GPath("../SysWOW64")  # GPath("C:/Windows/SysWOW64")
GPath("C:/Windows/System32") + GPath("/usr/bin")     # GPath("C:/usr/bin")
GPath("..") + GPath("../..")                         # GPath("../../..")
GPath("..") / GPath("../..")                         # GPath("../../..")
def __sub__(self, n: int) -> GPath:
1136	def __sub__(self, n: int) -> GPath:
1137		"""
1138			Remove `n` components from the end of the path and return a new copy.
1139
1140			Usage: <code><var>self</var> - <var>n</var></code>
1141
1142			Raises `ValueError` if `self` is an invalid GPath or if `n` is negative
1143
1144			Examples
1145			--------
1146			```python
1147			GPath("C:/Windows/System32") - 1  # GPath("C:/Windows")
1148			GPath("/usr/bin") - 2             # GPath("/")
1149			GPath("Documents") - 3            # GPath("..")
1150			GPath("/") - 1                    # GPath("/")
1151			```
1152		"""
1153		if n < 0:
1154			raise ValueError("cannot subtract a negative number of components from the path: {n}; use __add__() instead")
1155
1156		new_path = GPath(self)
1157		new_parts = [part for part in self._parts]
1158		for i in range(n):
1159			if len(new_parts) > 0:
1160				new_parts.pop()
1161			elif not new_path._root:
1162				new_path._parent_level += 1
1163			else:
1164				pass  # removing components from root should still give root
1165		new_path._parts = tuple(new_parts)
1166		return new_path

Remove n components from the end of the path and return a new copy.

Usage: self - n

Raises ValueError if self is an invalid GPath or if n is negative

Examples

GPath("C:/Windows/System32") - 1  # GPath("C:/Windows")
GPath("/usr/bin") - 2             # GPath("/")
GPath("Documents") - 3            # GPath("..")
GPath("/") - 1                    # GPath("/")
def __mul__(self, n: int) -> GPath:
1169	def __mul__(self, n: int) -> GPath:
1170		"""
1171			Duplicate the named components of `self` `n` times and return a new path with the duplicated components.
1172
1173			Named components will be duplicated separately from the components representing a parent directory. If `self` is an absolute path, only the relative components will be duplicated.
1174
1175			If `n` is 0, the result is an empty path (either relative or absolute).
1176
1177			Usage: <code><var>self</var> * <var>n</var></code>
1178
1179			Raises `ValueError` if `self` is an invalid GPath or if `n` is negative.
1180
1181			Examples
1182			--------
1183			```python
1184			GPath("/usr/bin") * 2    # GPath("/usr/bin/usr/bin")
1185			GPath("../docs") * 2     # GPath("../../docs/docs")
1186			GPath("C:/Windows") * 0  # GPath("C:/")
1187			```
1188		"""
1189		if n < 0:
1190			raise ValueError("cannot multiply path by a negative integer: {n}")
1191		new_path = GPath(self)
1192		new_path._parent_level = self._parent_level * n
1193		new_path._parts = self._parts * n
1194		return new_path

Duplicate the named components of self n times and return a new path with the duplicated components.

Named components will be duplicated separately from the components representing a parent directory. If self is an absolute path, only the relative components will be duplicated.

If n is 0, the result is an empty path (either relative or absolute).

Usage: self * n

Raises ValueError if self is an invalid GPath or if n is negative.

Examples

GPath("/usr/bin") * 2    # GPath("/usr/bin/usr/bin")
GPath("../docs") * 2     # GPath("../../docs/docs")
GPath("C:/Windows") * 0  # GPath("C:/")
def __truediv__( self, other: Union[GPath, str, bytes, os.PathLike]) -> GPath:
1197	def __truediv__(self, other: GPathLike) -> GPath:
1198		"""
1199			Alias of `__add__()`.
1200
1201			Usage: <code><var>self</var> + <var>other</var></code> or <code><var>self</var> / <var>other</var></code>
1202		"""
1203		return self.__add__(other)

Alias of __add__().

Usage: self + other or self / other

def __and__( self, other: Union[GPath, str, bytes, os.PathLike]) -> Optional[GPath]:
1206	def __and__(self, other: GPathLike) -> Union[GPath, None]:
1207		"""
1208			Equivalent to `self.common_with(other)`, using the default options of `common_with()`.
1209
1210			Usage: <code><var>g1</var> & <var>g2</var></code>
1211		"""
1212		return self.common_with(other)

Equivalent to self.common_with(other), using the default options of common_with().

Usage: g1 & g2

def __lshift__(self, n: int) -> GPath:
1215	def __lshift__(self, n: int) -> GPath:
1216		"""
1217			Move the imaginary current working directory `n` steps up the filesystem tree.
1218
1219			If `self` is a relative path, remove up to `n` levels of parent directories from the start of the path and return a copy. If it is an absolute path, return a copy of `self` unchanged.
1220
1221			If `n` is negative, this is equivalent to `__rshift__(-n)`.
1222
1223			Usage: <code><var>self</var> << <var>n</var></code>
1224
1225			Raises `ValueError` if `self` is an invalid GPath.
1226
1227			Examples
1228			--------
1229			```python
1230			GPath("../SysWOW64/drivers") << 1  # GPath("SysWOW64/drivers")
1231			GPath("../doc") << 2               # GPath("doc")
1232			GPath("/usr/bin") << 2             # GPath("/usr/bin")
1233			```
1234		"""
1235		if n < 0:
1236			return self.__rshift__(-1 * n)
1237		new_path = GPath(self)
1238		if not new_path._root:
1239			new_path._parent_level = max(new_path._parent_level - n, 0)
1240		return new_path

Move the imaginary current working directory n steps up the filesystem tree.

If self is a relative path, remove up to n levels of parent directories from the start of the path and return a copy. If it is an absolute path, return a copy of self unchanged.

If n is negative, this is equivalent to __rshift__(-n).

Usage: self << n

Raises ValueError if self is an invalid GPath.

Examples

GPath("../SysWOW64/drivers") << 1  # GPath("SysWOW64/drivers")
GPath("../doc") << 2               # GPath("doc")
GPath("/usr/bin") << 2             # GPath("/usr/bin")
def __rshift__(self, n: int) -> GPath:
1243	def __rshift__(self, n: int) -> GPath:
1244		"""
1245			Move the imaginary current working directory `n` steps down the filesystem tree.
1246
1247			If `self` is a relative path, add `n` levels of parent directories to the start of the path and return a copy. If it is an absolute path, return a copy of `self` unchanged.
1248
1249			If `n` is negative, this is equivalent to `__lshift__(-n)`.
1250
1251			Usage: <code><var>self</var> >> <var>n</var></code>
1252
1253			Raises `ValueError` if `self` is an invalid GPath
1254
1255			Examples
1256			--------
1257			```python
1258			GPath("../SysWOW64/drivers") >> 1  # GPath("../../SysWOW64/drivers")
1259			GPath("/usr/bin") >> 2             # GPath("/usr/bin")
1260			```
1261		"""
1262		if n < 0:
1263			return self.__lshift__(-1 * n)
1264		new_path = GPath(self)
1265		if not new_path._root:
1266			new_path._parent_level += n
1267		return new_path

Move the imaginary current working directory n steps down the filesystem tree.

If self is a relative path, add n levels of parent directories to the start of the path and return a copy. If it is an absolute path, return a copy of self unchanged.

If n is negative, this is equivalent to __lshift__(-n).

Usage: self >> n

Raises ValueError if self is an invalid GPath

Examples

GPath("../SysWOW64/drivers") >> 1  # GPath("../../SysWOW64/drivers")
GPath("/usr/bin") >> 2             # GPath("/usr/bin")
Inherited Members
collections.abc.Hashable
__subclasshook__
collections.abc.Iterable
__class_getitem__
builtins.object
__new__
__getattribute__
__setattr__
__delattr__
__lt__
__le__
__ne__
__gt__
__ge__
__reduce_ex__
__reduce__
__getstate__
__init_subclass__
__format__
__sizeof__
__dir__
GPathLike = Union[GPath, str, bytes, os.PathLike]