_path.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import os
  2. import platform
  3. _WINDOWS_PLATFORM = platform.system() == "Windows"
  4. def combine(path1: str, path2) -> str:
  5. if not path1:
  6. return path2
  7. return "{}/{}".format(path1.rstrip("/"), path2.lstrip("/"))
  8. def split(path: str) -> tuple[str, str]:
  9. if "/" not in path:
  10. return ("", path)
  11. split = path.rsplit("/", 1)
  12. return (split[0] or "/", split[1])
  13. def dirname(path: str) -> str:
  14. return split(path)[0]
  15. def basename(path: str) -> str:
  16. return split(path)[1]
  17. def forcedir(path: str) -> str:
  18. # Ensure the path ends with a trailing forward slash.
  19. if not path.endswith("/"):
  20. return path + "/"
  21. return path
  22. def abspath(path: str) -> str:
  23. # FS objects have no concept of a *current directory*. This simply
  24. # ensures the path starts with a forward slash.
  25. if not path.startswith("/"):
  26. return "/" + path
  27. return path
  28. def isbase(path1: str, path2: str) -> bool:
  29. # Check if `path1` is a base or prefix of `path2`.
  30. _path1 = forcedir(abspath(path1))
  31. _path2 = forcedir(abspath(path2))
  32. return _path2.startswith(_path1)
  33. def frombase(path1: str, path2: str) -> str:
  34. # Get the final path of `path2` that isn't in `path1`.
  35. if not isbase(path1, path2):
  36. raise ValueError(f"path1 must be a prefix of path2: {path1!r} vs {path2!r}")
  37. return path2[len(path1) :]
  38. def relpath(path: str) -> str:
  39. return path.lstrip("/")
  40. def normpath(path: str) -> str:
  41. normalized = os.path.normpath(path)
  42. if _WINDOWS_PLATFORM:
  43. # os.path.normpath converts backslashes to forward slashes on Windows
  44. # but we want forward slashes, so we convert them back
  45. normalized = normalized.replace("\\", "/")
  46. return normalized