paths.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import os
  2. import re
  3. from pathlib import Path
  4. from typing import Union
  5. from urllib.parse import unquote, urlparse
  6. RE_PATH_ANCHOR = r"^file://([^/]+|/[A-Z]:)"
  7. def normalized_uri(root_dir):
  8. """Attempt to make an LSP rootUri from a ContentsManager root_dir
  9. Special care must be taken around windows paths: the canonical form of
  10. windows drives and UNC paths is lower case
  11. """
  12. root_uri = Path(root_dir).expanduser().resolve().as_uri()
  13. root_uri = re.sub(
  14. RE_PATH_ANCHOR, lambda m: "file://{}".format(m.group(1).lower()), root_uri
  15. )
  16. return root_uri
  17. def file_uri_to_path(file_uri):
  18. """Return a path string for give file:/// URI.
  19. Respect the different path convention on Windows.
  20. Based on https://stackoverflow.com/a/57463161/6646912, BSD 0
  21. """
  22. windows_path = os.name == "nt"
  23. file_uri_parsed = urlparse(file_uri)
  24. file_uri_path_unquoted = unquote(file_uri_parsed.path)
  25. if windows_path and file_uri_path_unquoted.startswith("/"):
  26. result = file_uri_path_unquoted[1:] # pragma: no cover
  27. else:
  28. result = file_uri_path_unquoted # pragma: no cover
  29. return result
  30. def is_relative(root: Union[str, Path], path: Union[str, Path]) -> bool:
  31. """Return if path is relative to root"""
  32. try:
  33. Path(path).resolve().relative_to(Path(root).resolve())
  34. return True
  35. except ValueError:
  36. return False