zrb 1.0.0b1__py3-none-any.whl → 1.0.0b2__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 (90) hide show
  1. zrb/__main__.py +0 -3
  2. zrb/builtin/__init__.py +3 -0
  3. zrb/builtin/group.py +1 -0
  4. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +1 -1
  5. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +66 -21
  6. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +67 -41
  7. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service.py +69 -15
  8. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service_factory.py +2 -1
  9. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_db_repository.py +0 -10
  10. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_repository.py +37 -16
  11. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_repository_factory.py +2 -2
  12. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/schema/my_entity.py +16 -6
  13. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/client_method.py +57 -0
  14. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +63 -28
  15. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +1 -0
  16. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_api_client.py +6 -0
  17. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/{any_client.py → my_module_client.py} +1 -1
  18. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_client_factory.py +11 -0
  19. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_direct_client.py +5 -0
  20. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/route.py +1 -1
  21. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +2 -2
  22. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +4 -4
  23. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/util.py +47 -20
  24. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app_factory.py +29 -0
  25. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_db_repository.py +185 -101
  26. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +99 -108
  27. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/{db_engine.py → db_engine_factory.py} +1 -1
  28. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/error.py +12 -0
  29. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/logger_factory.py +10 -0
  30. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/parser_factory.py +7 -0
  31. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/app.py +47 -0
  32. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +105 -0
  33. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/user_agent.py +58 -0
  34. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +1 -1
  35. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/main.py +1 -1
  36. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_api_client.py +16 -0
  37. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client.py +163 -0
  38. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client_factory.py +9 -0
  39. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_direct_client.py +15 -0
  40. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +160 -0
  41. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration_metadata.py +18 -1
  42. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/route.py +5 -1
  43. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/__init__.py +0 -0
  44. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service.py +117 -0
  45. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service_factory.py +11 -0
  46. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_db_repository.py +26 -0
  47. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository.py +61 -0
  48. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository_factory.py +13 -0
  49. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/__init__.py +0 -0
  50. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_db_repository.py +75 -0
  51. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository.py +59 -0
  52. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository_factory.py +13 -0
  53. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service.py +105 -0
  54. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service_factory.py +7 -0
  55. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +42 -13
  56. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository.py +38 -17
  57. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository_factory.py +2 -2
  58. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +69 -17
  59. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service_factory.py +2 -1
  60. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +1 -1
  61. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +198 -28
  62. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +1 -1
  63. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +1 -1
  64. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +17 -5
  65. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/role.py +50 -4
  66. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/session.py +52 -0
  67. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +30 -5
  68. zrb/builtin/random.py +61 -0
  69. zrb/cmd/cmd_val.py +6 -5
  70. zrb/runner/cli.py +10 -1
  71. zrb/runner/web_util/token.py +7 -3
  72. zrb/task/base_task.py +24 -2
  73. zrb/task/cmd_task.py +7 -5
  74. zrb/util/cmd/command.py +1 -0
  75. zrb/util/file.py +7 -1
  76. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/METADATA +1 -1
  77. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/RECORD +80 -61
  78. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/any_client_method.py +0 -27
  79. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/api_client.py +0 -6
  80. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/direct_client.py +0 -5
  81. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/factory.py +0 -9
  82. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app.py +0 -57
  83. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/any_client.py +0 -33
  84. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/api_client.py +0 -7
  85. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/direct_client.py +0 -6
  86. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/factory.py +0 -9
  87. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_user_table.py +0 -37
  88. /zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/{view.py → util/view.py} +0 -0
  89. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/WHEEL +0 -0
  90. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/entry_points.txt +0 -0
zrb/__main__.py CHANGED
@@ -14,9 +14,6 @@ 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
20
17
  except KeyboardInterrupt:
21
18
  print(stylize_warning("\nStopped"), file=sys.stderr)
22
19
  except NodeNotFoundError as e:
zrb/builtin/__init__.py CHANGED
@@ -12,6 +12,7 @@ from zrb.builtin.md5 import hash_md5, sum_md5
12
12
  from zrb.builtin.project.add.fastapp.fastapp_task import add_fastapp_to_project
13
13
  from zrb.builtin.project.create.project_task import create_project
14
14
  from zrb.builtin.python import format_python_code
15
+ from zrb.builtin.random import shuffle_values, throw_dice
15
16
  from zrb.builtin.setup.asdf.asdf import setup_asdf
16
17
  from zrb.builtin.setup.latex.ubuntu import setup_latex_on_ubuntu
17
18
  from zrb.builtin.setup.tmux.tmux import setup_tmux
@@ -55,6 +56,8 @@ assert edit_todo
55
56
  assert complete_todo
56
57
  assert log_todo
57
58
  assert show_todo
59
+ assert throw_dice
60
+ assert shuffle_values
58
61
  assert setup_ubuntu
59
62
  assert setup_latex_on_ubuntu
60
63
  assert setup_asdf
zrb/builtin/group.py CHANGED
@@ -2,6 +2,7 @@ from zrb.group.group import Group
2
2
  from zrb.runner.cli import cli
3
3
 
4
4
  base64_group = cli.add_group(Group(name="base64", description="📄 Base64 operations"))
5
+ random_group = cli.add_group(Group(name="random", description="🔀 Random operation"))
5
6
  git_group = cli.add_group(Group(name="git", description="🌱 Git related commands"))
6
7
  git_branch_group = git_group.add_group(
7
8
  Group(name="branch", description="🌿 Git branch related commands")
@@ -17,4 +17,4 @@ MONOLITH_ENV_VARS = {
17
17
  if platform.system() == "Windows":
18
18
  ACTIVATE_VENV_SCRIPT = "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser; . .venv\\Scripts\\Activate" # noqa
19
19
  else:
20
- ACTIVATE_VENV_SCRIPT = "source .venv/bin/activate"
20
+ ACTIVATE_VENV_SCRIPT = ". .venv/bin/activate"
@@ -1,21 +1,21 @@
1
1
  import os
2
2
 
3
- from my_app_name._zrb.config import APP_DIR
3
+ from my_app_name._zrb.config import ACTIVATE_VENV_SCRIPT, APP_DIR
4
4
  from my_app_name._zrb.entity.add_entity_util import (
5
5
  is_in_app_schema_dir,
6
6
  is_in_module_entity_dir,
7
- is_module_any_client_file,
8
7
  is_module_api_client_file,
8
+ is_module_client_file,
9
9
  is_module_direct_client_file,
10
10
  is_module_gateway_subroute_file,
11
11
  is_module_migration_metadata_file,
12
12
  is_module_route_file,
13
- update_any_client,
14
- update_api_client,
15
- update_direct_client,
16
- update_gateway_subroute,
17
- update_migration_metadata,
18
- update_route,
13
+ update_api_client_file,
14
+ update_client_file,
15
+ update_direct_client_file,
16
+ update_gateway_subroute_file,
17
+ update_migration_metadata_file,
18
+ update_route_file,
19
19
  )
20
20
  from my_app_name._zrb.format_task import format_my_app_name_code
21
21
  from my_app_name._zrb.group import app_create_group
@@ -25,9 +25,25 @@ from my_app_name._zrb.input import (
25
25
  new_entity_input,
26
26
  plural_entity_input,
27
27
  )
28
- from my_app_name._zrb.util import get_existing_module_names, get_existing_schema_names
28
+ from my_app_name._zrb.util import (
29
+ cd_module_script,
30
+ get_existing_module_names,
31
+ get_existing_schema_names,
32
+ set_create_migration_db_url_env,
33
+ set_env,
34
+ )
35
+ from my_app_name._zrb.venv_task import prepare_venv
29
36
 
30
- from zrb import AnyContext, ContentTransformer, Scaffolder, Task, make_task
37
+ from zrb import (
38
+ AnyContext,
39
+ Cmd,
40
+ CmdTask,
41
+ ContentTransformer,
42
+ EnvFile,
43
+ Scaffolder,
44
+ Task,
45
+ make_task,
46
+ )
31
47
  from zrb.util.string.conversion import to_snake_case
32
48
 
33
49
 
@@ -93,49 +109,78 @@ scaffold_my_app_name_entity = Scaffolder(
93
109
  ContentTransformer(
94
110
  name="transform-module-migration-metadata",
95
111
  match=is_module_migration_metadata_file,
96
- transform=update_migration_metadata,
112
+ transform=update_migration_metadata_file,
97
113
  ),
98
- # Update API Client (my_app_name/module/snake_module_name/client/api_client.py)
114
+ # Update API Client
115
+ # (my_app_name/module/snake_module_name/client/snake_module_name_api_client.py)
99
116
  ContentTransformer(
100
117
  name="transform-module-api-client",
101
118
  match=is_module_api_client_file,
102
- transform=update_api_client,
119
+ transform=update_api_client_file,
103
120
  ),
104
- # Update Direct Client (my_app_name/module/snake_module_name/client/direct_client.py)
121
+ # Update Direct Client
122
+ # (my_app_name/module/snake_module_name/client/snake_module_name_direct_client.py)
105
123
  ContentTransformer(
106
124
  name="transform-module-direct-client",
107
125
  match=is_module_direct_client_file,
108
- transform=update_direct_client,
126
+ transform=update_direct_client_file,
109
127
  ),
110
- # Update Any Client (my_app_name/module/snake_module_name/client/any_client.py)
128
+ # Update Client
129
+ # (my_app_name/module/snake_module_name/client/snake_module_name_client.py)
111
130
  ContentTransformer(
112
131
  name="transform-module-any-client",
113
- match=is_module_any_client_file,
114
- transform=update_any_client,
132
+ match=is_module_client_file,
133
+ transform=update_client_file,
115
134
  ),
116
135
  # Update module route (my_app_name/module/route.py)
117
136
  ContentTransformer(
118
137
  name="transform-module-route",
119
138
  match=is_module_route_file,
120
- transform=update_route,
139
+ transform=update_route_file,
121
140
  ),
122
141
  # Update module gateway subroute
123
142
  # (my_app_name/module/gateway/subroute/snake_module_name.py)
124
143
  ContentTransformer(
125
144
  name="transform-module-gateway-subroute",
126
145
  match=is_module_gateway_subroute_file,
127
- transform=update_gateway_subroute,
146
+ transform=update_gateway_subroute_file,
128
147
  ),
129
148
  ],
130
149
  retries=0,
131
150
  upstream=validate_create_my_app_name_entity,
132
151
  )
133
152
 
153
+ create_my_app_name_entity_migration = CmdTask(
154
+ name="create-my-app-name-entity-migration",
155
+ input=[
156
+ existing_module_input,
157
+ new_entity_input,
158
+ ],
159
+ env=EnvFile(path=os.path.join(APP_DIR, "template.env")),
160
+ cwd=APP_DIR,
161
+ cmd=[
162
+ ACTIVATE_VENV_SCRIPT,
163
+ Cmd(lambda ctx: set_create_migration_db_url_env(ctx.input.module)),
164
+ Cmd(lambda ctx: set_env("MY_APP_NAME_MODULES", ctx.input.module)),
165
+ Cmd(lambda ctx: cd_module_script(ctx.input.module)),
166
+ "alembic upgrade head",
167
+ Cmd(
168
+ 'alembic revision --autogenerate -m "create_{to_snake_case(ctx.input.entity)}_table"', # noqa
169
+ ),
170
+ ],
171
+ render_cmd=False,
172
+ retries=0,
173
+ upstream=[
174
+ prepare_venv,
175
+ scaffold_my_app_name_entity,
176
+ ],
177
+ )
178
+
134
179
  add_my_app_name_entity = app_create_group.add_task(
135
180
  Task(
136
181
  name="add-my-app-name-entity",
137
182
  description="🏗️ Create new entity on a module",
138
- upstream=scaffold_my_app_name_entity,
183
+ upstream=create_my_app_name_entity_migration,
139
184
  successor=format_my_app_name_code,
140
185
  retries=0,
141
186
  ),
@@ -8,7 +8,7 @@ from zrb.util.codemod.append_code_to_function import append_code_to_function
8
8
  from zrb.util.codemod.prepend_code_to_module import prepend_code_to_module
9
9
  from zrb.util.codemod.prepend_parent_to_class import prepend_parent_class
10
10
  from zrb.util.file import read_file, write_file
11
- from zrb.util.string.conversion import to_pascal_case, to_snake_case
11
+ from zrb.util.string.conversion import to_kebab_case, to_pascal_case, to_snake_case
12
12
 
13
13
 
14
14
  def is_in_app_schema_dir(ctx: AnyContext, file_path: str) -> bool:
@@ -49,13 +49,13 @@ def is_module_migration_metadata_file(ctx: AnyContext, file_path: str) -> bool:
49
49
  return file_path == module_migration_metadata_file
50
50
 
51
51
 
52
- def is_module_any_client_file(ctx: AnyContext, file_path: str) -> bool:
52
+ def is_module_client_file(ctx: AnyContext, file_path: str) -> bool:
53
53
  module_any_client_file = os.path.join(
54
54
  APP_DIR,
55
55
  "module",
56
56
  to_snake_case(ctx.input.module),
57
57
  "client",
58
- "any_client.py",
58
+ f"{to_snake_case(ctx.input.module)}_client.py",
59
59
  )
60
60
  return file_path == module_any_client_file
61
61
 
@@ -66,7 +66,7 @@ def is_module_api_client_file(ctx: AnyContext, file_path: str) -> bool:
66
66
  "module",
67
67
  to_snake_case(ctx.input.module),
68
68
  "client",
69
- "api_client.py",
69
+ f"{to_snake_case(ctx.input.module)}_api_client.py",
70
70
  )
71
71
  return file_path == module_api_client_file
72
72
 
@@ -77,7 +77,7 @@ def is_module_direct_client_file(ctx: AnyContext, file_path: str) -> bool:
77
77
  "module",
78
78
  to_snake_case(ctx.input.module),
79
79
  "client",
80
- "direct_client.py",
80
+ f"{to_snake_case(ctx.input.module)}_direct_client.py",
81
81
  )
82
82
  return file_path == module_direct_client_file
83
83
 
@@ -93,24 +93,24 @@ def is_module_gateway_subroute_file(ctx: AnyContext, file_path: str) -> bool:
93
93
  return file_path == module_gateway_subroute_file
94
94
 
95
95
 
96
- def update_migration_metadata(ctx: AnyContext, migration_metadata_file_path: str):
96
+ def update_migration_metadata_file(ctx: AnyContext, migration_metadata_file_path: str):
97
97
  app_name = os.path.basename(APP_DIR)
98
98
  existing_migration_metadata_code = read_file(migration_metadata_file_path)
99
99
  write_file(
100
100
  file_path=migration_metadata_file_path,
101
101
  content=[
102
- _get_import_schema_code(
102
+ _get_migration_import_schema_code(
103
103
  existing_migration_metadata_code, app_name, ctx.input.entity
104
104
  ),
105
105
  existing_migration_metadata_code.strip(),
106
- _get_entity_metadata_assignment_code(
106
+ _get_migration_entity_metadata_assignment_code(
107
107
  existing_migration_metadata_code, ctx.input.entity
108
108
  ),
109
109
  ],
110
110
  )
111
111
 
112
112
 
113
- def _get_import_schema_code(
113
+ def _get_migration_import_schema_code(
114
114
  existing_code: str, app_name: str, entity_name: str
115
115
  ) -> str | None:
116
116
  snake_entity_name = to_snake_case(entity_name)
@@ -122,7 +122,7 @@ def _get_import_schema_code(
122
122
  return import_schema_code
123
123
 
124
124
 
125
- def _get_entity_metadata_assignment_code(
125
+ def _get_migration_entity_metadata_assignment_code(
126
126
  existing_code: str, entity_name: str
127
127
  ) -> str | None:
128
128
  pascal_entity_name = to_pascal_case(entity_name)
@@ -137,42 +137,66 @@ def _get_entity_metadata_assignment_code(
137
137
  return entity_metadata_assignment_code
138
138
 
139
139
 
140
- def update_any_client(ctx: AnyContext, any_client_file_path: str):
141
- existing_any_client_code = read_file(any_client_file_path)
142
- app_name = os.path.basename(APP_DIR)
140
+ def update_client_file(ctx: AnyContext, client_file_path: str):
141
+ existing_client_code = read_file(client_file_path)
142
+ pascal_module_name = to_pascal_case(ctx.input.module)
143
143
  snake_entity_name = to_snake_case(ctx.input.entity)
144
144
  snake_plural_entity_name = to_snake_case(ctx.input.plural)
145
145
  pascal_entity_name = to_pascal_case(ctx.input.entity)
146
- any_client_method = read_file(
147
- file_path=os.path.join(
148
- os.path.dirname(__file__), "template", "any_client_method.py"
149
- ),
150
- replace_map={
151
- "my_entity": snake_entity_name,
152
- "my_entities": snake_plural_entity_name,
153
- "MyEntity": pascal_entity_name,
154
- },
155
- )
156
- new_code = append_code_to_class(
157
- existing_any_client_code, "AnyClient", any_client_method
158
- )
159
146
  write_file(
160
- file_path=any_client_file_path,
147
+ file_path=client_file_path,
161
148
  content=[
162
- f"from {app_name}.schema.{snake_entity_name} import (",
163
- f" {pascal_entity_name}CreateWithAudit, {pascal_entity_name}Response, {pascal_entity_name}UpdateWithAudit", # noqa
164
- ")",
165
- new_code.strip(),
149
+ _get_import_schema_for_client_code(
150
+ existing_code=existing_client_code, entity_name=ctx.input.entity
151
+ ),
152
+ append_code_to_class(
153
+ original_code=existing_client_code,
154
+ class_name=f"{pascal_module_name}Client",
155
+ new_code=read_file(
156
+ file_path=os.path.join(
157
+ os.path.dirname(__file__), "template", "client_method.py"
158
+ ),
159
+ replace_map={
160
+ "my_entity": snake_entity_name,
161
+ "my_entities": snake_plural_entity_name,
162
+ "MyEntity": pascal_entity_name,
163
+ },
164
+ ),
165
+ ),
166
166
  ],
167
167
  )
168
168
 
169
169
 
170
- def update_api_client(ctx: AnyContext, api_client_file_path: str):
170
+ def _get_import_schema_for_client_code(
171
+ existing_code: str, entity_name: str
172
+ ) -> str | None:
173
+ snake_entity_name = to_snake_case(entity_name)
174
+ pascal_entity_name = to_pascal_case(entity_name)
175
+ schema_import_path = f"my_app_name.schema.{snake_entity_name}"
176
+ new_code = "\n".join(
177
+ [
178
+ f"from {schema_import_path} import (",
179
+ f" Multiple{pascal_entity_name}Response,",
180
+ f" {pascal_entity_name}Create,",
181
+ f" {pascal_entity_name}CreateWithAudit,",
182
+ f" {pascal_entity_name}Response,",
183
+ f" {pascal_entity_name}Update,",
184
+ f" {pascal_entity_name}UpdateWithAudit,",
185
+ ")",
186
+ ]
187
+ )
188
+ if new_code in existing_code:
189
+ return None
190
+ return new_code
191
+
192
+
193
+ def update_api_client_file(ctx: AnyContext, api_client_file_path: str):
171
194
  existing_api_client_code = read_file(api_client_file_path)
172
195
  upper_snake_module_name = to_snake_case(ctx.input.module).upper()
173
196
  app_name = os.path.basename(APP_DIR)
174
197
  snake_entity_name = to_snake_case(ctx.input.entity)
175
198
  snake_module_name = to_snake_case(ctx.input.module)
199
+ pascal_module_name = to_pascal_case(ctx.input.module)
176
200
  write_file(
177
201
  file_path=api_client_file_path,
178
202
  content=[
@@ -180,7 +204,7 @@ def update_api_client(ctx: AnyContext, api_client_file_path: str):
180
204
  prepend_code_to_module(
181
205
  prepend_parent_class(
182
206
  original_code=existing_api_client_code,
183
- class_name="APIClient",
207
+ class_name=f"{pascal_module_name}APIClient",
184
208
  parent_class_name=f"{snake_entity_name}_api_client",
185
209
  ),
186
210
  f"{snake_entity_name}_api_client = {snake_entity_name}_service.as_api_client(base_url=APP_{upper_snake_module_name}_BASE_URL)", # noqa
@@ -189,11 +213,12 @@ def update_api_client(ctx: AnyContext, api_client_file_path: str):
189
213
  )
190
214
 
191
215
 
192
- def update_direct_client(ctx: AnyContext, direct_client_file_path: str):
216
+ def update_direct_client_file(ctx: AnyContext, direct_client_file_path: str):
193
217
  existing_direct_client_code = read_file(direct_client_file_path)
194
218
  app_name = os.path.basename(APP_DIR)
195
219
  snake_entity_name = to_snake_case(ctx.input.entity)
196
220
  snake_module_name = to_snake_case(ctx.input.module)
221
+ pascal_module_name = to_pascal_case(ctx.input.module)
197
222
  write_file(
198
223
  file_path=direct_client_file_path,
199
224
  content=[
@@ -201,7 +226,7 @@ def update_direct_client(ctx: AnyContext, direct_client_file_path: str):
201
226
  prepend_code_to_module(
202
227
  prepend_parent_class(
203
228
  original_code=existing_direct_client_code,
204
- class_name="DirectClient",
229
+ class_name=f"{pascal_module_name}DirectClient",
205
230
  parent_class_name=f"{snake_entity_name}_direct_client",
206
231
  ),
207
232
  f"{snake_entity_name}_direct_client = {snake_entity_name}_service.as_direct_client()", # noqa
@@ -210,7 +235,7 @@ def update_direct_client(ctx: AnyContext, direct_client_file_path: str):
210
235
  )
211
236
 
212
237
 
213
- def update_route(ctx: AnyContext, route_file_path: str):
238
+ def update_route_file(ctx: AnyContext, route_file_path: str):
214
239
  existing_route_code = read_file(route_file_path)
215
240
  entity_name = to_snake_case(ctx.input.entity)
216
241
  app_name = os.path.basename(APP_DIR)
@@ -228,10 +253,11 @@ def update_route(ctx: AnyContext, route_file_path: str):
228
253
  )
229
254
 
230
255
 
231
- def update_gateway_subroute(ctx: AnyContext, module_gateway_subroute_path: str):
256
+ def update_gateway_subroute_file(ctx: AnyContext, module_gateway_subroute_path: str):
232
257
  snake_module_name = to_snake_case(ctx.input.module)
233
258
  snake_entity_name = to_snake_case(ctx.input.entity)
234
259
  snake_plural_entity_name = to_snake_case(ctx.input.plural)
260
+ kebab_plural_entity_name = to_kebab_case(ctx.input.plural)
235
261
  pascal_entity_name = to_pascal_case(ctx.input.entity)
236
262
  existing_gateway_subroute_code = read_file(module_gateway_subroute_path)
237
263
  write_file(
@@ -254,6 +280,7 @@ def update_gateway_subroute(ctx: AnyContext, module_gateway_subroute_path: str):
254
280
  "my_module": snake_module_name,
255
281
  "my_entity": snake_entity_name,
256
282
  "my_entities": snake_plural_entity_name,
283
+ "my-entities": kebab_plural_entity_name,
257
284
  "MyEntity": pascal_entity_name,
258
285
  },
259
286
  ),
@@ -266,8 +293,8 @@ def _get_import_client_for_gateway_subroute_code(
266
293
  existing_code: str, module_name: str
267
294
  ) -> str | None:
268
295
  snake_module_name = to_snake_case(module_name)
269
- client_import_path = f"my_app_name.module.{snake_module_name}.client.factory"
270
- new_code = f"from {client_import_path} import client as {snake_module_name}_client"
296
+ client_import_path = f"my_app_name.module.{snake_module_name}.client.{snake_module_name}_client_factory" # noqa
297
+ new_code = f"from {client_import_path} import {snake_module_name}_client"
271
298
  if new_code in existing_code:
272
299
  return None
273
300
  return new_code
@@ -282,11 +309,10 @@ def _get_import_schema_for_gateway_subroute_code(
282
309
  new_code = "\n".join(
283
310
  [
284
311
  f"from {schema_import_path} import (",
312
+ f" Multiple{pascal_entity_name}Response,",
285
313
  f" {pascal_entity_name}Create,",
286
- f" {pascal_entity_name}CreateWithAudit,",
287
314
  f" {pascal_entity_name}Response,",
288
315
  f" {pascal_entity_name}Update,",
289
- f" {pascal_entity_name}UpdateWithAudit,",
290
316
  ")",
291
317
  ]
292
318
  )
@@ -1,8 +1,11 @@
1
+ from logging import Logger
2
+
1
3
  from my_app_name.common.base_service import BaseService
2
4
  from my_app_name.module.my_module.service.my_entity.repository.my_entity_repository import (
3
5
  MyEntityRepository,
4
6
  )
5
7
  from my_app_name.schema.my_entity import (
8
+ MultipleMyEntityResponse,
6
9
  MyEntityCreateWithAudit,
7
10
  MyEntityResponse,
8
11
  MyEntityUpdateWithAudit,
@@ -10,8 +13,9 @@ from my_app_name.schema.my_entity import (
10
13
 
11
14
 
12
15
  class MyEntityService(BaseService):
13
- def __init__(self, my_entity_repository: MyEntityRepository):
14
- super().__init__()
16
+
17
+ def __init__(self, logger: Logger, my_entity_repository: MyEntityRepository):
18
+ super().__init__(logger)
15
19
  self.my_entity_repository = my_entity_repository
16
20
 
17
21
  @BaseService.route(
@@ -23,22 +27,55 @@ class MyEntityService(BaseService):
23
27
  return await self.my_entity_repository.get_by_id(my_entity_id)
24
28
 
25
29
  @BaseService.route(
26
- "/api/v1/my-entities", methods=["get"], response_model=list[MyEntityResponse]
30
+ "/api/v1/my-entities",
31
+ methods=["get"],
32
+ response_model=MultipleMyEntityResponse,
33
+ )
34
+ async def get_my_entities(
35
+ self,
36
+ page: int = 1,
37
+ page_size: int = 10,
38
+ sort: str | None = None,
39
+ filter: str | None = None,
40
+ ) -> MultipleMyEntityResponse:
41
+ my_entities = await self.my_entity_repository.get(page, page_size, filter, sort)
42
+ count = await self.my_entity_repository.count(filter)
43
+ return MultipleMyEntityResponse(data=my_entities, count=count)
44
+
45
+ @BaseService.route(
46
+ "/api/v1/my-entities/bulk",
47
+ methods=["post"],
48
+ response_model=list[MyEntityResponse],
27
49
  )
28
- async def get_all_my_entities(self) -> list[MyEntityResponse]:
29
- return await self.my_entity_repository.get_all()
50
+ async def create_my_entity_bulk(
51
+ self, data: list[MyEntityCreateWithAudit]
52
+ ) -> list[MyEntityResponse]:
53
+ my_entities = await self.my_entity_repository.create_bulk(data)
54
+ return await self.my_entity_repository.get_by_ids(
55
+ [my_entity.id for my_entity in my_entities]
56
+ )
30
57
 
31
58
  @BaseService.route(
32
59
  "/api/v1/my-entities",
33
60
  methods=["post"],
34
- response_model=MyEntityResponse | list[MyEntityResponse],
61
+ response_model=MyEntityResponse,
35
62
  )
36
- async def create_my_entity(
37
- self, data: MyEntityCreateWithAudit | list[MyEntityCreateWithAudit]
38
- ) -> MyEntityResponse | list[MyEntityResponse]:
39
- if isinstance(data, MyEntityCreateWithAudit):
40
- return await self.my_entity_repository.create(data)
41
- return await self.my_entity_repository.create_bulk(data)
63
+ async def create_my_entity(self, data: MyEntityCreateWithAudit) -> MyEntityResponse:
64
+ my_entity = await self.my_entity_repository.create(data)
65
+ return await self.my_entity_repository.get_by_id(my_entity.id)
66
+
67
+ @BaseService.route(
68
+ "/api/v1/my-entities/bulk",
69
+ methods=["put"],
70
+ response_model=MyEntityResponse,
71
+ )
72
+ async def update_my_entity_bulk(
73
+ self, my_entity_ids: list[str], data: MyEntityUpdateWithAudit
74
+ ) -> MyEntityResponse:
75
+ my_entities = await self.my_entity_repository.update_bulk(my_entity_ids, data)
76
+ return await self.my_entity_repository.get_by_ids(
77
+ [my_entity.id for my_entity in my_entities]
78
+ )
42
79
 
43
80
  @BaseService.route(
44
81
  "/api/v1/my-entities/{my_entity_id}",
@@ -48,12 +85,29 @@ class MyEntityService(BaseService):
48
85
  async def update_my_entity(
49
86
  self, my_entity_id: str, data: MyEntityUpdateWithAudit
50
87
  ) -> MyEntityResponse:
51
- return await self.my_entity_repository.update(my_entity_id, data)
88
+ my_entity = await self.my_entity_repository.update(my_entity_id, data)
89
+ return await self.my_entity_repository.get_by_id(my_entity.id)
52
90
 
53
91
  @BaseService.route(
54
92
  "/api/v1/my-entities/{my_entity_id}",
55
93
  methods=["delete"],
56
94
  response_model=MyEntityResponse,
57
95
  )
58
- async def delete_my_entity(self, my_entity_id: str) -> MyEntityResponse:
59
- return await self.my_entity_repository.delete(my_entity_id)
96
+ async def delete_my_entity_bulk(
97
+ self, my_entity_ids: list[str], deleted_by: str
98
+ ) -> MyEntityResponse:
99
+ my_entities = await self.my_entity_repository.delete_bulk(my_entity_ids)
100
+ return await self.my_entity_repository.get_by_ids(
101
+ [my_entity.id for my_entity in my_entities]
102
+ )
103
+
104
+ @BaseService.route(
105
+ "/api/v1/my-entities/{my_entity_id}",
106
+ methods=["delete"],
107
+ response_model=MyEntityResponse,
108
+ )
109
+ async def delete_my_entity(
110
+ self, my_entity_id: str, deleted_by: str
111
+ ) -> MyEntityResponse:
112
+ my_entity = await self.my_entity_repository.delete(my_entity_id)
113
+ return await self.my_entity_repository.get_by_id(my_entity.id)
@@ -1,3 +1,4 @@
1
+ from my_app_name.common.logger_factory import logger
1
2
  from my_app_name.module.my_module.service.my_entity.my_entity_service import (
2
3
  MyEntityService,
3
4
  )
@@ -5,4 +6,4 @@ from my_app_name.module.my_module.service.my_entity.repository.my_entity_reposit
5
6
  my_entity_repository,
6
7
  )
7
8
 
8
- my_entity_service = MyEntityService(my_entity_repository=my_entity_repository)
9
+ my_entity_service = MyEntityService(logger, my_entity_repository=my_entity_repository)
@@ -1,5 +1,4 @@
1
1
  from my_app_name.common.base_db_repository import BaseDBRepository
2
- from my_app_name.common.error import NotFoundError
3
2
  from my_app_name.module.my_module.service.my_entity.repository.my_entity_repository import (
4
3
  MyEntityRepository,
5
4
  )
@@ -10,15 +9,6 @@ from my_app_name.schema.my_entity import (
10
9
  MyEntityUpdateWithAudit,
11
10
  )
12
11
  from passlib.context import CryptContext
13
- from sqlalchemy.ext.asyncio import AsyncSession
14
- from sqlmodel import Session, select
15
-
16
- # Password hashing context
17
- pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
18
-
19
-
20
- def hash_password(password: str) -> str:
21
- return pwd_context.hash(password)
22
12
 
23
13
 
24
14
  class MyEntityDBRepository(
@@ -9,30 +9,51 @@ from my_app_name.schema.my_entity import (
9
9
 
10
10
 
11
11
  class MyEntityRepository(ABC):
12
+
13
+ @abstractmethod
14
+ async def get_by_id(self, id: str) -> MyEntityResponse:
15
+ """Get my entity by id"""
16
+
17
+ @abstractmethod
18
+ async def get_by_ids(self, id_list: list[str]) -> MyEntityResponse:
19
+ """Get my entities by ids"""
20
+
21
+ @abstractmethod
22
+ async def get(
23
+ self,
24
+ page: int = 1,
25
+ page_size: int = 10,
26
+ filter: str | None = None,
27
+ sort: str | None = None,
28
+ ) -> list[MyEntity]:
29
+ """Get my entities by filter and sort"""
30
+
31
+ @abstractmethod
32
+ async def count(self, filter: str | None = None) -> int:
33
+ """Count my entities by filter"""
34
+
12
35
  @abstractmethod
13
- async def create(self, my_entity_data: MyEntityCreateWithAudit) -> MyEntityResponse:
14
- pass
36
+ async def create(self, data: MyEntityCreateWithAudit) -> MyEntity:
37
+ """Create a new my entity"""
15
38
 
16
39
  @abstractmethod
17
- async def get_by_id(self, my_entity_id: str) -> MyEntity:
18
- pass
40
+ async def create_bulk(self, data: list[MyEntityCreateWithAudit]) -> list[MyEntity]:
41
+ """Create some my entities"""
19
42
 
20
43
  @abstractmethod
21
- async def get_all(self) -> list[MyEntity]:
22
- pass
44
+ async def delete(self, id: str) -> MyEntity:
45
+ """Delete a my entity"""
23
46
 
24
47
  @abstractmethod
25
- async def update(
26
- self, my_entity_id: str, my_entity_data: MyEntityUpdateWithAudit
27
- ) -> MyEntity:
28
- pass
48
+ async def delete_bulk(self, id_list: list[str]) -> list[MyEntity]:
49
+ """Delete some my entities"""
29
50
 
30
51
  @abstractmethod
31
- async def delete(self, my_entity_id: str) -> MyEntity:
32
- pass
52
+ async def update(self, id: str, data: MyEntityUpdateWithAudit) -> MyEntity:
53
+ """Update a my entity"""
33
54
 
34
55
  @abstractmethod
35
- async def create_bulk(
36
- self, my_entity_data_list: list[MyEntityCreateWithAudit]
37
- ) -> list[MyEntityResponse]:
38
- pass
56
+ async def update_bulk(
57
+ self, id_list: list[str], data: MyEntityUpdateWithAudit
58
+ ) -> list[MyEntity]:
59
+ """Update some my entities"""