scaffolding.py 13 KB

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