zrb 1.0.0b9__py3-none-any.whl → 1.0.0b10__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 (61) hide show
  1. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.coveragerc +11 -0
  2. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.gitignore +4 -0
  3. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_task.py +4 -4
  4. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +5 -0
  5. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +107 -1
  6. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +67 -4
  7. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_create_my_entity.py +53 -0
  8. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_delete_my_entity.py +62 -0
  9. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_read_my_entity.py +65 -0
  10. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_update_my_entity.py +61 -0
  11. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +57 -13
  12. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +2 -2
  13. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/gateway/subroute/my_module.py +6 -1
  14. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +10 -6
  15. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +56 -12
  16. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task_util.py +10 -4
  17. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +136 -52
  18. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +1 -1
  19. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +1 -0
  20. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +46 -43
  21. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/8ed025bcc845_create_permissions.py +69 -0
  22. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +5 -2
  23. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +16 -21
  24. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +193 -43
  25. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/auth.py +57 -0
  26. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +6 -1
  27. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +1 -0
  28. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +9 -0
  29. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/_util/access_token.py +19 -0
  30. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_create_permission.py +59 -0
  31. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_delete_permission.py +68 -0
  32. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_read_permission.py +71 -0
  33. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_update_permission.py +66 -0
  34. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/test_user_session.py +195 -0
  35. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_health_and_readiness.py +28 -0
  36. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_homepage.py +17 -0
  37. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_not_found_error.py +16 -0
  38. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test.sh +7 -0
  39. zrb/task/base_task.py +10 -10
  40. zrb/util/codemod/modification_mode.py +3 -0
  41. zrb/util/codemod/modify_class.py +58 -0
  42. zrb/util/codemod/modify_class_parent.py +68 -0
  43. zrb/util/codemod/modify_class_property.py +128 -0
  44. zrb/util/codemod/modify_dict.py +75 -0
  45. zrb/util/codemod/modify_function.py +65 -0
  46. zrb/util/codemod/modify_function_call.py +68 -0
  47. zrb/util/codemod/modify_method.py +88 -0
  48. zrb/util/codemod/{prepend_code_to_module.py → modify_module.py} +2 -3
  49. zrb/util/file.py +3 -2
  50. {zrb-1.0.0b9.dist-info → zrb-1.0.0b10.dist-info}/METADATA +1 -1
  51. {zrb-1.0.0b9.dist-info → zrb-1.0.0b10.dist-info}/RECORD +53 -36
  52. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/migrate.py +0 -3
  53. zrb/util/codemod/append_code_to_class.py +0 -35
  54. zrb/util/codemod/append_code_to_function.py +0 -38
  55. zrb/util/codemod/append_code_to_method.py +0 -55
  56. zrb/util/codemod/append_key_to_dict.py +0 -51
  57. zrb/util/codemod/append_param_to_function_call.py +0 -39
  58. zrb/util/codemod/prepend_parent_to_class.py +0 -38
  59. zrb/util/codemod/prepend_property_to_class.py +0 -55
  60. {zrb-1.0.0b9.dist-info → zrb-1.0.0b10.dist-info}/WHEEL +0 -0
  61. {zrb-1.0.0b9.dist-info → zrb-1.0.0b10.dist-info}/entry_points.txt +0 -0
@@ -4,8 +4,8 @@ from my_app_name._zrb.config import APP_DIR
4
4
  from my_app_name._zrb.util import get_existing_module_names
5
5
 
6
6
  from zrb.context.any_context import AnyContext
7
- from zrb.util.codemod.append_code_to_function import append_code_to_function
8
- from zrb.util.codemod.append_key_to_dict import append_key_to_dict
7
+ from zrb.util.codemod.modify_dict import append_key_to_dict
8
+ from zrb.util.codemod.modify_function import append_code_to_function
9
9
  from zrb.util.file import read_file, write_file
10
10
  from zrb.util.string.conversion import to_kebab_case, to_pascal_case, to_snake_case
11
11
 
@@ -1,4 +1,9 @@
1
- from fastapi import FastAPI
1
+ from typing import Annotated
2
+
3
+ from fastapi import Depends, FastAPI
4
+ from my_app_name.common.error import ForbiddenError
5
+ from my_app_name.module.gateway.util.auth import get_current_user
6
+ from my_app_name.schema.user import AuthUserResponse
2
7
 
3
8
 
4
9
  def serve_my_module_route(app: FastAPI):
@@ -1,26 +1,30 @@
1
1
  # 🔐 Run/Migrate My Module ==========================================================
2
2
 
3
3
  run_my_module = app_run_group.add_task(
4
- run_microservice("my-module", 3000, "my_module"), alias="svc-my_module"
4
+ run_microservice("my_module", 3000), alias="svc-my-module"
5
5
  )
6
6
  prepare_venv >> run_my_module >> run_microservices
7
7
 
8
8
  create_my_module_migration = app_create_migration_group.add_task(
9
- create_migration("my-module", "my_module"), alias="my_module"
9
+ create_migration("my_module"), alias="my_module"
10
10
  )
11
11
  prepare_venv >> create_my_module_migration >> create_all_migration
12
12
 
13
- migrate_monolith_my_module = migrate_module(
14
- "my_module", "my_module", as_microservices=False
15
- )
13
+ migrate_monolith_my_module = migrate_module("my_module", as_microservices=False)
16
14
  prepare_venv >> migrate_monolith_my_module >> [migrate_monolith, run_monolith]
17
15
 
18
16
  migrate_microservices_my_module = app_migrate_group.add_task(
19
- migrate_module("my-module", "my_module", as_microservices=True),
17
+ migrate_module("my_module", as_microservices=True),
20
18
  alias="svc-my-module",
21
19
  )
20
+
22
21
  (
23
22
  prepare_venv
24
23
  >> migrate_microservices_my_module
25
24
  >> [migrate_microservices, run_my_module]
26
25
  )
26
+
27
+ migrate_test_my_module = migrate_module(
28
+ "my_module", as_microservices=False, additional_env_vars=TEST_ENV_VARS
29
+ )
30
+ prepare_venv >> migrate_test_my_module >> migrate_test
@@ -1,11 +1,17 @@
1
1
  import os
2
2
 
3
3
  from my_app_name._zrb.column.add_column_task import add_my_app_name_column
4
- from my_app_name._zrb.config import ACTIVATE_VENV_SCRIPT, APP_DIR, MONOLITH_ENV_VARS
4
+ from my_app_name._zrb.config import (
5
+ ACTIVATE_VENV_SCRIPT,
6
+ APP_DIR,
7
+ MONOLITH_ENV_VARS,
8
+ TEST_ENV_VARS,
9
+ )
5
10
  from my_app_name._zrb.entity.add_entity_task import add_my_app_name_entity
6
11
  from my_app_name._zrb.format_task import format_my_app_name_code
7
12
  from my_app_name._zrb.group import (
8
13
  app_create_migration_group,
14
+ app_group,
9
15
  app_migrate_group,
10
16
  app_run_group,
11
17
  )
@@ -19,13 +25,42 @@ from my_app_name._zrb.task_util import (
19
25
  )
20
26
  from my_app_name._zrb.venv_task import prepare_venv
21
27
 
22
- from zrb import CmdTask, EnvFile, EnvMap, Task
28
+ from zrb import AnyContext, CmdPath, CmdTask, EnvFile, EnvMap, Task, make_task
23
29
 
24
30
  assert add_my_app_name_entity
25
31
  assert add_my_app_name_module
26
32
  assert add_my_app_name_column
27
33
  assert format_my_app_name_code
28
34
 
35
+ # 🧪 Test ======================================================================
36
+
37
+
38
+ @make_task(
39
+ name="prepare-my-app-name-test",
40
+ )
41
+ def prepare_test(ctx: AnyContext):
42
+ db_test_path = os.path.join(APP_DIR, "test.db")
43
+ if os.path.exists(db_test_path):
44
+ ctx.print(f"Removing test db: {db_test_path}")
45
+ os.remove(db_test_path)
46
+
47
+
48
+ migrate_test = Task(name="migrate-test")
49
+
50
+ test_app = app_group.add_task(
51
+ CmdTask(
52
+ name="test-my-app-name",
53
+ description="🧪 Test My App Name",
54
+ env=EnvMap(vars=TEST_ENV_VARS),
55
+ cwd=APP_DIR,
56
+ cmd=CmdPath(os.path.join(APP_DIR, "test.sh")),
57
+ retries=0,
58
+ ),
59
+ alias="test",
60
+ )
61
+ prepare_venv >> prepare_test >> migrate_test >> test_app
62
+
63
+
29
64
  # 🚀 Run/Migrate All ===========================================================
30
65
 
31
66
  run_all = app_run_group.add_task(
@@ -107,40 +142,49 @@ migrate_microservices >> migrate_all
107
142
  # 📡 Run/Migrate Gateway =======================================================
108
143
 
109
144
  run_gateway = app_run_group.add_task(
110
- run_microservice("gateway", 3001, "gateway"), alias="svc-gateway"
145
+ run_microservice("gateway", 3001), alias="svc-gateway"
111
146
  )
112
147
  prepare_venv >> run_gateway >> run_microservices
113
148
 
114
149
  create_gateway_migration = app_create_migration_group.add_task(
115
- create_migration("gateway", "gateway"), alias="gateway"
150
+ create_migration("gateway"), alias="gateway"
116
151
  )
117
152
  prepare_venv >> create_gateway_migration >> create_all_migration
118
153
 
119
- migrate_monolith_gateway = migrate_module("gateway", "gateway", as_microservices=False)
154
+ migrate_monolith_gateway = migrate_module("gateway", as_microservices=False)
120
155
  prepare_venv >> migrate_monolith_gateway >> [migrate_monolith, run_monolith]
121
156
 
122
157
  migrate_microservices_gateway = app_migrate_group.add_task(
123
- migrate_module("gateway", "gateway", as_microservices=True),
158
+ migrate_module("gateway", as_microservices=True),
124
159
  alias="svc-gateway",
125
160
  )
126
161
  prepare_venv >> migrate_microservices_gateway >> [migrate_microservices, run_gateway]
127
162
 
163
+ migrate_test_gateway = migrate_module(
164
+ "gateway", as_microservices=False, additional_env_vars=TEST_ENV_VARS
165
+ )
166
+ prepare_venv >> migrate_test_gateway >> migrate_test
167
+
168
+
128
169
  # 🔐 Run/Migrate Auth ==========================================================
129
170
 
130
- run_auth = app_run_group.add_task(
131
- run_microservice("auth", 3002, "auth"), alias="svc-auth"
132
- )
171
+ run_auth = app_run_group.add_task(run_microservice("auth", 3002), alias="svc-auth")
133
172
  prepare_venv >> run_auth >> run_microservices
134
173
 
135
174
  create_auth_migration = app_create_migration_group.add_task(
136
- create_migration("auth", "auth"), alias="auth"
175
+ create_migration("auth"), alias="auth"
137
176
  )
138
177
  prepare_venv >> create_auth_migration >> create_all_migration
139
178
 
140
- migrate_monolith_auth = migrate_module("auth", "auth", as_microservices=False)
179
+ migrate_monolith_auth = migrate_module("auth", as_microservices=False)
141
180
  prepare_venv >> migrate_monolith_auth >> [migrate_monolith, run_monolith]
142
181
 
143
182
  migrate_microservices_auth = app_migrate_group.add_task(
144
- migrate_module("auth", "auth", as_microservices=True), alias="svc-auth"
183
+ migrate_module("auth", as_microservices=True), alias="svc-auth"
145
184
  )
146
185
  prepare_venv >> migrate_microservices_auth >> [migrate_microservices, run_auth]
186
+
187
+ migrate_test_auth = migrate_module(
188
+ "auth", as_microservices=False, additional_env_vars=TEST_ENV_VARS
189
+ )
190
+ prepare_venv >> migrate_test_auth >> migrate_test
@@ -16,10 +16,11 @@ from my_app_name._zrb.util import (
16
16
  )
17
17
 
18
18
  from zrb import Cmd, CmdTask, EnvFile, EnvMap, StrInput, Task
19
- from zrb.util.string.conversion import to_snake_case
19
+ from zrb.util.string.conversion import to_kebab_case, to_snake_case
20
20
 
21
21
 
22
- def create_migration(name: str, module: str) -> Task:
22
+ def create_migration(module: str) -> Task:
23
+ name = to_kebab_case(module)
23
24
  return CmdTask(
24
25
  name=f"create-my-app-name-{name}-migration",
25
26
  description=f"🧩 Create My App Name {name.capitalize()} DB migration",
@@ -47,10 +48,14 @@ def create_migration(name: str, module: str) -> Task:
47
48
  )
48
49
 
49
50
 
50
- def migrate_module(name: str, module: str, as_microservices: bool) -> Task:
51
+ def migrate_module(
52
+ module: str, as_microservices: bool, additional_env_vars: dict[str, str] = {}
53
+ ) -> Task:
54
+ name = to_kebab_case(module)
51
55
  env_vars = (
52
56
  dict(MICROSERVICES_ENV_VARS) if as_microservices else dict(MONOLITH_ENV_VARS)
53
57
  )
58
+ env_vars.update(additional_env_vars)
54
59
  if as_microservices:
55
60
  env_vars["MY_APP_NAME_MODULES"] = to_snake_case(module)
56
61
  return CmdTask(
@@ -75,7 +80,8 @@ def migrate_module(name: str, module: str, as_microservices: bool) -> Task:
75
80
  )
76
81
 
77
82
 
78
- def run_microservice(name: str, port: int, module: str) -> Task:
83
+ def run_microservice(module: str, port: int) -> Task:
84
+ name = to_kebab_case(module)
79
85
  return CmdTask(
80
86
  name=f"run-my-app-name-{name}",
81
87
  description=f"🧩 Run My App Name {name.capitalize()}",
@@ -2,10 +2,10 @@ import inspect
2
2
  from enum import Enum
3
3
  from functools import partial
4
4
  from logging import Logger
5
- from typing import Any, Callable, Sequence
5
+ from typing import Any, Callable, Union, get_args, get_origin
6
6
 
7
7
  import httpx
8
- from fastapi import APIRouter, Depends, params
8
+ from fastapi import APIRouter, Depends
9
9
  from my_app_name.common.error import ClientAPIError
10
10
  from pydantic import BaseModel
11
11
 
@@ -162,58 +162,20 @@ def _create_direct_client_method(logger: Logger, func: Callable, service: BaseSe
162
162
  def _create_api_client_method(logger: Logger, route_param: RouteParam, base_url: str):
163
163
  async def client_method(*args, **kwargs):
164
164
  url = base_url + route_param.path
165
- method = (
166
- route_param.methods[0].lower()
167
- if isinstance(route_param.methods, list)
168
- else route_param.methods.lower()
165
+ method = _get_api_client_method(route_param)
166
+ body_param_names = _get_api_client_body_param_names(route_param, method)
167
+ path_params, query_params, body_params = _create_api_client_request_params(
168
+ route_param, body_param_names, args, kwargs
169
169
  )
170
- # Get the signature of the original function
171
- sig = inspect.signature(route_param.func)
172
- # Bind the arguments to the signature
173
- bound_args = sig.bind(*args, **kwargs)
174
- bound_args.apply_defaults()
175
- # Analyze parameters
176
- function_params = list(sig.parameters.values())
177
- body_param_names = [
178
- p.name
179
- for p in function_params
180
- if (
181
- p.name != "self"
182
- and f"{{{p.name}}}" not in route_param.path
183
- and p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
184
- and (
185
- method not in ["get", "delete"]
186
- or (method == "delete" and p.annotation not in [str, float, bool])
187
- )
188
- )
189
- ]
190
- # Prepare the request
191
- path_params = {}
192
- query_params = {}
193
- body_params = {}
194
- for name, value in bound_args.arguments.items():
195
- if name == "self":
196
- continue
197
- if f"{{{name}}}" in route_param.path:
198
- path_params[name] = value
199
- elif name not in body_param_names:
200
- query_params[name] = _parse_api_param(value)
201
- elif len(body_param_names) == 1 and name == body_param_names[0]:
202
- # If there's only one body parameter, use its value directly
203
- body_params = _parse_api_param(value)
204
- else:
205
- body_params[name] = _parse_api_param(value)
206
170
  # Format the URL with path parameters
207
171
  url = url.format(**path_params)
172
+ json_body_params = None if method == "get" else body_params
208
173
  logger.info(
209
- f"Sending request to {url} with method {method}, json={body_params}, params={query_params}" # noqa
174
+ f"Sending request to {url} with method {method}, json={json_body_params}, params={query_params}" # noqa
210
175
  )
211
176
  async with httpx.AsyncClient() as client:
212
177
  response = await client.request(
213
- method=method,
214
- url=url,
215
- params=query_params,
216
- json=None if method == "get" else body_params,
178
+ method=method, url=url, params=query_params, json=json_body_params
217
179
  )
218
180
  logger.info(
219
181
  f"Received response: status={response.status_code}, content={response.content}"
@@ -225,17 +187,139 @@ def _create_api_client_method(logger: Logger, route_param: RouteParam, base_url:
225
187
  else response.text
226
188
  )
227
189
  raise ClientAPIError(response.status_code, error_detail)
228
- return response.json()
190
+ return _parse_api_client_response(logger, route_param, response)
229
191
 
230
192
  return client_method
231
193
 
232
194
 
233
- def _parse_api_param(data: Any) -> Any:
195
+ def _parse_api_client_response(
196
+ logger: Logger, route_param: RouteParam, response: Any
197
+ ) -> Any:
198
+ sig = inspect.signature(route_param.func)
199
+ try:
200
+ response_data = response.json()
201
+ except Exception:
202
+ logger.warning("Failed to parse JSON")
203
+ return None
204
+ return_annotation = sig.return_annotation # e.g., list[User]
205
+ if return_annotation is inspect.Signature.empty:
206
+ logger.warning("No return annotation detected, return value as is")
207
+ return response_data # No return type specified, return raw JSON
208
+ origin = get_origin(return_annotation) # e.g., list
209
+ args = get_args(return_annotation) # e.g., (User,)
210
+ try:
211
+ if origin is None: # Not a generic type, so check it directly
212
+ if inspect.isclass(return_annotation) and issubclass(
213
+ return_annotation, BaseModel
214
+ ):
215
+ if response_data:
216
+ return return_annotation.model_validate(response_data)
217
+ return None
218
+ elif origin in {list, set, tuple} and args:
219
+ model_type = args[0]
220
+ if inspect.isclass(model_type) and issubclass(model_type, BaseModel):
221
+ if isinstance(response_data, list):
222
+ return [model_type.model_validate(item) for item in response_data]
223
+ elif isinstance(response_data, tuple):
224
+ return tuple(
225
+ model_type.model_validate(item) for item in response_data
226
+ )
227
+ elif isinstance(response_data, set):
228
+ return {model_type.model_validate(item) for item in response_data}
229
+ return None
230
+ elif origin is Union and len(args) == 2 and type(None) in args:
231
+ model_type = next(
232
+ (
233
+ arg
234
+ for arg in args
235
+ if inspect.isclass(arg) and issubclass(arg, BaseModel)
236
+ ),
237
+ None,
238
+ )
239
+ if response_data and model_type:
240
+ return model_type.model_validate(response_data)
241
+ return None
242
+ elif origin is dict and len(args) == 2:
243
+ key_type, value_type = args
244
+ if inspect.isclass(value_type) and issubclass(value_type, BaseModel):
245
+ if inspect(response_data, dict):
246
+ return {
247
+ k: value_type.model_validate(v)
248
+ for k, v in response_data.items()
249
+ }
250
+ return None
251
+ return response_data
252
+ except Exception:
253
+ logger.warning(
254
+ "Return annotation detected, but parsing error, return value as is"
255
+ )
256
+ return response_data
257
+
258
+
259
+ def _create_api_client_request_params(
260
+ route_param: RouteParam,
261
+ body_param_names: list[str],
262
+ args: list[Any],
263
+ kwargs: dict[str, Any],
264
+ ) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any]]:
265
+ # Get the signature of the original function
266
+ sig = inspect.signature(route_param.func)
267
+ # Bind the arguments to the signature
268
+ bound_args = sig.bind(*args, **kwargs)
269
+ bound_args.apply_defaults()
270
+ # Prepare the request
271
+ path_params = {}
272
+ query_params = {}
273
+ body_params = {}
274
+ for name, value in bound_args.arguments.items():
275
+ if name == "self":
276
+ continue
277
+ if f"{{{name}}}" in route_param.path:
278
+ path_params[name] = value
279
+ elif name not in body_param_names:
280
+ query_params[name] = _parse_api_client_param(value)
281
+ elif len(body_param_names) == 1 and name == body_param_names[0]:
282
+ # If there's only one body parameter, use its value directly
283
+ body_params = _parse_api_client_param(value)
284
+ else:
285
+ body_params[name] = _parse_api_client_param(value)
286
+ return path_params, query_params, body_params
287
+
288
+
289
+ def _parse_api_client_param(data: Any) -> Any:
234
290
  if isinstance(data, BaseModel):
235
291
  return data.model_dump()
236
- elif isinstance(data, list):
237
- return [_parse_api_param(item) for item in data]
238
292
  elif isinstance(data, dict):
239
- return {key: _parse_api_param(value) for key, value in data.items()}
293
+ return {key: _parse_api_client_param(value) for key, value in data.items()}
294
+ elif isinstance(data, list):
295
+ return [_parse_api_client_param(item) for item in data]
296
+ elif isinstance(data, tuple):
297
+ return tuple(_parse_api_client_param(item) for item in data)
298
+ elif isinstance(data, set):
299
+ return {_parse_api_client_param(item) for item in data}
240
300
  else:
241
301
  return data
302
+
303
+
304
+ def _get_api_client_method(route_param: RouteParam) -> str:
305
+ if isinstance(route_param.methods, list):
306
+ return route_param.methods[0].lower()
307
+ return route_param.methods.lower()
308
+
309
+
310
+ def _get_api_client_body_param_names(route_param: RouteParam, method: str):
311
+ sig = inspect.signature(route_param.func)
312
+ function_params = list(sig.parameters.values())
313
+ return [
314
+ p.name
315
+ for p in function_params
316
+ if (
317
+ p.name != "self"
318
+ and f"{{{p.name}}}" not in route_param.path
319
+ and p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
320
+ and (
321
+ method not in ["get", "delete"]
322
+ or (method == "delete" and p.annotation not in [str, float, bool])
323
+ )
324
+ )
325
+ ]
@@ -45,7 +45,7 @@ def create_default_filter_param_parser() -> (
45
45
  Callable[[SQLModel, str], list[ClauseElement]]
46
46
  ):
47
47
  def parse_filter_param(model: SQLModel, query: str) -> list[ClauseElement]:
48
- """
48
+ r"""
49
49
  Parse the filter parameter and return a list of SQLAlchemy ClauseElement objects.
50
50
 
51
51
  Args:
@@ -80,4 +80,5 @@ APP_AUTH_SECRET_KEY = os.getenv("MY_APP_NAME_AUTH_SECRET_KEY", "my-secret-key")
80
80
  APP_AUTH_PRIORITIZE_NEW_SESSION = (
81
81
  os.getenv("MY_APP_NAME_AUTH_PRIORITIZE_NEW_SESSION", "1").lower() in TRUE_STRS
82
82
  )
83
+
83
84
  APP_AUTH_BASE_URL = os.getenv("MY_APP_NAME_AUTH_BASE_URL", "http://localhost:3001")
@@ -32,18 +32,18 @@ def upgrade() -> None:
32
32
  sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
33
33
  sa.PrimaryKeyConstraint("id"),
34
34
  )
35
- op.create_index(op.f("ix_permission_name"), "permissions", ["name"], unique=True)
35
+ op.create_index(op.f("ix_permissions_name"), "permissions", ["name"], unique=True)
36
36
  op.create_index(
37
- op.f("ix_permission_created_at"), "permissions", ["created_at"], unique=False
37
+ op.f("ix_permissions_created_at"), "permissions", ["created_at"], unique=False
38
38
  )
39
39
  op.create_index(
40
- op.f("ix_permission_created_by"), "permissions", ["created_by"], unique=False
40
+ op.f("ix_permissions_created_by"), "permissions", ["created_by"], unique=False
41
41
  )
42
42
  op.create_index(
43
- op.f("ix_permission_updated_at"), "permissions", ["updated_at"], unique=False
43
+ op.f("ix_permissions_updated_at"), "permissions", ["updated_at"], unique=False
44
44
  )
45
45
  op.create_index(
46
- op.f("ix_permission_updated_by"), "permissions", ["updated_by"], unique=False
46
+ op.f("ix_permissions_updated_by"), "permissions", ["updated_by"], unique=False
47
47
  )
48
48
 
49
49
  op.create_table(
@@ -57,11 +57,11 @@ def upgrade() -> None:
57
57
  sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
58
58
  sa.PrimaryKeyConstraint("id"),
59
59
  )
60
- op.create_index(op.f("ix_role_name"), "roles", ["name"], unique=True)
61
- op.create_index(op.f("ix_role_created_at"), "roles", ["created_at"], unique=False)
62
- op.create_index(op.f("ix_role_created_by"), "roles", ["created_by"], unique=False)
63
- op.create_index(op.f("ix_role_updated_at"), "roles", ["updated_at"], unique=False)
64
- op.create_index(op.f("ix_role_updated_by"), "roles", ["updated_by"], unique=False)
60
+ op.create_index(op.f("ix_roles_name"), "roles", ["name"], unique=True)
61
+ op.create_index(op.f("ix_roles_created_at"), "roles", ["created_at"], unique=False)
62
+ op.create_index(op.f("ix_roles_created_by"), "roles", ["created_by"], unique=False)
63
+ op.create_index(op.f("ix_roles_updated_at"), "roles", ["updated_at"], unique=False)
64
+ op.create_index(op.f("ix_roles_updated_by"), "roles", ["updated_by"], unique=False)
65
65
 
66
66
  op.create_table(
67
67
  "role_permissions",
@@ -97,12 +97,12 @@ def upgrade() -> None:
97
97
  sa.Column("updated_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
98
98
  sa.PrimaryKeyConstraint("id"),
99
99
  )
100
- op.create_index(op.f("ix_user_username"), "users", ["username"], unique=True)
101
- op.create_index(op.f("ix_user_active"), "users", ["active"], unique=False)
102
- op.create_index(op.f("ix_user_created_at"), "users", ["created_at"], unique=False)
103
- op.create_index(op.f("ix_user_created_by"), "users", ["created_by"], unique=False)
104
- op.create_index(op.f("ix_user_updated_at"), "users", ["updated_at"], unique=False)
105
- op.create_index(op.f("ix_user_updated_by"), "users", ["updated_by"], unique=False)
100
+ op.create_index(op.f("ix_users_username"), "users", ["username"], unique=True)
101
+ op.create_index(op.f("ix_users_active"), "users", ["active"], unique=False)
102
+ op.create_index(op.f("ix_users_created_at"), "users", ["created_at"], unique=False)
103
+ op.create_index(op.f("ix_users_created_by"), "users", ["created_by"], unique=False)
104
+ op.create_index(op.f("ix_users_updated_at"), "users", ["updated_at"], unique=False)
105
+ op.create_index(op.f("ix_users_updated_by"), "users", ["updated_by"], unique=False)
106
106
 
107
107
  op.create_table(
108
108
  "user_roles",
@@ -131,24 +131,27 @@ def upgrade() -> None:
131
131
  sa.PrimaryKeyConstraint("id"),
132
132
  )
133
133
  op.create_index(
134
- op.f("ix_user_session_user_id"), "user_sessions", ["user_id"], unique=False
134
+ op.f("ix_user_sessions_user_id"), "user_sessions", ["user_id"], unique=False
135
135
  )
136
136
  op.create_index(
137
- op.f("ix_user_session_token"), "user_sessions", ["access_token"], unique=True
137
+ op.f("ix_user_sessions_access_token"),
138
+ "user_sessions",
139
+ ["access_token"],
140
+ unique=False,
138
141
  )
139
142
  op.create_index(
140
- op.f("ix_user_session_refresh_token"),
143
+ op.f("ix_user_sessions_refresh_token"),
141
144
  "user_sessions",
142
145
  ["refresh_token"],
143
- unique=True,
146
+ unique=False,
144
147
  )
145
148
  op.create_index(
146
- op.f("ix_user_session_access_token_expired_at"),
149
+ op.f("ix_user_sessions_access_token_expired_at"),
147
150
  "user_sessions",
148
151
  ["access_token_expired_at"],
149
152
  )
150
153
  op.create_index(
151
- op.f("ix_user_session_refresh_token_expired_at"),
154
+ op.f("ix_user_sessions_refresh_token_expired_at"),
152
155
  "user_sessions",
153
156
  ["refresh_token_expired_at"],
154
157
  )
@@ -157,14 +160,14 @@ def upgrade() -> None:
157
160
 
158
161
  def downgrade() -> None:
159
162
  # ### commands auto generated by Alembic - please adjust! ###
160
- op.drop_index(op.f("ix_user_session_user_id"), table_name="user_sessions")
161
- op.drop_index(op.f("ix_user_session_access_token"), table_name="user_sessions")
162
- op.drop_index(op.f("ix_user_session_refresh_token"), table_name="user_sessions")
163
+ op.drop_index(op.f("ix_user_sessions_user_id"), table_name="user_sessions")
164
+ op.drop_index(op.f("ix_user_sessions_access_token"), table_name="user_sessions")
165
+ op.drop_index(op.f("ix_user_sessions_refresh_token"), table_name="user_sessions")
163
166
  op.drop_index(
164
- op.f("ix_user_session_access_token_expired_at"), table_name="user_sessions"
167
+ op.f("ix_user_sessions_access_token_expired_at"), table_name="user_sessions"
165
168
  )
166
169
  op.drop_index(
167
- op.f("ix_user_session_refresh_token_expired_at"), table_name="user_sessions"
170
+ op.f("ix_user_sessions_refresh_token_expired_at"), table_name="user_sessions"
168
171
  )
169
172
  op.drop_table("user_sessions")
170
173
 
@@ -172,12 +175,12 @@ def downgrade() -> None:
172
175
  op.drop_index(op.f("ix_user_roles_role_id"), table_name="user_roles")
173
176
  op.drop_table("user_roles")
174
177
 
175
- op.drop_index(op.f("ix_user_username"), table_name="users")
176
- op.drop_index(op.f("ix_user_active"), table_name="users")
177
- op.drop_index(op.f("ix_user_updated_by"), table_name="users")
178
- op.drop_index(op.f("ix_user_updated_at"), table_name="users")
179
- op.drop_index(op.f("ix_user_created_by"), table_name="users")
180
- op.drop_index(op.f("ix_user_created_at"), table_name="users")
178
+ op.drop_index(op.f("ix_users_username"), table_name="users")
179
+ op.drop_index(op.f("ix_users_active"), table_name="users")
180
+ op.drop_index(op.f("ix_users_updated_by"), table_name="users")
181
+ op.drop_index(op.f("ix_users_updated_at"), table_name="users")
182
+ op.drop_index(op.f("ix_users_created_by"), table_name="users")
183
+ op.drop_index(op.f("ix_users_created_at"), table_name="users")
181
184
  op.drop_table("users")
182
185
 
183
186
  op.drop_index(op.f("ix_role_permissions_role_id"), table_name="role_permissions")
@@ -186,17 +189,17 @@ def downgrade() -> None:
186
189
  )
187
190
  op.drop_table("role_permissions")
188
191
 
189
- op.drop_index(op.f("ix_role_name"), table_name="roles")
190
- op.drop_index(op.f("ix_role_updated_by"), table_name="roles")
191
- op.drop_index(op.f("ix_role_updated_at"), table_name="roles")
192
- op.drop_index(op.f("ix_role_created_by"), table_name="roles")
193
- op.drop_index(op.f("ix_role_created_at"), table_name="roles")
192
+ op.drop_index(op.f("ix_roles_name"), table_name="roles")
193
+ op.drop_index(op.f("ix_roles_updated_by"), table_name="roles")
194
+ op.drop_index(op.f("ix_roles_updated_at"), table_name="roles")
195
+ op.drop_index(op.f("ix_roles_created_by"), table_name="roles")
196
+ op.drop_index(op.f("ix_roles_created_at"), table_name="roles")
194
197
  op.drop_table("roles")
195
198
 
196
- op.drop_index(op.f("ix_permission_updated_by"), table_name="permissions")
197
- op.drop_index(op.f("ix_permission_updated_at"), table_name="permissions")
198
- op.drop_index(op.f("ix_permission_created_by"), table_name="permissions")
199
- op.drop_index(op.f("ix_permission_created_at"), table_name="permissions")
200
- op.drop_index(op.f("ix_permission_name"), table_name="permissions")
199
+ op.drop_index(op.f("ix_permissions_updated_by"), table_name="permissions")
200
+ op.drop_index(op.f("ix_permissions_updated_at"), table_name="permissions")
201
+ op.drop_index(op.f("ix_permissions_created_by"), table_name="permissions")
202
+ op.drop_index(op.f("ix_permissions_created_at"), table_name="permissions")
203
+ op.drop_index(op.f("ix_permissions_name"), table_name="permissions")
201
204
  op.drop_table("permissions")
202
205
  # ### end Alembic commands ###