path_ops.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. """Path operations."""
  2. from __future__ import annotations
  3. import json
  4. import os
  5. import re
  6. import shutil
  7. from pathlib import Path
  8. from reflex import constants
  9. # Shorthand for join.
  10. join = os.linesep.join
  11. def rm(path: str):
  12. """Remove a file or directory.
  13. Args:
  14. path: The path to the file or directory.
  15. """
  16. if os.path.isdir(path):
  17. shutil.rmtree(path)
  18. elif os.path.isfile(path):
  19. os.remove(path)
  20. def cp(src: str, dest: str, overwrite: bool = True) -> bool:
  21. """Copy a file or directory.
  22. Args:
  23. src: The path to the file or directory.
  24. dest: The path to the destination.
  25. overwrite: Whether to overwrite the destination.
  26. Returns:
  27. Whether the copy was successful.
  28. """
  29. if src == dest:
  30. return False
  31. if not overwrite and os.path.exists(dest):
  32. return False
  33. if os.path.isdir(src):
  34. rm(dest)
  35. shutil.copytree(src, dest)
  36. else:
  37. shutil.copyfile(src, dest)
  38. return True
  39. def mv(src: str, dest: str, overwrite: bool = True) -> bool:
  40. """Move a file or directory.
  41. Args:
  42. src: The path to the file or directory.
  43. dest: The path to the destination.
  44. overwrite: Whether to overwrite the destination.
  45. Returns:
  46. Whether the move was successful.
  47. """
  48. if src == dest:
  49. return False
  50. if not overwrite and os.path.exists(dest):
  51. return False
  52. rm(dest)
  53. shutil.move(src, dest)
  54. return True
  55. def mkdir(path: str):
  56. """Create a directory.
  57. Args:
  58. path: The path to the directory.
  59. """
  60. os.makedirs(path, exist_ok=True)
  61. def ln(src: str, dest: str, overwrite: bool = False) -> bool:
  62. """Create a symbolic link.
  63. Args:
  64. src: The path to the file or directory.
  65. dest: The path to the destination.
  66. overwrite: Whether to overwrite the destination.
  67. Returns:
  68. Whether the link was successful.
  69. """
  70. if src == dest:
  71. return False
  72. if not overwrite and (os.path.exists(dest) or os.path.islink(dest)):
  73. return False
  74. if os.path.isdir(src):
  75. rm(dest)
  76. os.symlink(src, dest, target_is_directory=True)
  77. else:
  78. os.symlink(src, dest)
  79. return True
  80. def which(program: str) -> str | None:
  81. """Find the path to an executable.
  82. Args:
  83. program: The name of the executable.
  84. Returns:
  85. The path to the executable.
  86. """
  87. return shutil.which(program)
  88. def get_node_bin_path() -> str | None:
  89. """Get the node binary dir path.
  90. Returns:
  91. The path to the node bin folder.
  92. """
  93. if not os.path.exists(constants.Node.BIN_PATH):
  94. str_path = which("node")
  95. return str(Path(str_path).parent) if str_path else str_path
  96. return constants.Node.BIN_PATH
  97. def get_node_path() -> str | None:
  98. """Get the node binary path.
  99. Returns:
  100. The path to the node binary file.
  101. """
  102. if not os.path.exists(constants.Node.PATH):
  103. return which("node")
  104. return constants.Node.PATH
  105. def get_npm_path() -> str | None:
  106. """Get npm binary path.
  107. Returns:
  108. The path to the npm binary file.
  109. """
  110. if not os.path.exists(constants.Node.PATH):
  111. return which("npm")
  112. return constants.Node.NPM_PATH
  113. def update_json_file(file_path: str, update_dict: dict[str, int | str]):
  114. """Update the contents of a json file.
  115. Args:
  116. file_path: the path to the JSON file.
  117. update_dict: object to update json.
  118. """
  119. fp = Path(file_path)
  120. # Create the file if it doesn't exist.
  121. fp.touch(exist_ok=True)
  122. # Create an empty json object if file is empty
  123. fp.write_text("{}") if fp.stat().st_size == 0 else None
  124. # Read the existing json object from the file.
  125. json_object = {}
  126. if fp.stat().st_size == 0:
  127. with open(fp) as f:
  128. json_object = json.load(f)
  129. # Update the json object with the new data.
  130. json_object.update(update_dict)
  131. # Write the updated json object to the file
  132. with open(fp, "w") as f:
  133. json.dump(json_object, f, ensure_ascii=False)
  134. def find_replace(directory: str, find: str, replace: str):
  135. """Recursively find and replace text in files in a directory.
  136. Args:
  137. directory: The directory to search.
  138. find: The text to find.
  139. replace: The text to replace.
  140. """
  141. for root, _dirs, files in os.walk(directory):
  142. for file in files:
  143. filepath = os.path.join(root, file)
  144. with open(filepath, "r", encoding="utf-8") as f:
  145. text = f.read()
  146. text = re.sub(find, replace, text)
  147. with open(filepath, "w") as f:
  148. f.write(text)