nsj-rest-lib2 0.0.34__tar.gz → 0.0.36__tar.gz
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.
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/PKG-INFO +1 -1
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/compiler.py +111 -3
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/dto_compiler.py +5 -1
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/api_model.py +18 -6
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/model.py +12 -0
- nsj_rest_lib2-0.0.36/nsj_rest_lib2/compiler/response_dto_compiler.py +104 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/util/type_naming_util.py +19 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/controller/dynamic_controller.py +84 -4
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/dto/escopo_dto.py +20 -1
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/service/entity_config_writer.py +24 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/service/entity_loader.py +201 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2.egg-info/PKG-INFO +1 -1
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2.egg-info/SOURCES.txt +2 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/setup.cfg +1 -1
- nsj_rest_lib2-0.0.36/tests/test_function_handler_compilation.py +472 -0
- nsj_rest_lib2-0.0.34/tests/test_function_handler_compilation.py +0 -159
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/README.md +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/compiler_structures.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/column_meta_model.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/entity_model.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/entity_model_base.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/entity_model_root.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/index_model.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/primitives.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/property_meta_model.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/repository_model.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/edl_model/trait_property_meta_model.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/entity_compiler.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/function_get_delete_compiler.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/function_insert_update_compiler.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/function_model.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/migration_compiler.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/migration_compiler_alter_table.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/migration_compiler_create_table.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/migration_compiler_util.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/property_compiler.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/util/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/util/relation_ref.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/util/str_util.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/util/type_util.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/controller/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/dto/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/entity/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/entity/escopo_entity.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/exception.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/redis_config.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/service/__init__.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/settings.py +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2.egg-info/dependency_links.txt +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2.egg-info/requires.txt +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2.egg-info/top_level.txt +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/pyproject.toml +0 -0
- {nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/tests/test_migration_generation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nsj_rest_lib2
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.36
|
|
4
4
|
Summary: Biblioteca para permitir a distribuição de rotas dinâmicas numa API, configuradas por meio de EDLs declarativos (em formato JSON).
|
|
5
5
|
Home-page: https://github.com/Nasajon/nsj_rest_lib2
|
|
6
6
|
Author: Nasajon Sistemas
|
|
@@ -28,6 +28,7 @@ from nsj_rest_lib2.compiler.util.type_naming_util import (
|
|
|
28
28
|
compile_entity_class_name,
|
|
29
29
|
compile_namespace_keys,
|
|
30
30
|
)
|
|
31
|
+
from nsj_rest_lib2.compiler.response_dto_compiler import ResponseDTOCompiler
|
|
31
32
|
from nsj_rest_lib2.compiler.util.relation_ref import RelationRefParser
|
|
32
33
|
|
|
33
34
|
from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
|
|
@@ -169,9 +170,12 @@ class EDLCompiler:
|
|
|
169
170
|
get_function_name = None
|
|
170
171
|
list_function_name = None
|
|
171
172
|
delete_function_name = None
|
|
173
|
+
handlers: dict[str, Any] = {}
|
|
174
|
+
post_handler = None
|
|
175
|
+
put_handler = None
|
|
176
|
+
patch_handler = None
|
|
172
177
|
|
|
173
178
|
if isinstance(entity_model, EntityModel) and entity_model.api:
|
|
174
|
-
handlers = {}
|
|
175
179
|
if entity_model.api.handlers:
|
|
176
180
|
handlers = {
|
|
177
181
|
(verb or "").lower(): handler
|
|
@@ -179,16 +183,20 @@ class EDLCompiler:
|
|
|
179
183
|
if handler
|
|
180
184
|
}
|
|
181
185
|
|
|
186
|
+
post_handler = handlers.get("post")
|
|
187
|
+
put_handler = handlers.get("put")
|
|
188
|
+
patch_handler = handlers.get("patch")
|
|
189
|
+
|
|
182
190
|
insert_output = self._function_compiler.compile_insert(
|
|
183
191
|
entity_model,
|
|
184
192
|
properties_structure,
|
|
185
|
-
|
|
193
|
+
post_handler,
|
|
186
194
|
prefx_class_name,
|
|
187
195
|
)
|
|
188
196
|
update_output = self._function_compiler.compile_update(
|
|
189
197
|
entity_model,
|
|
190
198
|
properties_structure,
|
|
191
|
-
|
|
199
|
+
put_handler,
|
|
192
200
|
prefx_class_name,
|
|
193
201
|
)
|
|
194
202
|
get_handler = handlers.get("get")
|
|
@@ -354,6 +362,16 @@ class EDLCompiler:
|
|
|
354
362
|
# Adicionando as dependências das relações
|
|
355
363
|
relations_dependencies_complete.extend(relations_dependencies)
|
|
356
364
|
|
|
365
|
+
response_dto_compiler = ResponseDTOCompiler(
|
|
366
|
+
dto_compiler=self._dto_compiler,
|
|
367
|
+
entity_model=entity_model,
|
|
368
|
+
prefx_class_name=prefx_class_name,
|
|
369
|
+
ast_dto_attributes=ast_dto_attributes,
|
|
370
|
+
aux_classes=aux_classes,
|
|
371
|
+
related_imports=related_imports,
|
|
372
|
+
fixed_filters=fixed_filters,
|
|
373
|
+
)
|
|
374
|
+
|
|
357
375
|
# Adicionando as dependências da extensão parcial
|
|
358
376
|
if partial_metadata and partial_base_model:
|
|
359
377
|
relation_dependency = RelationDependency()
|
|
@@ -367,6 +385,68 @@ class EDLCompiler:
|
|
|
367
385
|
relation_dependency.grupo_empresarial = partial_base_model.grupo_empresarial
|
|
368
386
|
relations_dependencies_complete.append(relation_dependency)
|
|
369
387
|
|
|
388
|
+
post_expected = "empty"
|
|
389
|
+
put_expected = "empty"
|
|
390
|
+
patch_expected = "empty"
|
|
391
|
+
get_expected = "empty"
|
|
392
|
+
list_expected = "empty"
|
|
393
|
+
delete_expected = "empty"
|
|
394
|
+
post_properties = None
|
|
395
|
+
put_properties = None
|
|
396
|
+
patch_properties = None
|
|
397
|
+
if isinstance(entity_model, EntityModel) and entity_model.api:
|
|
398
|
+
post_expected, post_properties = (
|
|
399
|
+
response_dto_compiler.handler_result_details(post_handler)
|
|
400
|
+
)
|
|
401
|
+
put_expected, put_properties = (
|
|
402
|
+
response_dto_compiler.handler_result_details(put_handler)
|
|
403
|
+
)
|
|
404
|
+
patch_expected, patch_properties = (
|
|
405
|
+
response_dto_compiler.handler_result_details(patch_handler)
|
|
406
|
+
)
|
|
407
|
+
get_expected, _ = response_dto_compiler.handler_result_details(
|
|
408
|
+
get_handler
|
|
409
|
+
)
|
|
410
|
+
list_expected, _ = response_dto_compiler.handler_result_details(
|
|
411
|
+
list_handler
|
|
412
|
+
)
|
|
413
|
+
delete_expected, _ = response_dto_compiler.handler_result_details(
|
|
414
|
+
delete_handler
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
if post_expected == "partial_row":
|
|
418
|
+
post_class_name, post_code = (
|
|
419
|
+
response_dto_compiler.compile_partial_response_dto(
|
|
420
|
+
"post", post_properties or []
|
|
421
|
+
)
|
|
422
|
+
)
|
|
423
|
+
compiler_result_post_class = post_class_name
|
|
424
|
+
dto_code += "\n\n" + post_code
|
|
425
|
+
else:
|
|
426
|
+
compiler_result_post_class = None
|
|
427
|
+
|
|
428
|
+
if put_expected == "partial_row":
|
|
429
|
+
put_class_name, put_code = (
|
|
430
|
+
response_dto_compiler.compile_partial_response_dto(
|
|
431
|
+
"put", put_properties or []
|
|
432
|
+
)
|
|
433
|
+
)
|
|
434
|
+
compiler_result_put_class = put_class_name
|
|
435
|
+
dto_code += "\n\n" + put_code
|
|
436
|
+
else:
|
|
437
|
+
compiler_result_put_class = None
|
|
438
|
+
|
|
439
|
+
if patch_expected == "partial_row":
|
|
440
|
+
patch_class_name, patch_code = (
|
|
441
|
+
response_dto_compiler.compile_partial_response_dto(
|
|
442
|
+
"patch", patch_properties or []
|
|
443
|
+
)
|
|
444
|
+
)
|
|
445
|
+
compiler_result_patch_class = patch_class_name
|
|
446
|
+
dto_code += "\n\n" + patch_code
|
|
447
|
+
else:
|
|
448
|
+
compiler_result_patch_class = None
|
|
449
|
+
|
|
370
450
|
# Construindo o resultado
|
|
371
451
|
compiler_result = CompilerResult()
|
|
372
452
|
compiler_result.entity_class_name = entity_class_name
|
|
@@ -389,6 +469,34 @@ class EDLCompiler:
|
|
|
389
469
|
compiler_result.source_delete_function_type = (
|
|
390
470
|
delete_function_code.strip() or None
|
|
391
471
|
)
|
|
472
|
+
compiler_result.retrieve_after_insert = post_expected == "entity_row"
|
|
473
|
+
compiler_result.retrieve_after_update = put_expected == "entity_row"
|
|
474
|
+
compiler_result.retrieve_after_partial_update = (
|
|
475
|
+
patch_expected == "entity_row"
|
|
476
|
+
)
|
|
477
|
+
compiler_result.post_response_dto_class_name = compiler_result_post_class
|
|
478
|
+
compiler_result.put_response_dto_class_name = compiler_result_put_class
|
|
479
|
+
compiler_result.patch_response_dto_class_name = (
|
|
480
|
+
compiler_result_patch_class
|
|
481
|
+
)
|
|
482
|
+
compiler_result.custom_json_post_response = (
|
|
483
|
+
post_expected == "custom_json"
|
|
484
|
+
)
|
|
485
|
+
compiler_result.custom_json_put_response = (
|
|
486
|
+
put_expected == "custom_json"
|
|
487
|
+
)
|
|
488
|
+
compiler_result.custom_json_patch_response = (
|
|
489
|
+
patch_expected == "custom_json"
|
|
490
|
+
)
|
|
491
|
+
compiler_result.custom_json_get_response = (
|
|
492
|
+
get_expected == "custom_json"
|
|
493
|
+
)
|
|
494
|
+
compiler_result.custom_json_list_response = (
|
|
495
|
+
list_expected == "custom_json"
|
|
496
|
+
)
|
|
497
|
+
compiler_result.custom_json_delete_response = (
|
|
498
|
+
delete_expected == "custom_json"
|
|
499
|
+
)
|
|
392
500
|
|
|
393
501
|
insert_code_compiled = insert_function_code.strip()
|
|
394
502
|
update_code_compiled = update_function_code.strip()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import ast
|
|
2
|
+
from typing import Optional
|
|
2
3
|
|
|
3
4
|
import black
|
|
4
5
|
|
|
@@ -21,6 +22,7 @@ class DTOCompiler:
|
|
|
21
22
|
fixed_filters: list[tuple[str, BasicTypes]],
|
|
22
23
|
prefx_class_name: str,
|
|
23
24
|
partial_metadata: dict[str, str] | None,
|
|
25
|
+
class_name_override: Optional[str] = None,
|
|
24
26
|
) -> tuple[str, str]:
|
|
25
27
|
"""
|
|
26
28
|
Compila o código do DTO a partir do AST e retorna o código compilado.
|
|
@@ -158,7 +160,9 @@ class DTOCompiler:
|
|
|
158
160
|
)
|
|
159
161
|
|
|
160
162
|
# Criando o ast da classe
|
|
161
|
-
class_name = compile_dto_class_name(
|
|
163
|
+
class_name = class_name_override or compile_dto_class_name(
|
|
164
|
+
entity_model.id, prefx_class_name
|
|
165
|
+
)
|
|
162
166
|
ast_class = ast.ClassDef(
|
|
163
167
|
name=class_name,
|
|
164
168
|
bases=[ast.Name(id="DTOBase", ctx=ast.Load())],
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Dict, List, Literal, Optional
|
|
4
4
|
|
|
5
|
-
from pydantic import AliasChoices, BaseModel, Field
|
|
5
|
+
from pydantic import AliasChoices, BaseModel, Field, model_validator
|
|
6
6
|
|
|
7
7
|
APIVerbs = Literal["GET", "POST", "PUT", "DELETE", "PATCH"]
|
|
8
8
|
|
|
@@ -46,10 +46,22 @@ class HandlerCall(BaseModel):
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
class HandlerResult(BaseModel):
|
|
49
|
-
expected: Literal["empty", "entity_row"] = Field(
|
|
49
|
+
expected: Literal["empty", "entity_row", "custom_json", "partial_row"] = Field(
|
|
50
50
|
default="empty",
|
|
51
51
|
description="Define o formato esperado do retorno da função.",
|
|
52
52
|
)
|
|
53
|
+
properties: Optional[List[str]] = Field(
|
|
54
|
+
default=None,
|
|
55
|
+
description="Lista de propriedades a serem retornadas quando o resultado esperado for 'partial_row'.",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
@model_validator(mode="after")
|
|
59
|
+
def validate_partial_row(self):
|
|
60
|
+
if self.expected == "partial_row" and not self.properties:
|
|
61
|
+
raise ValueError(
|
|
62
|
+
"result.properties é obrigatório quando result.expected for 'partial_row'."
|
|
63
|
+
)
|
|
64
|
+
return self
|
|
53
65
|
|
|
54
66
|
|
|
55
67
|
class HandlerError(BaseModel):
|
|
@@ -68,12 +80,12 @@ class HandlerError(BaseModel):
|
|
|
68
80
|
|
|
69
81
|
|
|
70
82
|
class HandlerConfig(BaseModel):
|
|
71
|
-
impl: Literal["pg_function"] = Field(
|
|
72
|
-
|
|
83
|
+
impl: Optional[Literal["pg_function"]] = Field(
|
|
84
|
+
default=None,
|
|
73
85
|
description="Somente funções PostgreSQL (pg_function) são suportadas neste estágio.",
|
|
74
86
|
)
|
|
75
|
-
function_ref: str = Field(
|
|
76
|
-
|
|
87
|
+
function_ref: Optional[str] = Field(
|
|
88
|
+
default=None,
|
|
77
89
|
description="Referência qualificada para a função no banco (ex.: schema.fn_nome).",
|
|
78
90
|
)
|
|
79
91
|
call: Optional[HandlerCall] = Field(
|
|
@@ -59,3 +59,15 @@ class CompilerResult:
|
|
|
59
59
|
self.source_get_function_type: str | None = None
|
|
60
60
|
self.source_list_function_type: str | None = None
|
|
61
61
|
self.source_delete_function_type: str | None = None
|
|
62
|
+
self.retrieve_after_insert: bool | None = None
|
|
63
|
+
self.retrieve_after_update: bool | None = None
|
|
64
|
+
self.retrieve_after_partial_update: bool | None = None
|
|
65
|
+
self.post_response_dto_class_name: str | None = None
|
|
66
|
+
self.put_response_dto_class_name: str | None = None
|
|
67
|
+
self.patch_response_dto_class_name: str | None = None
|
|
68
|
+
self.custom_json_post_response: bool | None = None
|
|
69
|
+
self.custom_json_put_response: bool | None = None
|
|
70
|
+
self.custom_json_patch_response: bool | None = None
|
|
71
|
+
self.custom_json_get_response: bool | None = None
|
|
72
|
+
self.custom_json_list_response: bool | None = None
|
|
73
|
+
self.custom_json_delete_response: bool | None = None
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
from nsj_rest_lib2.compiler.dto_compiler import DTOCompiler
|
|
7
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
|
|
8
|
+
from nsj_rest_lib2.compiler.edl_model.primitives import BasicTypes
|
|
9
|
+
from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
|
|
10
|
+
from nsj_rest_lib2.compiler.util.type_naming_util import (
|
|
11
|
+
compile_response_dto_class_name,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ResponseDTOCompiler:
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
dto_compiler: DTOCompiler,
|
|
19
|
+
entity_model: EntityModelBase,
|
|
20
|
+
prefx_class_name: str,
|
|
21
|
+
ast_dto_attributes: list[ast.stmt],
|
|
22
|
+
aux_classes: list[ast.stmt],
|
|
23
|
+
related_imports: list[tuple[str, str, str]],
|
|
24
|
+
fixed_filters: list[tuple[str, BasicTypes]],
|
|
25
|
+
) -> None:
|
|
26
|
+
self._dto_compiler = dto_compiler
|
|
27
|
+
self._entity_model = entity_model
|
|
28
|
+
self._prefx_class_name = prefx_class_name
|
|
29
|
+
self._aux_classes = aux_classes
|
|
30
|
+
self._related_imports = related_imports
|
|
31
|
+
self._fixed_filters = fixed_filters
|
|
32
|
+
self._dto_attr_map = self._build_attr_map(ast_dto_attributes)
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def handler_result_details(handler: Any) -> tuple[str, list[str] | None]:
|
|
36
|
+
expected = "empty"
|
|
37
|
+
properties = None
|
|
38
|
+
if handler and getattr(handler, "result", None):
|
|
39
|
+
expected = handler.result.expected or "empty"
|
|
40
|
+
properties = handler.result.properties
|
|
41
|
+
return (expected, properties)
|
|
42
|
+
|
|
43
|
+
def compile_partial_response_dto(
|
|
44
|
+
self, verb: str, properties: list[str]
|
|
45
|
+
) -> tuple[str, str]:
|
|
46
|
+
if not properties:
|
|
47
|
+
raise Exception(
|
|
48
|
+
f"result.properties não pode ser vazio para '{verb}' na entidade '{self._entity_model.id}'."
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
normalized = [
|
|
52
|
+
CompilerStrUtil.to_snake_case(prop) for prop in properties
|
|
53
|
+
]
|
|
54
|
+
missing = [
|
|
55
|
+
properties[idx]
|
|
56
|
+
for idx, norm in enumerate(normalized)
|
|
57
|
+
if norm not in self._dto_attr_map
|
|
58
|
+
]
|
|
59
|
+
if missing:
|
|
60
|
+
raise Exception(
|
|
61
|
+
f"As propriedades {missing} não foram encontradas na entidade '{self._entity_model.id}'."
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
filtered_attrs = [self._dto_attr_map[name] for name in normalized]
|
|
65
|
+
filtered_fixed_filters = [
|
|
66
|
+
item for item in self._fixed_filters if item[0] in normalized
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
class_name = compile_response_dto_class_name(
|
|
70
|
+
self._entity_model.id,
|
|
71
|
+
self._prefx_class_name,
|
|
72
|
+
verb,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return self._dto_compiler.compile(
|
|
76
|
+
self._entity_model,
|
|
77
|
+
filtered_attrs,
|
|
78
|
+
self._aux_classes,
|
|
79
|
+
self._related_imports,
|
|
80
|
+
filtered_fixed_filters,
|
|
81
|
+
self._prefx_class_name,
|
|
82
|
+
None,
|
|
83
|
+
class_name_override=class_name,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def _extract_attr_name(stmt: ast.stmt) -> Optional[str]:
|
|
88
|
+
if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name):
|
|
89
|
+
return stmt.target.id
|
|
90
|
+
if isinstance(stmt, ast.Assign) and stmt.targets:
|
|
91
|
+
target = stmt.targets[0]
|
|
92
|
+
if isinstance(target, ast.Name):
|
|
93
|
+
return target.id
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
def _build_attr_map(
|
|
97
|
+
self, ast_dto_attributes: list[ast.stmt]
|
|
98
|
+
) -> dict[str, ast.stmt]:
|
|
99
|
+
dto_attr_map: dict[str, ast.stmt] = {}
|
|
100
|
+
for stmt in ast_dto_attributes:
|
|
101
|
+
name = self._extract_attr_name(stmt)
|
|
102
|
+
if name:
|
|
103
|
+
dto_attr_map[name] = stmt
|
|
104
|
+
return dto_attr_map
|
{nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/compiler/util/type_naming_util.py
RENAMED
|
@@ -18,6 +18,25 @@ def compile_dto_class_name(entity_id: str, prefx_class_name: str = "") -> str:
|
|
|
18
18
|
return f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}{CompilerStrUtil.to_pascal_case(entity_id)}DTO"
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
def compile_response_dto_class_name(
|
|
22
|
+
entity_id: str, prefx_class_name: str, verb: str
|
|
23
|
+
) -> str:
|
|
24
|
+
verb = (verb or "").lower()
|
|
25
|
+
suffix_map = {
|
|
26
|
+
"post": "PostResponseDTO",
|
|
27
|
+
"put": "PutResponseDTO",
|
|
28
|
+
"patch": "PatchResponseDTO",
|
|
29
|
+
}
|
|
30
|
+
suffix = suffix_map.get(
|
|
31
|
+
verb, f"{CompilerStrUtil.to_pascal_case(verb)}ResponseDTO"
|
|
32
|
+
)
|
|
33
|
+
return (
|
|
34
|
+
f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}"
|
|
35
|
+
f"{CompilerStrUtil.to_pascal_case(entity_id)}"
|
|
36
|
+
f"{suffix}"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
21
40
|
def compile_entity_class_name(entity_id: str, prefx_class_name: str = "") -> str:
|
|
22
41
|
return f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}{CompilerStrUtil.to_pascal_case(entity_id)}Entity"
|
|
23
42
|
|
{nsj_rest_lib2-0.0.34 → nsj_rest_lib2-0.0.36}/nsj_rest_lib2/controller/dynamic_controller.py
RENAMED
|
@@ -11,12 +11,12 @@ from nsj_gcf_utils.rest_error_util import format_json_error
|
|
|
11
11
|
from nsj_multi_database_lib.decorator.multi_database import multi_database
|
|
12
12
|
|
|
13
13
|
from nsj_rest_lib.controller.controller_util import DEFAULT_RESP_HEADERS
|
|
14
|
-
from nsj_rest_lib.controller.
|
|
14
|
+
from nsj_rest_lib.controller.delete_route import DeleteRoute
|
|
15
15
|
from nsj_rest_lib.controller.get_route import GetRoute
|
|
16
|
+
from nsj_rest_lib.controller.list_route import ListRoute
|
|
17
|
+
from nsj_rest_lib.controller.patch_route import PatchRoute
|
|
16
18
|
from nsj_rest_lib.controller.post_route import PostRoute
|
|
17
19
|
from nsj_rest_lib.controller.put_route import PutRoute
|
|
18
|
-
from nsj_rest_lib.controller.patch_route import PatchRoute
|
|
19
|
-
from nsj_rest_lib.controller.delete_route import DeleteRoute
|
|
20
20
|
|
|
21
21
|
from nsj_rest_lib2.exception import MissingEntityConfigException
|
|
22
22
|
from nsj_rest_lib2.service.entity_loader import EntityLoader
|
|
@@ -133,6 +133,10 @@ def setup_dynamic_routes(
|
|
|
133
133
|
_get_function_type_class_name,
|
|
134
134
|
list_function_type_class_name,
|
|
135
135
|
_delete_function_type_class_name,
|
|
136
|
+
*_,
|
|
137
|
+
_custom_json_get_response,
|
|
138
|
+
custom_json_list_response,
|
|
139
|
+
_custom_json_delete_response,
|
|
136
140
|
) = entity_config
|
|
137
141
|
|
|
138
142
|
def list_dynamic(*args: Any, **kwargs: Any) -> Any:
|
|
@@ -149,6 +153,7 @@ def setup_dynamic_routes(
|
|
|
149
153
|
list_function_type_class=etities_dict.get(
|
|
150
154
|
list_function_type_class_name
|
|
151
155
|
),
|
|
156
|
+
custom_json_response=bool(custom_json_list_response),
|
|
152
157
|
)
|
|
153
158
|
|
|
154
159
|
return route.handle_request(*args, **kwargs)
|
|
@@ -173,6 +178,10 @@ def setup_dynamic_routes(
|
|
|
173
178
|
get_function_type_class_name,
|
|
174
179
|
_list_function_type_class_name,
|
|
175
180
|
_delete_function_type_class_name,
|
|
181
|
+
*_,
|
|
182
|
+
custom_json_get_response,
|
|
183
|
+
_custom_json_list_response,
|
|
184
|
+
_custom_json_delete_response,
|
|
176
185
|
) = entity_config
|
|
177
186
|
|
|
178
187
|
def get_dynamic(*args: Any, **kwargs: Any) -> Any:
|
|
@@ -187,6 +196,7 @@ def setup_dynamic_routes(
|
|
|
187
196
|
injector_factory=injector_factory,
|
|
188
197
|
get_function_name=get_function_name,
|
|
189
198
|
get_function_type_class=etities_dict.get(get_function_type_class_name),
|
|
199
|
+
custom_json_response=bool(custom_json_get_response),
|
|
190
200
|
)
|
|
191
201
|
|
|
192
202
|
return route.handle_request(*args, **kwargs)
|
|
@@ -211,6 +221,18 @@ def setup_dynamic_routes(
|
|
|
211
221
|
_get_function_type_class_name,
|
|
212
222
|
_list_function_type_class_name,
|
|
213
223
|
_delete_function_type_class_name,
|
|
224
|
+
retrieve_after_insert,
|
|
225
|
+
_retrieve_after_update,
|
|
226
|
+
_retrieve_after_partial_update,
|
|
227
|
+
post_response_dto_class_name,
|
|
228
|
+
_put_response_dto_class_name,
|
|
229
|
+
_patch_response_dto_class_name,
|
|
230
|
+
custom_json_post_response,
|
|
231
|
+
_custom_json_put_response,
|
|
232
|
+
_custom_json_patch_response,
|
|
233
|
+
_custom_json_get_response,
|
|
234
|
+
_custom_json_list_response,
|
|
235
|
+
_custom_json_delete_response,
|
|
214
236
|
) = entity_config
|
|
215
237
|
|
|
216
238
|
def post_dynamic(*args: Any, **kwargs: Any) -> Any:
|
|
@@ -223,6 +245,12 @@ def setup_dynamic_routes(
|
|
|
223
245
|
else None
|
|
224
246
|
)
|
|
225
247
|
|
|
248
|
+
dto_response_class = (
|
|
249
|
+
etities_dict.get(post_response_dto_class_name)
|
|
250
|
+
if post_response_dto_class_name
|
|
251
|
+
else None
|
|
252
|
+
)
|
|
253
|
+
|
|
226
254
|
route = PostRoute(
|
|
227
255
|
url=COLLECTION_DYNAMIC_ROUTE,
|
|
228
256
|
http_method="POST",
|
|
@@ -231,6 +259,9 @@ def setup_dynamic_routes(
|
|
|
231
259
|
injector_factory=injector_factory,
|
|
232
260
|
insert_function_type_class=insert_function_type_class,
|
|
233
261
|
insert_function_name=insert_function_name,
|
|
262
|
+
dto_response_class=dto_response_class,
|
|
263
|
+
retrieve_after_insert=retrieve_after_insert,
|
|
264
|
+
custom_json_response=bool(custom_json_post_response),
|
|
234
265
|
)
|
|
235
266
|
|
|
236
267
|
return route.handle_request(*args, **kwargs)
|
|
@@ -255,8 +286,26 @@ def setup_dynamic_routes(
|
|
|
255
286
|
_get_function_type_class_name,
|
|
256
287
|
_list_function_type_class_name,
|
|
257
288
|
_delete_function_type_class_name,
|
|
289
|
+
_retrieve_after_insert,
|
|
290
|
+
retrieve_after_update,
|
|
291
|
+
_retrieve_after_partial_update,
|
|
292
|
+
_post_response_dto_class_name,
|
|
293
|
+
put_response_dto_class_name,
|
|
294
|
+
_patch_response_dto_class_name,
|
|
295
|
+
_custom_json_post_response,
|
|
296
|
+
custom_json_put_response,
|
|
297
|
+
_custom_json_patch_response,
|
|
298
|
+
_custom_json_get_response,
|
|
299
|
+
_custom_json_list_response,
|
|
300
|
+
_custom_json_delete_response,
|
|
258
301
|
) = entity_config
|
|
259
302
|
|
|
303
|
+
dto_response_class = (
|
|
304
|
+
etities_dict.get(put_response_dto_class_name)
|
|
305
|
+
if put_response_dto_class_name
|
|
306
|
+
else None
|
|
307
|
+
)
|
|
308
|
+
|
|
260
309
|
def put_dynamic(*args: Any, **kwargs: Any) -> Any:
|
|
261
310
|
if not api_expose or "PUT" not in api_verbs:
|
|
262
311
|
return ("", 405, {})
|
|
@@ -275,6 +324,9 @@ def setup_dynamic_routes(
|
|
|
275
324
|
injector_factory=injector_factory,
|
|
276
325
|
update_function_type_class=update_function_type_class,
|
|
277
326
|
update_function_name=update_function_name,
|
|
327
|
+
dto_response_class=dto_response_class,
|
|
328
|
+
retrieve_after_update=retrieve_after_update,
|
|
329
|
+
custom_json_response=bool(custom_json_put_response),
|
|
278
330
|
)
|
|
279
331
|
|
|
280
332
|
return route.handle_request(*args, **kwargs)
|
|
@@ -296,19 +348,42 @@ def setup_dynamic_routes(
|
|
|
296
348
|
_get_function_name,
|
|
297
349
|
_list_function_name,
|
|
298
350
|
_delete_function_name,
|
|
299
|
-
|
|
351
|
+
_get_function_type_class_name,
|
|
352
|
+
_list_function_type_class_name,
|
|
353
|
+
_delete_function_type_class_name,
|
|
354
|
+
_retrieve_after_insert,
|
|
355
|
+
_retrieve_after_update,
|
|
356
|
+
retrieve_after_partial_update,
|
|
357
|
+
_post_response_dto_class_name,
|
|
358
|
+
_put_response_dto_class_name,
|
|
359
|
+
patch_response_dto_class_name,
|
|
360
|
+
_custom_json_post_response,
|
|
361
|
+
_custom_json_put_response,
|
|
362
|
+
custom_json_patch_response,
|
|
363
|
+
_custom_json_get_response,
|
|
364
|
+
_custom_json_list_response,
|
|
365
|
+
_custom_json_delete_response,
|
|
300
366
|
) = entity_config
|
|
301
367
|
|
|
302
368
|
def patch_dynamic(*args: Any, **kwargs: Any) -> Any:
|
|
303
369
|
if not api_expose or "PATCH" not in api_verbs:
|
|
304
370
|
return ("", 405, {})
|
|
305
371
|
|
|
372
|
+
dto_response_class = (
|
|
373
|
+
etities_dict.get(patch_response_dto_class_name)
|
|
374
|
+
if patch_response_dto_class_name
|
|
375
|
+
else None
|
|
376
|
+
)
|
|
377
|
+
|
|
306
378
|
route = PatchRoute(
|
|
307
379
|
url=ONE_DYNAMIC_ROUTE,
|
|
308
380
|
http_method="PATCH",
|
|
309
381
|
dto_class=etities_dict[dto_class_name],
|
|
310
382
|
entity_class=etities_dict[entity_class_name],
|
|
311
383
|
injector_factory=injector_factory,
|
|
384
|
+
dto_response_class=dto_response_class,
|
|
385
|
+
retrieve_after_partial_update=retrieve_after_partial_update,
|
|
386
|
+
custom_json_response=bool(custom_json_patch_response),
|
|
312
387
|
)
|
|
313
388
|
|
|
314
389
|
return route.handle_request(*args, **kwargs)
|
|
@@ -333,6 +408,10 @@ def setup_dynamic_routes(
|
|
|
333
408
|
_get_function_type_class_name,
|
|
334
409
|
_list_function_type_class_name,
|
|
335
410
|
delete_function_type_class_name,
|
|
411
|
+
*_,
|
|
412
|
+
_custom_json_get_response,
|
|
413
|
+
_custom_json_list_response,
|
|
414
|
+
custom_json_delete_response,
|
|
336
415
|
) = entity_config
|
|
337
416
|
|
|
338
417
|
def delete_dynamic(*args: Any, **kwargs: Any) -> Any:
|
|
@@ -349,6 +428,7 @@ def setup_dynamic_routes(
|
|
|
349
428
|
delete_function_type_class=etities_dict.get(
|
|
350
429
|
delete_function_type_class_name
|
|
351
430
|
),
|
|
431
|
+
custom_json_response=bool(custom_json_delete_response),
|
|
352
432
|
)
|
|
353
433
|
|
|
354
434
|
return route.handle_request(*args, **kwargs)
|
|
@@ -6,6 +6,25 @@ from nsj_rest_lib.descriptor.dto_field_validators import DTOFieldValidators
|
|
|
6
6
|
from nsj_rest_lib.dto.dto_base import DTOBase
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
def _validate_service_account(dto_field: DTOField, value):
|
|
10
|
+
if value is None:
|
|
11
|
+
return None
|
|
12
|
+
|
|
13
|
+
if not isinstance(value, str):
|
|
14
|
+
raise ValueError(
|
|
15
|
+
f"{dto_field.storage_name} deve ser do tipo string. Valor recebido: {value}."
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
value = value.strip()
|
|
19
|
+
|
|
20
|
+
if not value.startswith("serv_acc_"):
|
|
21
|
+
raise ValueError(
|
|
22
|
+
f"{dto_field.storage_name} deve comecar com \"serv_acc_\". Valor recebido: {value}."
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
return DTOFieldValidators().validate_email(dto_field, value)
|
|
26
|
+
|
|
27
|
+
|
|
9
28
|
@DTO()
|
|
10
29
|
class EscopoDTO(DTOBase):
|
|
11
30
|
|
|
@@ -35,5 +54,5 @@ class EscopoDTO(DTOBase):
|
|
|
35
54
|
strip=True,
|
|
36
55
|
min=5,
|
|
37
56
|
max=320,
|
|
38
|
-
validator=
|
|
57
|
+
validator=_validate_service_account,
|
|
39
58
|
)
|
|
@@ -86,6 +86,18 @@ class EntityConfigWriter:
|
|
|
86
86
|
"source_get_function_type": compiler_result.source_get_function_type,
|
|
87
87
|
"source_list_function_type": compiler_result.source_list_function_type,
|
|
88
88
|
"source_delete_function_type": compiler_result.source_delete_function_type,
|
|
89
|
+
"retrieve_after_insert": compiler_result.retrieve_after_insert,
|
|
90
|
+
"retrieve_after_update": compiler_result.retrieve_after_update,
|
|
91
|
+
"retrieve_after_partial_update": compiler_result.retrieve_after_partial_update,
|
|
92
|
+
"post_response_dto_class_name": compiler_result.post_response_dto_class_name,
|
|
93
|
+
"put_response_dto_class_name": compiler_result.put_response_dto_class_name,
|
|
94
|
+
"patch_response_dto_class_name": compiler_result.patch_response_dto_class_name,
|
|
95
|
+
"custom_json_post_response": compiler_result.custom_json_post_response,
|
|
96
|
+
"custom_json_put_response": compiler_result.custom_json_put_response,
|
|
97
|
+
"custom_json_patch_response": compiler_result.custom_json_patch_response,
|
|
98
|
+
"custom_json_get_response": compiler_result.custom_json_get_response,
|
|
99
|
+
"custom_json_list_response": compiler_result.custom_json_list_response,
|
|
100
|
+
"custom_json_delete_response": compiler_result.custom_json_delete_response,
|
|
89
101
|
"source_dto": compiler_result.dto_code,
|
|
90
102
|
"source_entity": compiler_result.entity_code,
|
|
91
103
|
"entity_hash": entity_hash
|
|
@@ -142,6 +154,18 @@ class EntityConfigWriter:
|
|
|
142
154
|
compiler_result.source_get_function_type,
|
|
143
155
|
compiler_result.source_list_function_type,
|
|
144
156
|
compiler_result.source_delete_function_type,
|
|
157
|
+
compiler_result.post_response_dto_class_name,
|
|
158
|
+
compiler_result.put_response_dto_class_name,
|
|
159
|
+
compiler_result.patch_response_dto_class_name,
|
|
160
|
+
str(compiler_result.retrieve_after_insert),
|
|
161
|
+
str(compiler_result.retrieve_after_update),
|
|
162
|
+
str(compiler_result.retrieve_after_partial_update),
|
|
163
|
+
str(compiler_result.custom_json_post_response),
|
|
164
|
+
str(compiler_result.custom_json_put_response),
|
|
165
|
+
str(compiler_result.custom_json_patch_response),
|
|
166
|
+
str(compiler_result.custom_json_get_response),
|
|
167
|
+
str(compiler_result.custom_json_list_response),
|
|
168
|
+
str(compiler_result.custom_json_delete_response),
|
|
145
169
|
compiler_result.service_account,
|
|
146
170
|
):
|
|
147
171
|
hasher.update(content)
|