No Description

generator.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. """
  2. File: generator.py
  3. Author: Fx Lesaffre
  4. Email: fx@zrkf.pw
  5. Git: https://git.zrkf.pw/fx
  6. Description: generator class for askelerator
  7. """
  8. import os
  9. import re
  10. from . import helpers
  11. class Generator():
  12. """A skeleton generator"""
  13. def substitute(self, string):
  14. """Apply all substitutions to a target string
  15. :string: target string
  16. :returns: processed string
  17. """
  18. for act in self.template.actions:
  19. string = re.sub(act["regexp"], act["output"], string)
  20. return string
  21. def list_files(self, source_dir=None, target_dir=None):
  22. """
  23. Prepare two dictionnaries, one for directoy matching, the other for files.
  24. This functions is recursive and will finish once bottom of source tree
  25. structure reached.
  26. :source_dir: source directory to be processed
  27. :source_dir: target directory to be processed
  28. """
  29. if source_dir is None:
  30. source_dir = self.template.path
  31. if target_dir is None:
  32. target_dir = self.target_path
  33. for file_name in os.listdir(source_dir):
  34. if os.path.isdir(source_dir + '/' + file_name):
  35. target_name = self.substitute(file_name)
  36. self.source_to_target_dirs.update(
  37. {source_dir + '/' + file_name: target_dir + '/' + target_name})
  38. self.list_files(source_dir + '/' + file_name, target_dir + '/' + target_name)
  39. elif os.path.isfile(source_dir + '/' + file_name):
  40. target_name = self.substitute(file_name)
  41. self.source_to_target_files.update(
  42. {source_dir + '/' + file_name: target_dir + '/' + target_name})
  43. def check_files(self):
  44. """
  45. Check for no collisions in target skeleton
  46. :return: 0 if ready to build tree
  47. """
  48. conflicting = []
  49. for key in self.source_to_target_files:
  50. if os.path.lexists(self.source_to_target_files[key]):
  51. conflicting.append(self.source_to_target_files[key])
  52. for key in self.source_to_target_dirs:
  53. if os.path.lexists(self.source_to_target_dirs[key]):
  54. if not os.path.isdir(self.source_to_target_dirs[key]):
  55. conflicting.append(self.source_to_target_dirs[key])
  56. if conflicting:
  57. conflict_message = conflicting[0]
  58. for i in range(1, len(conflicting)):
  59. if len(conflicting) - i == 1:
  60. conflict_message += ' and ' + conflicting[i]
  61. else:
  62. conflict_message += ', ' + conflicting[i]
  63. conflict_message += " are in conflict." if len(conflicting) > 1 else " is in conflict."
  64. print(conflict_message)
  65. answer = input('(O)verwrite, (A)bort : ')
  66. if not re.match(r'^[Oo]', answer):
  67. helpers.exit_error('Aborting...')
  68. return 0
  69. def build_skel(self):
  70. """Build skeleton from template to taget"""
  71. for directory in self.source_to_target_dirs:
  72. if not os.path.lexists(self.source_to_target_dirs[directory]):
  73. os.makedirs(self.source_to_target_dirs[directory])
  74. else:
  75. if not os.path.isdir(self.source_to_target_dirs[directory]):
  76. os.remove(self.source_to_target_dirs[directory])
  77. os.makedirs(self.source_to_target_dirs[directory])
  78. for file in self.source_to_target_files:
  79. if not os.path.lexists(self.source_to_target_files[file]):
  80. buf = open(file, 'r')
  81. content = buf.read()
  82. buf.close()
  83. content = self.substitute(content)
  84. fout = open(self.source_to_target_files[file], 'w')
  85. fout.write(self.substitute(content))
  86. fout.close()
  87. def process(self):
  88. """TODO: Docstring for process.
  89. :returns: TODO
  90. """
  91. self.list_files()
  92. if self.force:
  93. self.check_files()
  94. self.build_skel()
  95. def __init__(self, template, target_path):
  96. """Read json file from template
  97. :template: A template object
  98. :target_path: target directory
  99. """
  100. self.template = template
  101. self.target_path = target_path
  102. self.source_to_target_dirs = {}
  103. self.source_to_target_files = {}
  104. self.force = False