nsj-rest-lib2 0.0.10__py3-none-any.whl → 0.0.12__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.
- nsj_rest_lib2/compiler/compiler.py +21 -14
- nsj_rest_lib2/compiler/dto_compiler.py +28 -1
- nsj_rest_lib2/compiler/edl_model/column_meta_model.py +1 -1
- nsj_rest_lib2/compiler/edl_model/trait_property_meta_model.py +6 -0
- nsj_rest_lib2/compiler/model.py +45 -0
- nsj_rest_lib2/compiler/property_compiler.py +445 -105
- nsj_rest_lib2/service/entity_loader.py +57 -11
- {nsj_rest_lib2-0.0.10.dist-info → nsj_rest_lib2-0.0.12.dist-info}/METADATA +1 -1
- {nsj_rest_lib2-0.0.10.dist-info → nsj_rest_lib2-0.0.12.dist-info}/RECORD +11 -10
- {nsj_rest_lib2-0.0.10.dist-info → nsj_rest_lib2-0.0.12.dist-info}/WHEEL +0 -0
- {nsj_rest_lib2-0.0.10.dist-info → nsj_rest_lib2-0.0.12.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
+
|
|
2
3
|
from typing import Any
|
|
3
4
|
|
|
4
5
|
from nsj_rest_lib2.compiler.compiler_structures import (
|
|
@@ -7,8 +8,8 @@ from nsj_rest_lib2.compiler.compiler_structures import (
|
|
|
7
8
|
)
|
|
8
9
|
from nsj_rest_lib2.compiler.dto_compiler import DTOCompiler
|
|
9
10
|
from nsj_rest_lib2.compiler.edl_model.primitives import REGEX_EXTERNAL_REF
|
|
10
|
-
from nsj_rest_lib2.compiler.edl_model.repository_model import RepositoryModel
|
|
11
11
|
from nsj_rest_lib2.compiler.entity_compiler import EntityCompiler
|
|
12
|
+
from nsj_rest_lib2.compiler.model import CompilerResult
|
|
12
13
|
from nsj_rest_lib2.compiler.property_compiler import EDLPropertyCompiler
|
|
13
14
|
|
|
14
15
|
from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
|
|
@@ -26,17 +27,6 @@ from nsj_rest_lib2.settings import get_logger
|
|
|
26
27
|
# TODO Criar imagem docker base para as aplicações, usando venv (para poderem atualizar o pydantic)
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
class CompilerResult:
|
|
30
|
-
def __init__(self):
|
|
31
|
-
self.dto_class_name: str | None = None
|
|
32
|
-
self.dto_code: str | None = None
|
|
33
|
-
self.entity_class_name: str | None = None
|
|
34
|
-
self.entity_code: str | None = None
|
|
35
|
-
self.api_expose: bool | None = None
|
|
36
|
-
self.api_resource: str | None = None
|
|
37
|
-
self.api_verbs: list[str] | None = None
|
|
38
|
-
|
|
39
|
-
|
|
40
30
|
class EDLCompiler:
|
|
41
31
|
def __init__(self) -> None:
|
|
42
32
|
self._properties_compiler = EDLPropertyCompiler()
|
|
@@ -114,6 +104,8 @@ class EDLCompiler:
|
|
|
114
104
|
props_pk,
|
|
115
105
|
enum_classes,
|
|
116
106
|
related_imports,
|
|
107
|
+
relations_dependencies,
|
|
108
|
+
fixed_filters,
|
|
117
109
|
) = self._properties_compiler.compile(
|
|
118
110
|
properties_structure,
|
|
119
111
|
map_unique_by_property,
|
|
@@ -123,7 +115,11 @@ class EDLCompiler:
|
|
|
123
115
|
|
|
124
116
|
# Gerando o código do DTO
|
|
125
117
|
dto_class_name, code_dto = self._dto_compiler.compile(
|
|
126
|
-
entity_model,
|
|
118
|
+
entity_model,
|
|
119
|
+
ast_dto_attributes,
|
|
120
|
+
enum_classes,
|
|
121
|
+
related_imports,
|
|
122
|
+
fixed_filters,
|
|
127
123
|
)
|
|
128
124
|
|
|
129
125
|
# Gerando o código da Entity
|
|
@@ -142,6 +138,7 @@ class EDLCompiler:
|
|
|
142
138
|
compiler_result.api_expose = entity_model.api.expose
|
|
143
139
|
compiler_result.api_resource = entity_model.api.resource
|
|
144
140
|
compiler_result.api_verbs = entity_model.api.verbs
|
|
141
|
+
compiler_result.relations_dependencies = relations_dependencies
|
|
145
142
|
|
|
146
143
|
return compiler_result
|
|
147
144
|
|
|
@@ -244,10 +241,20 @@ class EDLCompiler:
|
|
|
244
241
|
def _list_dependencies(self, entity_model: EntityModel) -> list[str]:
|
|
245
242
|
entities: list[str] = []
|
|
246
243
|
|
|
244
|
+
# Adicionando dependências por traits
|
|
247
245
|
if entity_model.trait_from:
|
|
248
246
|
entities.append(entity_model.trait_from)
|
|
249
247
|
|
|
250
|
-
# Populando com as dependências de propriedades de relacionamento
|
|
248
|
+
# Populando com as dependências de propriedades de relacionamento
|
|
249
|
+
relations = self._list_dependencies_relations(entity_model)
|
|
250
|
+
entities.extend(relations)
|
|
251
|
+
|
|
252
|
+
return entities
|
|
253
|
+
|
|
254
|
+
def _list_dependencies_relations(self, entity_model) -> list[str]:
|
|
255
|
+
entities = []
|
|
256
|
+
|
|
257
|
+
# Relacionamento 1_N
|
|
251
258
|
for pkey in entity_model.properties:
|
|
252
259
|
prop = entity_model.properties[pkey]
|
|
253
260
|
|
|
@@ -3,6 +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.primitives import BasicTypes
|
|
6
7
|
from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
|
|
7
8
|
from nsj_rest_lib2.compiler.util.type_naming_util import compile_dto_class_name
|
|
8
9
|
|
|
@@ -17,6 +18,7 @@ class DTOCompiler:
|
|
|
17
18
|
ast_dto_attributes: list[ast.stmt],
|
|
18
19
|
enum_classes: list[ast.stmt],
|
|
19
20
|
related_imports: list[tuple[str, str, str]],
|
|
21
|
+
fixed_filters: list[tuple[str, BasicTypes]],
|
|
20
22
|
) -> tuple[str, str]:
|
|
21
23
|
"""
|
|
22
24
|
Compila o código do DTO a partir do AST e retorna o código compilado.
|
|
@@ -71,6 +73,18 @@ class DTOCompiler:
|
|
|
71
73
|
names=[ast.alias(name="DTOBase", asname=None)],
|
|
72
74
|
level=0,
|
|
73
75
|
),
|
|
76
|
+
# from nsj_rest_lib.descriptor.dto_left_join_field import EntityRelationOwner
|
|
77
|
+
ast.ImportFrom(
|
|
78
|
+
module="nsj_rest_lib.descriptor.dto_left_join_field",
|
|
79
|
+
names=[ast.alias(name="EntityRelationOwner", asname=None)],
|
|
80
|
+
level=0,
|
|
81
|
+
),
|
|
82
|
+
# from nsj_rest_lib.descriptor.dto_object_field import DTOObjectField
|
|
83
|
+
ast.ImportFrom(
|
|
84
|
+
module="nsj_rest_lib.descriptor.dto_object_field",
|
|
85
|
+
names=[ast.alias(name="DTOObjectField", asname=None)],
|
|
86
|
+
level=0,
|
|
87
|
+
),
|
|
74
88
|
]
|
|
75
89
|
|
|
76
90
|
for import_ in related_imports:
|
|
@@ -89,6 +103,19 @@ class DTOCompiler:
|
|
|
89
103
|
)
|
|
90
104
|
)
|
|
91
105
|
|
|
106
|
+
# Keywords para tipos usados em fixed_filters
|
|
107
|
+
keywords_decorator_dto = []
|
|
108
|
+
for fixed_filter in fixed_filters:
|
|
109
|
+
keywords_decorator_dto.append(
|
|
110
|
+
ast.keyword(
|
|
111
|
+
arg="fixed_filters",
|
|
112
|
+
value=ast.Dict(
|
|
113
|
+
keys=[ast.Constant(value=fixed_filter[0])],
|
|
114
|
+
values=[ast.Constant(value=fixed_filter[1])],
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
|
|
92
119
|
# Criando o ast da classe
|
|
93
120
|
class_name = compile_dto_class_name(entity_model.id)
|
|
94
121
|
ast_class = ast.ClassDef(
|
|
@@ -99,7 +126,7 @@ class DTOCompiler:
|
|
|
99
126
|
ast.Call(
|
|
100
127
|
func=ast.Name(id="DTO", ctx=ast.Load()),
|
|
101
128
|
args=[],
|
|
102
|
-
keywords=
|
|
129
|
+
keywords=keywords_decorator_dto,
|
|
103
130
|
)
|
|
104
131
|
],
|
|
105
132
|
body=ast_dto_attributes,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
1
2
|
from pydantic import BaseModel, Field
|
|
2
3
|
|
|
3
4
|
from nsj_rest_lib2.compiler.edl_model.primitives import BasicTypes, PropertyType
|
|
5
|
+
from nsj_rest_lib2.compiler.edl_model.property_meta_model import DomainConfigModel
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class TraitPropertyMetaModel(BaseModel):
|
|
@@ -8,3 +10,7 @@ class TraitPropertyMetaModel(BaseModel):
|
|
|
8
10
|
value: BasicTypes = Field(
|
|
9
11
|
..., description="Valor fixo da propriedade de condicionamento do trait."
|
|
10
12
|
)
|
|
13
|
+
domain_config: Optional[List[DomainConfigModel]] = Field(
|
|
14
|
+
None,
|
|
15
|
+
description="Lista de valores permitidos.",
|
|
16
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RelationDependency:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.tenant: int | None = None
|
|
9
|
+
self.grupo_empresarial: uuid.UUID | None = None
|
|
10
|
+
self.entity_resource: str | None = None
|
|
11
|
+
self.entity_scope: str | None = None
|
|
12
|
+
|
|
13
|
+
def to_dict(self) -> dict[str, Any]:
|
|
14
|
+
return {
|
|
15
|
+
"tenant": self.tenant,
|
|
16
|
+
"grupo_empresarial": (
|
|
17
|
+
str(self.grupo_empresarial) if self.grupo_empresarial else None
|
|
18
|
+
),
|
|
19
|
+
"entity_resource": self.entity_resource,
|
|
20
|
+
"entity_scope": self.entity_scope,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def from_dict(self, data: dict[str, Any]) -> "RelationDependency":
|
|
24
|
+
self.tenant = data.get("tenant")
|
|
25
|
+
self.grupo_empresarial = (
|
|
26
|
+
uuid.UUID(data["grupo_empresarial"])
|
|
27
|
+
if data.get("grupo_empresarial")
|
|
28
|
+
else None
|
|
29
|
+
)
|
|
30
|
+
self.entity_resource = data.get("entity_resource")
|
|
31
|
+
self.entity_scope = data.get("entity_scope")
|
|
32
|
+
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CompilerResult:
|
|
37
|
+
def __init__(self):
|
|
38
|
+
self.dto_class_name: str | None = None
|
|
39
|
+
self.dto_code: str | None = None
|
|
40
|
+
self.entity_class_name: str | None = None
|
|
41
|
+
self.entity_code: str | None = None
|
|
42
|
+
self.api_expose: bool | None = None
|
|
43
|
+
self.api_resource: str | None = None
|
|
44
|
+
self.api_verbs: list[str] | None = None
|
|
45
|
+
self.relations_dependencies: list[RelationDependency] | None = None
|
|
@@ -7,12 +7,17 @@ from nsj_rest_lib2.compiler.compiler_structures import (
|
|
|
7
7
|
)
|
|
8
8
|
from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
|
|
9
9
|
from nsj_rest_lib2.compiler.edl_model.primitives import (
|
|
10
|
+
BasicTypes,
|
|
10
11
|
CardinalityTypes,
|
|
11
12
|
PrimitiveTypes,
|
|
12
13
|
REGEX_EXTERNAL_REF,
|
|
13
14
|
REGEX_INTERNAL_REF,
|
|
14
15
|
)
|
|
15
16
|
from nsj_rest_lib2.compiler.edl_model.property_meta_model import PropertyMetaModel
|
|
17
|
+
from nsj_rest_lib2.compiler.edl_model.trait_property_meta_model import (
|
|
18
|
+
TraitPropertyMetaModel,
|
|
19
|
+
)
|
|
20
|
+
from nsj_rest_lib2.compiler.model import RelationDependency
|
|
16
21
|
from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
|
|
17
22
|
from nsj_rest_lib2.compiler.util.type_naming_util import (
|
|
18
23
|
compile_dto_class_name,
|
|
@@ -40,6 +45,8 @@ class EDLPropertyCompiler:
|
|
|
40
45
|
list[str],
|
|
41
46
|
list[ast.stmt],
|
|
42
47
|
list[tuple[str, str, str]],
|
|
48
|
+
list[RelationDependency],
|
|
49
|
+
list[tuple[str, BasicTypes]],
|
|
43
50
|
]:
|
|
44
51
|
|
|
45
52
|
# TODO Criar opção de campo calculado?
|
|
@@ -70,6 +77,8 @@ class EDLPropertyCompiler:
|
|
|
70
77
|
props_pk = []
|
|
71
78
|
enum_classes = []
|
|
72
79
|
related_imports = []
|
|
80
|
+
relations_dependencies = []
|
|
81
|
+
fixed_filters = []
|
|
73
82
|
|
|
74
83
|
if properties_structure.properties is None:
|
|
75
84
|
return (ast_dto_attributes, ast_entity_attributes, props_pk, enum_classes)
|
|
@@ -80,7 +89,7 @@ class EDLPropertyCompiler:
|
|
|
80
89
|
# DTO
|
|
81
90
|
## Tratando propriedade simples (não array, não object)
|
|
82
91
|
if isinstance(prop.type, PrimitiveTypes):
|
|
83
|
-
self.
|
|
92
|
+
self._compile_simple_property(
|
|
84
93
|
properties_structure,
|
|
85
94
|
map_unique_by_property,
|
|
86
95
|
entity_model,
|
|
@@ -94,119 +103,48 @@ class EDLPropertyCompiler:
|
|
|
94
103
|
|
|
95
104
|
elif isinstance(prop.type, str):
|
|
96
105
|
external_match = re.match(REGEX_EXTERNAL_REF, prop.type)
|
|
106
|
+
internal_match = re.match(REGEX_INTERNAL_REF, prop.type)
|
|
97
107
|
|
|
98
108
|
if external_match:
|
|
99
109
|
# Resolvendo o id da entidade
|
|
100
110
|
related_entity_id = external_match.group(2)
|
|
101
|
-
|
|
102
|
-
# Resolvendo o nome das classes de DTO e Entity
|
|
103
|
-
related_dto_class_name = compile_dto_class_name(related_entity_id)
|
|
104
|
-
related_entity_class_name = compile_entity_class_name(
|
|
105
|
-
related_entity_id
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
# Resolvendo o caminho do import
|
|
109
111
|
related_entity_key = external_match.group(0)
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
self._compile_external_relation(
|
|
114
|
+
related_entity_id,
|
|
115
|
+
related_entity_key,
|
|
116
|
+
entity_model,
|
|
117
|
+
entity_models,
|
|
118
|
+
properties_structure,
|
|
119
|
+
ast_dto_attributes,
|
|
120
|
+
related_imports,
|
|
121
|
+
relations_dependencies,
|
|
122
|
+
pkey,
|
|
123
|
+
prop,
|
|
121
124
|
)
|
|
122
125
|
|
|
123
|
-
|
|
124
|
-
tenant
|
|
125
|
-
and tenant != 0
|
|
126
|
-
and grupo_empresarial
|
|
127
|
-
and grupo_empresarial != "00000000-0000-0000-0000-000000000000"
|
|
128
|
-
):
|
|
129
|
-
related_import = grupo_key
|
|
130
|
-
elif tenant and tenant != 0:
|
|
131
|
-
related_import = tenant_key
|
|
132
|
-
else:
|
|
133
|
-
related_import = default_key
|
|
134
|
-
|
|
135
|
-
related_imports.append(
|
|
136
|
-
(
|
|
137
|
-
related_import,
|
|
138
|
-
related_dto_class_name,
|
|
139
|
-
related_entity_class_name,
|
|
140
|
-
)
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
# Instanciando o ast
|
|
144
|
-
if prop.cardinality == CardinalityTypes.C1_N:
|
|
145
|
-
# Para relacionamentos 1_N
|
|
146
|
-
keywords = [
|
|
147
|
-
ast.keyword(
|
|
148
|
-
arg="dto_type",
|
|
149
|
-
value=ast.Name(
|
|
150
|
-
id=related_dto_class_name, ctx=ast.Load()
|
|
151
|
-
),
|
|
152
|
-
),
|
|
153
|
-
ast.keyword(
|
|
154
|
-
arg="entity_type",
|
|
155
|
-
value=ast.Name(
|
|
156
|
-
id=related_entity_class_name, ctx=ast.Load()
|
|
157
|
-
),
|
|
158
|
-
),
|
|
159
|
-
]
|
|
160
|
-
|
|
161
|
-
# Resolvendo a coluna usada no relacionamento
|
|
162
|
-
if (
|
|
163
|
-
not properties_structure.entity_properties
|
|
164
|
-
or pkey not in properties_structure.entity_properties
|
|
165
|
-
or not properties_structure.entity_properties[
|
|
166
|
-
pkey
|
|
167
|
-
].relation_column
|
|
168
|
-
):
|
|
169
|
-
raise Exception(
|
|
170
|
-
f"Propriedade '{pkey}' possui um relacionamento, mas nenhuma coluna de relacioanamento foi apontada na propriedade correspondente no repository."
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
relation_column = properties_structure.entity_properties[
|
|
174
|
-
pkey
|
|
175
|
-
].relation_column
|
|
176
|
-
|
|
177
|
-
keywords.append(
|
|
178
|
-
ast.keyword(
|
|
179
|
-
arg="related_entity_field",
|
|
180
|
-
value=ast.Constant(value=relation_column),
|
|
181
|
-
)
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
ast_attr = ast.AnnAssign(
|
|
185
|
-
target=ast.Name(
|
|
186
|
-
id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()
|
|
187
|
-
),
|
|
188
|
-
annotation=ast.Name(
|
|
189
|
-
id="list",
|
|
190
|
-
ctx=ast.Load(),
|
|
191
|
-
),
|
|
192
|
-
value=ast.Call(
|
|
193
|
-
func=ast.Name(id="DTOListField", ctx=ast.Load()),
|
|
194
|
-
args=[],
|
|
195
|
-
keywords=keywords,
|
|
196
|
-
),
|
|
197
|
-
simple=1,
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
ast_dto_attributes.append(ast_attr)
|
|
201
|
-
else:
|
|
202
|
-
# TODO
|
|
203
|
-
pass
|
|
204
|
-
|
|
205
|
-
elif re.match(REGEX_INTERNAL_REF, prop.type):
|
|
126
|
+
elif internal_match:
|
|
206
127
|
# TODO
|
|
207
128
|
pass
|
|
208
129
|
else:
|
|
209
|
-
raise Exception(
|
|
130
|
+
raise Exception(
|
|
131
|
+
f"Tipo da propriedade '{pkey}' não suportado: {prop.type}"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
for pkey in properties_structure.trait_properties:
|
|
135
|
+
prop = properties_structure.trait_properties[pkey]
|
|
136
|
+
|
|
137
|
+
self._compile_trait_property(
|
|
138
|
+
properties_structure,
|
|
139
|
+
map_unique_by_property,
|
|
140
|
+
pkey,
|
|
141
|
+
prop,
|
|
142
|
+
ast_dto_attributes,
|
|
143
|
+
ast_entity_attributes,
|
|
144
|
+
fixed_filters,
|
|
145
|
+
entity_model,
|
|
146
|
+
enum_classes,
|
|
147
|
+
)
|
|
210
148
|
|
|
211
149
|
return (
|
|
212
150
|
ast_dto_attributes,
|
|
@@ -214,9 +152,411 @@ class EDLPropertyCompiler:
|
|
|
214
152
|
props_pk,
|
|
215
153
|
enum_classes,
|
|
216
154
|
related_imports,
|
|
155
|
+
relations_dependencies,
|
|
156
|
+
fixed_filters,
|
|
217
157
|
)
|
|
218
158
|
|
|
219
|
-
def
|
|
159
|
+
def _compile_trait_property(
|
|
160
|
+
self,
|
|
161
|
+
properties_structure: PropertiesCompilerStructure,
|
|
162
|
+
map_unique_by_property: dict[str, IndexCompilerStructure],
|
|
163
|
+
pkey: str,
|
|
164
|
+
prop: TraitPropertyMetaModel,
|
|
165
|
+
ast_dto_attributes: list[ast.stmt],
|
|
166
|
+
ast_entity_attributes: list[ast.stmt],
|
|
167
|
+
fixed_filters: list[tuple[str, BasicTypes]],
|
|
168
|
+
entity_model: EntityModel,
|
|
169
|
+
enum_classes: list[ast.stmt],
|
|
170
|
+
):
|
|
171
|
+
enum_class_name = None
|
|
172
|
+
keywords = []
|
|
173
|
+
|
|
174
|
+
if (
|
|
175
|
+
properties_structure.main_properties
|
|
176
|
+
and pkey in properties_structure.main_properties
|
|
177
|
+
):
|
|
178
|
+
keywords.append(ast.keyword(arg="resume", value=ast.Constant(True)))
|
|
179
|
+
|
|
180
|
+
if properties_structure.required and pkey in properties_structure.required:
|
|
181
|
+
keywords.append(ast.keyword(arg="not_null", value=ast.Constant(True)))
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
properties_structure.partition_data
|
|
185
|
+
and pkey in properties_structure.partition_data
|
|
186
|
+
):
|
|
187
|
+
keywords.append(ast.keyword(arg="partition_data", value=ast.Constant(True)))
|
|
188
|
+
|
|
189
|
+
if pkey in map_unique_by_property:
|
|
190
|
+
unique = map_unique_by_property[pkey].index_model
|
|
191
|
+
keywords.append(
|
|
192
|
+
ast.keyword(
|
|
193
|
+
arg="unique",
|
|
194
|
+
value=ast.Constant(unique.name),
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
if (
|
|
199
|
+
properties_structure.search_properties
|
|
200
|
+
and pkey in properties_structure.search_properties
|
|
201
|
+
):
|
|
202
|
+
keywords.append(ast.keyword(arg="search", value=ast.Constant(True)))
|
|
203
|
+
else:
|
|
204
|
+
keywords.append(ast.keyword(arg="search", value=ast.Constant(False)))
|
|
205
|
+
|
|
206
|
+
if (
|
|
207
|
+
properties_structure.metric_label
|
|
208
|
+
and pkey in properties_structure.metric_label
|
|
209
|
+
):
|
|
210
|
+
keywords.append(ast.keyword(arg="metric_label", value=ast.Constant(True)))
|
|
211
|
+
|
|
212
|
+
if prop.type == PrimitiveTypes.CPF:
|
|
213
|
+
keywords.append(
|
|
214
|
+
ast.keyword(
|
|
215
|
+
arg="validator",
|
|
216
|
+
value=ast.Attribute(
|
|
217
|
+
value=ast.Call(
|
|
218
|
+
func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
|
|
219
|
+
args=[],
|
|
220
|
+
keywords=[],
|
|
221
|
+
),
|
|
222
|
+
attr="validate_cpf",
|
|
223
|
+
ctx=ast.Load(),
|
|
224
|
+
),
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
elif prop.type == PrimitiveTypes.CNPJ:
|
|
228
|
+
keywords.append(
|
|
229
|
+
ast.keyword(
|
|
230
|
+
arg="validator",
|
|
231
|
+
value=ast.Attribute(
|
|
232
|
+
value=ast.Call(
|
|
233
|
+
func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
|
|
234
|
+
args=[],
|
|
235
|
+
keywords=[],
|
|
236
|
+
),
|
|
237
|
+
attr="validate_cnpj",
|
|
238
|
+
ctx=ast.Load(),
|
|
239
|
+
),
|
|
240
|
+
)
|
|
241
|
+
)
|
|
242
|
+
elif prop.type == PrimitiveTypes.CPF_CNPJ:
|
|
243
|
+
keywords.append(
|
|
244
|
+
ast.keyword(
|
|
245
|
+
arg="validator",
|
|
246
|
+
value=ast.Attribute(
|
|
247
|
+
value=ast.Call(
|
|
248
|
+
func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
|
|
249
|
+
args=[],
|
|
250
|
+
keywords=[],
|
|
251
|
+
),
|
|
252
|
+
attr="validate_cpf_or_cnpj",
|
|
253
|
+
ctx=ast.Load(),
|
|
254
|
+
),
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
elif prop.type == PrimitiveTypes.EMAIL:
|
|
258
|
+
keywords.append(
|
|
259
|
+
ast.keyword(
|
|
260
|
+
arg="validator",
|
|
261
|
+
value=ast.Attribute(
|
|
262
|
+
value=ast.Call(
|
|
263
|
+
func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
|
|
264
|
+
args=[],
|
|
265
|
+
keywords=[],
|
|
266
|
+
),
|
|
267
|
+
attr="validate_email",
|
|
268
|
+
ctx=ast.Load(),
|
|
269
|
+
),
|
|
270
|
+
)
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# Trtando de uma definição de enum
|
|
274
|
+
if prop.domain_config:
|
|
275
|
+
result = self._compile_domain_config(pkey, prop, entity_model)
|
|
276
|
+
if not result:
|
|
277
|
+
raise Exception(f"Erro desconhecido ao compilar a propriedade {pkey}")
|
|
278
|
+
|
|
279
|
+
enum_class_name, ast_enum_class = result
|
|
280
|
+
enum_classes.append(ast_enum_class)
|
|
281
|
+
|
|
282
|
+
# Resolvendo o nome da propriedade no Entity
|
|
283
|
+
if (
|
|
284
|
+
properties_structure.entity_properties
|
|
285
|
+
and pkey in properties_structure.entity_properties
|
|
286
|
+
):
|
|
287
|
+
entity_field_name = properties_structure.entity_properties[pkey].column
|
|
288
|
+
else:
|
|
289
|
+
entity_field_name = pkey
|
|
290
|
+
|
|
291
|
+
# Escrevendo, se necessário, o alias para o nome da entity
|
|
292
|
+
if entity_field_name != pkey:
|
|
293
|
+
keywords.append(
|
|
294
|
+
ast.keyword(
|
|
295
|
+
arg="entity_field",
|
|
296
|
+
value=ast.Constant(value=entity_field_name),
|
|
297
|
+
)
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Instanciando o atributo AST
|
|
301
|
+
if not isinstance(prop.type, PrimitiveTypes):
|
|
302
|
+
raise Exception(
|
|
303
|
+
f"Tipo da trait_property '{pkey}' não suportado: {prop.type} (deveria ser um Tipo Primitivo)"
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
# Instanciando o atributo AST
|
|
307
|
+
if enum_class_name:
|
|
308
|
+
prop_type = enum_class_name
|
|
309
|
+
else:
|
|
310
|
+
prop_type = TypeUtil.property_type_to_python_type(prop.type)
|
|
311
|
+
|
|
312
|
+
ast_attr = ast.AnnAssign(
|
|
313
|
+
target=ast.Name(id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()),
|
|
314
|
+
annotation=ast.Name(
|
|
315
|
+
id=prop_type,
|
|
316
|
+
ctx=ast.Load(),
|
|
317
|
+
),
|
|
318
|
+
value=ast.Call(
|
|
319
|
+
func=ast.Name(id="DTOField", ctx=ast.Load()),
|
|
320
|
+
args=[],
|
|
321
|
+
keywords=keywords,
|
|
322
|
+
),
|
|
323
|
+
simple=1,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
ast_dto_attributes.append(ast_attr)
|
|
327
|
+
|
|
328
|
+
# Entity
|
|
329
|
+
ast_entity_attr = ast.AnnAssign(
|
|
330
|
+
target=ast.Name(
|
|
331
|
+
id=CompilerStrUtil.to_snake_case(entity_field_name),
|
|
332
|
+
ctx=ast.Store(),
|
|
333
|
+
),
|
|
334
|
+
annotation=ast.Name(
|
|
335
|
+
id=TypeUtil.property_type_to_python_type(prop.type),
|
|
336
|
+
ctx=ast.Load(),
|
|
337
|
+
),
|
|
338
|
+
value=ast.Constant(value=None),
|
|
339
|
+
simple=1,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
ast_entity_attributes.append(ast_entity_attr)
|
|
343
|
+
|
|
344
|
+
# Guardando como um fixed_filter
|
|
345
|
+
# TODO Pernsar em validações para esse value (se está de acordo com o tipo ou enum)
|
|
346
|
+
fixed_filters.append((pkey, prop.value))
|
|
347
|
+
|
|
348
|
+
def _compile_external_relation(
|
|
349
|
+
self,
|
|
350
|
+
related_entity_id: str,
|
|
351
|
+
related_entity_key: str,
|
|
352
|
+
entity_model: EntityModel,
|
|
353
|
+
entity_models: dict[str, EntityModel],
|
|
354
|
+
properties_structure: PropertiesCompilerStructure,
|
|
355
|
+
ast_dto_attributes: list[ast.stmt],
|
|
356
|
+
related_imports: list[tuple[str, str, str]],
|
|
357
|
+
relations_dependencies: list[RelationDependency],
|
|
358
|
+
pkey: str,
|
|
359
|
+
prop: PropertyMetaModel,
|
|
360
|
+
):
|
|
361
|
+
# Resolvendo o nome das classes de DTO e Entity
|
|
362
|
+
related_dto_class_name = compile_dto_class_name(related_entity_id)
|
|
363
|
+
related_entity_class_name = compile_entity_class_name(related_entity_id)
|
|
364
|
+
|
|
365
|
+
# Resolvendo o caminho do import
|
|
366
|
+
related_entity = entity_models.get(related_entity_key)
|
|
367
|
+
if not related_entity:
|
|
368
|
+
raise Exception(
|
|
369
|
+
f"Entidade '{entity_model.id}' possui uma referência externa para uma entidade inexistente: '{related_entity_key}', por meio da propriedade: '{pkey}'."
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
tenant = related_entity.tenant
|
|
373
|
+
grupo_empresarial = related_entity.grupo_empresarial
|
|
374
|
+
grupo_key, tenant_key, default_key = compile_namespace_keys(
|
|
375
|
+
tenant, grupo_empresarial
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
if (
|
|
379
|
+
tenant
|
|
380
|
+
and tenant != 0
|
|
381
|
+
and grupo_empresarial
|
|
382
|
+
and grupo_empresarial != "00000000-0000-0000-0000-000000000000"
|
|
383
|
+
):
|
|
384
|
+
related_import = grupo_key
|
|
385
|
+
elif tenant and tenant != 0:
|
|
386
|
+
related_import = tenant_key
|
|
387
|
+
else:
|
|
388
|
+
related_import = default_key
|
|
389
|
+
|
|
390
|
+
related_imports.append(
|
|
391
|
+
(
|
|
392
|
+
related_import,
|
|
393
|
+
related_dto_class_name,
|
|
394
|
+
related_entity_class_name,
|
|
395
|
+
)
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
# Gravando a dependência de relacionamento
|
|
399
|
+
relation_dependency = RelationDependency()
|
|
400
|
+
relation_dependency.entity_resource = related_entity.api.resource
|
|
401
|
+
relation_dependency.entity_scope = related_entity.escopo
|
|
402
|
+
relation_dependency.tenant = tenant
|
|
403
|
+
relation_dependency.grupo_empresarial = grupo_empresarial
|
|
404
|
+
relations_dependencies.append(relation_dependency)
|
|
405
|
+
|
|
406
|
+
# Instanciando o ast
|
|
407
|
+
if prop.cardinality == CardinalityTypes.C1_N:
|
|
408
|
+
# Para relacionamentos 1_N
|
|
409
|
+
self._build_ast_1_N(
|
|
410
|
+
properties_structure,
|
|
411
|
+
ast_dto_attributes,
|
|
412
|
+
pkey,
|
|
413
|
+
related_dto_class_name,
|
|
414
|
+
related_entity_class_name,
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
elif prop.cardinality == CardinalityTypes.C1_1:
|
|
418
|
+
self._build_ast_1_1(
|
|
419
|
+
properties_structure,
|
|
420
|
+
ast_dto_attributes,
|
|
421
|
+
pkey,
|
|
422
|
+
related_dto_class_name,
|
|
423
|
+
related_entity_class_name,
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
elif prop.cardinality == CardinalityTypes.CN_N:
|
|
427
|
+
# TODO
|
|
428
|
+
pass
|
|
429
|
+
else:
|
|
430
|
+
raise Exception(
|
|
431
|
+
f"Propriedade '{pkey}' da entidade '{entity_model.id}' possui cardinalidade inválida ou não suportada: {prop.cardinality}"
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
def _build_ast_1_N(
|
|
435
|
+
self,
|
|
436
|
+
properties_structure: PropertiesCompilerStructure,
|
|
437
|
+
ast_dto_attributes: list[ast.stmt],
|
|
438
|
+
pkey: str,
|
|
439
|
+
related_dto_class_name: str,
|
|
440
|
+
related_entity_class_name: str,
|
|
441
|
+
):
|
|
442
|
+
# Propriedade do property descriptor
|
|
443
|
+
keywords = [
|
|
444
|
+
ast.keyword(
|
|
445
|
+
arg="dto_type",
|
|
446
|
+
value=ast.Name(id=related_dto_class_name, ctx=ast.Load()),
|
|
447
|
+
),
|
|
448
|
+
ast.keyword(
|
|
449
|
+
arg="entity_type",
|
|
450
|
+
value=ast.Name(id=related_entity_class_name, ctx=ast.Load()),
|
|
451
|
+
),
|
|
452
|
+
]
|
|
453
|
+
|
|
454
|
+
# Resolvendo a coluna usada no relacionamento
|
|
455
|
+
if (
|
|
456
|
+
not properties_structure.entity_properties
|
|
457
|
+
or pkey not in properties_structure.entity_properties
|
|
458
|
+
or not properties_structure.entity_properties[pkey].relation_column
|
|
459
|
+
):
|
|
460
|
+
raise Exception(
|
|
461
|
+
f"Propriedade '{pkey}' possui um relacionamento, mas nenhuma coluna de relacioanamento foi apontada na propriedade correspondente no repository."
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
relation_column = properties_structure.entity_properties[pkey].relation_column
|
|
465
|
+
|
|
466
|
+
keywords.append(
|
|
467
|
+
ast.keyword(
|
|
468
|
+
arg="related_entity_field",
|
|
469
|
+
value=ast.Constant(value=relation_column),
|
|
470
|
+
)
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
ast_attr = ast.AnnAssign(
|
|
474
|
+
target=ast.Name(id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()),
|
|
475
|
+
annotation=ast.Name(
|
|
476
|
+
id="list",
|
|
477
|
+
ctx=ast.Load(),
|
|
478
|
+
),
|
|
479
|
+
value=ast.Call(
|
|
480
|
+
func=ast.Name(id="DTOListField", ctx=ast.Load()),
|
|
481
|
+
args=[],
|
|
482
|
+
keywords=keywords,
|
|
483
|
+
),
|
|
484
|
+
simple=1,
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
ast_dto_attributes.append(ast_attr)
|
|
488
|
+
|
|
489
|
+
def _build_ast_1_1(
|
|
490
|
+
self,
|
|
491
|
+
properties_structure: PropertiesCompilerStructure,
|
|
492
|
+
ast_dto_attributes: list[ast.stmt],
|
|
493
|
+
pkey: str,
|
|
494
|
+
related_dto_class_name: str,
|
|
495
|
+
related_entity_class_name: str,
|
|
496
|
+
):
|
|
497
|
+
# Propriedade do property descriptor
|
|
498
|
+
keywords = [
|
|
499
|
+
ast.keyword(
|
|
500
|
+
arg="entity_type",
|
|
501
|
+
value=ast.Name(id=related_entity_class_name, ctx=ast.Load()),
|
|
502
|
+
),
|
|
503
|
+
]
|
|
504
|
+
|
|
505
|
+
# Resolvendo a coluna usada no relacionamento
|
|
506
|
+
if (
|
|
507
|
+
not properties_structure.entity_properties
|
|
508
|
+
or pkey not in properties_structure.entity_properties
|
|
509
|
+
or not properties_structure.entity_properties[pkey].relation_column
|
|
510
|
+
):
|
|
511
|
+
raise Exception(
|
|
512
|
+
f"Propriedade '{pkey}' possui um relacionamento, mas nenhuma coluna de relacioanamento foi apontada na propriedade correspondente no repository."
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
relation_column = str(
|
|
516
|
+
properties_structure.entity_properties[pkey].relation_column
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
owner_relation = False
|
|
520
|
+
if "/" in relation_column:
|
|
521
|
+
owner_relation = True
|
|
522
|
+
relation_column = relation_column.split("/")[-1]
|
|
523
|
+
|
|
524
|
+
keywords.append(
|
|
525
|
+
ast.keyword(
|
|
526
|
+
arg="relation_field",
|
|
527
|
+
value=ast.Constant(value=relation_column),
|
|
528
|
+
)
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
if not owner_relation:
|
|
532
|
+
keywords.append(
|
|
533
|
+
ast.keyword(
|
|
534
|
+
arg="entity_relation_owner",
|
|
535
|
+
value=ast.Attribute(
|
|
536
|
+
value=ast.Name(id="EntityRelationOwner", ctx=ast.Load()),
|
|
537
|
+
attr="OTHER",
|
|
538
|
+
ctx=ast.Load(),
|
|
539
|
+
),
|
|
540
|
+
)
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
ast_attr = ast.AnnAssign(
|
|
544
|
+
target=ast.Name(id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()),
|
|
545
|
+
annotation=ast.Name(
|
|
546
|
+
id=related_dto_class_name,
|
|
547
|
+
ctx=ast.Load(),
|
|
548
|
+
),
|
|
549
|
+
value=ast.Call(
|
|
550
|
+
func=ast.Name(id="DTOObjectField", ctx=ast.Load()),
|
|
551
|
+
args=[],
|
|
552
|
+
keywords=keywords,
|
|
553
|
+
),
|
|
554
|
+
simple=1,
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
ast_dto_attributes.append(ast_attr)
|
|
558
|
+
|
|
559
|
+
def _compile_simple_property(
|
|
220
560
|
self,
|
|
221
561
|
properties_structure,
|
|
222
562
|
map_unique_by_property,
|
|
@@ -461,7 +801,7 @@ class EDLPropertyCompiler:
|
|
|
461
801
|
def _compile_domain_config(
|
|
462
802
|
self,
|
|
463
803
|
pkey: str,
|
|
464
|
-
prop: PropertyMetaModel,
|
|
804
|
+
prop: PropertyMetaModel | TraitPropertyMetaModel,
|
|
465
805
|
entity_model: EntityModel,
|
|
466
806
|
) -> tuple[str, ast.stmt] | None:
|
|
467
807
|
if not prop.domain_config:
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import json
|
|
3
|
+
import re
|
|
3
4
|
import sys
|
|
4
5
|
import threading
|
|
5
6
|
import types
|
|
6
7
|
|
|
7
8
|
from nsj_rest_lib.settings import get_logger
|
|
8
9
|
|
|
10
|
+
from nsj_rest_lib2.compiler.edl_model.primitives import REGEX_EXTERNAL_REF
|
|
11
|
+
from nsj_rest_lib2.compiler.model import RelationDependency
|
|
9
12
|
from nsj_rest_lib2.compiler.util.type_naming_util import compile_namespace_keys
|
|
10
13
|
from nsj_rest_lib2.exception import MissingEntityConfigException
|
|
11
14
|
from nsj_rest_lib2.redis_config import get_redis
|
|
@@ -21,14 +24,15 @@ class LoadedEntity:
|
|
|
21
24
|
self.loaded_at: datetime.datetime = datetime.datetime.now()
|
|
22
25
|
self.api_expose: bool = False
|
|
23
26
|
self.api_verbs: list[str] = []
|
|
27
|
+
self.relations_dependencies: list[RelationDependency] = []
|
|
24
28
|
|
|
25
29
|
|
|
26
30
|
class Namespace:
|
|
27
31
|
def __init__(self):
|
|
28
32
|
self.key: str = ""
|
|
29
33
|
self.loaded_entities: dict[str, LoadedEntity] = {}
|
|
30
|
-
self.entities_dict: dict =
|
|
31
|
-
self.module: types.ModuleType =
|
|
34
|
+
self.entities_dict: dict = {}
|
|
35
|
+
self.module: types.ModuleType = types.ModuleType("empty")
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
namespaces_dict: dict[str, Namespace] = {}
|
|
@@ -43,17 +47,18 @@ class EntityLoader:
|
|
|
43
47
|
entity_resource: str,
|
|
44
48
|
tenant: str | None,
|
|
45
49
|
grupo_empresarial: str | None,
|
|
50
|
+
escopo: str = ESCOPO_RESTLIB2,
|
|
46
51
|
) -> tuple[str, str, dict, bool, list[str]]:
|
|
47
52
|
# Montando as chaves dos namespaces
|
|
48
53
|
grupo_key, tenant_key, default_key = compile_namespace_keys(
|
|
49
54
|
tenant, grupo_empresarial
|
|
50
55
|
)
|
|
51
56
|
|
|
52
|
-
result = self.
|
|
57
|
+
result = self._search_entity_namespace_in_memory(
|
|
53
58
|
entity_resource, grupo_key, tenant_key, default_key
|
|
54
59
|
)
|
|
55
60
|
|
|
56
|
-
# Se conseguiu
|
|
61
|
+
# Se conseguiu localizar na memória, verifica se houve alteração no hash, em relação ao redis
|
|
57
62
|
if result is not None:
|
|
58
63
|
# Desempacotando o result e recuperando informações do namespace
|
|
59
64
|
(
|
|
@@ -67,6 +72,21 @@ class EntityLoader:
|
|
|
67
72
|
entities_dict = namespace.entities_dict
|
|
68
73
|
api_expose = loaded_entity.api_expose
|
|
69
74
|
api_verbs = loaded_entity.api_verbs
|
|
75
|
+
relations_dependencies = loaded_entity.relations_dependencies
|
|
76
|
+
|
|
77
|
+
# Verificando se alguma de suas dependências precisariam ser recarregadas
|
|
78
|
+
for rd in relations_dependencies:
|
|
79
|
+
if rd.entity_resource is None or rd.entity_scope is None:
|
|
80
|
+
raise RuntimeError(
|
|
81
|
+
f"Erro: Dependência de entidade mal formada na entidade {entity_resource}."
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
self.load_entity_source(
|
|
85
|
+
rd.entity_resource,
|
|
86
|
+
str(rd.tenant),
|
|
87
|
+
str(rd.grupo_empresarial),
|
|
88
|
+
rd.entity_scope,
|
|
89
|
+
)
|
|
70
90
|
|
|
71
91
|
# Se o tempo entre o carregamento e agora for maior do que MIN_TIME_SOURCE_REFRESH minutos,
|
|
72
92
|
# verifica se precisa de refresh
|
|
@@ -83,6 +103,7 @@ class EntityLoader:
|
|
|
83
103
|
tenant_key,
|
|
84
104
|
default_key,
|
|
85
105
|
entity_config_key,
|
|
106
|
+
escopo=escopo,
|
|
86
107
|
)
|
|
87
108
|
|
|
88
109
|
# Se não achar no redis, usa o que estava em memória
|
|
@@ -142,7 +163,12 @@ class EntityLoader:
|
|
|
142
163
|
|
|
143
164
|
# Se não conseguir recuperar a entidade, procura no redis:
|
|
144
165
|
loaded_config = self._load_entity_config_from_redis(
|
|
145
|
-
entity_resource,
|
|
166
|
+
entity_resource,
|
|
167
|
+
grupo_key,
|
|
168
|
+
tenant_key,
|
|
169
|
+
default_key,
|
|
170
|
+
None,
|
|
171
|
+
escopo=escopo,
|
|
146
172
|
)
|
|
147
173
|
|
|
148
174
|
# Se também não achar no redis, lanca exceção
|
|
@@ -215,6 +241,10 @@ class EntityLoader:
|
|
|
215
241
|
api_expose = entity_config["api_expose"]
|
|
216
242
|
# api_resource = entity_config["api_resource"]
|
|
217
243
|
api_verbs = entity_config["api_verbs"]
|
|
244
|
+
relations_dependencies = [
|
|
245
|
+
RelationDependency().from_dict(rd)
|
|
246
|
+
for rd in entity_config.get("relations_dependencies", [])
|
|
247
|
+
]
|
|
218
248
|
except json.JSONDecodeError as e:
|
|
219
249
|
if not check_refresh:
|
|
220
250
|
raise RuntimeError(
|
|
@@ -226,6 +256,20 @@ class EntityLoader:
|
|
|
226
256
|
)
|
|
227
257
|
return None
|
|
228
258
|
|
|
259
|
+
# Verificando se alguma de suas dependências precisariam ser carregadas (ou recarregadas)
|
|
260
|
+
for rd in relations_dependencies:
|
|
261
|
+
if rd.entity_resource is None or rd.entity_scope is None:
|
|
262
|
+
raise RuntimeError(
|
|
263
|
+
f"Erro: Dependência de entidade mal formada na entidade {entity_resource}."
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
self.load_entity_source(
|
|
267
|
+
rd.entity_resource,
|
|
268
|
+
str(rd.tenant),
|
|
269
|
+
str(rd.grupo_empresarial),
|
|
270
|
+
rd.entity_scope,
|
|
271
|
+
)
|
|
272
|
+
|
|
229
273
|
# Verificando se a entidade precisa ou não de refresh
|
|
230
274
|
if check_refresh:
|
|
231
275
|
loaded_namespace = namespaces_dict.get(entity_config_key)
|
|
@@ -283,6 +327,7 @@ class EntityLoader:
|
|
|
283
327
|
loaded_entity.entity_hash = entity_hash
|
|
284
328
|
loaded_entity.api_expose = api_expose
|
|
285
329
|
loaded_entity.api_verbs = api_verbs
|
|
330
|
+
loaded_entity.relations_dependencies = relations_dependencies
|
|
286
331
|
|
|
287
332
|
namespace.loaded_entities[entity_resource] = loaded_entity
|
|
288
333
|
|
|
@@ -302,30 +347,31 @@ class EntityLoader:
|
|
|
302
347
|
tenant_key: str,
|
|
303
348
|
default_key: str,
|
|
304
349
|
entity_config_key: str | None,
|
|
350
|
+
escopo: str,
|
|
305
351
|
) -> tuple[str, str] | None:
|
|
306
352
|
get_logger().debug(
|
|
307
|
-
f"Procurando a configuração da entidade {entity_resource} no redis"
|
|
353
|
+
f"Procurando a configuração da entidade {entity_resource} no redis. Tenant key: {tenant_key} e Grupo key: {grupo_key}"
|
|
308
354
|
)
|
|
309
355
|
|
|
310
356
|
if entity_config_key is not None:
|
|
311
357
|
entity_config_str = get_redis(
|
|
312
|
-
"entity_config",
|
|
358
|
+
"entity_config", escopo, entity_config_key, entity_resource
|
|
313
359
|
)
|
|
314
360
|
|
|
315
361
|
else:
|
|
316
362
|
entity_config_key = grupo_key
|
|
317
363
|
entity_config_str = get_redis(
|
|
318
|
-
"entity_config",
|
|
364
|
+
"entity_config", escopo, grupo_key, entity_resource
|
|
319
365
|
)
|
|
320
366
|
if entity_config_str is None:
|
|
321
367
|
entity_config_key = tenant_key
|
|
322
368
|
entity_config_str = get_redis(
|
|
323
|
-
"entity_config",
|
|
369
|
+
"entity_config", escopo, tenant_key, entity_resource
|
|
324
370
|
)
|
|
325
371
|
if entity_config_str is None:
|
|
326
372
|
entity_config_key = default_key
|
|
327
373
|
entity_config_str = get_redis(
|
|
328
|
-
"entity_config",
|
|
374
|
+
"entity_config", escopo, default_key, entity_resource
|
|
329
375
|
)
|
|
330
376
|
|
|
331
377
|
# Se não encontrar no redis, retorna None
|
|
@@ -334,7 +380,7 @@ class EntityLoader:
|
|
|
334
380
|
|
|
335
381
|
return (entity_config_key, entity_config_str)
|
|
336
382
|
|
|
337
|
-
def
|
|
383
|
+
def _search_entity_namespace_in_memory(
|
|
338
384
|
self,
|
|
339
385
|
entity_resource: str,
|
|
340
386
|
grupo_key: str,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nsj_rest_lib2
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
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
|
|
@@ -4,21 +4,22 @@ nsj_rest_lib2/redis_config.py,sha256=4KLcvYS3nJO7PMQgF6F9_j6r-TyqcS7TBbd3LEQuKDU
|
|
|
4
4
|
nsj_rest_lib2/settings.py,sha256=Hn_o1HZmievnYb8D1kNT2Nq-OEjxbyNjOiOpbnFsMwE,367
|
|
5
5
|
nsj_rest_lib2/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
nsj_rest_lib2/compiler/ai_compiler.py,sha256=shAtN4T0ai_52qh15L3mK1QbeC6glHOR6C3J3gj14II,9029
|
|
7
|
-
nsj_rest_lib2/compiler/compiler.py,sha256=
|
|
7
|
+
nsj_rest_lib2/compiler/compiler.py,sha256=tWnhDuHpvpJMWMPxt6U76ZS6J-hSpiB7xRZaeOP3CMc,12334
|
|
8
8
|
nsj_rest_lib2/compiler/compiler_structures.py,sha256=2bM4_7lG1fytDGxJl6SU9pLsbspiNV36gVn9-O-23Q8,1009
|
|
9
|
-
nsj_rest_lib2/compiler/dto_compiler.py,sha256=
|
|
9
|
+
nsj_rest_lib2/compiler/dto_compiler.py,sha256=4e9_8EsNSHPCUEmiuEPdudj9_tFuw2O4ZTv6EYwJrGc,5333
|
|
10
10
|
nsj_rest_lib2/compiler/entity_compiler.py,sha256=zLXO6USY4Rr0Hnk4wGep5K8DiHxJv-W-BBz_-g4OhCA,4307
|
|
11
|
-
nsj_rest_lib2/compiler/
|
|
11
|
+
nsj_rest_lib2/compiler/model.py,sha256=QDBoM26qoZdiNcykl1nvXCrFDhg-6Q__QzVq6uY1QzE,1460
|
|
12
|
+
nsj_rest_lib2/compiler/property_compiler.py,sha256=kr9Pi0kkIrvgEmxrmV_NEQuqekM1h6-jqvF85nZTUcY,29808
|
|
12
13
|
nsj_rest_lib2/compiler/edl_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
14
|
nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py,sha256=664QBDcOgVnyfwtUOXO1W7AKaZhueBG335x5DuogruY,7644
|
|
14
15
|
nsj_rest_lib2/compiler/edl_model/api_model.py,sha256=pH0Uiq_64AGvkHqwY44TrulWWZXbi6M0EKJWUhSqKj0,837
|
|
15
|
-
nsj_rest_lib2/compiler/edl_model/column_meta_model.py,sha256=
|
|
16
|
+
nsj_rest_lib2/compiler/edl_model/column_meta_model.py,sha256=s0sEVkoW1hV2_hto1mws4XhzKGH_b4NzhaOiwFH25Ks,694
|
|
16
17
|
nsj_rest_lib2/compiler/edl_model/entity_model.py,sha256=sXVfC30P3-q2-fQ3XB_-3vpNjqFPIK5oBIVbwkXNFLU,3662
|
|
17
18
|
nsj_rest_lib2/compiler/edl_model/index_model.py,sha256=cXWlu0hxtro5vvYoirkDW4R3PCnBW5oCCWjRJ6AX5zE,508
|
|
18
19
|
nsj_rest_lib2/compiler/edl_model/primitives.py,sha256=cWEys87xDpgotyRUXkzvFvY4LHeawzBEEyz0Xed18AQ,1454
|
|
19
20
|
nsj_rest_lib2/compiler/edl_model/property_meta_model.py,sha256=x2SApvI-5MZTErAHeOXnR6qfjflhSs8r6Y9KMtCykV0,3960
|
|
20
21
|
nsj_rest_lib2/compiler/edl_model/repository_model.py,sha256=Vt1HxlaoifP4w5ij1laKDkD1-COBihE8EX1HkdEDUSo,977
|
|
21
|
-
nsj_rest_lib2/compiler/edl_model/trait_property_meta_model.py,sha256=
|
|
22
|
+
nsj_rest_lib2/compiler/edl_model/trait_property_meta_model.py,sha256=SBSfiu4v0PMsWRsGDySR3P2tkabLbDZxx_FFy_3rGXA,605
|
|
22
23
|
nsj_rest_lib2/compiler/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
24
|
nsj_rest_lib2/compiler/util/str_util.py,sha256=lVP1yHhj1pOd6ULtTnkcfX6Gqrpe4yCBratHUhBNGcI,843
|
|
24
25
|
nsj_rest_lib2/compiler/util/type_naming_util.py,sha256=sahlxtYUPcksqlX1hygaoTF7vuD8tY8eosgOR04YLAs,612
|
|
@@ -26,8 +27,8 @@ nsj_rest_lib2/compiler/util/type_util.py,sha256=HTKOH4uRTOY0YgoM8oUv_6cEcReE_bgK
|
|
|
26
27
|
nsj_rest_lib2/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
28
|
nsj_rest_lib2/controller/dynamic_controller.py,sha256=XMqxe1NW-NE5XwomXb4pSNdALQHpP74Hc26R4fnmXqg,15194
|
|
28
29
|
nsj_rest_lib2/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
nsj_rest_lib2/service/entity_loader.py,sha256=
|
|
30
|
-
nsj_rest_lib2-0.0.
|
|
31
|
-
nsj_rest_lib2-0.0.
|
|
32
|
-
nsj_rest_lib2-0.0.
|
|
33
|
-
nsj_rest_lib2-0.0.
|
|
30
|
+
nsj_rest_lib2/service/entity_loader.py,sha256=KVLFQSqj4DL-K-T29ksJE2or9QkekFmyAGUIKjQX6Qk,15372
|
|
31
|
+
nsj_rest_lib2-0.0.12.dist-info/METADATA,sha256=CTk1vS9FJ_U2e6-Vz38wj3Ba2efwuKPW-iDpHlosHzk,1361
|
|
32
|
+
nsj_rest_lib2-0.0.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
33
|
+
nsj_rest_lib2-0.0.12.dist-info/top_level.txt,sha256=L6zh0EfH8_rur7OJ8_V-El-XEMf4qg3bkF8ADgqLVIA,14
|
|
34
|
+
nsj_rest_lib2-0.0.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|