nsj-rest-lib2 0.0.13__tar.gz → 0.0.15__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.13 → nsj_rest_lib2-0.0.15}/PKG-INFO +1 -1
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/compiler.py +144 -29
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/compiler_structures.py +6 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/dto_compiler.py +4 -3
- nsj_rest_lib2-0.0.15/nsj_rest_lib2/compiler/edl_model/entity_model.py +22 -0
- nsj_rest_lib2-0.0.13/nsj_rest_lib2/compiler/edl_model/entity_model.py → nsj_rest_lib2-0.0.15/nsj_rest_lib2/compiler/edl_model/entity_model_base.py +14 -15
- nsj_rest_lib2-0.0.15/nsj_rest_lib2/compiler/edl_model/entity_model_mixin.py +7 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/primitives.py +1 -1
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/entity_compiler.py +9 -4
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/property_compiler.py +160 -33
- nsj_rest_lib2-0.0.15/nsj_rest_lib2/compiler/util/type_naming_util.py +21 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/service/entity_loader.py +7 -1
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2.egg-info/PKG-INFO +1 -1
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2.egg-info/SOURCES.txt +4 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/setup.cfg +1 -1
- nsj_rest_lib2-0.0.13/nsj_rest_lib2/compiler/util/type_naming_util.py +0 -21
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/README.md +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/__init__.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/__init__.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/ai_compiler.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/__init__.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/api_model.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/column_meta_model.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/index_model.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/property_meta_model.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/repository_model.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/trait_property_meta_model.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/model.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/util/__init__.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/util/str_util.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/util/type_util.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/controller/__init__.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/controller/dynamic_controller.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/exception.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/redis_config.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/service/__init__.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/settings.py +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2.egg-info/dependency_links.txt +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2.egg-info/requires.txt +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2.egg-info/top_level.txt +0 -0
- {nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/pyproject.toml +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.15
|
|
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
|
|
@@ -3,10 +3,13 @@ import re
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
5
|
from nsj_rest_lib2.compiler.compiler_structures import (
|
|
6
|
+
ComponentsCompilerStructure,
|
|
6
7
|
IndexCompilerStructure,
|
|
7
8
|
PropertiesCompilerStructure,
|
|
8
9
|
)
|
|
9
10
|
from nsj_rest_lib2.compiler.dto_compiler import DTOCompiler
|
|
11
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
|
|
12
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_mixin import EntityModelMixin
|
|
10
13
|
from nsj_rest_lib2.compiler.edl_model.primitives import REGEX_EXTERNAL_REF
|
|
11
14
|
from nsj_rest_lib2.compiler.entity_compiler import EntityCompiler
|
|
12
15
|
from nsj_rest_lib2.compiler.model import CompilerResult
|
|
@@ -16,16 +19,17 @@ from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
|
|
|
16
19
|
|
|
17
20
|
from nsj_rest_lib2.settings import get_logger
|
|
18
21
|
|
|
22
|
+
# TODO Revisar compilação de valores default (sensível a tipos)
|
|
23
|
+
# TODO Implementar suporte a conjuntos
|
|
19
24
|
# TODO Autenticação nas rotas
|
|
20
|
-
# TODO Carregar, dinamicamente, em memória, o código compilado das dependÊncias por relacionamento
|
|
21
25
|
# TODO Atualizar o status da entidade pelo worker de compilação (e talvez parar uma compilação, quando se delete uma entidade)
|
|
22
|
-
# TODO Relacionamentos
|
|
23
26
|
# TODO Classes Abstratas
|
|
24
27
|
# TODO Partial Classes
|
|
25
28
|
# TODO Migrations
|
|
26
|
-
# TODO Adicionar autenticação aos endpoints dinâmicos
|
|
27
29
|
# TODO Criar imagem docker base para as aplicações, usando venv (para poderem atualizar o pydantic)
|
|
28
30
|
|
|
31
|
+
# TODO Suporte ao "min_items" dos relacionamentos no RestLib1
|
|
32
|
+
|
|
29
33
|
|
|
30
34
|
class EDLCompiler:
|
|
31
35
|
def __init__(self) -> None:
|
|
@@ -40,8 +44,8 @@ class EDLCompiler:
|
|
|
40
44
|
compiler_results = []
|
|
41
45
|
for entity_model_id in entity_models:
|
|
42
46
|
entity_model = entity_models[entity_model_id]
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
compiler_result = self._compile_model(entity_model, entity_models)
|
|
48
|
+
if compiler_result:
|
|
45
49
|
compiler_results.append(compiler_result)
|
|
46
50
|
|
|
47
51
|
return compiler_results
|
|
@@ -50,35 +54,46 @@ class EDLCompiler:
|
|
|
50
54
|
self,
|
|
51
55
|
edl_json: dict[str, Any],
|
|
52
56
|
dependencies_edls: list[dict[str, Any]],
|
|
53
|
-
) -> CompilerResult:
|
|
57
|
+
) -> CompilerResult | None:
|
|
54
58
|
entity_model = EntityModel(**edl_json)
|
|
55
59
|
|
|
56
60
|
entity_models = []
|
|
57
61
|
for dependency_edl in dependencies_edls:
|
|
58
|
-
|
|
62
|
+
if "mixin" in dependency_edl and dependency_edl["mixin"]:
|
|
63
|
+
dependency_entity_model = EntityModelMixin(**dependency_edl)
|
|
64
|
+
else:
|
|
65
|
+
dependency_entity_model = EntityModel(**dependency_edl)
|
|
59
66
|
entity_models.append(dependency_entity_model)
|
|
60
67
|
|
|
61
68
|
return self.compile_model(entity_model, entity_models)
|
|
62
69
|
|
|
63
70
|
def compile_model(
|
|
64
71
|
self,
|
|
65
|
-
entity_model:
|
|
66
|
-
dependencies_models: list[
|
|
67
|
-
) -> CompilerResult:
|
|
72
|
+
entity_model: EntityModelBase,
|
|
73
|
+
dependencies_models: list[tuple[str, EntityModelBase]],
|
|
74
|
+
) -> CompilerResult | None:
|
|
68
75
|
entity_models = {}
|
|
69
76
|
for dependency_entity_model in dependencies_models:
|
|
70
|
-
complete_entity_id =
|
|
71
|
-
|
|
72
|
-
)
|
|
73
|
-
entity_models[complete_entity_id] = dependency_entity_model
|
|
77
|
+
complete_entity_id = dependency_entity_model[0]
|
|
78
|
+
entity_models[complete_entity_id] = dependency_entity_model[1]
|
|
74
79
|
|
|
75
80
|
return self._compile_model(entity_model, entity_models)
|
|
76
81
|
|
|
77
82
|
def _compile_model(
|
|
78
83
|
self,
|
|
79
|
-
entity_model:
|
|
84
|
+
entity_model: EntityModelBase,
|
|
80
85
|
entity_models: dict[str, EntityModel],
|
|
81
|
-
|
|
86
|
+
escopo: str | None = None,
|
|
87
|
+
prefx_class_name: str = "",
|
|
88
|
+
) -> CompilerResult | None:
|
|
89
|
+
if entity_model.mixin:
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
if escopo is None and (isinstance(entity_model, EntityModel)):
|
|
93
|
+
escopo = entity_model.escopo
|
|
94
|
+
|
|
95
|
+
if not escopo:
|
|
96
|
+
raise Exception(f"Escopo não definido para a entidade: {entity_model.id}.")
|
|
82
97
|
|
|
83
98
|
# Criando um mapa de índices por nome de property
|
|
84
99
|
# TODO Implementar tratamento dos índices de apoio às query (não de unicidade)
|
|
@@ -109,10 +124,48 @@ class EDLCompiler:
|
|
|
109
124
|
) = self._properties_compiler.compile(
|
|
110
125
|
properties_structure,
|
|
111
126
|
map_unique_by_property,
|
|
127
|
+
escopo,
|
|
112
128
|
entity_model,
|
|
113
129
|
entity_models,
|
|
130
|
+
prefx_class_name,
|
|
114
131
|
)
|
|
115
132
|
|
|
133
|
+
# Gerando o buffer para os códigos de DTO e Entity
|
|
134
|
+
dto_code = ""
|
|
135
|
+
entity_code = ""
|
|
136
|
+
relations_dependencies_complete = []
|
|
137
|
+
|
|
138
|
+
# Carregando a estrutura de compilação dos components
|
|
139
|
+
components_structure = ComponentsCompilerStructure()
|
|
140
|
+
self._make_components_structures(
|
|
141
|
+
components_structure, entity_model, entity_models
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Gerando o código das entidades filhas (components)
|
|
145
|
+
for component_key in components_structure.components:
|
|
146
|
+
component = components_structure.components[component_key]
|
|
147
|
+
component_compiled = self._compile_model(
|
|
148
|
+
component,
|
|
149
|
+
entity_models,
|
|
150
|
+
escopo,
|
|
151
|
+
prefx_class_name=f"{prefx_class_name}_{entity_model.id}",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if not component_compiled:
|
|
155
|
+
raise Exception(
|
|
156
|
+
f"Erro ao compilar o component '{component_key}' da entidade '{entity_model.id}'. Gerou saída None, como se fosse um mixin."
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Guardando o código gerado no buffer
|
|
160
|
+
if component_compiled.dto_code:
|
|
161
|
+
dto_code += component_compiled.dto_code + "\n\n"
|
|
162
|
+
if component_compiled.entity_code:
|
|
163
|
+
entity_code += component_compiled.entity_code + "\n\n"
|
|
164
|
+
if component_compiled.relations_dependencies:
|
|
165
|
+
relations_dependencies_complete.extend(
|
|
166
|
+
component_compiled.relations_dependencies
|
|
167
|
+
)
|
|
168
|
+
|
|
116
169
|
# Gerando o código do DTO
|
|
117
170
|
dto_class_name, code_dto = self._dto_compiler.compile(
|
|
118
171
|
entity_model,
|
|
@@ -120,32 +173,71 @@ class EDLCompiler:
|
|
|
120
173
|
enum_classes,
|
|
121
174
|
related_imports,
|
|
122
175
|
fixed_filters,
|
|
176
|
+
prefx_class_name,
|
|
123
177
|
)
|
|
124
178
|
|
|
125
179
|
# Gerando o código da Entity
|
|
126
180
|
entity_class_name, code_entity = self._entity_compiler.compile(
|
|
127
|
-
entity_model,
|
|
181
|
+
entity_model,
|
|
182
|
+
ast_entity_attributes,
|
|
183
|
+
props_pk,
|
|
184
|
+
prefx_class_name,
|
|
128
185
|
)
|
|
129
186
|
|
|
187
|
+
# Extendendo os buffers com os códigos gerados
|
|
188
|
+
dto_code += code_dto
|
|
189
|
+
entity_code += code_entity
|
|
190
|
+
relations_dependencies_complete.extend(relations_dependencies)
|
|
191
|
+
|
|
130
192
|
# Construindo o resultado
|
|
131
193
|
compiler_result = CompilerResult()
|
|
132
194
|
compiler_result.entity_class_name = entity_class_name
|
|
133
|
-
compiler_result.entity_code =
|
|
195
|
+
compiler_result.entity_code = entity_code
|
|
134
196
|
compiler_result.dto_class_name = dto_class_name
|
|
135
|
-
compiler_result.dto_code =
|
|
197
|
+
compiler_result.dto_code = dto_code
|
|
136
198
|
|
|
137
199
|
# Compilando questões das APIs
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
200
|
+
if isinstance(entity_model, EntityModel):
|
|
201
|
+
compiler_result.api_expose = entity_model.api.expose
|
|
202
|
+
compiler_result.api_resource = entity_model.api.resource
|
|
203
|
+
compiler_result.api_verbs = entity_model.api.verbs
|
|
204
|
+
compiler_result.relations_dependencies = relations_dependencies_complete
|
|
205
|
+
|
|
206
|
+
get_logger().debug(f"código gerado para a entidade: {entity_model.id}")
|
|
207
|
+
get_logger().debug("DTO Code:")
|
|
208
|
+
get_logger().debug(f"\n{dto_code}")
|
|
209
|
+
get_logger().debug("Entity Code:")
|
|
210
|
+
get_logger().debug(f"\n{entity_code}")
|
|
142
211
|
|
|
143
212
|
return compiler_result
|
|
144
213
|
|
|
214
|
+
def _make_components_structures(
|
|
215
|
+
self,
|
|
216
|
+
components_structure: ComponentsCompilerStructure,
|
|
217
|
+
entity_model: EntityModelBase,
|
|
218
|
+
entity_models: dict[str, EntityModel],
|
|
219
|
+
):
|
|
220
|
+
if not entity_model:
|
|
221
|
+
return
|
|
222
|
+
|
|
223
|
+
# Populando com os components do trait
|
|
224
|
+
if entity_model.trait_from:
|
|
225
|
+
trait_model = entity_models[entity_model.trait_from]
|
|
226
|
+
|
|
227
|
+
self._make_components_structures(
|
|
228
|
+
components_structure,
|
|
229
|
+
trait_model,
|
|
230
|
+
entity_models,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Populando com os components da entidade atual
|
|
234
|
+
if entity_model.components:
|
|
235
|
+
components_structure.components.update(entity_model.components)
|
|
236
|
+
|
|
145
237
|
def _make_properties_structures(
|
|
146
238
|
self,
|
|
147
239
|
properties_structure: PropertiesCompilerStructure,
|
|
148
|
-
entity_model:
|
|
240
|
+
entity_model: EntityModelBase,
|
|
149
241
|
entity_models: dict[str, EntityModel],
|
|
150
242
|
):
|
|
151
243
|
if not entity_model:
|
|
@@ -184,11 +276,24 @@ class EDLCompiler:
|
|
|
184
276
|
entity_model.repository.properties
|
|
185
277
|
)
|
|
186
278
|
|
|
279
|
+
# Populando com as propriedades dos mixins
|
|
280
|
+
if entity_model.mixins:
|
|
281
|
+
for mixin_id in entity_model.mixins:
|
|
282
|
+
if mixin_id not in entity_models:
|
|
283
|
+
raise Exception(f"Mixin '{mixin_id}' não encontrado.")
|
|
284
|
+
|
|
285
|
+
mixin_model = entity_models[mixin_id]
|
|
286
|
+
self._make_properties_structures(
|
|
287
|
+
properties_structure,
|
|
288
|
+
mixin_model,
|
|
289
|
+
entity_models,
|
|
290
|
+
)
|
|
291
|
+
|
|
187
292
|
def _make_unique_map_by_property(
|
|
188
293
|
self,
|
|
189
294
|
map_indexes_by_property: dict[str, list[IndexCompilerStructure]],
|
|
190
295
|
map_unique_by_property: dict[str, IndexCompilerStructure],
|
|
191
|
-
entity_model:
|
|
296
|
+
entity_model: EntityModelBase,
|
|
192
297
|
entity_models: dict[str, EntityModel],
|
|
193
298
|
deep: int = 1,
|
|
194
299
|
):
|
|
@@ -233,18 +338,25 @@ class EDLCompiler:
|
|
|
233
338
|
|
|
234
339
|
def list_dependencies(
|
|
235
340
|
self, edl_json: dict[str, Any]
|
|
236
|
-
) -> tuple[list[str],
|
|
237
|
-
|
|
341
|
+
) -> tuple[list[str], EntityModelBase]:
|
|
342
|
+
if edl_json.get("mixin", False):
|
|
343
|
+
entity_model = EntityModelMixin(**edl_json)
|
|
344
|
+
else:
|
|
345
|
+
entity_model = EntityModel(**edl_json)
|
|
238
346
|
|
|
239
347
|
return (self._list_dependencies(entity_model), entity_model)
|
|
240
348
|
|
|
241
|
-
def _list_dependencies(self, entity_model:
|
|
349
|
+
def _list_dependencies(self, entity_model: EntityModelBase) -> list[str]:
|
|
242
350
|
entities: list[str] = []
|
|
243
351
|
|
|
244
352
|
# Adicionando dependências por traits
|
|
245
353
|
if entity_model.trait_from:
|
|
246
354
|
entities.append(entity_model.trait_from)
|
|
247
355
|
|
|
356
|
+
# Adicionando dependências por mixins
|
|
357
|
+
if entity_model.mixins:
|
|
358
|
+
entities.extend(entity_model.mixins)
|
|
359
|
+
|
|
248
360
|
# Populando com as dependências de propriedades de relacionamento
|
|
249
361
|
relations = self._list_dependencies_relations(entity_model)
|
|
250
362
|
entities.extend(relations)
|
|
@@ -306,7 +418,10 @@ if __name__ == "__main__":
|
|
|
306
418
|
# Instanciando o objeto de modelo de entidade a partir do JSON,
|
|
307
419
|
# e já realizando as validações básicas de tipo e estrutura.
|
|
308
420
|
print(f"Validando arquivo: {file}")
|
|
309
|
-
|
|
421
|
+
if edl.get("mixin", False):
|
|
422
|
+
entity_model = EntityModelMixin(**edl)
|
|
423
|
+
else:
|
|
424
|
+
entity_model = EntityModel(**edl)
|
|
310
425
|
|
|
311
426
|
complete_entity_id = f"{entity_model.escopo}/{entity_model.id}"
|
|
312
427
|
entities[complete_entity_id] = entity_model
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from nsj_rest_lib2.compiler.edl_model.column_meta_model import ColumnMetaModel
|
|
2
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
|
|
2
3
|
from nsj_rest_lib2.compiler.edl_model.index_model import IndexModel
|
|
3
4
|
from nsj_rest_lib2.compiler.edl_model.property_meta_model import PropertyMetaModel
|
|
4
5
|
from nsj_rest_lib2.compiler.edl_model.trait_property_meta_model import (
|
|
@@ -22,3 +23,8 @@ class PropertiesCompilerStructure:
|
|
|
22
23
|
self.metric_label: list[str] = []
|
|
23
24
|
self.entity_properties: dict[str, ColumnMetaModel] = {}
|
|
24
25
|
self.trait_properties: dict[str, TraitPropertyMetaModel] = {}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ComponentsCompilerStructure:
|
|
29
|
+
def __init__(self) -> None:
|
|
30
|
+
self.components: dict[str, EntityModelBase] = {}
|
|
@@ -3,8 +3,8 @@ import ast
|
|
|
3
3
|
import black
|
|
4
4
|
|
|
5
5
|
from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
|
|
6
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
|
|
6
7
|
from nsj_rest_lib2.compiler.edl_model.primitives import BasicTypes
|
|
7
|
-
from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
|
|
8
8
|
from nsj_rest_lib2.compiler.util.type_naming_util import compile_dto_class_name
|
|
9
9
|
|
|
10
10
|
|
|
@@ -14,11 +14,12 @@ class DTOCompiler:
|
|
|
14
14
|
|
|
15
15
|
def compile(
|
|
16
16
|
self,
|
|
17
|
-
entity_model:
|
|
17
|
+
entity_model: EntityModelBase,
|
|
18
18
|
ast_dto_attributes: list[ast.stmt],
|
|
19
19
|
enum_classes: list[ast.stmt],
|
|
20
20
|
related_imports: list[tuple[str, str, str]],
|
|
21
21
|
fixed_filters: list[tuple[str, BasicTypes]],
|
|
22
|
+
prefx_class_name: str,
|
|
22
23
|
) -> tuple[str, str]:
|
|
23
24
|
"""
|
|
24
25
|
Compila o código do DTO a partir do AST e retorna o código compilado.
|
|
@@ -117,7 +118,7 @@ class DTOCompiler:
|
|
|
117
118
|
)
|
|
118
119
|
|
|
119
120
|
# Criando o ast da classe
|
|
120
|
-
class_name = compile_dto_class_name(entity_model.id)
|
|
121
|
+
class_name = compile_dto_class_name(entity_model.id, prefx_class_name)
|
|
121
122
|
ast_class = ast.ClassDef(
|
|
122
123
|
name=class_name,
|
|
123
124
|
bases=[ast.Name(id="DTOBase", ctx=ast.Load())],
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from nsj_rest_lib2.compiler.edl_model.api_model import APIModel
|
|
7
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_mixin import EntityModelMixin
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class EntityModel(EntityModelMixin):
|
|
11
|
+
edl_version: Optional[str] = Field(default="1.0", description="Versão do EDL")
|
|
12
|
+
version: Optional[str] = Field(
|
|
13
|
+
default="1.0", description="Versão da entidade (padrão: 1.0)."
|
|
14
|
+
)
|
|
15
|
+
abstract: Optional[bool] = Field(
|
|
16
|
+
default=False,
|
|
17
|
+
description="Indica se a entidade é abstrata (padrão: False). Caso positivo, não gera código, mas pode ser usada na geração de código de outras entidades.",
|
|
18
|
+
)
|
|
19
|
+
api: APIModel = Field(
|
|
20
|
+
...,
|
|
21
|
+
description="Definição da API REST associada ao modelo, com todos os seus endpoints.",
|
|
22
|
+
)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import uuid
|
|
2
4
|
|
|
3
5
|
from pydantic import BaseModel, Field
|
|
@@ -5,15 +7,12 @@ from typing import Dict, List, Optional
|
|
|
5
7
|
|
|
6
8
|
from nsj_rest_lib2.compiler.edl_model.property_meta_model import PropertyMetaModel
|
|
7
9
|
from nsj_rest_lib2.compiler.edl_model.repository_model import RepositoryModel
|
|
8
|
-
from nsj_rest_lib2.compiler.edl_model.api_model import APIModel
|
|
9
10
|
from nsj_rest_lib2.compiler.edl_model.trait_property_meta_model import (
|
|
10
11
|
TraitPropertyMetaModel,
|
|
11
12
|
)
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class
|
|
15
|
-
edl_version: Optional[str] = Field(default="1.0", description="Versão do EDL")
|
|
16
|
-
escopo: str = Field(..., description="Escopo do EDL (define a aplicação).")
|
|
15
|
+
class EntityModelBase(BaseModel):
|
|
17
16
|
description: str = Field(..., description="Descrição da entidade.")
|
|
18
17
|
id: str = Field(
|
|
19
18
|
...,
|
|
@@ -22,13 +21,6 @@ class EntityModel(BaseModel):
|
|
|
22
21
|
trait_from: Optional[str] = Field(
|
|
23
22
|
None, description="Identificador da entidade que a trait estende."
|
|
24
23
|
)
|
|
25
|
-
version: Optional[str] = Field(
|
|
26
|
-
default="1.0", description="Versão da entidade (padrão: 1.0)."
|
|
27
|
-
)
|
|
28
|
-
abstract: Optional[bool] = Field(
|
|
29
|
-
default=False,
|
|
30
|
-
description="Indica se a entidade é abstrata (padrão: False). Caso positivo, não gera código, mas pode ser usada na geração de código de outras entidades.",
|
|
31
|
-
)
|
|
32
24
|
mixins: Optional[List[str]] = Field(
|
|
33
25
|
None,
|
|
34
26
|
description="Lista de mixins (blocos reutilizáveis) aplicados ao modelo.",
|
|
@@ -36,6 +28,10 @@ class EntityModel(BaseModel):
|
|
|
36
28
|
required: Optional[List[str]] = Field(
|
|
37
29
|
None, description="Lista de campos obrigatórios no modelo."
|
|
38
30
|
)
|
|
31
|
+
mixin: Optional[bool] = Field(
|
|
32
|
+
False,
|
|
33
|
+
description="Indica se o modelo é um mixin (bloco reutilizável, que não gera contém tabela própria no banco).",
|
|
34
|
+
)
|
|
39
35
|
partition_data: Optional[List[str]] = Field(
|
|
40
36
|
None,
|
|
41
37
|
description="Lista de propriedades da entidade, que serã usadas para particionamento dos dados no banco (sendo obrigatórias em todas as chamadas, inclusive como um tipo de filtro obrigatório).",
|
|
@@ -59,16 +55,19 @@ class EntityModel(BaseModel):
|
|
|
59
55
|
properties: Dict[str, PropertyMetaModel] = Field(
|
|
60
56
|
..., description="Dicionário de propriedades do modelo."
|
|
61
57
|
)
|
|
58
|
+
components: Optional[Dict[str, "EntityModelBase"]] = Field(
|
|
59
|
+
None,
|
|
60
|
+
description="Entidades filhas, relacionadas por composição e definidas inline (evitando a criação de novos arquivos EDL para a definição de entidades componentes da entidade atual).",
|
|
61
|
+
)
|
|
62
62
|
repository: RepositoryModel = Field(
|
|
63
63
|
..., description="Configurações de mapeamento para o banco de dados."
|
|
64
64
|
)
|
|
65
|
-
api: APIModel = Field(
|
|
66
|
-
...,
|
|
67
|
-
description="Definição da API REST associada ao modelo, com todos os seus endpoints.",
|
|
68
|
-
)
|
|
69
65
|
|
|
70
66
|
# Propriedades de controle da compilação (não fazem parte do JSON de representação das entidades)
|
|
71
67
|
tenant: int = Field(default=0, exclude=True)
|
|
72
68
|
grupo_empresarial: uuid.UUID = Field(
|
|
73
69
|
default=uuid.UUID("00000000-0000-0000-0000-000000000000"), exclude=True
|
|
74
70
|
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
EntityModelBase.model_rebuild()
|
{nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/primitives.py
RENAMED
|
@@ -4,7 +4,7 @@ from typing import Annotated, List, Union
|
|
|
4
4
|
from pydantic import StringConstraints
|
|
5
5
|
|
|
6
6
|
REGEX_EXTERNAL_REF = r"^(\w+)\/(\w+)$"
|
|
7
|
-
REGEX_INTERNAL_REF = r"^#\/
|
|
7
|
+
REGEX_INTERNAL_REF = r"^#\/components\/(\w+)$"
|
|
8
8
|
|
|
9
9
|
ExternalRefType = Annotated[str, StringConstraints(pattern=REGEX_EXTERNAL_REF)]
|
|
10
10
|
InternalRefType = Annotated[str, StringConstraints(pattern=REGEX_INTERNAL_REF)]
|
|
@@ -3,7 +3,7 @@ import ast
|
|
|
3
3
|
import black
|
|
4
4
|
|
|
5
5
|
from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
|
|
6
|
-
from nsj_rest_lib2.compiler.edl_model.
|
|
6
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
|
|
7
7
|
from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
|
|
8
8
|
from nsj_rest_lib2.compiler.util.type_naming_util import compile_entity_class_name
|
|
9
9
|
|
|
@@ -14,9 +14,10 @@ class EntityCompiler:
|
|
|
14
14
|
|
|
15
15
|
def compile(
|
|
16
16
|
self,
|
|
17
|
-
entity_model:
|
|
17
|
+
entity_model: EntityModelBase,
|
|
18
18
|
ast_entity_attributes: list[ast.stmt],
|
|
19
19
|
props_pk: list[str],
|
|
20
|
+
prefix_class_name: str,
|
|
20
21
|
) -> tuple[str, str]:
|
|
21
22
|
# Imports
|
|
22
23
|
imports = [
|
|
@@ -49,7 +50,11 @@ class EntityCompiler:
|
|
|
49
50
|
)
|
|
50
51
|
|
|
51
52
|
default_order_props = []
|
|
52
|
-
if
|
|
53
|
+
if (
|
|
54
|
+
isinstance(entity_model, EntityModel)
|
|
55
|
+
and entity_model.api
|
|
56
|
+
and entity_model.api.default_sort
|
|
57
|
+
):
|
|
53
58
|
default_order_props = entity_model.api.default_sort
|
|
54
59
|
|
|
55
60
|
default_order_fields = []
|
|
@@ -67,7 +72,7 @@ class EntityCompiler:
|
|
|
67
72
|
if CompilerStrUtil.to_snake_case(props_pk[0]) not in default_order_fields:
|
|
68
73
|
default_order_fields.append(CompilerStrUtil.to_snake_case(props_pk[0]))
|
|
69
74
|
|
|
70
|
-
class_name = compile_entity_class_name(entity_model.id)
|
|
75
|
+
class_name = compile_entity_class_name(entity_model.id, prefix_class_name)
|
|
71
76
|
ast_class = ast.ClassDef(
|
|
72
77
|
name=class_name,
|
|
73
78
|
bases=[ast.Name(id="EntityBase", ctx=ast.Load())],
|
|
@@ -6,6 +6,7 @@ from nsj_rest_lib2.compiler.compiler_structures import (
|
|
|
6
6
|
PropertiesCompilerStructure,
|
|
7
7
|
)
|
|
8
8
|
from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
|
|
9
|
+
from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
|
|
9
10
|
from nsj_rest_lib2.compiler.edl_model.primitives import (
|
|
10
11
|
BasicTypes,
|
|
11
12
|
CardinalityTypes,
|
|
@@ -29,16 +30,18 @@ from nsj_rest_lib2.compiler.util.type_util import TypeUtil
|
|
|
29
30
|
# TODO pattern
|
|
30
31
|
# TODO lowercase
|
|
31
32
|
# TODO uppercase
|
|
32
|
-
# TODO Adicionar o nome da entidade, no nome das classes de enum (para evitar conflitos no caso das traits)
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class EDLPropertyCompiler:
|
|
36
|
+
|
|
36
37
|
def compile(
|
|
37
38
|
self,
|
|
38
39
|
properties_structure: PropertiesCompilerStructure,
|
|
39
40
|
map_unique_by_property: dict[str, IndexCompilerStructure],
|
|
40
|
-
|
|
41
|
+
escopo: str,
|
|
42
|
+
entity_model: EntityModelBase,
|
|
41
43
|
entity_models: dict[str, EntityModel],
|
|
44
|
+
prefx_class_name: str,
|
|
42
45
|
) -> tuple[
|
|
43
46
|
list[ast.stmt],
|
|
44
47
|
list[ast.stmt],
|
|
@@ -52,22 +55,24 @@ class EDLPropertyCompiler:
|
|
|
52
55
|
# TODO Criar opção de campo calculado?
|
|
53
56
|
|
|
54
57
|
# Descobrindo os atributos marcados como PK (e recuperando a chave primária)
|
|
55
|
-
#
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
# TODO Verificar se devemos manter essa verificação
|
|
59
|
+
pk_keys = []
|
|
60
|
+
for pkey in properties_structure.properties:
|
|
61
|
+
prop = properties_structure.properties[pkey]
|
|
62
|
+
|
|
63
|
+
if isinstance(prop.type, PrimitiveTypes):
|
|
64
|
+
if prop.pk:
|
|
65
|
+
pk_keys.append(pkey)
|
|
66
|
+
|
|
67
|
+
if not entity_model.mixin:
|
|
68
|
+
if len(pk_keys) > 1:
|
|
69
|
+
raise Exception(
|
|
70
|
+
f"Entidade '{entity_model.id}' possui mais de uma chave primária (ainda não suportado): {pk_keys}"
|
|
71
|
+
)
|
|
72
|
+
elif len(pk_keys) == 0:
|
|
73
|
+
raise Exception(
|
|
74
|
+
f"Entidade '{entity_model.id}' não tem nenhuma chave primária (ainda não suportado)"
|
|
75
|
+
)
|
|
71
76
|
|
|
72
77
|
# pk_key = pk_keys[0]
|
|
73
78
|
|
|
@@ -87,11 +92,12 @@ class EDLPropertyCompiler:
|
|
|
87
92
|
prop = properties_structure.properties[pkey]
|
|
88
93
|
|
|
89
94
|
# DTO
|
|
90
|
-
## Tratando propriedade simples (não array, não object)
|
|
91
95
|
if isinstance(prop.type, PrimitiveTypes):
|
|
96
|
+
# Tratando propriedade simples (não array, não object)
|
|
92
97
|
self._compile_simple_property(
|
|
93
98
|
properties_structure,
|
|
94
99
|
map_unique_by_property,
|
|
100
|
+
escopo,
|
|
95
101
|
entity_model,
|
|
96
102
|
ast_dto_attributes,
|
|
97
103
|
ast_entity_attributes,
|
|
@@ -99,9 +105,11 @@ class EDLPropertyCompiler:
|
|
|
99
105
|
enum_classes,
|
|
100
106
|
pkey,
|
|
101
107
|
prop,
|
|
108
|
+
prefx_class_name,
|
|
102
109
|
)
|
|
103
110
|
|
|
104
111
|
elif isinstance(prop.type, str):
|
|
112
|
+
# Tratando propriedade de relacionamento
|
|
105
113
|
external_match = re.match(REGEX_EXTERNAL_REF, prop.type)
|
|
106
114
|
internal_match = re.match(REGEX_INTERNAL_REF, prop.type)
|
|
107
115
|
|
|
@@ -125,8 +133,18 @@ class EDLPropertyCompiler:
|
|
|
125
133
|
)
|
|
126
134
|
|
|
127
135
|
elif internal_match:
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
related_entity_id = internal_match.group(1)
|
|
137
|
+
|
|
138
|
+
self._compile_internal_relation(
|
|
139
|
+
related_entity_id,
|
|
140
|
+
entity_model,
|
|
141
|
+
properties_structure,
|
|
142
|
+
ast_dto_attributes,
|
|
143
|
+
ast_entity_attributes,
|
|
144
|
+
pkey,
|
|
145
|
+
prop,
|
|
146
|
+
prefx_class_name,
|
|
147
|
+
)
|
|
130
148
|
else:
|
|
131
149
|
raise Exception(
|
|
132
150
|
f"Tipo da propriedade '{pkey}' não suportado: {prop.type}"
|
|
@@ -143,8 +161,10 @@ class EDLPropertyCompiler:
|
|
|
143
161
|
ast_dto_attributes,
|
|
144
162
|
ast_entity_attributes,
|
|
145
163
|
fixed_filters,
|
|
164
|
+
escopo,
|
|
146
165
|
entity_model,
|
|
147
166
|
enum_classes,
|
|
167
|
+
prefx_class_name,
|
|
148
168
|
)
|
|
149
169
|
|
|
150
170
|
return (
|
|
@@ -166,8 +186,10 @@ class EDLPropertyCompiler:
|
|
|
166
186
|
ast_dto_attributes: list[ast.stmt],
|
|
167
187
|
ast_entity_attributes: list[ast.stmt],
|
|
168
188
|
fixed_filters: list[tuple[str, BasicTypes]],
|
|
169
|
-
|
|
189
|
+
escopo: str,
|
|
190
|
+
entity_model: EntityModelBase,
|
|
170
191
|
enum_classes: list[ast.stmt],
|
|
192
|
+
prefx_class_name: str,
|
|
171
193
|
):
|
|
172
194
|
enum_class_name = None
|
|
173
195
|
keywords = []
|
|
@@ -273,7 +295,9 @@ class EDLPropertyCompiler:
|
|
|
273
295
|
|
|
274
296
|
# Trtando de uma definição de enum
|
|
275
297
|
if prop.domain_config:
|
|
276
|
-
result = self._compile_domain_config(
|
|
298
|
+
result = self._compile_domain_config(
|
|
299
|
+
pkey, prop, escopo, entity_model, prefx_class_name
|
|
300
|
+
)
|
|
277
301
|
if not result:
|
|
278
302
|
raise Exception(f"Erro desconhecido ao compilar a propriedade {pkey}")
|
|
279
303
|
|
|
@@ -343,14 +367,14 @@ class EDLPropertyCompiler:
|
|
|
343
367
|
ast_entity_attributes.append(ast_entity_attr)
|
|
344
368
|
|
|
345
369
|
# Guardando como um fixed_filter
|
|
346
|
-
# TODO
|
|
370
|
+
# TODO Pensar em validações para esse value (se está de acordo com o tipo ou enum)
|
|
347
371
|
fixed_filters.append((pkey, prop.value))
|
|
348
372
|
|
|
349
373
|
def _compile_external_relation(
|
|
350
374
|
self,
|
|
351
375
|
related_entity_id: str,
|
|
352
376
|
related_entity_key: str,
|
|
353
|
-
entity_model:
|
|
377
|
+
entity_model: EntityModelBase,
|
|
354
378
|
entity_models: dict[str, EntityModel],
|
|
355
379
|
properties_structure: PropertiesCompilerStructure,
|
|
356
380
|
ast_dto_attributes: list[ast.stmt],
|
|
@@ -414,6 +438,57 @@ class EDLPropertyCompiler:
|
|
|
414
438
|
pkey,
|
|
415
439
|
related_dto_class_name,
|
|
416
440
|
related_entity_class_name,
|
|
441
|
+
prop,
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
elif prop.cardinality == CardinalityTypes.C1_1:
|
|
445
|
+
self._build_ast_1_1(
|
|
446
|
+
properties_structure,
|
|
447
|
+
ast_dto_attributes,
|
|
448
|
+
ast_entity_attributes,
|
|
449
|
+
pkey,
|
|
450
|
+
related_dto_class_name,
|
|
451
|
+
related_entity_class_name,
|
|
452
|
+
prop,
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
elif prop.cardinality == CardinalityTypes.CN_N:
|
|
456
|
+
# TODO
|
|
457
|
+
pass
|
|
458
|
+
else:
|
|
459
|
+
raise Exception(
|
|
460
|
+
f"Propriedade '{pkey}' da entidade '{entity_model.id}' possui cardinalidade inválida ou não suportada: {prop.cardinality}"
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
def _compile_internal_relation(
|
|
464
|
+
self,
|
|
465
|
+
related_entity_id: str,
|
|
466
|
+
entity_model: EntityModelBase,
|
|
467
|
+
properties_structure: PropertiesCompilerStructure,
|
|
468
|
+
ast_dto_attributes: list[ast.stmt],
|
|
469
|
+
ast_entity_attributes: list[ast.stmt],
|
|
470
|
+
pkey: str,
|
|
471
|
+
prop: PropertyMetaModel,
|
|
472
|
+
prefx_class_name: str,
|
|
473
|
+
):
|
|
474
|
+
# Resolvendo o nome das classes de DTO e Entity
|
|
475
|
+
related_dto_class_name = compile_dto_class_name(
|
|
476
|
+
related_entity_id, f"{prefx_class_name}_{entity_model.id}"
|
|
477
|
+
)
|
|
478
|
+
related_entity_class_name = compile_entity_class_name(
|
|
479
|
+
related_entity_id, f"{prefx_class_name}_{entity_model.id}"
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
# Instanciando o ast
|
|
483
|
+
if prop.cardinality == CardinalityTypes.C1_N:
|
|
484
|
+
# Para relacionamentos 1_N
|
|
485
|
+
self._build_ast_1_N(
|
|
486
|
+
properties_structure,
|
|
487
|
+
ast_dto_attributes,
|
|
488
|
+
pkey,
|
|
489
|
+
related_dto_class_name,
|
|
490
|
+
related_entity_class_name,
|
|
491
|
+
prop,
|
|
417
492
|
)
|
|
418
493
|
|
|
419
494
|
elif prop.cardinality == CardinalityTypes.C1_1:
|
|
@@ -424,6 +499,7 @@ class EDLPropertyCompiler:
|
|
|
424
499
|
pkey,
|
|
425
500
|
related_dto_class_name,
|
|
426
501
|
related_entity_class_name,
|
|
502
|
+
prop,
|
|
427
503
|
)
|
|
428
504
|
|
|
429
505
|
elif prop.cardinality == CardinalityTypes.CN_N:
|
|
@@ -441,7 +517,10 @@ class EDLPropertyCompiler:
|
|
|
441
517
|
pkey: str,
|
|
442
518
|
related_dto_class_name: str,
|
|
443
519
|
related_entity_class_name: str,
|
|
520
|
+
prop: PropertyMetaModel,
|
|
444
521
|
):
|
|
522
|
+
# TODO Verificar uso da propriedade relation_key_field do Rest_lib_1
|
|
523
|
+
|
|
445
524
|
# Propriedade do property descriptor
|
|
446
525
|
keywords = [
|
|
447
526
|
ast.keyword(
|
|
@@ -454,6 +533,23 @@ class EDLPropertyCompiler:
|
|
|
454
533
|
),
|
|
455
534
|
]
|
|
456
535
|
|
|
536
|
+
# Tratando das opções básicas do descritor de propriedade
|
|
537
|
+
if properties_structure.required and pkey in properties_structure.required:
|
|
538
|
+
keywords.append(ast.keyword(arg="not_null", value=ast.Constant(True)))
|
|
539
|
+
|
|
540
|
+
if prop.max_length:
|
|
541
|
+
keywords.append(ast.keyword(arg="max", value=ast.Constant(prop.max_length)))
|
|
542
|
+
if prop.min_length:
|
|
543
|
+
keywords.append(ast.keyword(arg="min", value=ast.Constant(prop.min_length)))
|
|
544
|
+
|
|
545
|
+
if prop.validator:
|
|
546
|
+
keywords.append(
|
|
547
|
+
ast.keyword(
|
|
548
|
+
arg="validator",
|
|
549
|
+
value=ast.Name(prop.validator, ctx=ast.Load()),
|
|
550
|
+
)
|
|
551
|
+
)
|
|
552
|
+
|
|
457
553
|
# Resolvendo a coluna usada no relacionamento
|
|
458
554
|
if (
|
|
459
555
|
not properties_structure.entity_properties
|
|
@@ -464,7 +560,10 @@ class EDLPropertyCompiler:
|
|
|
464
560
|
f"Propriedade '{pkey}' possui um relacionamento, mas nenhuma coluna de relacioanamento foi apontada na propriedade correspondente no repository."
|
|
465
561
|
)
|
|
466
562
|
|
|
467
|
-
|
|
563
|
+
relation_column_ref = properties_structure.entity_properties[
|
|
564
|
+
pkey
|
|
565
|
+
].relation_column
|
|
566
|
+
relation_column = str(relation_column_ref).split("/")[-1]
|
|
468
567
|
|
|
469
568
|
keywords.append(
|
|
470
569
|
ast.keyword(
|
|
@@ -497,6 +596,7 @@ class EDLPropertyCompiler:
|
|
|
497
596
|
pkey: str,
|
|
498
597
|
related_dto_class_name: str,
|
|
499
598
|
related_entity_class_name: str,
|
|
599
|
+
prop: PropertyMetaModel,
|
|
500
600
|
):
|
|
501
601
|
# Propriedade do property descriptor
|
|
502
602
|
keywords = [
|
|
@@ -506,6 +606,24 @@ class EDLPropertyCompiler:
|
|
|
506
606
|
),
|
|
507
607
|
]
|
|
508
608
|
|
|
609
|
+
# Tratando das opções básicas do descritor de propriedade
|
|
610
|
+
if properties_structure.required and pkey in properties_structure.required:
|
|
611
|
+
keywords.append(ast.keyword(arg="not_null", value=ast.Constant(True)))
|
|
612
|
+
|
|
613
|
+
if (
|
|
614
|
+
properties_structure.main_properties
|
|
615
|
+
and pkey in properties_structure.main_properties
|
|
616
|
+
):
|
|
617
|
+
keywords.append(ast.keyword(arg="resume", value=ast.Constant(True)))
|
|
618
|
+
|
|
619
|
+
if prop.validator:
|
|
620
|
+
keywords.append(
|
|
621
|
+
ast.keyword(
|
|
622
|
+
arg="validator",
|
|
623
|
+
value=ast.Name(prop.validator, ctx=ast.Load()),
|
|
624
|
+
)
|
|
625
|
+
)
|
|
626
|
+
|
|
509
627
|
# Resolvendo a coluna usada no relacionamento
|
|
510
628
|
if (
|
|
511
629
|
not properties_structure.entity_properties
|
|
@@ -525,6 +643,9 @@ class EDLPropertyCompiler:
|
|
|
525
643
|
owner_relation = True
|
|
526
644
|
relation_column = relation_column.split("/")[-1]
|
|
527
645
|
|
|
646
|
+
# TODO Verificar, porque desconfio que o apontamento para a coluna de relacionamento
|
|
647
|
+
# para o caso do relacionamento OTHER, não é suportado pelo RestLib (acho que, quando
|
|
648
|
+
# o dono é OTHER, o RestLib sempre aponta para a PK da entidade corrente).
|
|
528
649
|
keywords.append(
|
|
529
650
|
ast.keyword(
|
|
530
651
|
arg="relation_field",
|
|
@@ -621,6 +742,7 @@ class EDLPropertyCompiler:
|
|
|
621
742
|
self,
|
|
622
743
|
properties_structure,
|
|
623
744
|
map_unique_by_property,
|
|
745
|
+
escopo,
|
|
624
746
|
entity_model,
|
|
625
747
|
ast_dto_attributes,
|
|
626
748
|
ast_entity_attributes,
|
|
@@ -628,6 +750,7 @@ class EDLPropertyCompiler:
|
|
|
628
750
|
enum_classes,
|
|
629
751
|
pkey,
|
|
630
752
|
prop,
|
|
753
|
+
prefx_class_name: str,
|
|
631
754
|
):
|
|
632
755
|
enum_class_name = None
|
|
633
756
|
keywords = []
|
|
@@ -681,18 +804,18 @@ class EDLPropertyCompiler:
|
|
|
681
804
|
if prop.type in [PrimitiveTypes.STRING, PrimitiveTypes.EMAIL]:
|
|
682
805
|
if prop.max_length:
|
|
683
806
|
max = prop.max_length
|
|
684
|
-
|
|
807
|
+
if prop.min_length:
|
|
685
808
|
min = prop.min_length
|
|
686
809
|
elif prop.type in [PrimitiveTypes.INTEGER, PrimitiveTypes.NUMBER]:
|
|
687
810
|
if prop.minimum:
|
|
688
811
|
min = prop.minimum
|
|
689
|
-
|
|
812
|
+
if prop.maximum:
|
|
690
813
|
max = prop.maximum
|
|
691
814
|
|
|
692
815
|
if max:
|
|
693
|
-
keywords.append(ast.keyword(arg="max", value=ast.Constant(
|
|
816
|
+
keywords.append(ast.keyword(arg="max", value=ast.Constant(max)))
|
|
694
817
|
if min:
|
|
695
|
-
keywords.append(ast.keyword(arg="min", value=ast.Constant(
|
|
818
|
+
keywords.append(ast.keyword(arg="min", value=ast.Constant(min)))
|
|
696
819
|
|
|
697
820
|
if (
|
|
698
821
|
properties_structure.search_properties
|
|
@@ -796,7 +919,9 @@ class EDLPropertyCompiler:
|
|
|
796
919
|
)
|
|
797
920
|
|
|
798
921
|
if prop.domain_config:
|
|
799
|
-
result = self._compile_domain_config(
|
|
922
|
+
result = self._compile_domain_config(
|
|
923
|
+
pkey, prop, escopo, entity_model, prefx_class_name
|
|
924
|
+
)
|
|
800
925
|
if not result:
|
|
801
926
|
raise Exception(f"Erro desconhecido ao compilar a propriedade {pkey}")
|
|
802
927
|
|
|
@@ -839,7 +964,9 @@ class EDLPropertyCompiler:
|
|
|
839
964
|
self,
|
|
840
965
|
pkey: str,
|
|
841
966
|
prop: PropertyMetaModel | TraitPropertyMetaModel,
|
|
842
|
-
|
|
967
|
+
escopo: str,
|
|
968
|
+
entity_model: EntityModelBase,
|
|
969
|
+
prefx_class_name: str,
|
|
843
970
|
) -> tuple[str, ast.stmt] | None:
|
|
844
971
|
if not prop.domain_config:
|
|
845
972
|
return None
|
|
@@ -881,7 +1008,7 @@ class EDLPropertyCompiler:
|
|
|
881
1008
|
ast_values.append(ast_value)
|
|
882
1009
|
|
|
883
1010
|
# Instanciando o atributo AST
|
|
884
|
-
enum_class_name = f"{CompilerStrUtil.to_pascal_case(
|
|
1011
|
+
enum_class_name = f"{CompilerStrUtil.to_pascal_case(escopo)}{CompilerStrUtil.to_pascal_case(prefx_class_name)}{CompilerStrUtil.to_pascal_case(entity_model.id)}{CompilerStrUtil.to_pascal_case(pkey)}Enum"
|
|
885
1012
|
ast_enum_class = ast.ClassDef(
|
|
886
1013
|
name=enum_class_name,
|
|
887
1014
|
bases=[
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def compile_namespace_keys(
|
|
7
|
+
tenant: str | int | None, grupo_empresarial: str | uuid.UUID | None
|
|
8
|
+
) -> tuple[str, str, str]:
|
|
9
|
+
grupo_key = f"tenant_{tenant}.ge_{grupo_empresarial}"
|
|
10
|
+
tenant_key = f"tenant_{tenant}"
|
|
11
|
+
default_key = "default"
|
|
12
|
+
|
|
13
|
+
return (grupo_key, tenant_key, default_key)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def compile_dto_class_name(entity_id: str, prefx_class_name: str = "") -> str:
|
|
17
|
+
return f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}{CompilerStrUtil.to_pascal_case(entity_id)}DTO"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def compile_entity_class_name(entity_id: str, prefx_class_name: str = "") -> str:
|
|
21
|
+
return f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}{CompilerStrUtil.to_pascal_case(entity_id)}Entity"
|
|
@@ -317,8 +317,14 @@ class EntityLoader:
|
|
|
317
317
|
namespace.module = module
|
|
318
318
|
namespace.entities_dict = module.__dict__
|
|
319
319
|
|
|
320
|
-
|
|
320
|
+
get_logger().debug(
|
|
321
|
+
f"Executando o código da entidade {entity_resource} no namespace {entity_config_key}. Código:"
|
|
322
|
+
)
|
|
323
|
+
get_logger().debug(f"Entity source:\n{source_entity}")
|
|
324
|
+
get_logger().debug(f"DTO source:\n{source_dto}")
|
|
325
|
+
|
|
321
326
|
self._safe_exec(source_entity, namespace.entities_dict, "Entity source")
|
|
327
|
+
self._safe_exec(source_dto, namespace.entities_dict, "DTO source")
|
|
322
328
|
|
|
323
329
|
# Gravando a entidade no dict de entidades carregadas
|
|
324
330
|
loaded_entity = LoadedEntity()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nsj_rest_lib2
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.15
|
|
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
|
|
@@ -23,6 +23,8 @@ setup.cfg
|
|
|
23
23
|
./nsj_rest_lib2/compiler/edl_model/api_model.py
|
|
24
24
|
./nsj_rest_lib2/compiler/edl_model/column_meta_model.py
|
|
25
25
|
./nsj_rest_lib2/compiler/edl_model/entity_model.py
|
|
26
|
+
./nsj_rest_lib2/compiler/edl_model/entity_model_base.py
|
|
27
|
+
./nsj_rest_lib2/compiler/edl_model/entity_model_mixin.py
|
|
26
28
|
./nsj_rest_lib2/compiler/edl_model/index_model.py
|
|
27
29
|
./nsj_rest_lib2/compiler/edl_model/primitives.py
|
|
28
30
|
./nsj_rest_lib2/compiler/edl_model/property_meta_model.py
|
|
@@ -58,6 +60,8 @@ nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py
|
|
|
58
60
|
nsj_rest_lib2/compiler/edl_model/api_model.py
|
|
59
61
|
nsj_rest_lib2/compiler/edl_model/column_meta_model.py
|
|
60
62
|
nsj_rest_lib2/compiler/edl_model/entity_model.py
|
|
63
|
+
nsj_rest_lib2/compiler/edl_model/entity_model_base.py
|
|
64
|
+
nsj_rest_lib2/compiler/edl_model/entity_model_mixin.py
|
|
61
65
|
nsj_rest_lib2/compiler/edl_model/index_model.py
|
|
62
66
|
nsj_rest_lib2/compiler/edl_model/primitives.py
|
|
63
67
|
nsj_rest_lib2/compiler/edl_model/property_meta_model.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = nsj_rest_lib2
|
|
3
|
-
version = 0.0.
|
|
3
|
+
version = 0.0.15
|
|
4
4
|
author = Nasajon Sistemas
|
|
5
5
|
author_email = contact.dev@nasajon.com.br
|
|
6
6
|
description = Biblioteca para permitir a distribuição de rotas dinâmicas numa API, configuradas por meio de EDLs declarativos (em formato JSON).
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import uuid
|
|
2
|
-
|
|
3
|
-
from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def compile_namespace_keys(
|
|
7
|
-
tenant: str | int | None, grupo_empresarial: str | uuid.UUID | None
|
|
8
|
-
) -> tuple[str, str, str]:
|
|
9
|
-
grupo_key = f"tenant_{tenant}.ge_{grupo_empresarial}"
|
|
10
|
-
tenant_key = f"tenant_{tenant}"
|
|
11
|
-
default_key = "default"
|
|
12
|
-
|
|
13
|
-
return (grupo_key, tenant_key, default_key)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def compile_dto_class_name(entity_id: str) -> str:
|
|
17
|
-
return f"{CompilerStrUtil.to_pascal_case(entity_id)}DTO"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def compile_entity_class_name(entity_id: str) -> str:
|
|
21
|
-
return f"{CompilerStrUtil.to_pascal_case(entity_id)}Entity"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py
RENAMED
|
File without changes
|
|
File without changes
|
{nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/column_meta_model.py
RENAMED
|
File without changes
|
{nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/index_model.py
RENAMED
|
File without changes
|
|
File without changes
|
{nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/compiler/edl_model/repository_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nsj_rest_lib2-0.0.13 → nsj_rest_lib2-0.0.15}/nsj_rest_lib2/controller/dynamic_controller.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|