scaffolding.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. # -*- coding: utf-8 -*-
  2. import os, re
  3. from shutil import copytree
  4. from toolset.utils.metadata_helper import gather_frameworks, gather_langauges
  5. class Scaffolding:
  6. def __init__(self):
  7. print("""
  8. -------------------------------------------------------------------------------
  9. This wizard is intended to help build the scaffolding required for a new
  10. test to be benchmarked.
  11. From here, you will be prompted for values related to the test you
  12. wish to add.
  13. -------------------------------------------------------------------------------"""
  14. )
  15. try:
  16. self.__gather_display_name()
  17. self.__gather_language()
  18. self.__gather_approach()
  19. self.__gather_classification()
  20. self.__gather_orm()
  21. self.__gather_webserver()
  22. self.__gather_versus()
  23. self.__confirm_values()
  24. self.__print_success()
  25. except:
  26. print("")
  27. def __gather_display_name(self):
  28. print("""
  29. The name of your test as you wish it to be displayed on the results page.
  30. Example: Gemini, Gin, Express
  31. """)
  32. self.__prompt_display_name()
  33. while not self.display_name:
  34. self.__prompt_display_name()
  35. self.name = self.display_name.lower()
  36. def __prompt_display_name(self):
  37. self.display_name = input("Name: ").strip()
  38. found = False
  39. for framework in gather_frameworks():
  40. if framework.lower() == self.display_name.lower():
  41. found = True
  42. if found:
  43. print("""
  44. It appears that there is already a '%s' framework in the test suite. You will
  45. have to pick a different name.
  46. """ % self.display_name)
  47. self.display_name = None
  48. def __gather_language(self):
  49. print("""
  50. The language in which your test implementation is written.
  51. Example: Java, Go, PHP
  52. """)
  53. self.language = None
  54. while not self.language:
  55. self.__prompt_language()
  56. def __prompt_language(self):
  57. self.language = input("Language: ").strip()
  58. known_languages = gather_langauges()
  59. language = None
  60. for lang in known_languages:
  61. if lang.lower() == self.language.lower():
  62. language = lang
  63. if not language:
  64. similar = []
  65. for lang in known_languages:
  66. if lang.lower()[:1] == self.language.lower()[:1]:
  67. similar.append(lang)
  68. similar = ', '.join(similar)
  69. print("""
  70. That language is not currently in our list of known languages.
  71. Here is a list of similar languages present in our benchmark suite that you
  72. may have meant:
  73. %s
  74. Did you mean to add the new language, '%s', to the benchmark suite?
  75. """ % (similar, self.language))
  76. valid = self.__prompt_confirm_new_language(known_languages)
  77. while not valid:
  78. valid = self.__prompt_confirm_new_language(known_languages)
  79. if self.confirm_new_lang == 'n':
  80. self.language = None
  81. else:
  82. self.language = self.language.title()
  83. return self.language
  84. def __prompt_confirm_new_language(self, known_languages):
  85. self.confirm_new_lang = input("Create New Language '%s' (y/n): " %
  86. self.language).strip().lower()
  87. return self.confirm_new_lang == 'y' or self.confirm_new_lang == 'n'
  88. def __gather_approach(self):
  89. print("""
  90. The approach of your test implementation.
  91. 1) Realistic: Uses the framework with most out-of-the-box functionality
  92. enabled. We consider this realistic because most applications
  93. built with the framework will leave these features enabled.
  94. 2) Stripped: Removes or outright avoids implementing features that are
  95. unnecessary for the particulars of the benchmark exercise. This
  96. might illuminate the marginal improvement available in fine-
  97. tuning a framework to your application's use-case.
  98. Note: If you are unsure, then your approach is probably Realistic. The
  99. Stripped approach is seldom used and will not have results displayed
  100. by default on the results website.
  101. """)
  102. valid = self.__prompt_approach()
  103. while not valid:
  104. valid = self.__prompt_approach()
  105. def __prompt_approach(self):
  106. self.approach = input("Approach [1/2]: ").strip()
  107. if self.approach == '1':
  108. self.approach = 'Realistic'
  109. if self.approach == '2':
  110. self.approach = 'Stripped'
  111. return self.approach == 'Realistic' or self.approach == 'Stripped'
  112. def __gather_classification(self):
  113. print("""
  114. The classification of your test implementation.
  115. 1) Fullstack: Robust framework expected to provide high-level functionality
  116. for serving as a web application; for example, ability to
  117. compose views, provide functions for responding with several
  118. data types (json, html, etc), connecting to a database, form
  119. processing, etc.
  120. 2) Micro: Simple framework expected to provide enough middleware to build
  121. a robust web application such as request routing and some
  122. simple plumbing, but may not include built-in functionality
  123. such as, for example, server-composed views.
  124. 3) Platform: Barebones infrastructure for servicing HTTP requests, but does
  125. not include a framework at all.
  126. """)
  127. valid = self.__prompt_classification()
  128. while not valid:
  129. valid = self.__prompt_classification()
  130. if self.classification == 'Platform':
  131. self.platform = 'None'
  132. self.framework = 'None'
  133. else:
  134. self.framework = self.display_name
  135. self.__gather_platform()
  136. def __prompt_classification(self):
  137. self.classification = input("Classification [1/2/3]: ").strip()
  138. if self.classification == '1':
  139. self.classification = 'Fullstack'
  140. if self.classification == '2':
  141. self.classification = 'Micro'
  142. if self.classification == '3':
  143. self.classification = 'Platform'
  144. return self.classification == 'Fullstack' or \
  145. self.classification == 'Micro' or \
  146. self.classification == 'Platform'
  147. def __gather_platform(self):
  148. print("""
  149. The platform of your test implementation.
  150. The platform is the low-level software or API used to host web applications
  151. for the framework; the platform provides an implementation of the HTTP
  152. fundamentals.
  153. Not all frameworks have a platform and if your programming language provides
  154. much of that by which we define a platform, leave black.
  155. Example: Servlet, Wai, .NET
  156. """)
  157. self.__prompt_platform()
  158. def __prompt_platform(self):
  159. self.platform = input("Platform (optional): ").strip()
  160. if self.platform == '':
  161. self.platform = 'None'
  162. def __gather_orm(self):
  163. print("""
  164. How you would classify the ORM (object relational mapper) of your test?
  165. 1) Full: A feature-rich ORM which provides functionality for interacting
  166. with a database without writing a query in all but the most edge
  167. cases.
  168. 2) Micro: An ORM which provides functionality for interacting with a database
  169. for many trivial operations (querying, updating), but not more
  170. robust cases (for example, gathering relations).
  171. 3) Raw: No ORM; raw database access.
  172. """)
  173. valid = self.__prompt_orm()
  174. while not valid:
  175. valid = self.__prompt_orm()
  176. def __prompt_orm(self):
  177. self.orm = input("ORM [1/2/3]: ").strip()
  178. if self.orm == '1':
  179. self.orm = 'Full'
  180. if self.orm == '2':
  181. self.orm = 'Micro'
  182. if self.orm == '3':
  183. self.orm = 'Raw'
  184. return self.orm == 'Full' or \
  185. self.orm == 'Micro' or \
  186. self.orm == 'Raw'
  187. def __gather_webserver(self):
  188. print("""
  189. Name of the front-end webserver sitting in front of your test implementation.
  190. Your test implementation may not use a web-server and may act as its own; you
  191. can leave this blank in this case.
  192. Example: nginx, Meinheld, httplight
  193. """)
  194. self.__prompt_webserver()
  195. def __prompt_webserver(self):
  196. self.webserver = input("Webserver (optional): ").strip()
  197. if self.webserver == '':
  198. self.webserver = 'None'
  199. def __gather_versus(self):
  200. print("""
  201. The name of another test (elsewhere in this project) that is a subset of this
  202. framework.
  203. This allows for the generation of the framework efficiency chart in the
  204. results web site.
  205. For example, Compojure is compared to "servlet" since Compojure is built on
  206. the Servlet platform.
  207. Example: Servlet, Wai, Undertow
  208. """)
  209. self.__prompt_versus()
  210. def __prompt_versus(self):
  211. self.versus = input("Versus (optional): ").strip()
  212. if self.versus == '':
  213. self.versus = 'None'
  214. def __confirm_values(self):
  215. print("""
  216. Name: %s
  217. Language: %s
  218. Approach: %s
  219. Classification: %s
  220. Platform: %s
  221. ORM: %s
  222. Webserver: %s
  223. Versus: %s
  224. Finalize the initialization of your test given the above values?
  225. Note: once you have initialized your test, you can change these values later.
  226. """ % (self.display_name, self.language, self.approach,
  227. self.classification, self.platform, self.orm, self.webserver,
  228. self.versus))
  229. valid = self.__prompt_confirmation()
  230. while not valid:
  231. valid = self.__prompt_confirmation()
  232. if self.confirmation == 'y':
  233. self.__build_scaffolding()
  234. else:
  235. print('Aborting')
  236. def __prompt_confirmation(self):
  237. self.confirmation = input("Initialize [y/n]: ").strip().lower()
  238. return self.confirmation == 'y' or self.confirmation == 'n'
  239. def __build_scaffolding(self):
  240. if self.__create_test_folder():
  241. self.__copy_scaffold_files()
  242. self.__edit_scaffold_files()
  243. def __create_test_folder(self):
  244. self.language_dir = os.path.join("frameworks", self.language)
  245. self.test_dir = os.path.join(self.language_dir, self.name)
  246. if os.path.exists(self.test_dir):
  247. print("Test '%s' already exists; aborting." % self.name)
  248. return False
  249. return True
  250. def __copy_scaffold_files(self):
  251. self.scaffold_dir = os.path.join("toolset", "setup", "scaffolding")
  252. copytree(self.scaffold_dir, self.test_dir)
  253. def __edit_scaffold_files(self):
  254. for file in os.listdir(os.path.join(self.test_dir)):
  255. self.__replace_text(
  256. os.path.join(self.test_dir, file), "\$NAME", self.name)
  257. self.__replace_text(
  258. os.path.join(self.test_dir, file), "\$DISPLAY_NAME",
  259. self.display_name)
  260. self.__replace_text(
  261. os.path.join(self.test_dir, file), "\$APPROACH", self.approach)
  262. self.__replace_text(
  263. os.path.join(self.test_dir, file), "\$CLASSIFICATION",
  264. self.classification)
  265. self.__replace_text(
  266. os.path.join(self.test_dir, file), "\$FRAMEWORK",
  267. self.framework)
  268. self.__replace_text(
  269. os.path.join(self.test_dir, file), "\$LANGUAGE", self.language)
  270. self.__replace_text(
  271. os.path.join(self.test_dir, file), "\$ORM", self.orm)
  272. self.__replace_text(
  273. os.path.join(self.test_dir, file), "\$PLATFORM", self.platform)
  274. self.__replace_text(
  275. os.path.join(self.test_dir, file), "\$WEBSERVER",
  276. self.webserver)
  277. self.__replace_text(
  278. os.path.join(self.test_dir, file), "\$VERSUS", self.versus)
  279. def __print_success(self):
  280. print("""
  281. -------------------------------------------------------------------------------
  282. Success!
  283. Your new test structure has been built to the sepcifications of the suite.
  284. Here is a brief run-down of what has been built:
  285. frameworks
  286. └─── %s
  287. └─── %s
  288. ├─── .gitignore
  289. ├─── benchmark_config.json
  290. ├─── README.md
  291. ├─── setup.sh
  292. ├─── setup_mysql.sh
  293. └─── source_code
  294. The next step is to read through your README.md and follow the instructions
  295. provided therein.
  296. -------------------------------------------------------------------------------"""
  297. % (self.language, self.name))
  298. # Replaces all text found using the regular expression to_replace with the supplied replacement.
  299. def __replace_text(self, file, to_replace, replacement):
  300. with open(file, "r") as conf:
  301. contents = conf.read()
  302. replaced_text = re.sub(to_replace, replacement, contents)
  303. with open(file, "w") as f:
  304. f.write(replaced_text)