zrb 1.0.0a10__py3-none-any.whl → 1.0.0a14__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.
- zrb/builtin/__init__.py +15 -5
- zrb/builtin/project/add/fastapp.py +32 -17
- zrb/builtin/project/add/fastapp_template/_zrb/column/create_column_task.py +11 -0
- zrb/builtin/project/add/fastapp_template/_zrb/config.py +4 -4
- zrb/builtin/project/add/fastapp_template/_zrb/entity/create_entity_task.py +196 -0
- zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/my_entity_usecase.py +66 -0
- zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/repository/factory.py +13 -0
- zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/repository/my_entity_db_repository.py +33 -0
- zrb/builtin/project/add/fastapp_template/_zrb/entity/module_template/service/my_entity/repository/my_entity_repository.py +39 -0
- zrb/builtin/project/add/fastapp_template/_zrb/entity/schema.template.py +29 -0
- zrb/builtin/project/add/fastapp_template/_zrb/group.py +9 -5
- zrb/builtin/project/add/fastapp_template/_zrb/helper.py +25 -11
- zrb/builtin/project/add/fastapp_template/_zrb/input.py +43 -0
- zrb/builtin/project/add/fastapp_template/_zrb/main.py +30 -21
- zrb/builtin/project/add/fastapp_template/_zrb/module/create_module_task.py +136 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/alembic.ini +117 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/api_client.py +6 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/direct_client.py +6 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/client/factory.py +9 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/README +1 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/env.py +108 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/script.py.mako +26 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration/versions/3093c7336477_add_user_table.py +37 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/migration_metadata.py +3 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/module_template/route.py +19 -0
- zrb/builtin/project/add/fastapp_template/_zrb/module/run_module.template.py +26 -0
- zrb/builtin/project/add/fastapp_template/_zrb/venv_task.py +2 -5
- zrb/builtin/project/add/fastapp_template/common/app.py +3 -1
- zrb/builtin/project/add/fastapp_template/config.py +7 -7
- zrb/builtin/project/add/fastapp_template/module/auth/client/any_client.py +27 -0
- zrb/builtin/project/add/fastapp_template/module/auth/client/api_client.py +2 -2
- zrb/builtin/project/add/fastapp_template/module/auth/client/direct_client.py +2 -2
- zrb/builtin/project/add/fastapp_template/module/auth/client/factory.py +1 -1
- zrb/builtin/project/add/fastapp_template/module/auth/route.py +1 -1
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/factory.py +2 -2
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/{db_repository.py → user_db_repository.py} +2 -2
- zrb/builtin/project/add/fastapp_template/module/auth/service/user/{usecase.py → user_usecase.py} +15 -8
- zrb/builtin/project/add/fastapp_template/requirements.txt +5 -6
- zrb/builtin/project/add/fastapp_template/schema/permission.py +31 -0
- zrb/builtin/project/add/fastapp_template/template.env +2 -2
- zrb/builtin/project/create/create.py +2 -2
- zrb/builtin/project/create/project-template/zrb_init.py +0 -4
- zrb/builtin/setup/{dev → asdf}/asdf.py +6 -6
- zrb/builtin/setup/{system/latex → latex}/ubuntu.py +1 -1
- zrb/builtin/setup/{dev → tmux}/tmux.py +1 -1
- zrb/builtin/setup/tmux/tmux_config.sh +12 -0
- zrb/builtin/todo.py +101 -15
- zrb/config.py +2 -2
- zrb/content_transformer/content_transformer.py +14 -2
- zrb/context/context.py +13 -10
- zrb/input/base_input.py +3 -2
- zrb/input/bool_input.py +1 -1
- zrb/input/float_input.py +1 -1
- zrb/input/int_input.py +1 -1
- zrb/input/option_input.py +1 -1
- zrb/input/password_input.py +1 -1
- zrb/input/text_input.py +1 -1
- zrb/runner/cli.py +16 -5
- zrb/runner/web_app.py +30 -18
- zrb/runner/web_controller/task_ui/controller.py +8 -6
- zrb/session/session.py +4 -1
- zrb/task/scaffolder.py +7 -9
- zrb/util/cli/style.py +7 -0
- zrb/util/codemod/add_code_to_module.py +12 -0
- zrb/util/load.py +9 -7
- zrb/util/string/conversion.py +52 -0
- zrb/util/todo.py +152 -34
- {zrb-1.0.0a10.dist-info → zrb-1.0.0a14.dist-info}/METADATA +1 -2
- {zrb-1.0.0a10.dist-info → zrb-1.0.0a14.dist-info}/RECORD +79 -55
- {zrb-1.0.0a10.dist-info → zrb-1.0.0a14.dist-info}/WHEEL +1 -1
- /zrb/builtin/project/add/fastapp_template/{module/auth/client/base_client.py → _zrb/module/module_template/client/any_client.py} +0 -0
- /zrb/builtin/{setup/dev/tmux_config.sh → project/add/fastapp_template/_zrb/module/module_template/service/__init__.py} +0 -0
- /zrb/builtin/project/add/fastapp_template/common/{db_repository.py → base_db_repository.py} +0 -0
- /zrb/builtin/project/add/fastapp_template/common/{usecase.py → base_usecase.py} +0 -0
- /zrb/builtin/project/add/fastapp_template/module/auth/service/user/repository/{repository.py → user_repository.py} +0 -0
- /zrb/builtin/setup/{dev → asdf}/asdf_helper.py +0 -0
- /zrb/builtin/setup/{dev → tmux}/tmux_helper.py +0 -0
- /zrb/builtin/setup/{system/ubuntu.py → ubuntu.py} +0 -0
- {zrb-1.0.0a10.dist-info → zrb-1.0.0a14.dist-info}/entry_points.txt +0 -0
zrb/builtin/__init__.py
CHANGED
@@ -12,14 +12,22 @@ from zrb.builtin.md5 import hash_md5, sum_md5
|
|
12
12
|
from zrb.builtin.project.add.fastapp import add_fastapp_to_project
|
13
13
|
from zrb.builtin.project.create.create import create_project
|
14
14
|
from zrb.builtin.python import format_python_code
|
15
|
-
from zrb.builtin.setup.
|
16
|
-
from zrb.builtin.setup.
|
17
|
-
from zrb.builtin.setup.
|
18
|
-
from zrb.builtin.setup.
|
15
|
+
from zrb.builtin.setup.asdf.asdf import setup_asdf
|
16
|
+
from zrb.builtin.setup.latex.ubuntu import setup_latex_on_ubuntu
|
17
|
+
from zrb.builtin.setup.tmux.tmux import setup_tmux
|
18
|
+
from zrb.builtin.setup.ubuntu import setup_ubuntu
|
19
19
|
from zrb.builtin.shell.autocomplete.bash import make_bash_autocomplete
|
20
20
|
from zrb.builtin.shell.autocomplete.subcmd import get_shell_subcommands
|
21
21
|
from zrb.builtin.shell.autocomplete.zsh import make_zsh_autocomplete
|
22
|
-
from zrb.builtin.todo import
|
22
|
+
from zrb.builtin.todo import (
|
23
|
+
add_todo,
|
24
|
+
archive_todo,
|
25
|
+
complete_todo,
|
26
|
+
edit_todo,
|
27
|
+
list_todo,
|
28
|
+
log_todo,
|
29
|
+
show_todo,
|
30
|
+
)
|
23
31
|
|
24
32
|
assert create_project
|
25
33
|
assert add_fastapp_to_project
|
@@ -42,9 +50,11 @@ assert git_pull_subtree
|
|
42
50
|
assert git_push_subtree
|
43
51
|
assert list_todo
|
44
52
|
assert add_todo
|
53
|
+
assert archive_todo
|
45
54
|
assert edit_todo
|
46
55
|
assert complete_todo
|
47
56
|
assert log_todo
|
57
|
+
assert show_todo
|
48
58
|
assert setup_ubuntu
|
49
59
|
assert setup_latex_on_ubuntu
|
50
60
|
assert setup_asdf
|
@@ -6,7 +6,7 @@ from zrb.input.str_input import StrInput
|
|
6
6
|
from zrb.task.make_task import make_task
|
7
7
|
from zrb.task.scaffolder import Scaffolder
|
8
8
|
from zrb.task.task import Task
|
9
|
-
from zrb.util.string.conversion import double_quote
|
9
|
+
from zrb.util.string.conversion import double_quote, to_snake_case
|
10
10
|
from zrb.util.string.name import get_random_name
|
11
11
|
|
12
12
|
_DIR = os.path.dirname(__file__)
|
@@ -22,25 +22,21 @@ scaffold_fastapp = Scaffolder(
|
|
22
22
|
default_str=lambda _: os.getcwd(),
|
23
23
|
),
|
24
24
|
StrInput(
|
25
|
-
name="app
|
25
|
+
name="app",
|
26
26
|
description="App name",
|
27
27
|
prompt="App name",
|
28
|
-
default_str=lambda _: get_random_name(separator="_"),
|
29
28
|
),
|
30
29
|
],
|
31
30
|
source_path=os.path.join(_DIR, "fastapp_template"),
|
32
31
|
render_source_path=False,
|
33
|
-
destination_path=lambda ctx: os.path.join(
|
34
|
-
ctx.input["project-dir"], ctx.input["app-name"]
|
35
|
-
),
|
32
|
+
destination_path=lambda ctx: os.path.join(ctx.input["project-dir"], ctx.input.app),
|
36
33
|
transform_content={
|
37
|
-
"fastapp_template": "{to_snake_case(ctx.input
|
38
|
-
"App Name": "{ctx.input
|
39
|
-
"
|
40
|
-
"
|
41
|
-
"
|
42
|
-
"
|
43
|
-
"secure-password": lambda _: get_random_name(),
|
34
|
+
"fastapp_template": "{to_snake_case(ctx.input.app)}",
|
35
|
+
"My App Name": "{ctx.input.app.title()}",
|
36
|
+
"my-app-name": "{to_kebab_case(ctx.input.app)}",
|
37
|
+
"my_app_name": "{to_snake_case(ctx.input.app)}",
|
38
|
+
"MY_APP_NAME": "{to_snake_case(ctx.input.app).upper()}",
|
39
|
+
"my-secure-password": lambda _: get_random_name(),
|
44
40
|
},
|
45
41
|
retries=0,
|
46
42
|
)
|
@@ -48,16 +44,34 @@ scaffold_fastapp = Scaffolder(
|
|
48
44
|
|
49
45
|
@make_task(
|
50
46
|
name="register-fastapp-automation",
|
47
|
+
retries=0,
|
51
48
|
)
|
52
49
|
def register_fastapp_automation(ctx: AnyContext):
|
53
50
|
project_dir_path = ctx.input["project-dir"]
|
54
51
|
zrb_init_path = os.path.join(project_dir_path, "zrb_init.py")
|
55
|
-
app_dir_path = ctx.input
|
56
|
-
|
52
|
+
app_dir_path = ctx.input.app
|
53
|
+
app_name = to_snake_case(ctx.input.app)
|
54
|
+
with open(zrb_init_path, "r") as f:
|
55
|
+
file_content = f.read().strip()
|
56
|
+
# Assemble new content
|
57
|
+
new_content_list = [file_content]
|
58
|
+
# Check if import load_file is exists, if not exists, add
|
59
|
+
import_load_file_script = "from zrb import load_file"
|
60
|
+
if import_load_file_script not in file_content:
|
61
|
+
new_content_list = [import_load_file_script] + new_content_list
|
62
|
+
# Add fastapp-automation script
|
63
|
+
automation_file_part = ", ".join(
|
57
64
|
[double_quote(part) for part in [app_dir_path, "_zrb", "main.py"]]
|
58
65
|
)
|
59
|
-
|
60
|
-
f
|
66
|
+
new_content_list = new_content_list + [
|
67
|
+
f"{app_name} = load_file(os.path.join(_DIR, {automation_file_part}))",
|
68
|
+
f"assert {app_name}",
|
69
|
+
"",
|
70
|
+
]
|
71
|
+
new_content = "\n".join(new_content_list)
|
72
|
+
# Write new content
|
73
|
+
with open(zrb_init_path, "w") as f:
|
74
|
+
f.write(new_content)
|
61
75
|
|
62
76
|
|
63
77
|
scaffold_fastapp >> register_fastapp_automation
|
@@ -66,6 +80,7 @@ add_fastapp_to_project = add_to_project_group.add_task(
|
|
66
80
|
Task(
|
67
81
|
name="add-fastapp",
|
68
82
|
description="🚀 Add FastApp to project",
|
83
|
+
retries=0,
|
69
84
|
),
|
70
85
|
alias="fastapp",
|
71
86
|
)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
from fastapp_template._zrb.group import app_create_group
|
2
|
+
|
3
|
+
from zrb import Task
|
4
|
+
|
5
|
+
create_my_app_name_column = app_create_group.add_task(
|
6
|
+
Task(
|
7
|
+
name="create-my-app-name-column",
|
8
|
+
description="📊 Create new column on an entity",
|
9
|
+
),
|
10
|
+
alias="column",
|
11
|
+
)
|
@@ -6,12 +6,12 @@ APP_DIR = os.path.dirname(DIR)
|
|
6
6
|
APP_MODULE_NAME = os.path.basename(APP_DIR)
|
7
7
|
|
8
8
|
MICROSERVICES_ENV_VARS = {
|
9
|
-
"
|
10
|
-
"
|
9
|
+
"MY_APP_NAME_MODE": "microservices",
|
10
|
+
"MY_APP_NAME_AUTH_BASE_URL": "http://localhost:3002",
|
11
11
|
}
|
12
|
-
MONOLITH_ENV_VARS = {"
|
12
|
+
MONOLITH_ENV_VARS = {"MY_APP_NAME_MODE": "monolith"}
|
13
13
|
|
14
14
|
if platform.system() == "Windows":
|
15
|
-
ACTIVATE_VENV_SCRIPT = "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser; . .venv
|
15
|
+
ACTIVATE_VENV_SCRIPT = "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser; . .venv\\Scripts\\Activate" # noqa
|
16
16
|
else:
|
17
17
|
ACTIVATE_VENV_SCRIPT = "source .venv/bin/activate"
|
@@ -0,0 +1,196 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from fastapp_template._zrb.config import APP_DIR
|
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
|
+
from fastapp_template._zrb.input import (
|
10
|
+
existing_module_input,
|
11
|
+
new_entity_column_input,
|
12
|
+
new_entity_input,
|
13
|
+
plural_entity_input,
|
14
|
+
)
|
15
|
+
|
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
|
19
|
+
from zrb.util.string.conversion import to_pascal_case, to_snake_case
|
20
|
+
|
21
|
+
|
22
|
+
@make_task(
|
23
|
+
name="validate-create-my-app-name-entity",
|
24
|
+
input=[
|
25
|
+
existing_module_input,
|
26
|
+
new_entity_input,
|
27
|
+
plural_entity_input,
|
28
|
+
new_entity_column_input,
|
29
|
+
],
|
30
|
+
retries=0,
|
31
|
+
)
|
32
|
+
async def validate_create_my_app_name_entity(ctx: AnyContext):
|
33
|
+
module_name = to_snake_case(ctx.input.module)
|
34
|
+
if module_name not in get_existing_module_names():
|
35
|
+
raise ValueError(f"Module not exist: {module_name}")
|
36
|
+
schema_name = to_snake_case(ctx.input.entity)
|
37
|
+
if schema_name in get_existing_schema_names():
|
38
|
+
raise ValueError(f"Schema already exists: {schema_name}")
|
39
|
+
|
40
|
+
|
41
|
+
scaffold_my_app_name_schema = Scaffolder(
|
42
|
+
name="scaffold-my-app-name-schema",
|
43
|
+
input=[
|
44
|
+
existing_module_input,
|
45
|
+
new_entity_input,
|
46
|
+
new_entity_column_input,
|
47
|
+
],
|
48
|
+
source_path=os.path.join(os.path.dirname(__file__), "schema.template.py"),
|
49
|
+
render_source_path=False,
|
50
|
+
destination_path=lambda ctx: os.path.join(
|
51
|
+
APP_DIR,
|
52
|
+
"schema",
|
53
|
+
f"{to_snake_case(ctx.input.entity)}.py",
|
54
|
+
),
|
55
|
+
transform_content={
|
56
|
+
"MyEntity": "{to_pascal_case(ctx.input.entity)}",
|
57
|
+
"my_column": "{to_snake_case(ctx.input.column)}",
|
58
|
+
},
|
59
|
+
retries=0,
|
60
|
+
upstream=validate_create_my_app_name_entity,
|
61
|
+
)
|
62
|
+
|
63
|
+
scaffold_my_app_name_module_entity = Scaffolder(
|
64
|
+
name="scaffold-my-app-name-schema",
|
65
|
+
input=[
|
66
|
+
existing_module_input,
|
67
|
+
new_entity_input,
|
68
|
+
plural_entity_input,
|
69
|
+
],
|
70
|
+
source_path=os.path.join(os.path.dirname(__file__), "module_template"),
|
71
|
+
render_source_path=False,
|
72
|
+
destination_path=lambda ctx: os.path.join(
|
73
|
+
APP_DIR,
|
74
|
+
"module",
|
75
|
+
f"{to_snake_case(ctx.input.module)}",
|
76
|
+
),
|
77
|
+
transform_content={
|
78
|
+
"my_module": "{to_snake_case(ctx.input.module)}",
|
79
|
+
"MyEntity": "{to_pascal_case(ctx.input.entity)}",
|
80
|
+
"my_entity": "{to_snake_case(ctx.input.entity)}",
|
81
|
+
"my_entities": "{to_snake_case(ctx.input.plural)}",
|
82
|
+
"my-entities": "{to_kebab_case(ctx.input.plural)}",
|
83
|
+
},
|
84
|
+
retries=0,
|
85
|
+
upstream=validate_create_my_app_name_entity,
|
86
|
+
)
|
87
|
+
|
88
|
+
|
89
|
+
@make_task(
|
90
|
+
name="register-my-app-name-migration",
|
91
|
+
input=[existing_module_input, new_entity_input],
|
92
|
+
retries=0,
|
93
|
+
upstream=validate_create_my_app_name_entity,
|
94
|
+
)
|
95
|
+
async def register_my_app_name_migration(ctx: AnyContext):
|
96
|
+
migration_metadata_file_path = os.path.join(
|
97
|
+
APP_DIR, "module", to_snake_case(ctx.input.module), "migration_metadata.py"
|
98
|
+
)
|
99
|
+
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)
|
104
|
+
new_file_content_list = (
|
105
|
+
[f"from {app_name}.schema.{entity_name} import {entity_class}"]
|
106
|
+
+ file_content.strip()
|
107
|
+
+ [
|
108
|
+
f"{entity_class}.metadata = metadata",
|
109
|
+
f"{entity_class}.__table__.tometadata(metadata)",
|
110
|
+
"",
|
111
|
+
]
|
112
|
+
)
|
113
|
+
with open(migration_metadata_file_path, "w") as f:
|
114
|
+
f.write("\n".join(new_file_content_list))
|
115
|
+
|
116
|
+
|
117
|
+
@make_task(
|
118
|
+
name="register-my-app-name-api-client",
|
119
|
+
input=[existing_module_input, new_entity_input],
|
120
|
+
retries=0,
|
121
|
+
upstream=validate_create_my_app_name_entity,
|
122
|
+
)
|
123
|
+
async def register_my_app_name_api_client(ctx: AnyContext):
|
124
|
+
api_client_file_path = os.path.join(
|
125
|
+
APP_DIR, "module", to_snake_case(ctx.input.module), "client", "api_client.py"
|
126
|
+
)
|
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,
|
132
|
+
f"user_api_client = user_usecase.as_api_client(base_url=APP_{module_config_name}_BASE_URL)", # noqa
|
133
|
+
)
|
134
|
+
new_code = add_parent_to_class(
|
135
|
+
original_code=new_code,
|
136
|
+
class_name="APIClient",
|
137
|
+
parent_class_name="user_api_client",
|
138
|
+
)
|
139
|
+
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))
|
149
|
+
|
150
|
+
|
151
|
+
@make_task(
|
152
|
+
name="register-my-app-name-direct-client",
|
153
|
+
input=[existing_module_input, new_entity_input],
|
154
|
+
retries=0,
|
155
|
+
upstream=validate_create_my_app_name_entity,
|
156
|
+
)
|
157
|
+
async def register_my_app_name_direct_client(ctx: AnyContext):
|
158
|
+
direct_client_file_path = os.path.join(
|
159
|
+
APP_DIR, "module", to_snake_case(ctx.input.module), "client", "direct_client.py"
|
160
|
+
)
|
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
|
+
)
|
166
|
+
new_code = add_parent_to_class(
|
167
|
+
original_code=new_code,
|
168
|
+
class_name="DirectClient",
|
169
|
+
parent_class_name="user_direct_client",
|
170
|
+
)
|
171
|
+
app_name = os.path.basename(APP_DIR)
|
172
|
+
entity_name = to_snake_case(ctx.input.entity)
|
173
|
+
module_name = to_snake_case(ctx.input.module)
|
174
|
+
new_file_content_list = [
|
175
|
+
f"from {app_name}.module.{module_name}.service.{entity_name} import {entity_name}_usecase", # noqa
|
176
|
+
new_code.strip(),
|
177
|
+
"",
|
178
|
+
]
|
179
|
+
with open(direct_client_file_path, "w") as f:
|
180
|
+
f.write("\n".join(new_file_content_list))
|
181
|
+
|
182
|
+
|
183
|
+
create_my_app_name_entity = app_create_group.add_task(
|
184
|
+
Task(
|
185
|
+
name="create-my-app-name-entity",
|
186
|
+
description="🏗️ Create new entity on a module",
|
187
|
+
successor="",
|
188
|
+
),
|
189
|
+
alias="entity",
|
190
|
+
)
|
191
|
+
create_my_app_name_entity << [
|
192
|
+
scaffold_my_app_name_schema,
|
193
|
+
scaffold_my_app_name_module_entity,
|
194
|
+
register_my_app_name_api_client,
|
195
|
+
register_my_app_name_direct_client,
|
196
|
+
]
|
@@ -0,0 +1,66 @@
|
|
1
|
+
from fastapp_template.common.base_usecase import BaseUsecase
|
2
|
+
from fastapp_template.module.my_module.service.my_entity.repository.factory import (
|
3
|
+
my_entity_repository,
|
4
|
+
)
|
5
|
+
from fastapp_template.module.my_module.service.my_entity.repository.repository import (
|
6
|
+
MyEntityRepository,
|
7
|
+
)
|
8
|
+
from fastapp_template.schema.my_entity import (
|
9
|
+
MyEntityCreate,
|
10
|
+
MyEntityResponse,
|
11
|
+
MyEntityUpdate,
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
class MyEntityUsecase(BaseUsecase):
|
16
|
+
|
17
|
+
def __init__(self, my_entity_repository: MyEntityRepository):
|
18
|
+
super().__init__()
|
19
|
+
self.my_entity_repository = my_entity_repository
|
20
|
+
|
21
|
+
@BaseUsecase.route(
|
22
|
+
"/api/v1/my-entities/{my_entity_id}",
|
23
|
+
methods=["get"],
|
24
|
+
response_model=MyEntityResponse,
|
25
|
+
)
|
26
|
+
async def get_my_entity_by_id(self, my_entity_id: str) -> MyEntityResponse:
|
27
|
+
return await self.my_entity_repository.get_by_id(my_entity_id)
|
28
|
+
|
29
|
+
@BaseUsecase.route(
|
30
|
+
"/api/v1/my-entities", methods=["get"], response_model=list[MyEntityResponse]
|
31
|
+
)
|
32
|
+
async def get_all_my_entities(self) -> list[MyEntityResponse]:
|
33
|
+
return await self.my_entity_repository.get_all()
|
34
|
+
|
35
|
+
@BaseUsecase.route(
|
36
|
+
"/api/v1/my-entities",
|
37
|
+
methods=["post"],
|
38
|
+
response_model=MyEntityResponse | list[MyEntityResponse],
|
39
|
+
)
|
40
|
+
async def create_my_entity(
|
41
|
+
self, data: MyEntityCreate | list[MyEntityCreate]
|
42
|
+
) -> MyEntityResponse | list[MyEntityResponse]:
|
43
|
+
if isinstance(data, MyEntityCreate):
|
44
|
+
return await self.my_entity_repository.create(data)
|
45
|
+
return await self.my_entity_repository.create_bulk(data)
|
46
|
+
|
47
|
+
@BaseUsecase.route(
|
48
|
+
"/api/v1/my-entities/{my_entity_id}",
|
49
|
+
methods=["put"],
|
50
|
+
response_model=MyEntityResponse,
|
51
|
+
)
|
52
|
+
async def update_my_entity(
|
53
|
+
self, my_entity_id: str, data: MyEntityUpdate
|
54
|
+
) -> MyEntityResponse:
|
55
|
+
return await self.my_entity_repository.update(my_entity_id, data)
|
56
|
+
|
57
|
+
@BaseUsecase.route(
|
58
|
+
"/api/v1/my-entities/{my_entity_id}",
|
59
|
+
methods=["delete"],
|
60
|
+
response_model=MyEntityResponse,
|
61
|
+
)
|
62
|
+
async def delete_my_entity(self, my_entity_id: str) -> MyEntityResponse:
|
63
|
+
return await self.my_entity_repository.delete(my_entity_id)
|
64
|
+
|
65
|
+
|
66
|
+
my_entity_usecase = MyEntityUsecase(my_entity_repository=my_entity_repository)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from fastapp_template.common.db_engine import engine
|
2
|
+
from fastapp_template.config import APP_REPOSITORY_TYPE
|
3
|
+
from fastapp_template.module.my_module.service.my_entity.repository.my_entity_db_repository import (
|
4
|
+
MyEntityDBRepository,
|
5
|
+
)
|
6
|
+
from fastapp_template.module.my_module.service.my_entity.repository.my_entity_repository import (
|
7
|
+
MyEntityRepository,
|
8
|
+
)
|
9
|
+
|
10
|
+
if APP_REPOSITORY_TYPE == "db":
|
11
|
+
my_entity_repository: MyEntityRepository = MyEntityDBRepository(engine)
|
12
|
+
else:
|
13
|
+
my_entity_repository: MyEntityRepository = None
|
@@ -0,0 +1,33 @@
|
|
1
|
+
from fastapp_template.common.base_db_repository import BaseDBRepository
|
2
|
+
from fastapp_template.common.error import NotFoundError
|
3
|
+
from fastapp_template.module.my_module.service.my_entity.repository.my_entity_repository import (
|
4
|
+
MyEntityRepository,
|
5
|
+
)
|
6
|
+
from fastapp_template.schema.my_entity import (
|
7
|
+
MyEntity,
|
8
|
+
MyEntityCreate,
|
9
|
+
MyEntityResponse,
|
10
|
+
MyEntityUpdate,
|
11
|
+
)
|
12
|
+
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
|
+
|
23
|
+
|
24
|
+
class MyEntityDBRepository(
|
25
|
+
BaseDBRepository[MyEntity, MyEntityResponse, MyEntityCreate, MyEntityUpdate],
|
26
|
+
MyEntityRepository,
|
27
|
+
):
|
28
|
+
db_model = MyEntity
|
29
|
+
response_model = MyEntityResponse
|
30
|
+
create_model = MyEntityCreate
|
31
|
+
update_model = MyEntityUpdate
|
32
|
+
entity_name = "my_entity"
|
33
|
+
column_preprocessors = {}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from fastapp_template.schema.my_entity import (
|
4
|
+
MyEntity,
|
5
|
+
MyEntityCreate,
|
6
|
+
MyEntityResponse,
|
7
|
+
MyEntityUpdate,
|
8
|
+
)
|
9
|
+
|
10
|
+
|
11
|
+
class MyEntityRepository(ABC):
|
12
|
+
|
13
|
+
@abstractmethod
|
14
|
+
async def create(self, my_entity_data: MyEntityCreate) -> MyEntityResponse:
|
15
|
+
pass
|
16
|
+
|
17
|
+
@abstractmethod
|
18
|
+
async def get_by_id(self, my_entity_id: str) -> MyEntity:
|
19
|
+
pass
|
20
|
+
|
21
|
+
@abstractmethod
|
22
|
+
async def get_all(self) -> list[MyEntity]:
|
23
|
+
pass
|
24
|
+
|
25
|
+
@abstractmethod
|
26
|
+
async def update(
|
27
|
+
self, my_entity_id: str, my_entity_data: MyEntityUpdate
|
28
|
+
) -> MyEntity:
|
29
|
+
pass
|
30
|
+
|
31
|
+
@abstractmethod
|
32
|
+
async def delete(self, my_entity_id: str) -> MyEntity:
|
33
|
+
pass
|
34
|
+
|
35
|
+
@abstractmethod
|
36
|
+
async def create_bulk(
|
37
|
+
self, my_entity_data_list: list[MyEntityCreate]
|
38
|
+
) -> list[MyEntityResponse]:
|
39
|
+
pass
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import datetime
|
2
|
+
|
3
|
+
import ulid
|
4
|
+
from sqlmodel import Field, SQLModel
|
5
|
+
|
6
|
+
|
7
|
+
class MyEntityBase(SQLModel):
|
8
|
+
my_column: str
|
9
|
+
|
10
|
+
|
11
|
+
class MyEntityCreate(MyEntityBase):
|
12
|
+
pass
|
13
|
+
|
14
|
+
|
15
|
+
class MyEntityUpdate(SQLModel):
|
16
|
+
my_column: str | None = None
|
17
|
+
|
18
|
+
|
19
|
+
class MyEntityResponse(MyEntityBase):
|
20
|
+
id: str
|
21
|
+
|
22
|
+
|
23
|
+
class MyEntity(SQLModel, table=True):
|
24
|
+
id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
|
25
|
+
created_at: datetime.datetime
|
26
|
+
created_by: str
|
27
|
+
updated_at: datetime.datetime
|
28
|
+
updated_by: str
|
29
|
+
my_column: str
|
@@ -1,16 +1,20 @@
|
|
1
1
|
from zrb import Group
|
2
|
-
from zrb.builtin import project_group
|
2
|
+
from zrb.builtin.group import project_group
|
3
3
|
|
4
4
|
app_group = project_group.add_group(
|
5
|
-
Group(name="app-name", description="🚀 Managing App Name")
|
5
|
+
Group(name="my-app-name", description="🚀 Managing My App Name")
|
6
6
|
)
|
7
7
|
|
8
|
-
app_run_group = app_group.add_group(Group(name="run", description="🟢 Run App Name"))
|
8
|
+
app_run_group = app_group.add_group(Group(name="run", description="🟢 Run My App Name"))
|
9
9
|
|
10
10
|
app_migrate_group = app_group.add_group(
|
11
|
-
Group(name="migrate", description="📦 Run App Name DB migration")
|
11
|
+
Group(name="migrate", description="📦 Run My App Name DB migration")
|
12
12
|
)
|
13
13
|
|
14
14
|
app_create_group = app_group.add_group(
|
15
|
-
Group(name="create", description="✨ Create resources for App Name")
|
15
|
+
Group(name="create", description="✨ Create resources for My App Name")
|
16
|
+
)
|
17
|
+
|
18
|
+
app_create_migration_group = app_create_group.add_group(
|
19
|
+
Group(name="migration", description="📦 Create My App Name DB migration")
|
16
20
|
)
|
@@ -12,8 +12,8 @@ from zrb import Cmd, CmdTask, EnvFile, EnvMap, StrInput, Task
|
|
12
12
|
|
13
13
|
def create_migration(name: str, module: str) -> Task:
|
14
14
|
return CmdTask(
|
15
|
-
name=f"create-app-name-{name}-migration",
|
16
|
-
description=f"🧩 Create App Name {name.capitalize()} DB migration",
|
15
|
+
name=f"create-my-app-name-{name}-migration",
|
16
|
+
description=f"🧩 Create My App Name {name.capitalize()} DB migration",
|
17
17
|
input=StrInput(
|
18
18
|
name="message",
|
19
19
|
description="Migration message",
|
@@ -25,7 +25,7 @@ def create_migration(name: str, module: str) -> Task:
|
|
25
25
|
EnvMap(
|
26
26
|
vars={
|
27
27
|
"APP_DB_URL": f"sqlite:///{APP_DIR}/.migration.{module}.db",
|
28
|
-
"
|
28
|
+
"MY_APP_NAME_MODULES": f"{module}",
|
29
29
|
}
|
30
30
|
),
|
31
31
|
],
|
@@ -48,17 +48,17 @@ def migrate_module(name: str, module: str, as_microservices: bool) -> Task:
|
|
48
48
|
env_vars = MICROSERVICES_ENV_VARS if as_microservices else MONOLITH_ENV_VARS
|
49
49
|
return CmdTask(
|
50
50
|
name=(
|
51
|
-
f"migrate-app-name-{name}"
|
51
|
+
f"migrate-my-app-name-{name}"
|
52
52
|
if as_microservices
|
53
53
|
else f"migrate-{name}-on-monolith"
|
54
54
|
),
|
55
|
-
description=f"🧩 Run App Name {name.capitalize()} DB migration",
|
55
|
+
description=f"🧩 Run My App Name {name.capitalize()} DB migration",
|
56
56
|
env=[
|
57
57
|
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
58
58
|
EnvMap(
|
59
59
|
vars={
|
60
60
|
**env_vars,
|
61
|
-
"
|
61
|
+
"MY_APP_NAME_MODULES": f"{module}",
|
62
62
|
}
|
63
63
|
),
|
64
64
|
],
|
@@ -75,23 +75,37 @@ def migrate_module(name: str, module: str, as_microservices: bool) -> Task:
|
|
75
75
|
|
76
76
|
def run_microservice(name: str, port: int, module: str) -> Task:
|
77
77
|
return CmdTask(
|
78
|
-
name=f"run-app-name-{name}",
|
79
|
-
description=f"🧩 Run App Name {name.capitalize()}",
|
78
|
+
name=f"run-my-app-name-{name}",
|
79
|
+
description=f"🧩 Run My App Name {name.capitalize()}",
|
80
80
|
env=[
|
81
81
|
EnvFile(path=os.path.join(APP_DIR, "template.env")),
|
82
82
|
EnvMap(
|
83
83
|
vars={
|
84
84
|
**MICROSERVICES_ENV_VARS,
|
85
|
-
"
|
86
|
-
"
|
85
|
+
"MY_APP_NAME_PORT": f"{port}",
|
86
|
+
"MY_APP_NAME_MODULES": f"{module}",
|
87
87
|
}
|
88
88
|
),
|
89
89
|
],
|
90
90
|
cwd=APP_DIR,
|
91
91
|
cmd=[
|
92
92
|
ACTIVATE_VENV_SCRIPT,
|
93
|
-
'fastapi dev main.py --port "${
|
93
|
+
'fastapi dev main.py --port "${MY_APP_NAME_PORT}"',
|
94
94
|
],
|
95
95
|
render_cmd=False,
|
96
96
|
retries=2,
|
97
97
|
)
|
98
|
+
|
99
|
+
|
100
|
+
def get_existing_module_names() -> list[str]:
|
101
|
+
module_dir_path = os.path.join(APP_DIR, "module")
|
102
|
+
return [entry.name for entry in os.scandir(module_dir_path) if entry.is_dir()]
|
103
|
+
|
104
|
+
|
105
|
+
def get_existing_schema_names() -> list[str]:
|
106
|
+
module_dir_path = os.path.join(APP_DIR, "schema")
|
107
|
+
return [
|
108
|
+
os.path.splitext(entry.name)[0]
|
109
|
+
for entry in os.scandir(module_dir_path)
|
110
|
+
if entry.is_file() and entry.name.endswith(".py")
|
111
|
+
]
|