workspace.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import os
  2. import yaml
  3. class PnpmWorkspace(object):
  4. @classmethod
  5. def load(cls, path):
  6. ws = cls(path)
  7. ws.read()
  8. return ws
  9. def __init__(self, path):
  10. if not os.path.isabs(path):
  11. raise TypeError("Absolute path required, given: {}".format(path))
  12. self.path = path
  13. # NOTE: pnpm requires relative workspace paths.
  14. self.packages = set()
  15. def read(self):
  16. with open(self.path) as f:
  17. parsed = yaml.load(f, Loader=yaml.CSafeLoader) or {}
  18. self.packages = set(parsed.get("packages", []))
  19. def write(self, path=None):
  20. if not path:
  21. path = self.path
  22. with open(path, "w") as f:
  23. data = {
  24. "packages": list(self.packages),
  25. }
  26. yaml.dump(data, f, Dumper=yaml.CSafeDumper)
  27. def get_paths(self, base_path=None, ignore_self=False):
  28. """
  29. Returns absolute paths of the workspace packages.
  30. :param base_path: base path to resolve relative dep paths
  31. :type base_path: str
  32. :param ignore_self: whether path of the current module will be excluded (if present)
  33. :type ignore_self: bool
  34. :rtype: list of str
  35. """
  36. if base_path is None:
  37. base_path = os.path.dirname(self.path)
  38. return [
  39. os.path.normpath(os.path.join(base_path, pkg_path))
  40. for pkg_path in self.packages
  41. if not ignore_self or pkg_path != "."
  42. ]
  43. def set_from_package_json(self, package_json):
  44. """
  45. Sets packages to "workspace" deps from given package.json.
  46. :param package_json: package.json of workspace
  47. :type package_json: PackageJson
  48. """
  49. if os.path.dirname(package_json.path) != os.path.dirname(self.path):
  50. raise TypeError(
  51. "package.json should be in workspace directory {}, given: {}".format(
  52. os.path.dirname(self.path), package_json.path
  53. )
  54. )
  55. self.packages = set(path for _, path in package_json.get_workspace_dep_spec_paths())
  56. # Add relative path to self.
  57. self.packages.add(".")
  58. def merge(self, ws):
  59. """
  60. Adds `ws`'s packages to the workspace.
  61. :param ws: workspace to merge
  62. :type ws: PnpmWorkspace
  63. """
  64. dir_path = os.path.dirname(self.path)
  65. ws_dir_path = os.path.dirname(ws.path)
  66. for p_rel_path in ws.packages:
  67. p_path = os.path.normpath(os.path.join(ws_dir_path, p_rel_path))
  68. self.packages.add(os.path.relpath(p_path, dir_path))