zrb 1.0.0a15__py3-none-any.whl → 1.0.0a17__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 (121) hide show
  1. zrb/__main__.py +3 -0
  2. zrb/builtin/__init__.py +2 -2
  3. zrb/builtin/git.py +16 -8
  4. zrb/builtin/git_subtree.py +7 -2
  5. zrb/builtin/llm/tool/rag.py +2 -2
  6. zrb/builtin/project/add/fastapp/fastapp_input.py +16 -0
  7. zrb/builtin/project/add/fastapp/fastapp_task.py +92 -0
  8. zrb/builtin/project/add/fastapp/fastapp_template/_zrb/entity/any_client_method.template.py +27 -0
  9. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/entity/module_template/service/my_entity/my_entity_usecase.py +6 -6
  10. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/entity/module_template/service/my_entity/repository/my_entity_db_repository.py +10 -5
  11. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/entity/module_template/service/my_entity/repository/my_entity_repository.py +5 -5
  12. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/entity/schema.template.py +8 -0
  13. zrb/builtin/project/add/{fastapp_template/_zrb/entity/create_entity_task.py → fastapp/fastapp_template/_zrb/entity/task.py} +106 -42
  14. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/input.py +1 -1
  15. zrb/builtin/project/add/{fastapp_template/_zrb/module/create_module_task.py → fastapp/fastapp_template/_zrb/module/task.py} +38 -31
  16. zrb/builtin/project/add/fastapp/fastapp_template/_zrb/module/template/module_template/client/any_client.py +7 -0
  17. zrb/builtin/project/add/fastapp/fastapp_template/_zrb/module/template/module_template/client/api_client.py +6 -0
  18. zrb/builtin/project/add/{fastapp_template/_zrb/module → fastapp/fastapp_template/_zrb/module/template}/module_template/client/direct_client.py +2 -2
  19. zrb/builtin/project/add/{fastapp_template/_zrb/module → fastapp/fastapp_template/_zrb/module/template}/module_template/client/factory.py +3 -3
  20. zrb/builtin/project/add/fastapp/fastapp_template/_zrb/module/template/module_template/route.py +33 -0
  21. zrb/builtin/project/add/{fastapp_template/_zrb/main.py → fastapp/fastapp_template/_zrb/task.py} +3 -3
  22. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/common/base_usecase.py +19 -6
  23. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/config.py +1 -0
  24. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/client/any_client.py +10 -4
  25. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/client/api_client.py +2 -2
  26. zrb/builtin/project/add/fastapp/fastapp_template/module/auth/client/direct_client.py +6 -0
  27. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/client/factory.py +3 -3
  28. zrb/builtin/project/add/fastapp/fastapp_template/module/auth/route.py +37 -0
  29. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/service/user/repository/user_db_repository.py +10 -4
  30. zrb/builtin/project/add/fastapp/fastapp_template/module/auth/service/user/repository/user_repository.py +43 -0
  31. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/service/user/user_usecase.py +10 -4
  32. zrb/builtin/project/add/fastapp/fastapp_template/module/gateway/route.py +43 -0
  33. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/requirements.txt +1 -1
  34. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/schema/permission.py +8 -0
  35. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/schema/role.py +8 -0
  36. zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/schema/user.py +8 -0
  37. zrb/builtin/project/add/fastapp/fastapp_util.py +22 -0
  38. zrb/builtin/project/create/{create.py → project_task.py} +1 -1
  39. zrb/builtin/setup/asdf/asdf_helper.py +4 -8
  40. zrb/builtin/setup/tmux/tmux.py +7 -12
  41. zrb/builtin/todo.py +14 -19
  42. zrb/cmd/cmd_val.py +2 -2
  43. zrb/content_transformer/content_transformer.py +3 -4
  44. zrb/input/base_input.py +13 -1
  45. zrb/input/text_input.py +4 -4
  46. zrb/runner/web_controller/group_info_ui/controller.py +6 -14
  47. zrb/runner/web_controller/home_page/controller.py +6 -14
  48. zrb/runner/web_controller/task_ui/controller.py +11 -18
  49. zrb/session_state_logger/file_session_state_logger.py +4 -7
  50. zrb/task/cmd_task.py +1 -1
  51. zrb/task/llm_task.py +3 -5
  52. zrb/task/scaffolder.py +13 -1
  53. zrb/util/codemod/{add_code_to_class.py → append_code_to_class.py} +1 -1
  54. zrb/util/codemod/{add_code_to_function.py → append_code_to_function.py} +3 -1
  55. zrb/util/codemod/{add_code_to_method.py → append_code_to_method.py} +1 -1
  56. zrb/util/codemod/{add_key_to_dict.py → append_key_to_dict.py} +1 -1
  57. zrb/util/codemod/{add_param_to_function_call.py → append_param_to_function_call.py} +1 -1
  58. zrb/util/codemod/{add_code_to_module.py → prepend_code_to_module.py} +1 -1
  59. zrb/util/codemod/{add_parent_to_class.py → prepend_parent_to_class.py} +1 -1
  60. zrb/util/codemod/{add_property_to_class.py → prepend_property_to_class.py} +1 -1
  61. zrb/util/file.py +18 -0
  62. zrb/util/git_subtree.py +3 -4
  63. zrb/util/todo.py +5 -7
  64. {zrb-1.0.0a15.dist-info → zrb-1.0.0a17.dist-info}/METADATA +2 -2
  65. zrb-1.0.0a17.dist-info/RECORD +234 -0
  66. zrb/builtin/project/add/fastapp.py +0 -87
  67. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/any_client.py +0 -27
  68. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/api_client.py +0 -6
  69. zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/route.py +0 -19
  70. zrb/builtin/project/add/fastapp_template/module/auth/client/direct_client.py +0 -6
  71. zrb/builtin/project/add/fastapp_template/module/auth/migration/versions/3093c7336477_add_user_table.py +0 -37
  72. zrb/builtin/project/add/fastapp_template/module/auth/route.py +0 -22
  73. zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/user_repository.py +0 -34
  74. zrb/builtin/project/add/fastapp_template/module/gateway/route.py +0 -27
  75. zrb-1.0.0a15.dist-info/RECORD +0 -231
  76. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/.gitignore +0 -0
  77. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/README.md +0 -0
  78. /zrb/builtin/project/add/{__init__.py → fastapp/fastapp_template/__init__.py} +0 -0
  79. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/column/create_column_task.py +0 -0
  80. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/config.py +0 -0
  81. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/entity/module_template/service/my_entity/repository/factory.py +0 -0
  82. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/group.py +0 -0
  83. /zrb/builtin/project/add/{fastapp_template/_zrb/module → fastapp/fastapp_template/_zrb/module/template}/module_template/alembic.ini +0 -0
  84. /zrb/builtin/project/add/{fastapp_template/_zrb/module → fastapp/fastapp_template/_zrb/module/template}/module_template/migration/README +0 -0
  85. /zrb/builtin/project/add/{fastapp_template/_zrb/module → fastapp/fastapp_template/_zrb/module/template}/module_template/migration/env.py +0 -0
  86. /zrb/builtin/project/add/{fastapp_template/_zrb/module → fastapp/fastapp_template/_zrb/module/template}/module_template/migration/script.py.mako +0 -0
  87. /zrb/builtin/project/add/{fastapp_template/module/gateway → fastapp/fastapp_template/_zrb/module/template/module_template}/migration/versions/.gitkeep +0 -0
  88. /zrb/builtin/project/add/{fastapp_template/_zrb/module → fastapp/fastapp_template/_zrb/module/template}/module_template/migration_metadata.py +0 -0
  89. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template/_zrb/module/template/module_template/service}/__init__.py +0 -0
  90. /zrb/builtin/project/add/{fastapp_template/_zrb/module/run_module.template.py → fastapp/fastapp_template/_zrb/module/template/task_definition.py} +0 -0
  91. /zrb/builtin/project/add/{fastapp_template/_zrb/helper.py → fastapp/fastapp_template/_zrb/util.py} +0 -0
  92. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/_zrb/venv_task.py +0 -0
  93. /zrb/builtin/project/add/{fastapp_template/_zrb/module/module_template/service → fastapp/fastapp_template/common}/__init__.py +0 -0
  94. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/common/app.py +0 -0
  95. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/common/base_db_repository.py +0 -0
  96. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/common/db_engine.py +0 -0
  97. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/common/error.py +0 -0
  98. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/common/schema.py +0 -0
  99. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/main.py +0 -0
  100. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/migrate.py +0 -0
  101. /zrb/builtin/project/add/{fastapp_template/common → fastapp/fastapp_template/module}/__init__.py +0 -0
  102. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/alembic.ini +0 -0
  103. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/migration/README +0 -0
  104. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/migration/env.py +0 -0
  105. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/migration/script.py.mako +0 -0
  106. /zrb/builtin/project/add/{fastapp_template/_zrb/module/module_template → fastapp/fastapp_template/module/auth}/migration/versions/3093c7336477_add_user_table.py +0 -0
  107. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/migration_metadata.py +0 -0
  108. /zrb/builtin/project/add/{fastapp_template/module → fastapp/fastapp_template/module/auth/service}/__init__.py +0 -0
  109. /zrb/builtin/project/add/{fastapp_template/module/auth/service → fastapp/fastapp_template/module/auth/service/user}/__init__.py +0 -0
  110. /zrb/builtin/project/add/{fastapp_template/module/auth/service/user → fastapp/fastapp_template/module/auth/service/user/repository}/__init__.py +0 -0
  111. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/auth/service/user/repository/factory.py +0 -0
  112. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/gateway/alembic.ini +0 -0
  113. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/gateway/migration/README +0 -0
  114. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/gateway/migration/env.py +0 -0
  115. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/gateway/migration/script.py.mako +0 -0
  116. /zrb/builtin/project/add/{fastapp_template/module/auth/service/user/repository/__init__.py → fastapp/fastapp_template/module/gateway/migration/versions/.gitkeep} +0 -0
  117. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/module/gateway/migration_metadata.py +0 -0
  118. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/schema/__init__.py +0 -0
  119. /zrb/builtin/project/add/{fastapp_template → fastapp/fastapp_template}/template.env +0 -0
  120. {zrb-1.0.0a15.dist-info → zrb-1.0.0a17.dist-info}/WHEEL +0 -0
  121. {zrb-1.0.0a15.dist-info → zrb-1.0.0a17.dist-info}/entry_points.txt +0 -0
zrb/__main__.py CHANGED
@@ -14,6 +14,9 @@ def serve_cli():
14
14
  for init_script in INIT_SCRIPTS:
15
15
  load_file(init_script, -1)
16
16
  cli.run(sys.argv[1:])
17
+ except RuntimeError as e:
18
+ if "Event loop is closed" not in f"{e}":
19
+ raise e
17
20
  except KeyboardInterrupt:
18
21
  print(stylize_warning("\nStopped"), file=sys.stderr)
19
22
  except NodeNotFoundError as e:
zrb/builtin/__init__.py CHANGED
@@ -9,8 +9,8 @@ from zrb.builtin.git import (
9
9
  from zrb.builtin.git_subtree import git_add_subtree, git_pull_subtree, git_push_subtree
10
10
  from zrb.builtin.llm.llm_chat import llm_chat
11
11
  from zrb.builtin.md5 import hash_md5, sum_md5
12
- from zrb.builtin.project.add.fastapp import add_fastapp_to_project
13
- from zrb.builtin.project.create.create import create_project
12
+ from zrb.builtin.project.add.fastapp.fastapp_task import add_fastapp_to_project
13
+ from zrb.builtin.project.create.project_task import create_project
14
14
  from zrb.builtin.python import format_python_code
15
15
  from zrb.builtin.setup.asdf.asdf import setup_asdf
16
16
  from zrb.builtin.setup.latex.ubuntu import setup_latex_on_ubuntu
zrb/builtin/git.py CHANGED
@@ -3,7 +3,7 @@ from zrb.context.any_context import AnyContext
3
3
  from zrb.input.bool_input import BoolInput
4
4
  from zrb.input.str_input import StrInput
5
5
  from zrb.task.make_task import make_task
6
- from zrb.util.cli.style import stylize_green, stylize_red, stylize_yellow
6
+ from zrb.util.cli.style import stylize_faint, stylize_green, stylize_red, stylize_yellow
7
7
  from zrb.util.git import (
8
8
  add,
9
9
  commit,
@@ -56,6 +56,7 @@ from zrb.util.git import (
56
56
  alias="diff",
57
57
  )
58
58
  async def get_git_diff(ctx: AnyContext):
59
+ ctx.print(stylize_faint("Get directory"))
59
60
  repo_dir = await get_repo_dir(log_method=ctx.print)
60
61
  diff = await get_diff(
61
62
  repo_dir, ctx.input.source, ctx.input.current, log_method=ctx.print
@@ -86,13 +87,16 @@ async def get_git_diff(ctx: AnyContext):
86
87
  alias="prune",
87
88
  )
88
89
  async def prune_local_branches(ctx: AnyContext):
90
+ ctx.print(stylize_faint("Get directory"))
89
91
  repo_dir = await get_repo_dir(log_method=ctx.print)
92
+ ctx.print(stylize_faint("Get existing branches"))
90
93
  branches = await get_branches(repo_dir, log_method=ctx.print)
94
+ ctx.print(stylize_faint("Get current branch"))
91
95
  current_branch = await get_current_branch(repo_dir, log_method=ctx.print)
92
96
  for branch in branches:
93
97
  if branch == current_branch or branch == "main" or branch == "master":
94
98
  continue
95
- ctx.print(stylize_yellow(f"Removing local branch: {branch}"))
99
+ ctx.print(stylize_faint(f"Removing local branch: {branch}"))
96
100
  try:
97
101
  await delete_branch(repo_dir, branch, log_method=ctx.print)
98
102
  except Exception as e:
@@ -112,10 +116,11 @@ async def prune_local_branches(ctx: AnyContext):
112
116
  alias="commit",
113
117
  )
114
118
  async def git_commit(ctx: AnyContext):
119
+ ctx.print(stylize_faint("Get directory"))
115
120
  repo_dir = await get_repo_dir(log_method=ctx.print)
116
- ctx.print("Add changes to staging")
121
+ ctx.print(stylize_faint("Add changes to staging"))
117
122
  await add(repo_dir, log_method=ctx.print)
118
- ctx.print("Commit changes")
123
+ ctx.print(stylize_faint("Commit changes"))
119
124
  await commit(repo_dir, ctx.input.message, log_method=ctx.print)
120
125
 
121
126
 
@@ -133,10 +138,12 @@ async def git_commit(ctx: AnyContext):
133
138
  alias="pull",
134
139
  )
135
140
  async def git_pull(ctx: AnyContext):
141
+ ctx.print(stylize_faint("Get directory"))
136
142
  repo_dir = await get_repo_dir(log_method=ctx.print)
137
- remote = ctx.input.remote
143
+ ctx.print(stylize_faint("Get current branch"))
138
144
  current_branch = await get_current_branch(repo_dir, log_method=ctx.print)
139
- ctx.print(f"Pulling from {remote}/{current_branch}")
145
+ remote = ctx.input.remote
146
+ ctx.print(stylize_faint(f"Pulling from {remote}/{current_branch}"))
140
147
  await pull(repo_dir, remote, current_branch, log_method=ctx.print)
141
148
 
142
149
 
@@ -155,7 +162,8 @@ async def git_pull(ctx: AnyContext):
155
162
  )
156
163
  async def git_push(ctx: AnyContext):
157
164
  repo_dir = await get_repo_dir(log_method=ctx.print)
158
- remote = ctx.input.remote
165
+ ctx.print(stylize_faint("Get current branch"))
159
166
  current_branch = await get_current_branch(repo_dir, log_method=ctx.print)
160
- ctx.print(f"Pushing to {remote}/{current_branch}")
167
+ remote = ctx.input.remote
168
+ ctx.print(stylize_faint(f"Pushing to {remote}/{current_branch}"))
161
169
  await push(repo_dir, remote, current_branch, log_method=ctx.print)
@@ -3,6 +3,7 @@ from zrb.builtin.group import git_subtree_group
3
3
  from zrb.context.any_context import AnyContext
4
4
  from zrb.input.str_input import StrInput
5
5
  from zrb.task.make_task import make_task
6
+ from zrb.util.cli.style import stylize_faint
6
7
  from zrb.util.git import get_repo_dir
7
8
  from zrb.util.git_subtree import add_subtree, load_config, pull_subtree, push_subtree
8
9
 
@@ -33,7 +34,9 @@ from zrb.util.git_subtree import add_subtree, load_config, pull_subtree, push_su
33
34
  alias="add",
34
35
  )
35
36
  async def git_add_subtree(ctx: AnyContext):
37
+ ctx.print(stylize_faint("Get directory"))
36
38
  repo_dir = await get_repo_dir(log_method=ctx.print)
39
+ ctx.print(stylize_faint("Add subtree"))
37
40
  await add_subtree(
38
41
  repo_dir=repo_dir,
39
42
  name=ctx.input.name,
@@ -52,6 +55,7 @@ async def git_add_subtree(ctx: AnyContext):
52
55
  alias="pull",
53
56
  )
54
57
  async def git_pull_subtree(ctx: AnyContext):
58
+ ctx.print(stylize_faint("Get directory"))
55
59
  repo_dir = await get_repo_dir(log_method=ctx.print)
56
60
  config = load_config(repo_dir)
57
61
  if not config.data:
@@ -59,7 +63,7 @@ async def git_pull_subtree(ctx: AnyContext):
59
63
  first_err: Exception | None = None
60
64
  for name, detail in config.data.items():
61
65
  try:
62
- ctx.print(f"Pull from subtree {name}")
66
+ ctx.print(stylize_faint(f"Pull from subtree {name}"))
63
67
  await pull_subtree(
64
68
  repo_dir=repo_dir,
65
69
  prefix=detail.prefix,
@@ -83,6 +87,7 @@ async def git_pull_subtree(ctx: AnyContext):
83
87
  alias="push",
84
88
  )
85
89
  async def git_push_subtree(ctx: AnyContext):
90
+ ctx.print(stylize_faint("Get directory"))
86
91
  repo_dir = await get_repo_dir(log_method=ctx.print)
87
92
  config = load_config(repo_dir)
88
93
  if not config.data:
@@ -90,7 +95,7 @@ async def git_push_subtree(ctx: AnyContext):
90
95
  first_err: Exception | None = None
91
96
  for name, detail in config.data.items():
92
97
  try:
93
- ctx.print(f"Push to subtree {name}")
98
+ ctx.print(stylize_faint(f"Push to subtree {name}"))
94
99
  await push_subtree(
95
100
  repo_dir=repo_dir,
96
101
  prefix=detail.prefix,
@@ -12,6 +12,7 @@ from zrb.config import (
12
12
  RAG_OVERLAP,
13
13
  )
14
14
  from zrb.util.cli.style import stylize_error, stylize_faint
15
+ from zrb.util.file import read_file
15
16
  from zrb.util.run import run_async
16
17
 
17
18
  Document = str | Callable[[], str]
@@ -137,8 +138,7 @@ def get_rag_documents(document_dir_path: str) -> Callable[[], list[Callable[[],
137
138
  def _get_text_reader(file_path: str):
138
139
  def read():
139
140
  print(stylize_faint(f"Start reading {file_path}"), file=sys.stderr)
140
- with open(file_path, "r", encoding="utf-8") as f:
141
- content = f.read()
141
+ content = read_file(file_path)
142
142
  print(stylize_faint(f"Complete reading {file_path}"), file=sys.stderr)
143
143
  return content
144
144
 
@@ -0,0 +1,16 @@
1
+ import os
2
+
3
+ from zrb.input.str_input import StrInput
4
+
5
+ project_dir_input = StrInput(
6
+ name="project-dir",
7
+ description="Project directory",
8
+ prompt="Project directory",
9
+ default_str=lambda _: os.getcwd(),
10
+ )
11
+
12
+ app_name_input = StrInput(
13
+ name="app",
14
+ description="App name",
15
+ prompt="App name",
16
+ )
@@ -0,0 +1,92 @@
1
+ import os
2
+
3
+ from zrb.builtin.group import add_to_project_group
4
+ from zrb.builtin.project.add.fastapp.fastapp_input import (
5
+ app_name_input,
6
+ project_dir_input,
7
+ )
8
+ from zrb.builtin.project.add.fastapp.fastapp_util import (
9
+ get_zrb_init_import_code,
10
+ get_zrb_init_load_app_name_task,
11
+ )
12
+ from zrb.context.any_context import AnyContext
13
+ from zrb.task.make_task import make_task
14
+ from zrb.task.scaffolder import Scaffolder
15
+ from zrb.task.task import Task
16
+ from zrb.util.file import read_file, write_file
17
+ from zrb.util.string.conversion import to_snake_case
18
+ from zrb.util.string.name import get_random_name
19
+
20
+ _DIR = os.path.dirname(__file__)
21
+
22
+
23
+ @make_task(
24
+ name="validate-create-fastapp",
25
+ input=[project_dir_input, app_name_input],
26
+ retries=0,
27
+ )
28
+ async def validate_create_fastapp(ctx: AnyContext):
29
+ project_dir = ctx.input.project_dir
30
+ if not os.path.isdir(project_dir):
31
+ raise ValueError(f"Project directory not exists: {project_dir}")
32
+ app_dir = os.path.join(project_dir, to_snake_case(ctx.input.app))
33
+ if os.path.exists(app_dir):
34
+ raise ValueError(f"Application directory already exists: {app_dir}")
35
+
36
+
37
+ scaffold_fastapp = Scaffolder(
38
+ name="scaffold-fastapp",
39
+ input=[
40
+ project_dir_input,
41
+ app_name_input,
42
+ ],
43
+ upstream=validate_create_fastapp,
44
+ source_path=os.path.join(_DIR, "fastapp_template"),
45
+ render_source_path=False,
46
+ destination_path=lambda ctx: os.path.join(
47
+ ctx.input.project_dir, to_snake_case(ctx.input.app)
48
+ ),
49
+ transform_content={
50
+ "fastapp_template": "{to_snake_case(ctx.input.app)}",
51
+ "My App Name": "{ctx.input.app.title()}",
52
+ "my-app-name": "{to_kebab_case(ctx.input.app)}",
53
+ "my_app_name": "{to_snake_case(ctx.input.app)}",
54
+ "MY_APP_NAME": "{to_snake_case(ctx.input.app).upper()}",
55
+ "my-secure-password": lambda _: get_random_name(),
56
+ },
57
+ retries=0,
58
+ )
59
+
60
+
61
+ @make_task(
62
+ name="update-fastapp-zrb-init",
63
+ input=[
64
+ project_dir_input,
65
+ app_name_input,
66
+ ],
67
+ upstream=scaffold_fastapp,
68
+ retries=0,
69
+ )
70
+ def update_fastapp_zrb_init(ctx: AnyContext):
71
+ zrb_init_path = os.path.join(ctx.input.project_dir, "zrb_init.py")
72
+ old_zrb_init_code = read_file(zrb_init_path)
73
+ write_file(
74
+ file_path=zrb_init_path,
75
+ content=[
76
+ get_zrb_init_import_code(old_zrb_init_code),
77
+ old_zrb_init_code.strip(),
78
+ get_zrb_init_load_app_name_task(ctx.input.app),
79
+ "",
80
+ ],
81
+ )
82
+
83
+
84
+ add_fastapp_to_project = add_to_project_group.add_task(
85
+ Task(
86
+ name="add-fastapp",
87
+ description="🚀 Add FastApp to project",
88
+ upstream=update_fastapp_zrb_init,
89
+ retries=0,
90
+ ),
91
+ alias="fastapp",
92
+ )
@@ -0,0 +1,27 @@
1
+ @abstractmethod
2
+ async def get_my_entity_by_id(self, my_entity_id: str) -> MyEntityResponse:
3
+ pass
4
+
5
+
6
+ @abstractmethod
7
+ async def get_all_my_entitys(self) -> list[MyEntityResponse]:
8
+ pass
9
+
10
+
11
+ @abstractmethod
12
+ async def create_my_entity(
13
+ self, data: MyEntityCreateWithAudit | list[MyEntityCreateWithAudit]
14
+ ) -> MyEntityResponse | list[MyEntityResponse]:
15
+ pass
16
+
17
+
18
+ @abstractmethod
19
+ async def update_my_entity(
20
+ self, my_entity_id: str, data: MyEntityUpdateWithAudit
21
+ ) -> MyEntityResponse:
22
+ pass
23
+
24
+
25
+ @abstractmethod
26
+ async def delete_my_entity(self, my_entity_id: str) -> MyEntityResponse:
27
+ pass
@@ -2,13 +2,13 @@ from fastapp_template.common.base_usecase import BaseUsecase
2
2
  from fastapp_template.module.my_module.service.my_entity.repository.factory import (
3
3
  my_entity_repository,
4
4
  )
5
- from fastapp_template.module.my_module.service.my_entity.repository.repository import (
5
+ from fastapp_template.module.my_module.service.my_entity.repository.my_entity_repository import (
6
6
  MyEntityRepository,
7
7
  )
8
8
  from fastapp_template.schema.my_entity import (
9
- MyEntityCreate,
9
+ MyEntityCreateWithAudit,
10
10
  MyEntityResponse,
11
- MyEntityUpdate,
11
+ MyEntityUpdateWithAudit,
12
12
  )
13
13
 
14
14
 
@@ -38,9 +38,9 @@ class MyEntityUsecase(BaseUsecase):
38
38
  response_model=MyEntityResponse | list[MyEntityResponse],
39
39
  )
40
40
  async def create_my_entity(
41
- self, data: MyEntityCreate | list[MyEntityCreate]
41
+ self, data: MyEntityCreateWithAudit | list[MyEntityCreateWithAudit]
42
42
  ) -> MyEntityResponse | list[MyEntityResponse]:
43
- if isinstance(data, MyEntityCreate):
43
+ if isinstance(data, MyEntityCreateWithAudit):
44
44
  return await self.my_entity_repository.create(data)
45
45
  return await self.my_entity_repository.create_bulk(data)
46
46
 
@@ -50,7 +50,7 @@ class MyEntityUsecase(BaseUsecase):
50
50
  response_model=MyEntityResponse,
51
51
  )
52
52
  async def update_my_entity(
53
- self, my_entity_id: str, data: MyEntityUpdate
53
+ self, my_entity_id: str, data: MyEntityUpdateWithAudit
54
54
  ) -> MyEntityResponse:
55
55
  return await self.my_entity_repository.update(my_entity_id, data)
56
56
 
@@ -5,9 +5,9 @@ from fastapp_template.module.my_module.service.my_entity.repository.my_entity_re
5
5
  )
6
6
  from fastapp_template.schema.my_entity import (
7
7
  MyEntity,
8
- MyEntityCreate,
8
+ MyEntityCreateWithAudit,
9
9
  MyEntityResponse,
10
- MyEntityUpdate,
10
+ MyEntityUpdateWithAudit,
11
11
  )
12
12
  from passlib.context import CryptContext
13
13
  from sqlalchemy.ext.asyncio import AsyncSession
@@ -22,12 +22,17 @@ def hash_password(password: str) -> str:
22
22
 
23
23
 
24
24
  class MyEntityDBRepository(
25
- BaseDBRepository[MyEntity, MyEntityResponse, MyEntityCreate, MyEntityUpdate],
25
+ BaseDBRepository[
26
+ MyEntity,
27
+ MyEntityResponse,
28
+ MyEntityCreateWithAudit,
29
+ MyEntityUpdateWithAudit,
30
+ ],
26
31
  MyEntityRepository,
27
32
  ):
28
33
  db_model = MyEntity
29
34
  response_model = MyEntityResponse
30
- create_model = MyEntityCreate
31
- update_model = MyEntityUpdate
35
+ create_model = MyEntityCreateWithAudit
36
+ update_model = MyEntityUpdateWithAudit
32
37
  entity_name = "my_entity"
33
38
  column_preprocessors = {}
@@ -2,16 +2,16 @@ from abc import ABC, abstractmethod
2
2
 
3
3
  from fastapp_template.schema.my_entity import (
4
4
  MyEntity,
5
- MyEntityCreate,
5
+ MyEntityCreateWithAudit,
6
6
  MyEntityResponse,
7
- MyEntityUpdate,
7
+ MyEntityUpdateWithAudit,
8
8
  )
9
9
 
10
10
 
11
11
  class MyEntityRepository(ABC):
12
12
 
13
13
  @abstractmethod
14
- async def create(self, my_entity_data: MyEntityCreate) -> MyEntityResponse:
14
+ async def create(self, my_entity_data: MyEntityCreateWithAudit) -> MyEntityResponse:
15
15
  pass
16
16
 
17
17
  @abstractmethod
@@ -24,7 +24,7 @@ class MyEntityRepository(ABC):
24
24
 
25
25
  @abstractmethod
26
26
  async def update(
27
- self, my_entity_id: str, my_entity_data: MyEntityUpdate
27
+ self, my_entity_id: str, my_entity_data: MyEntityUpdateWithAudit
28
28
  ) -> MyEntity:
29
29
  pass
30
30
 
@@ -34,6 +34,6 @@ class MyEntityRepository(ABC):
34
34
 
35
35
  @abstractmethod
36
36
  async def create_bulk(
37
- self, my_entity_data_list: list[MyEntityCreate]
37
+ self, my_entity_data_list: list[MyEntityCreateWithAudit]
38
38
  ) -> list[MyEntityResponse]:
39
39
  pass
@@ -12,10 +12,18 @@ class MyEntityCreate(MyEntityBase):
12
12
  pass
13
13
 
14
14
 
15
+ class MyEntityCreateWithAudit(MyEntityCreate):
16
+ created_by: str
17
+
18
+
15
19
  class MyEntityUpdate(SQLModel):
16
20
  my_column: str | None = None
17
21
 
18
22
 
23
+ class MyEntityUpdateWithAudit(MyEntityUpdate):
24
+ updated_by: str
25
+
26
+
19
27
  class MyEntityResponse(MyEntityBase):
20
28
  id: str
21
29
 
@@ -2,20 +2,23 @@ import os
2
2
 
3
3
  from fastapp_template._zrb.config import APP_DIR
4
4
  from fastapp_template._zrb.group import app_create_group
5
- from fastapp_template._zrb.helper import (
6
- get_existing_module_names,
7
- get_existing_schema_names,
8
- )
9
5
  from fastapp_template._zrb.input import (
10
6
  existing_module_input,
11
7
  new_entity_column_input,
12
8
  new_entity_input,
13
9
  plural_entity_input,
14
10
  )
11
+ from fastapp_template._zrb.util import (
12
+ get_existing_module_names,
13
+ get_existing_schema_names,
14
+ )
15
15
 
16
16
  from zrb import AnyContext, Scaffolder, Task, make_task
17
- from zrb.util.codemod.add_code_to_module import add_code_to_module
18
- from zrb.util.codemod.add_parent_to_class import add_parent_to_class
17
+ from zrb.util.codemod.append_code_to_class import append_code_to_class
18
+ from zrb.util.codemod.append_code_to_function import append_code_to_function
19
+ from zrb.util.codemod.prepend_code_to_module import prepend_code_to_module
20
+ from zrb.util.codemod.prepend_parent_to_class import prepend_parent_class
21
+ from zrb.util.file import read_file, write_file
19
22
  from zrb.util.string.conversion import to_pascal_case, to_snake_case
20
23
 
21
24
 
@@ -81,6 +84,9 @@ scaffold_my_app_name_module_entity = Scaffolder(
81
84
  "my_entities": "{to_snake_case(ctx.input.plural)}",
82
85
  "my-entities": "{to_kebab_case(ctx.input.plural)}",
83
86
  },
87
+ transform_path={
88
+ "my_entity": "{to_snake_case(ctx.input.entity)}",
89
+ },
84
90
  retries=0,
85
91
  upstream=validate_create_my_app_name_entity,
86
92
  )
@@ -97,21 +103,19 @@ async def register_my_app_name_migration(ctx: AnyContext):
97
103
  APP_DIR, "module", to_snake_case(ctx.input.module), "migration_metadata.py"
98
104
  )
99
105
  app_name = os.path.basename(APP_DIR)
100
- with open(migration_metadata_file_path, "r") as f:
101
- file_content = f.read()
102
- entity_name = to_snake_case(ctx.input.entity)
103
- entity_class = to_pascal_case(ctx.input.entity)
106
+ file_content = read_file(migration_metadata_file_path)
107
+ snake_entity_name = to_snake_case(ctx.input.entity)
108
+ pascal_entity_name = to_pascal_case(ctx.input.entity)
104
109
  new_file_content_list = (
105
- [f"from {app_name}.schema.{entity_name} import {entity_class}"]
110
+ [f"from {app_name}.schema.{snake_entity_name} import {pascal_entity_name}"]
106
111
  + file_content.strip()
107
112
  + [
108
- f"{entity_class}.metadata = metadata",
109
- f"{entity_class}.__table__.tometadata(metadata)",
113
+ f"{pascal_entity_name}.metadata = metadata",
114
+ f"{pascal_entity_name}.__table__.tometadata(metadata)",
110
115
  "",
111
116
  ]
112
117
  )
113
- with open(migration_metadata_file_path, "w") as f:
114
- f.write("\n".join(new_file_content_list))
118
+ write_file(migration_metadata_file_path, "\n".join(new_file_content_list))
115
119
 
116
120
 
117
121
  @make_task(
@@ -124,28 +128,28 @@ async def register_my_app_name_api_client(ctx: AnyContext):
124
128
  api_client_file_path = os.path.join(
125
129
  APP_DIR, "module", to_snake_case(ctx.input.module), "client", "api_client.py"
126
130
  )
127
- with open(api_client_file_path, "r") as f:
128
- file_content = f.read()
129
- module_config_name = to_snake_case(ctx.input.module).upper()
130
- new_code = add_code_to_module(
131
+ file_content = read_file(api_client_file_path)
132
+ upper_snake_module_name = to_snake_case(ctx.input.module).upper()
133
+ new_code = prepend_code_to_module(
131
134
  file_content,
132
- f"user_api_client = user_usecase.as_api_client(base_url=APP_{module_config_name}_BASE_URL)", # noqa
135
+ f"user_api_client = user_usecase.as_api_client(base_url=APP_{upper_snake_module_name}_BASE_URL)", # noqa
133
136
  )
134
- new_code = add_parent_to_class(
137
+ new_code = prepend_parent_class(
135
138
  original_code=new_code,
136
139
  class_name="APIClient",
137
140
  parent_class_name="user_api_client",
138
141
  )
139
142
  app_name = os.path.basename(APP_DIR)
140
- entity_name = to_snake_case(ctx.input.entity)
141
- module_name = to_snake_case(ctx.input.module)
142
- new_file_content_list = [
143
- f"from {app_name}.module.{module_name}.service.{entity_name} import {entity_name}_usecase", # noqa
144
- new_code.strip(),
145
- "",
146
- ]
147
- with open(api_client_file_path, "w") as f:
148
- f.write("\n".join(new_file_content_list))
143
+ snake_entity_name = to_snake_case(ctx.input.entity)
144
+ snake_module_name = to_snake_case(ctx.input.module)
145
+ write_file(
146
+ api_client_file_path,
147
+ [
148
+ f"from {app_name}.module.{snake_module_name}.service.{snake_entity_name}.{snake_entity_name}_usecase import {snake_entity_name}_usecase", # noqa
149
+ new_code.strip(),
150
+ "",
151
+ ],
152
+ )
149
153
 
150
154
 
151
155
  @make_task(
@@ -158,26 +162,85 @@ async def register_my_app_name_direct_client(ctx: AnyContext):
158
162
  direct_client_file_path = os.path.join(
159
163
  APP_DIR, "module", to_snake_case(ctx.input.module), "client", "direct_client.py"
160
164
  )
161
- with open(direct_client_file_path, "r") as f:
162
- file_content = f.read()
163
- new_code = add_code_to_module(
164
- file_content, "user_direct_client = user_usecase.as_direct_client()"
165
+ file_content = read_file(direct_client_file_path)
166
+ app_name = os.path.basename(APP_DIR)
167
+ snake_entity_name = to_snake_case(ctx.input.entity)
168
+ snake_module_name = to_snake_case(ctx.input.module)
169
+ write_file(
170
+ direct_client_file_path,
171
+ [
172
+ f"from {app_name}.module.{snake_module_name}.service.{snake_entity_name}.{snake_entity_name}_usecase import {snake_entity_name}_usecase", # noqa
173
+ prepend_code_to_module(
174
+ prepend_parent_class(
175
+ file_content, "DirectClient", "user_direct_client"
176
+ ),
177
+ "user_direct_client = user_usecase.as_direct_client()",
178
+ ).strip(),
179
+ "",
180
+ ],
165
181
  )
166
- new_code = add_parent_to_class(
167
- original_code=new_code,
168
- class_name="DirectClient",
169
- parent_class_name="user_direct_client",
182
+
183
+
184
+ @make_task(
185
+ name="register-my-app-name-route",
186
+ input=[existing_module_input, new_entity_input],
187
+ retries=0,
188
+ upstream=validate_create_my_app_name_entity,
189
+ )
190
+ async def register_my_app_name_route(ctx: AnyContext):
191
+ direct_client_file_path = os.path.join(
192
+ APP_DIR, "module", to_snake_case(ctx.input.module), "route.py"
170
193
  )
171
- app_name = os.path.basename(APP_DIR)
194
+ file_content = read_file(direct_client_file_path)
172
195
  entity_name = to_snake_case(ctx.input.entity)
196
+ new_code = append_code_to_function(
197
+ file_content, "serve_route", f"{entity_name}_usecase.serve_route(app)"
198
+ )
199
+ app_name = os.path.basename(APP_DIR)
173
200
  module_name = to_snake_case(ctx.input.module)
174
201
  new_file_content_list = [
175
- f"from {app_name}.module.{module_name}.service.{entity_name} import {entity_name}_usecase", # noqa
202
+ f"from {app_name}.module.{module_name}.service.{entity_name}.{entity_name}_usecase import {entity_name}_usecase", # noqa
176
203
  new_code.strip(),
177
204
  "",
178
205
  ]
179
- with open(direct_client_file_path, "w") as f:
180
- f.write("\n".join(new_file_content_list))
206
+ write_file(direct_client_file_path, "\n".join(new_file_content_list))
207
+
208
+
209
+ @make_task(
210
+ name="register-my-app-name-client-method",
211
+ input=[existing_module_input, new_entity_input],
212
+ retries=0,
213
+ upstream=validate_create_my_app_name_entity,
214
+ )
215
+ async def register_my_app_name_client_method(ctx: AnyContext):
216
+ any_client_file_path = os.path.join(
217
+ APP_DIR, "module", to_snake_case(ctx.input.module), "route.py"
218
+ )
219
+ file_content = read_file(any_client_file_path)
220
+ app_name = os.path.basename(APP_DIR)
221
+ snake_entity_name = to_snake_case(ctx.input.entity)
222
+ pascal_entity_name = to_pascal_case(ctx.input.entity)
223
+ # TODO: Register client methods
224
+ # get methods
225
+ any_client_method_template_path = (
226
+ os.path.join(os.path.dirname(__file__), "any_client_method.template.py"),
227
+ )
228
+ any_client_method_template = read_file(any_client_method_template_path)
229
+ any_client_method = any_client_method_template.replace(
230
+ "my_entity", snake_entity_name
231
+ ).replace("MyEntity", pascal_entity_name)
232
+ new_code = append_code_to_class(file_content, "AnyClient", any_client_method)
233
+ new_file_content_list = [
234
+ f"from {app_name}.schema.{snake_entity_name}.{snake_entity_name} import (",
235
+ f" {pascal_entity_name}CreateWithAudit, {pascal_entity_name}Response, {pascal_entity_name}UpdateWithAudit",
236
+ ")",
237
+ new_code.strip(),
238
+ "",
239
+ ]
240
+ write_file(any_client_file_path, "\n".join(new_file_content_list))
241
+
242
+
243
+ # TODO: Register gateway route
181
244
 
182
245
 
183
246
  create_my_app_name_entity = app_create_group.add_task(
@@ -193,4 +256,5 @@ create_my_app_name_entity << [
193
256
  scaffold_my_app_name_module_entity,
194
257
  register_my_app_name_api_client,
195
258
  register_my_app_name_direct_client,
259
+ register_my_app_name_route,
196
260
  ]
@@ -1,4 +1,4 @@
1
- from fastapp_template._zrb.helper import (
1
+ from fastapp_template._zrb.util import (
2
2
  get_existing_module_names,
3
3
  get_existing_schema_names,
4
4
  )