Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

289 рядки
8.1 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe, os, re
  5. from frappe.utils import touch_file, encode, cstr
  6. def make_boilerplate(dest, app_name):
  7. if not os.path.exists(dest):
  8. print "Destination directory does not exist"
  9. return
  10. # app_name should be in snake_case
  11. app_name = frappe.scrub(app_name)
  12. hooks = frappe._dict()
  13. hooks.app_name = app_name
  14. app_title = hooks.app_name.replace("_", " ").title()
  15. for key in ("App Title (default: {0})".format(app_title),
  16. "App Description", "App Publisher", "App Email",
  17. "App Icon (default 'octicon octicon-file-directory')",
  18. "App Color (default 'grey')",
  19. "App License (default 'MIT')"):
  20. hook_key = key.split(" (")[0].lower().replace(" ", "_")
  21. hook_val = None
  22. while not hook_val:
  23. hook_val = cstr(raw_input(key + ": "))
  24. if not hook_val:
  25. defaults = {
  26. "app_title": app_title,
  27. "app_icon": "octicon octicon-file-directory",
  28. "app_color": "grey",
  29. "app_license": "MIT"
  30. }
  31. if hook_key in defaults:
  32. hook_val = defaults[hook_key]
  33. if hook_key=="app_name" and hook_val.lower().replace(" ", "_") != hook_val:
  34. print "App Name must be all lowercase and without spaces"
  35. hook_val = ""
  36. elif hook_key=="app_title" and not re.match("^(?![\W])[^\d_\s][\w -]+$", hook_val, re.UNICODE):
  37. print "App Title should start with a letter and it can only consist of letters, numbers, spaces and underscores"
  38. hook_val = ""
  39. hooks[hook_key] = hook_val
  40. frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, frappe.scrub(hooks.app_title)),
  41. with_init=True)
  42. frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates"), with_init=True)
  43. frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "www"))
  44. frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
  45. "pages"), with_init=True)
  46. frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
  47. "generators"), with_init=True)
  48. frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "templates",
  49. "includes"))
  50. frappe.create_folder(os.path.join(dest, hooks.app_name, hooks.app_name, "config"), with_init=True)
  51. touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "__init__.py"))
  52. with open(os.path.join(dest, hooks.app_name, "MANIFEST.in"), "w") as f:
  53. f.write(encode(manifest_template.format(**hooks)))
  54. with open(os.path.join(dest, hooks.app_name, ".gitignore"), "w") as f:
  55. f.write(encode(gitignore_template.format(app_name = hooks.app_name)))
  56. with open(os.path.join(dest, hooks.app_name, "setup.py"), "w") as f:
  57. f.write(encode(setup_template.format(**hooks)))
  58. with open(os.path.join(dest, hooks.app_name, "requirements.txt"), "w") as f:
  59. f.write("frappe")
  60. with open(os.path.join(dest, hooks.app_name, "README.md"), "w") as f:
  61. f.write(encode("## {0}\n\n{1}\n\n#### License\n\n{2}".format(hooks.app_title,
  62. hooks.app_description, hooks.app_license)))
  63. with open(os.path.join(dest, hooks.app_name, "license.txt"), "w") as f:
  64. f.write(encode("License: " + hooks.app_license))
  65. with open(os.path.join(dest, hooks.app_name, hooks.app_name, "modules.txt"), "w") as f:
  66. f.write(encode(hooks.app_title))
  67. with open(os.path.join(dest, hooks.app_name, hooks.app_name, "hooks.py"), "w") as f:
  68. f.write(encode(hooks_template.format(**hooks)))
  69. touch_file(os.path.join(dest, hooks.app_name, hooks.app_name, "patches.txt"))
  70. with open(os.path.join(dest, hooks.app_name, hooks.app_name, "config", "desktop.py"), "w") as f:
  71. f.write(encode(desktop_template.format(**hooks)))
  72. with open(os.path.join(dest, hooks.app_name, hooks.app_name, "config", "docs.py"), "w") as f:
  73. f.write(encode(docs_template.format(**hooks)))
  74. print "'{app}' created at {path}".format(app=app_name, path=os.path.join(dest, app_name))
  75. manifest_template = """include MANIFEST.in
  76. include requirements.txt
  77. include *.json
  78. include *.md
  79. include *.py
  80. include *.txt
  81. recursive-include {app_name} *.css
  82. recursive-include {app_name} *.csv
  83. recursive-include {app_name} *.html
  84. recursive-include {app_name} *.ico
  85. recursive-include {app_name} *.js
  86. recursive-include {app_name} *.json
  87. recursive-include {app_name} *.md
  88. recursive-include {app_name} *.png
  89. recursive-include {app_name} *.py
  90. recursive-include {app_name} *.svg
  91. recursive-include {app_name} *.txt
  92. recursive-exclude {app_name} *.pyc"""
  93. hooks_template = """# -*- coding: utf-8 -*-
  94. from __future__ import unicode_literals
  95. app_name = "{app_name}"
  96. app_title = "{app_title}"
  97. app_publisher = "{app_publisher}"
  98. app_description = "{app_description}"
  99. app_icon = "{app_icon}"
  100. app_color = "{app_color}"
  101. app_email = "{app_email}"
  102. app_version = "0.0.1"
  103. app_license = "{app_license}"
  104. # Includes in <head>
  105. # ------------------
  106. # include js, css files in header of desk.html
  107. # app_include_css = "/assets/{app_name}/css/{app_name}.css"
  108. # app_include_js = "/assets/{app_name}/js/{app_name}.js"
  109. # include js, css files in header of web template
  110. # web_include_css = "/assets/{app_name}/css/{app_name}.css"
  111. # web_include_js = "/assets/{app_name}/js/{app_name}.js"
  112. # Home Pages
  113. # ----------
  114. # application home page (will override Website Settings)
  115. # home_page = "login"
  116. # website user home page (by Role)
  117. # role_home_page = {{
  118. # "Role": "home_page"
  119. # }}
  120. # Website user home page (by function)
  121. # get_website_user_home_page = "{app_name}.utils.get_home_page"
  122. # Generators
  123. # ----------
  124. # automatically create page for each record of this doctype
  125. # website_generators = ["Web Page"]
  126. # Installation
  127. # ------------
  128. # before_install = "{app_name}.install.before_install"
  129. # after_install = "{app_name}.install.after_install"
  130. # Desk Notifications
  131. # ------------------
  132. # See frappe.core.notifications.get_notification_config
  133. # notification_config = "{app_name}.notifications.get_notification_config"
  134. # Permissions
  135. # -----------
  136. # Permissions evaluated in scripted ways
  137. # permission_query_conditions = {{
  138. # "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions",
  139. # }}
  140. #
  141. # has_permission = {{
  142. # "Event": "frappe.desk.doctype.event.event.has_permission",
  143. # }}
  144. # Document Events
  145. # ---------------
  146. # Hook on document methods and events
  147. # doc_events = {{
  148. # "*": {{
  149. # "on_update": "method",
  150. # "on_cancel": "method",
  151. # "on_trash": "method"
  152. # }}
  153. # }}
  154. # Scheduled Tasks
  155. # ---------------
  156. # scheduler_events = {{
  157. # "all": [
  158. # "{app_name}.tasks.all"
  159. # ],
  160. # "daily": [
  161. # "{app_name}.tasks.daily"
  162. # ],
  163. # "hourly": [
  164. # "{app_name}.tasks.hourly"
  165. # ],
  166. # "weekly": [
  167. # "{app_name}.tasks.weekly"
  168. # ]
  169. # "monthly": [
  170. # "{app_name}.tasks.monthly"
  171. # ]
  172. # }}
  173. # Testing
  174. # -------
  175. # before_tests = "{app_name}.install.before_tests"
  176. # Overriding Whitelisted Methods
  177. # ------------------------------
  178. #
  179. # override_whitelisted_methods = {{
  180. # "frappe.desk.doctype.event.event.get_events": "{app_name}.event.get_events"
  181. # }}
  182. """
  183. desktop_template = """# -*- coding: utf-8 -*-
  184. from __future__ import unicode_literals
  185. from frappe import _
  186. def get_data():
  187. return [
  188. {{
  189. "module_name": "{app_title}",
  190. "color": "{app_color}",
  191. "icon": "{app_icon}",
  192. "type": "module",
  193. "label": _("{app_title}")
  194. }}
  195. ]
  196. """
  197. setup_template = """# -*- coding: utf-8 -*-
  198. from setuptools import setup, find_packages
  199. from pip.req import parse_requirements
  200. version = '0.0.1'
  201. requirements = parse_requirements("requirements.txt", session="")
  202. setup(
  203. name='{app_name}',
  204. version=version,
  205. description='{app_description}',
  206. author='{app_publisher}',
  207. author_email='{app_email}',
  208. packages=find_packages(),
  209. zip_safe=False,
  210. include_package_data=True,
  211. install_requires=[str(ir.req) for ir in requirements],
  212. dependency_links=[str(ir._link) for ir in requirements if ir._link]
  213. )
  214. """
  215. gitignore_template = """.DS_Store
  216. *.pyc
  217. *.egg-info
  218. *.swp
  219. tags
  220. {app_name}/docs/current"""
  221. docs_template = '''"""
  222. Configuration for docs
  223. """
  224. # source_link = "https://github.com/[org_name]/{app_name}"
  225. # docs_base_url = "https://[org_name].github.io/{app_name}"
  226. # headline = "App that does everything"
  227. # sub_heading = "Yes, you got that right the first time, everything"
  228. def get_context(context):
  229. context.brand_html = "{app_title}"
  230. '''