zrb 0.0.85__py3-none-any.whl → 0.0.87__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. zrb/__init__.py +4 -2
  2. zrb/action/runner.py +7 -3
  3. zrb/builtin/__init__.py +8 -22
  4. zrb/builtin/base64.py +1 -1
  5. zrb/builtin/devtool/__init__.py +20 -0
  6. zrb/builtin/devtool/devtool_install.py +45 -2
  7. zrb/builtin/devtool/docker/install.sh +8 -0
  8. zrb/builtin/devtool/gcloud/install.sh +8 -0
  9. zrb/builtin/devtool/helix/install.sh +20 -0
  10. zrb/builtin/devtool/helix/resource/config.toml +10 -0
  11. zrb/builtin/devtool/helix/resource/themes/gruvbox_transparent.toml +2 -0
  12. zrb/builtin/devtool/tmux/install.sh +8 -0
  13. zrb/builtin/devtool/zsh/install.sh +9 -0
  14. zrb/builtin/devtool/zsh/resource/config.sh +2 -0
  15. zrb/builtin/env.py +6 -3
  16. zrb/builtin/explain.py +129 -0
  17. zrb/builtin/generator/__init__.py +27 -0
  18. zrb/builtin/generator/app_generator/add.py +81 -0
  19. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/add.py +182 -0
  20. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/_common.py +38 -0
  21. zrb/builtin/generator/{fastapp/template/_automate/snake_zrb_app_name/cmd/prepare-load-test.sh → app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/cmd/app-activate-venv.sh} +0 -6
  22. zrb/builtin/generator/{simple_python_app/template/_automate/snake_zrb_app_name/cmd/start.sh → app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/cmd/app-start.sh} +0 -9
  23. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/cmd/pulumi-destroy.sh +1 -0
  24. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/cmd/pulumi-init-stack.sh +1 -0
  25. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/cmd/pulumi-up.sh +1 -0
  26. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/container.py +148 -0
  27. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/deployment.py +108 -0
  28. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/image.py +68 -0
  29. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/local.py +54 -0
  30. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/.gitignore +1 -0
  31. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/deployment/.gitignore +2 -0
  32. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/deployment/Pulumi.yaml +6 -0
  33. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/deployment/__main__.py +79 -0
  34. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/deployment/requirements.txt +3 -0
  35. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/deployment/state/.gitkeep +0 -0
  36. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/docker-compose.env +3 -0
  37. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/docker-compose.yml +20 -0
  38. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/src/.dockerignore +3 -0
  39. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/src/.gitignore +3 -0
  40. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/src/Dockerfile +7 -0
  41. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/src/main.py +20 -0
  42. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/src/requirements.txt +1 -0
  43. zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/src/kebab-zrb-app-name/src/template.env +4 -0
  44. zrb/builtin/generator/cmd_task/add.py +14 -14
  45. zrb/builtin/generator/cmd_task/template/_automate/snake_zrb_task_name.py +1 -1
  46. zrb/builtin/generator/common/__init__.py +0 -0
  47. zrb/builtin/generator/common/helper.py +57 -0
  48. zrb/builtin/generator/common/task_factory.py +82 -0
  49. zrb/builtin/generator/{_common/input.py → common/task_input.py} +46 -1
  50. zrb/builtin/generator/docker_compose_task/add.py +16 -15
  51. zrb/builtin/generator/docker_compose_task/template/_automate/snake_zrb_task_name.py +1 -1
  52. zrb/builtin/generator/fastapp/add.py +105 -101
  53. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/_common.py +2 -1
  54. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/activate-venv.sh +7 -0
  55. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/{load-test.sh → app-load-test.sh} +0 -3
  56. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/app-prepare-backend.sh +2 -0
  57. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/app-prepare-load-test.sh +3 -0
  58. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/app-start.sh +3 -0
  59. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/pulumi-destroy.sh +0 -1
  60. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/pulumi-init-stack.sh +1 -0
  61. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/pulumi-up.sh +0 -1
  62. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/container.py +1 -1
  63. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/deployment.py +9 -3
  64. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/frontend.py +3 -3
  65. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/image.py +1 -1
  66. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/load_test.py +11 -4
  67. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/local.py +13 -4
  68. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/local_microservices.py +4 -1
  69. zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/test.py +3 -5
  70. zrb/builtin/generator/fastapp/template/src/kebab-zrb-app-name/deployment/requirements.txt +2 -2
  71. zrb/builtin/generator/fastapp/template/src/kebab-zrb-app-name/loadtest/requirements.txt +1 -1
  72. zrb/builtin/generator/fastapp/template/src/kebab-zrb-app-name/src/requirements.txt +3 -3
  73. zrb/builtin/generator/fastapp_crud/add.py +13 -126
  74. zrb/builtin/generator/fastapp_crud/helper.py +115 -0
  75. zrb/builtin/generator/fastapp_crud/task_factory.py +34 -0
  76. zrb/builtin/generator/fastapp_field/add.py +10 -282
  77. zrb/builtin/generator/fastapp_field/helper.py +283 -0
  78. zrb/builtin/generator/fastapp_module/add.py +22 -331
  79. zrb/builtin/generator/fastapp_module/helper.py +326 -0
  80. zrb/builtin/generator/pip_package/__init__.py +0 -0
  81. zrb/builtin/generator/pip_package/add.py +84 -0
  82. zrb/builtin/generator/pip_package/template/_automate/snake_zrb_package_name/cmd/build.sh +12 -0
  83. zrb/builtin/generator/{fastapp/template/_automate/snake_zrb_app_name/cmd/start.sh → pip_package/template/_automate/snake_zrb_package_name/cmd/install-symlink.sh} +2 -2
  84. zrb/builtin/generator/pip_package/template/_automate/snake_zrb_package_name/cmd/publish.sh +6 -0
  85. zrb/builtin/generator/pip_package/template/_automate/snake_zrb_package_name/local.py +60 -0
  86. zrb/builtin/generator/pip_package/template/src/kebab-zrb-package-name/.gitignore +1 -0
  87. zrb/builtin/generator/pip_package/template/src/kebab-zrb-package-name/README.md +79 -0
  88. zrb/builtin/generator/pip_package/template/src/kebab-zrb-package-name/pyproject.toml +36 -0
  89. zrb/builtin/generator/pip_package/template/src/kebab-zrb-package-name/requirements.txt +4 -0
  90. zrb/builtin/generator/pip_package/template/src/kebab-zrb-package-name/src/snake_zrb_package_name/__init__.py +2 -0
  91. zrb/builtin/generator/pip_package/template/src/kebab-zrb-package-name/src/snake_zrb_package_name/__main__.py +2 -0
  92. zrb/builtin/generator/pip_package/template/src/kebab-zrb-package-name/src/snake_zrb_package_name/util.py +2 -0
  93. zrb/builtin/generator/project/create.py +12 -8
  94. zrb/builtin/generator/project_task/task_factory.py +167 -83
  95. zrb/builtin/generator/project_task/template/_automate/_project/build_project_images.py +1 -1
  96. zrb/builtin/generator/project_task/template/_automate/_project/deploy_project.py +1 -1
  97. zrb/builtin/generator/project_task/template/_automate/_project/destroy_project.py +1 -1
  98. zrb/builtin/generator/project_task/template/_automate/_project/push_project_images.py +1 -1
  99. zrb/builtin/generator/project_task/template/_automate/_project/remove_project_containers.py +1 -1
  100. zrb/builtin/generator/project_task/template/_automate/_project/start_project.py +1 -1
  101. zrb/builtin/generator/project_task/template/_automate/_project/start_project_containers.py +1 -1
  102. zrb/builtin/generator/project_task/template/_automate/_project/stop_project_containers.py +1 -1
  103. zrb/builtin/generator/python_task/add.py +14 -16
  104. zrb/builtin/generator/python_task/template/_automate/snake_zrb_task_name.py +1 -1
  105. zrb/builtin/generator/simple_python_app/add.py +95 -99
  106. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/cmd/app-activate-venv.sh +7 -0
  107. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/cmd/app-start.sh +6 -0
  108. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/cmd/pulumi-destroy.sh +0 -1
  109. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/cmd/pulumi-init-stack.sh +1 -0
  110. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/cmd/pulumi-up.sh +0 -1
  111. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/container.py +1 -1
  112. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/deployment.py +9 -3
  113. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/image.py +1 -1
  114. zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/local.py +5 -2
  115. zrb/builtin/generator/simple_python_app/template/src/kebab-zrb-app-name/deployment/requirements.txt +2 -2
  116. zrb/builtin/git.py +1 -1
  117. zrb/builtin/{_group.py → group.py} +2 -5
  118. zrb/builtin/md5.py +1 -1
  119. zrb/builtin/project.py +1 -1
  120. zrb/builtin/ubuntu.py +1 -1
  121. zrb/config/config.py +8 -6
  122. zrb/helper/accessories/color.py +5 -1
  123. zrb/helper/accessories/icon.py +2 -0
  124. zrb/helper/accessories/name.py +2 -0
  125. zrb/helper/advertisement.py +1 -0
  126. zrb/helper/cli.py +5 -1
  127. zrb/helper/codemod/add_argument_to_function.py +3 -0
  128. zrb/helper/codemod/add_argument_to_function_call.py +3 -0
  129. zrb/helper/codemod/add_assert_resource.py +2 -0
  130. zrb/helper/codemod/add_function_call.py +2 -0
  131. zrb/helper/codemod/add_import_module.py +3 -0
  132. zrb/helper/codemod/add_key_value_to_dict.py +2 -0
  133. zrb/helper/codemod/add_property_to_class.py +3 -0
  134. zrb/helper/codemod/add_upstream_to_task.py +3 -0
  135. zrb/helper/codemod/append_code_to_function.py +3 -0
  136. zrb/helper/codemod/format_code.py +2 -0
  137. zrb/helper/default_env.py +2 -0
  138. zrb/helper/docker_compose/fetch_external_env.py +3 -0
  139. zrb/helper/docker_compose/file.py +4 -0
  140. zrb/helper/env_map/fetch.py +7 -0
  141. zrb/helper/file/text.py +6 -0
  142. zrb/helper/git/detect_changes.py +4 -0
  143. zrb/helper/loader/load_module.py +2 -0
  144. zrb/helper/map/conversion.py +2 -0
  145. zrb/helper/string/conversion.py +5 -0
  146. zrb/helper/string/double_quote.py +6 -2
  147. zrb/helper/string/jinja.py +2 -0
  148. zrb/helper/string/parse_replacement.py +2 -0
  149. zrb/helper/util.py +13 -0
  150. zrb/task/any_task.py +2 -2
  151. zrb/task/base_task.py +16 -16
  152. zrb/task/base_task_composite.py +12 -9
  153. zrb/task/cmd_task.py +23 -12
  154. zrb/task/decorator.py +2 -2
  155. zrb/task/docker_compose_task.py +5 -5
  156. zrb/task/flow_task.py +5 -5
  157. zrb/task/http_checker.py +2 -2
  158. zrb/task/path_checker.py +2 -2
  159. zrb/task/port_checker.py +2 -2
  160. zrb/task/resource_maker.py +3 -5
  161. zrb/task_input/any_input.py +23 -0
  162. zrb/task_input/base_input.py +46 -43
  163. zrb/task_input/float_input.py +0 -1
  164. {zrb-0.0.85.dist-info → zrb-0.0.87.dist-info}/METADATA +16 -17
  165. {zrb-0.0.85.dist-info → zrb-0.0.87.dist-info}/RECORD +175 -122
  166. zrb/builtin/generator/_common/helper.py +0 -79
  167. zrb/builtin/generator/fastapp_crud/add_navigation.py +0 -32
  168. zrb/builtin/principle.py +0 -66
  169. /zrb/builtin/generator/{_common → app_generator}/__init__.py +0 -0
  170. /zrb/{config.toml → builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/__init__.py} +0 -0
  171. /zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/{build-frontend.sh → app-build-frontend.sh} +0 -0
  172. /zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/cmd/{test.sh → app-test.sh} +0 -0
  173. /zrb/builtin/generator/{fastapp/template/_automate/snake_zrb_app_name/cmd/prepare-backend.sh → pip_package/template/_automate/snake_zrb_package_name/cmd/prepare-venv.sh} +0 -0
  174. /zrb/task_input/{_constant.py → constant.py} +0 -0
  175. /zrb/task_input/{input.py → task_input.py} +0 -0
  176. {zrb-0.0.85.dist-info → zrb-0.0.87.dist-info}/LICENSE +0 -0
  177. {zrb-0.0.85.dist-info → zrb-0.0.87.dist-info}/WHEEL +0 -0
  178. {zrb-0.0.85.dist-info → zrb-0.0.87.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,283 @@
1
+ from typeguard import typechecked
2
+ from ....task.task import Task
3
+ from ....helper.codemod.add_property_to_class import add_property_to_class
4
+ from ....helper.codemod.add_key_value_to_dict import add_key_value_to_dict
5
+ from ....helper.file.text import read_text_file_async, write_text_file_async
6
+ import os
7
+ import re
8
+
9
+
10
+ @typechecked
11
+ async def add_column_to_insert_page(
12
+ task: Task,
13
+ project_dir: str,
14
+ kebab_app_name: str,
15
+ kebab_module_name: str,
16
+ kebab_entity_name: str,
17
+ kebab_column_name: str,
18
+ snake_column_name: str,
19
+ capitalized_human_readable_column_name: str
20
+ ):
21
+ list_page_file_path = os.path.join(
22
+ project_dir, 'src', kebab_app_name, 'src', 'frontend', 'src', 'routes',
23
+ kebab_module_name, kebab_entity_name, 'new', '+page.svelte'
24
+ )
25
+ task.print_out(f'Read HTML from: {list_page_file_path}')
26
+ html_content = await read_text_file_async(list_page_file_path)
27
+ task.print_out('Add default value to insert page')
28
+ default_value_regex = r"(.*)(// DON'T DELETE: set field default value here)" # noqa
29
+ default_value_subst = '\\n'.join([
30
+ f"\\1row.{snake_column_name} = '';",
31
+ '\\1\\2'
32
+ ])
33
+ html_content = re.sub(
34
+ default_value_regex, default_value_subst, html_content, 0, re.MULTILINE
35
+ )
36
+ task.print_out('Add field to insert page')
37
+ field_regex = r"(.*)(<!-- DON'T DELETE: insert new field here-->)"
38
+ field_subst = '\\n'.join([
39
+ '\\1<div class="mb-4">',
40
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
41
+ f'\\1 <input type="text" class="input w-full" id="{kebab_column_name}" placeholder="{capitalized_human_readable_column_name}" bind:value=' + '{row.' + snake_column_name + '} />', # noqa
42
+ '\\1</div>',
43
+ '\\1\\2'
44
+ ])
45
+ html_content = re.sub(
46
+ field_regex, field_subst, html_content, 0, re.MULTILINE
47
+ )
48
+ task.print_out(f'Write modified HTML to: {list_page_file_path}')
49
+ await write_text_file_async(list_page_file_path, html_content)
50
+
51
+
52
+ @typechecked
53
+ async def add_column_to_update_page(
54
+ task: Task,
55
+ project_dir: str,
56
+ kebab_app_name: str,
57
+ kebab_module_name: str,
58
+ kebab_entity_name: str,
59
+ kebab_column_name: str,
60
+ snake_column_name: str,
61
+ capitalized_human_readable_column_name: str
62
+ ):
63
+ list_page_file_path = os.path.join(
64
+ project_dir, 'src', kebab_app_name, 'src', 'frontend', 'src', 'routes',
65
+ kebab_module_name, kebab_entity_name, 'update', '[id]', '+page.svelte'
66
+ )
67
+ task.print_out(f'Read HTML from: {list_page_file_path}')
68
+ html_content = await read_text_file_async(list_page_file_path)
69
+ task.print_out('Add field to update page')
70
+ regex = r"(.*)(<!-- DON'T DELETE: insert new field here-->)"
71
+ subst = '\\n'.join([
72
+ '\\1<div class="mb-4">',
73
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
74
+ f'\\1 <input type="text" class="input w-full" id="{kebab_column_name}" placeholder="{capitalized_human_readable_column_name}" bind:value=' + '{row.' + snake_column_name + '} />', # noqa
75
+ '\\1</div>',
76
+ '\\1\\2'
77
+ ])
78
+ html_content = re.sub(
79
+ regex, subst, html_content, 0, re.MULTILINE
80
+ )
81
+ task.print_out(f'Write modified HTML to: {list_page_file_path}')
82
+ await write_text_file_async(list_page_file_path, html_content)
83
+
84
+
85
+ @typechecked
86
+ async def add_column_to_delete_page(
87
+ task: Task,
88
+ project_dir: str,
89
+ kebab_app_name: str,
90
+ kebab_module_name: str,
91
+ kebab_entity_name: str,
92
+ kebab_column_name: str,
93
+ snake_column_name: str,
94
+ capitalized_human_readable_column_name: str
95
+ ):
96
+ list_page_file_path = os.path.join(
97
+ project_dir, 'src', kebab_app_name, 'src', 'frontend', 'src', 'routes',
98
+ kebab_module_name, kebab_entity_name, 'delete', '[id]', '+page.svelte'
99
+ )
100
+ task.print_out(f'Read HTML from: {list_page_file_path}')
101
+ html_content = await read_text_file_async(list_page_file_path)
102
+ task.print_out('Add field to delete page')
103
+ regex = r"(.*)(<!-- DON'T DELETE: insert new field here-->)"
104
+ subst = '\\n'.join([
105
+ '\\1<div class="mb-4">',
106
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
107
+ f'\\1 <span id="{kebab_column_name}">' + '{row.' + snake_column_name + '}</span>', # noqa
108
+ '\\1</div>',
109
+ '\\1\\2'
110
+ ])
111
+ html_content = re.sub(
112
+ regex, subst, html_content, 0, re.MULTILINE
113
+ )
114
+ task.print_out(f'Write modified HTML to: {list_page_file_path}')
115
+ await write_text_file_async(list_page_file_path, html_content)
116
+
117
+
118
+ @typechecked
119
+ async def add_column_to_detail_page(
120
+ task: Task,
121
+ project_dir: str,
122
+ kebab_app_name: str,
123
+ kebab_module_name: str,
124
+ kebab_entity_name: str,
125
+ kebab_column_name: str,
126
+ snake_column_name: str,
127
+ capitalized_human_readable_column_name: str
128
+ ):
129
+ list_page_file_path = os.path.join(
130
+ project_dir, 'src', kebab_app_name, 'src', 'frontend', 'src', 'routes',
131
+ kebab_module_name, kebab_entity_name, 'detail', '[id]', '+page.svelte'
132
+ )
133
+ task.print_out(f'Read HTML from: {list_page_file_path}')
134
+ html_content = await read_text_file_async(list_page_file_path)
135
+ task.print_out('Add field to detail page')
136
+ regex = r"(.*)(<!-- DON'T DELETE: insert new field here-->)"
137
+ subst = '\\n'.join([
138
+ '\\1<div class="mb-4">',
139
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
140
+ f'\\1 <span id="{kebab_column_name}">' + '{row.' + snake_column_name + '}</span>', # noqa
141
+ '\\1</div>',
142
+ '\\1\\2'
143
+ ])
144
+ html_content = re.sub(
145
+ regex, subst, html_content, 0, re.MULTILINE
146
+ )
147
+ task.print_out(f'Write modified HTML to: {list_page_file_path}')
148
+ await write_text_file_async(list_page_file_path, html_content)
149
+
150
+
151
+ @typechecked
152
+ async def add_column_to_list_page(
153
+ task: Task,
154
+ project_dir: str,
155
+ kebab_app_name: str,
156
+ kebab_module_name: str,
157
+ kebab_entity_name: str,
158
+ snake_column_name: str,
159
+ capitalized_human_readable_column_name: str
160
+ ):
161
+ list_page_file_path = os.path.join(
162
+ project_dir, 'src', kebab_app_name, 'src', 'frontend', 'src', 'routes',
163
+ kebab_module_name, kebab_entity_name, '+page.svelte'
164
+ )
165
+ task.print_out(f'Read HTML from: {list_page_file_path}')
166
+ html_content = await read_text_file_async(list_page_file_path)
167
+ # process header
168
+ task.print_out('Add column header to table')
169
+ header_regex = r"(.*)(<!-- DON'T DELETE: insert new column header here-->)"
170
+ header_subst = '\\n'.join([
171
+ f'\\1<th>{capitalized_human_readable_column_name}</th>',
172
+ '\\1\\2'
173
+ ])
174
+ html_content = re.sub(
175
+ header_regex, header_subst, html_content, 0, re.MULTILINE
176
+ )
177
+ # process column
178
+ task.print_out('Add column to table')
179
+ column_regex = r"(.*)(<!-- DON'T DELETE: insert new column here-->)"
180
+ column_subst = '\\n'.join([
181
+ '\\1<td>{row.' + snake_column_name + '}</td>',
182
+ '\\1\\2'
183
+ ])
184
+ html_content = re.sub(
185
+ column_regex, column_subst, html_content, 0, re.MULTILINE
186
+ )
187
+ task.print_out(f'Write modified HTML to: {list_page_file_path}')
188
+ await write_text_file_async(list_page_file_path, html_content)
189
+
190
+
191
+ @typechecked
192
+ async def add_column_to_test(
193
+ task: Task,
194
+ project_dir: str,
195
+ kebab_app_name: str,
196
+ snake_module_name: str,
197
+ snake_entity_name: str,
198
+ snake_column_name: str,
199
+ column_type: str
200
+ ):
201
+ test_file_path = os.path.join(
202
+ project_dir, 'src', kebab_app_name, 'test', snake_module_name,
203
+ f'test_{snake_entity_name}.py'
204
+ )
205
+ task.print_out(f'Read code from: {test_file_path}')
206
+ code = await read_text_file_async(test_file_path)
207
+ task.print_out(
208
+ f'Add column "{snake_column_name}" to the test'
209
+ )
210
+ dict_names = [
211
+ 'inserted_success_data', 'to_be_updated_success_data',
212
+ 'updated_success_data', 'to_be_deleted_success_data'
213
+ ]
214
+ for dict_name in dict_names:
215
+ code = add_key_value_to_dict(
216
+ code=code,
217
+ dict_name=dict_name,
218
+ key=f"'{snake_column_name}'",
219
+ value="''"
220
+ )
221
+ task.print_out(f'Write modified code to: {test_file_path}')
222
+ await write_text_file_async(test_file_path, code)
223
+
224
+
225
+ @typechecked
226
+ async def add_column_to_schema(
227
+ task: Task,
228
+ project_dir: str,
229
+ kebab_app_name: str,
230
+ snake_module_name: str,
231
+ snake_entity_name: str,
232
+ pascal_entity_name: str,
233
+ snake_column_name: str,
234
+ column_type: str
235
+ ):
236
+ schema_file_path = os.path.join(
237
+ project_dir, 'src', kebab_app_name, 'src', 'module', snake_module_name,
238
+ 'schema', f'{snake_entity_name}.py'
239
+ )
240
+ task.print_out(f'Read code from: {schema_file_path}')
241
+ code = await read_text_file_async(schema_file_path)
242
+ task.print_out(
243
+ f'Add column "{snake_column_name}" to the schema'
244
+ )
245
+ code = add_property_to_class(
246
+ code=code,
247
+ class_name=f'{pascal_entity_name}Data',
248
+ property_name=snake_column_name,
249
+ property_type='str'
250
+ )
251
+ task.print_out(f'Write modified code to: {schema_file_path}')
252
+ await write_text_file_async(schema_file_path, code)
253
+
254
+
255
+ @typechecked
256
+ async def add_column_to_repo(
257
+ task: Task,
258
+ project_dir: str,
259
+ kebab_app_name: str,
260
+ snake_module_name: str,
261
+ snake_entity_name: str,
262
+ pascal_entity_name: str,
263
+ snake_column_name: str,
264
+ column_type: str
265
+ ):
266
+ repo_file_path = os.path.join(
267
+ project_dir, 'src', kebab_app_name, 'src', 'module', snake_module_name,
268
+ 'entity', snake_entity_name, 'repo.py'
269
+ )
270
+ task.print_out(f'Read code from: {repo_file_path}')
271
+ code = await read_text_file_async(repo_file_path)
272
+ task.print_out(
273
+ f'Add column "{snake_column_name}" to the repo'
274
+ )
275
+ code = add_property_to_class(
276
+ code=code,
277
+ class_name=f'DBEntity{pascal_entity_name}',
278
+ property_name=snake_column_name,
279
+ property_type='Column',
280
+ property_value='Column(String)'
281
+ )
282
+ task.print_out(f'Write modified code to: {repo_file_path}')
283
+ await write_text_file_async(repo_file_path, code)
@@ -1,29 +1,24 @@
1
- from typing import Any, List, Mapping
2
- from dotenv import dotenv_values
3
- from ..._group import project_add_group
1
+ from typing import Any
2
+ from .helper import (
3
+ create_microservice_config, register_module, register_migration,
4
+ create_app_config, append_all_enabled_env, append_all_disabled_env,
5
+ append_src_template_env, append_deployment_template_env
6
+ )
7
+ from ..common.helper import validate_existing_project_dir
8
+ from ..common.task_input import (
9
+ project_dir_input, app_name_input, module_name_input
10
+ )
11
+ from ...group import project_add_group
4
12
  from ....task.task import Task
5
13
  from ....task.decorator import python_task
6
14
  from ....task.resource_maker import ResourceMaker
7
15
  from ....runner import runner
8
- from .._common.input import (
9
- project_dir_input, app_name_input,
10
- module_name_input
11
- )
12
- from .._common.helper import validate_project_dir
13
16
  from ....helper import util
14
- from ....helper.codemod.add_import_module import add_import_module
15
- from ....helper.codemod.add_function_call import add_function_call
16
- from ....helper.codemod.append_code_to_function import append_code_to_function
17
- from ....helper.docker_compose.file import add_services
18
- from ....helper.file.text import (
19
- read_text_file_async, write_text_file_async, append_text_file_async
20
- )
21
17
 
22
18
  import asyncio
23
19
  import os
24
- import jsons
25
20
 
26
- current_dir = os.path.dirname(__file__)
21
+ CURRENT_DIR = os.path.dirname(__file__)
27
22
 
28
23
  ###############################################################################
29
24
  # Task Definitions
@@ -37,7 +32,7 @@ current_dir = os.path.dirname(__file__)
37
32
  )
38
33
  async def validate(*args: Any, **kwargs: Any):
39
34
  project_dir = kwargs.get('project_dir')
40
- validate_project_dir(project_dir)
35
+ validate_existing_project_dir(project_dir)
41
36
  app_name = kwargs.get('app_name')
42
37
  module_name = kwargs.get('module_name')
43
38
  snake_module_name = util.to_snake_case(module_name)
@@ -70,7 +65,7 @@ copy_resource = ResourceMaker(
70
65
  'zrbAppName': '{{input.app_name}}',
71
66
  'zrbModuleName': '{{input.module_name}}',
72
67
  },
73
- template_path=os.path.join(current_dir, 'template'),
68
+ template_path=os.path.join(CURRENT_DIR, 'template'),
74
69
  destination_path='{{ input.project_dir }}',
75
70
  excludes=[
76
71
  '*/__pycache__',
@@ -95,335 +90,31 @@ async def add_fastapp_module(*args: Any, **kwargs: Any):
95
90
  snake_module_name = util.to_snake_case(module_name)
96
91
  upper_snake_module_name = snake_module_name.upper()
97
92
  await asyncio.gather(
98
- asyncio.create_task(_create_microservice_config(
93
+ asyncio.create_task(create_microservice_config(
99
94
  task, project_dir, kebab_app_name, snake_app_name,
100
95
  kebab_module_name, snake_module_name, upper_snake_module_name
101
96
  )),
102
- asyncio.create_task(_register_module(
97
+ asyncio.create_task(register_module(
103
98
  task, project_dir, kebab_app_name, snake_module_name
104
99
  )),
105
- asyncio.create_task(_register_migration(
100
+ asyncio.create_task(register_migration(
106
101
  task, project_dir, kebab_app_name, snake_module_name
107
102
  )),
108
- asyncio.create_task(_create_app_config(
103
+ asyncio.create_task(create_app_config(
109
104
  task, project_dir, kebab_app_name, snake_module_name,
110
105
  upper_snake_module_name
111
106
  )),
112
- asyncio.create_task(_append_all_enabled_env(
107
+ asyncio.create_task(append_all_enabled_env(
113
108
  task, project_dir, kebab_app_name, upper_snake_module_name
114
109
  )),
115
- asyncio.create_task(_append_all_disabled_env(
110
+ asyncio.create_task(append_all_disabled_env(
116
111
  task, project_dir, kebab_app_name, upper_snake_module_name
117
112
  )),
118
- asyncio.create_task(_append_src_template_env(
113
+ asyncio.create_task(append_src_template_env(
119
114
  task, project_dir, kebab_app_name, upper_snake_module_name
120
115
  )),
121
- asyncio.create_task(_append_deployment_template_env(
116
+ asyncio.create_task(append_deployment_template_env(
122
117
  task, project_dir, kebab_app_name, upper_snake_module_name
123
118
  )),
124
119
  )
125
120
  task.print_out('Success')
126
-
127
-
128
- ###############################################################################
129
- # Helper Definitions
130
- ###############################################################################
131
-
132
-
133
- async def _create_microservice_config(
134
- task: Task,
135
- project_dir: str,
136
- kebab_app_name: str,
137
- snake_app_name: str,
138
- kebab_module_name: str,
139
- snake_module_name: str,
140
- upper_snake_module_name: str
141
- ):
142
- modules = await _create_automation_json_config(
143
- task, project_dir, snake_app_name, snake_module_name
144
- )
145
- return await asyncio.gather(
146
- asyncio.create_task(_add_docker_compose_service(
147
- task, modules, project_dir, kebab_app_name,
148
- snake_app_name, kebab_module_name, snake_module_name,
149
- upper_snake_module_name
150
- )),
151
- asyncio.create_task(_append_compose_env(
152
- task, modules, project_dir, kebab_app_name, upper_snake_module_name
153
- ))
154
- )
155
-
156
-
157
- async def _add_docker_compose_service(
158
- task: Task,
159
- modules: List[str],
160
- project_dir: str,
161
- kebab_app_name: str,
162
- snake_app_name: str,
163
- kebab_module_name: str,
164
- snake_module_name: str,
165
- upper_snake_module_name: str
166
- ):
167
- module_app_port = 8080 + len(modules)
168
- module_app_port_str = str(module_app_port)
169
- docker_compose_file_path = os.path.join(
170
- project_dir, 'src', kebab_app_name, 'docker-compose.yml'
171
- )
172
- app_container_port_env_name = f'APP_{upper_snake_module_name}_MODULE_PORT'
173
- app_container_port_env = '${' + app_container_port_env_name + ':-' + module_app_port_str + '}' # noqa
174
- app_host_port_env_name = f'APP_{upper_snake_module_name}_HOST_MODULE_PORT'
175
- app_host_port_env = '${' + app_host_port_env_name + ':-' + module_app_port_str + '}' # noqa
176
- service_definition = _get_new_docker_compose_service_definition(
177
- kebab_app_name, snake_app_name, kebab_module_name, snake_module_name,
178
- upper_snake_module_name, app_host_port_env, app_container_port_env
179
- )
180
- task.print_out(f'Add service at: {docker_compose_file_path}')
181
- add_services(
182
- file_name=docker_compose_file_path,
183
- new_services=service_definition,
184
- )
185
-
186
-
187
- def _get_new_docker_compose_service_definition(
188
- kebab_app_name: str,
189
- snake_app_name: str,
190
- kebab_module_name: str,
191
- snake_module_name: str,
192
- upper_snake_module_name: str,
193
- app_host_port_env: str,
194
- app_container_port_env: str
195
- ) -> Mapping[str, Any]:
196
- return {
197
- f'{kebab_app_name}-{kebab_module_name}-service': {
198
- 'build': {
199
- 'dockerfile': 'Dockerfile',
200
- 'context': './src'
201
- },
202
- 'image': '${IMAGE:-' + kebab_app_name + '}',
203
- 'container_name': '${CONTAINER_PREFIX:-my}-' + f'{kebab_app_name}-{kebab_module_name}-service', # noqa
204
- 'hostname': f'{kebab_app_name}-{kebab_module_name}-service',
205
- 'env_file': [
206
- 'src/template.env',
207
- 'all-module-disabled.env'
208
- ],
209
- 'environment': {
210
- 'APP_NAME': '${APP_NAME:-' + kebab_app_name + '}-' + f'{kebab_module_name}-service', # noqa
211
- 'APP_PORT': app_container_port_env,
212
- 'APP_ENABLE_EVENT_HANDLER': 'true',
213
- 'APP_ENABLE_RPC_SERVER': 'true',
214
- 'APP_ENABLE_API': 'false',
215
- 'APP_ENABLE_FRONTEND': 'false',
216
- f'APP_ENABLE_{upper_snake_module_name}_MODULE': 'true',
217
- },
218
- 'ports': [
219
- f'{app_host_port_env}:{app_container_port_env}'
220
- ],
221
- 'restart': 'unless-stopped',
222
- 'profiles': [
223
- 'microservices'
224
- ],
225
- 'healthcheck': {
226
- 'test': [
227
- 'CMD-SHELL',
228
- 'curl --fail http://localhost:' + app_container_port_env + '/readiness || exit 1' # noqa
229
- ],
230
- 'interval': '5s',
231
- 'timeout': '3s',
232
- 'retries': 10
233
- },
234
- 'networks': ['zrb']
235
- }
236
- }
237
-
238
-
239
- async def _append_compose_env(
240
- task: Task,
241
- modules: List[str],
242
- project_dir: str,
243
- kebab_app_name: str,
244
- upper_snake_module_name: str
245
- ):
246
- compose_template_env_path = os.path.join(
247
- project_dir, 'src', kebab_app_name, 'docker-compose.env'
248
- )
249
- compose_env_map = dotenv_values(compose_template_env_path)
250
- host_port = int(compose_env_map.get('APP_GATEWAY_HOST_PORT', '8080'))
251
- module_app_port = host_port + len(modules)
252
- new_env_str = '\n'.join([
253
- f'APP_{upper_snake_module_name}_HOST_MODULE_PORT={module_app_port}',
254
- f'APP_{upper_snake_module_name}_MODULE_PORT={module_app_port}',
255
- ])
256
- task.print_out(f'Add new environment to: {compose_template_env_path}')
257
- await append_text_file_async(compose_template_env_path, new_env_str)
258
-
259
-
260
- async def _append_src_template_env(
261
- task: Task,
262
- project_dir: str,
263
- kebab_app_name: str,
264
- upper_snake_module_name: str
265
- ):
266
- src_template_env_path = os.path.join(
267
- project_dir, 'src', kebab_app_name, 'src', 'template.env'
268
- )
269
- new_env_str = '\n'.join([
270
- f'APP_ENABLE_{upper_snake_module_name}_MODULE=true',
271
- ])
272
- task.print_out(f'Add new environment to: {src_template_env_path}')
273
- await append_text_file_async(src_template_env_path, new_env_str)
274
-
275
-
276
- async def _append_deployment_template_env(
277
- task: Task,
278
- project_dir: str,
279
- kebab_app_name: str,
280
- upper_snake_module_name: str
281
- ):
282
- deployment_template_env_path = os.path.join(
283
- project_dir, 'src', kebab_app_name, 'deployment', 'template.env'
284
- )
285
- new_env_str = '\n'.join([
286
- f'REPLICA_{upper_snake_module_name}_SERVICE=1',
287
- ])
288
- task.print_out(f'Add new environment to: {deployment_template_env_path}')
289
- await append_text_file_async(deployment_template_env_path, new_env_str)
290
-
291
-
292
- async def _append_all_enabled_env(
293
- task: Task,
294
- project_dir: str,
295
- kebab_app_name: str,
296
- upper_snake_module_name: str
297
- ):
298
- all_enabled_env_path = os.path.join(
299
- project_dir, 'src', kebab_app_name, 'all-module-enabled.env'
300
- )
301
- task.print_out(f'Add new environment to: {all_enabled_env_path}')
302
- await append_text_file_async(
303
- all_enabled_env_path,
304
- f'APP_ENABLE_{upper_snake_module_name}_MODULE=true'
305
- )
306
-
307
-
308
- async def _append_all_disabled_env(
309
- task: Task,
310
- project_dir: str,
311
- kebab_app_name: str,
312
- upper_snake_module_name: str
313
- ):
314
- all_disabled_env_path = os.path.join(
315
- project_dir, 'src', kebab_app_name, 'all-module-disabled.env'
316
- )
317
- task.print_out(f'Add new environment to: {all_disabled_env_path}')
318
- await append_text_file_async(
319
- all_disabled_env_path,
320
- f'APP_ENABLE_{upper_snake_module_name}_MODULE=false'
321
- )
322
-
323
-
324
- async def _create_app_config(
325
- task: Task,
326
- project_dir: str,
327
- kebab_app_name: str,
328
- snake_module_name: str,
329
- upper_snake_module_name: str
330
- ):
331
- config_file_path = os.path.join(
332
- project_dir, 'src', kebab_app_name, 'src', 'config.py'
333
- )
334
- config_code = '\n'.join([
335
- f'app_enable_{snake_module_name}_module = str_to_boolean(os.environ.get(', # noqa
336
- f" 'APP_ENABLE_{upper_snake_module_name}_MODULE', 'true'"
337
- '))'
338
- ])
339
- task.print_out(f'Read config from: {config_file_path}')
340
- code = await read_text_file_async(config_file_path)
341
- code += '\n' + config_code
342
- task.print_out(f'Write config to: {config_file_path}')
343
- await write_text_file_async(config_file_path, code)
344
-
345
-
346
- async def _create_automation_json_config(
347
- task: Task,
348
- project_dir: str,
349
- snake_app_name: str,
350
- snake_module_name: str,
351
- ):
352
- json_modules_file_path = os.path.join(
353
- project_dir, '_automate', snake_app_name, 'config', 'modules.json'
354
- )
355
- task.print_out(f'Read json config from: {json_modules_file_path}')
356
- json_str = await read_text_file_async(json_modules_file_path)
357
- task.print_out(f'Add "{snake_module_name}" to json config')
358
- modules: List[str] = jsons.loads(json_str)
359
- modules.append(snake_module_name)
360
- json_str = jsons.dumps(modules)
361
- task.print_out(f'Write new json config to: {json_modules_file_path}')
362
- await write_text_file_async(json_modules_file_path, json_str)
363
- return modules
364
-
365
-
366
- async def _register_migration(
367
- task: Task,
368
- project_dir: str,
369
- kebab_app_name: str,
370
- snake_module_name: str
371
- ):
372
- app_migration_file_path = os.path.join(
373
- project_dir, 'src', kebab_app_name, 'src', 'migrate.py'
374
- )
375
- import_module_path = '.'.join([
376
- 'module', snake_module_name, 'migrate'
377
- ])
378
- function_name = f'migrate_{snake_module_name}'
379
- task.print_out(f'Read code from: {app_migration_file_path}')
380
- code = await read_text_file_async(app_migration_file_path)
381
- task.print_out(
382
- f'Add import "{function_name}" from "{import_module_path}" to the code'
383
- )
384
- code = add_import_module(
385
- code=code,
386
- module_path=import_module_path,
387
- resource=function_name
388
- )
389
- task.print_out(f'Add "{function_name}" call to the code')
390
- code = append_code_to_function(
391
- code=code,
392
- function_name='migrate',
393
- new_code=f'await {function_name}()'
394
- )
395
- task.print_out(f'Write modified code to: {app_migration_file_path}')
396
- await write_text_file_async(app_migration_file_path, code)
397
-
398
-
399
- async def _register_module(
400
- task: Task,
401
- project_dir: str,
402
- kebab_app_name: str,
403
- snake_module_name: str
404
- ):
405
- app_main_file_path = os.path.join(
406
- project_dir, 'src', kebab_app_name, 'src', 'main.py'
407
- )
408
- import_module_path = '.'.join([
409
- 'module', snake_module_name, 'register_module'
410
- ])
411
- function_name = f'register_{snake_module_name}'
412
- task.print_out(f'Read code from: {app_main_file_path}')
413
- code = await read_text_file_async(app_main_file_path)
414
- task.print_out(
415
- f'Add import "{function_name}" from "{import_module_path}" to the code'
416
- )
417
- code = add_import_module(
418
- code=code,
419
- module_path=import_module_path,
420
- resource=function_name
421
- )
422
- task.print_out(f'Add "{function_name}" call to the code')
423
- code = add_function_call(
424
- code=code,
425
- function_name=function_name,
426
- parameters=[]
427
- )
428
- task.print_out(f'Write modified code to: {app_main_file_path}')
429
- await write_text_file_async(app_main_file_path, code)