nsj-rest-lib2 0.0.11__py3-none-any.whl → 0.0.13__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.
@@ -105,6 +105,7 @@ class EDLCompiler:
105
105
  enum_classes,
106
106
  related_imports,
107
107
  relations_dependencies,
108
+ fixed_filters,
108
109
  ) = self._properties_compiler.compile(
109
110
  properties_structure,
110
111
  map_unique_by_property,
@@ -114,7 +115,11 @@ class EDLCompiler:
114
115
 
115
116
  # Gerando o código do DTO
116
117
  dto_class_name, code_dto = self._dto_compiler.compile(
117
- entity_model, ast_dto_attributes, enum_classes, related_imports
118
+ entity_model,
119
+ ast_dto_attributes,
120
+ enum_classes,
121
+ related_imports,
122
+ fixed_filters,
118
123
  )
119
124
 
120
125
  # Gerando o código da Entity
@@ -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,5 +1,5 @@
1
1
  from pydantic import BaseModel, Field, model_validator
2
- from typing import List, Optional, Literal
2
+ from typing import Optional
3
3
 
4
4
 
5
5
  class ColumnMetaModel(BaseModel):
@@ -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
+ )
@@ -7,12 +7,16 @@ 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
+ )
16
20
  from nsj_rest_lib2.compiler.model import RelationDependency
17
21
  from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
18
22
  from nsj_rest_lib2.compiler.util.type_naming_util import (
@@ -42,6 +46,7 @@ class EDLPropertyCompiler:
42
46
  list[ast.stmt],
43
47
  list[tuple[str, str, str]],
44
48
  list[RelationDependency],
49
+ list[tuple[str, BasicTypes]],
45
50
  ]:
46
51
 
47
52
  # TODO Criar opção de campo calculado?
@@ -73,6 +78,7 @@ class EDLPropertyCompiler:
73
78
  enum_classes = []
74
79
  related_imports = []
75
80
  relations_dependencies = []
81
+ fixed_filters = []
76
82
 
77
83
  if properties_structure.properties is None:
78
84
  return (ast_dto_attributes, ast_entity_attributes, props_pk, enum_classes)
@@ -83,7 +89,7 @@ class EDLPropertyCompiler:
83
89
  # DTO
84
90
  ## Tratando propriedade simples (não array, não object)
85
91
  if isinstance(prop.type, PrimitiveTypes):
86
- self.compile_simple_property(
92
+ self._compile_simple_property(
87
93
  properties_structure,
88
94
  map_unique_by_property,
89
95
  entity_model,
@@ -97,127 +103,49 @@ class EDLPropertyCompiler:
97
103
 
98
104
  elif isinstance(prop.type, str):
99
105
  external_match = re.match(REGEX_EXTERNAL_REF, prop.type)
106
+ internal_match = re.match(REGEX_INTERNAL_REF, prop.type)
100
107
 
101
108
  if external_match:
102
109
  # Resolvendo o id da entidade
103
110
  related_entity_id = external_match.group(2)
104
-
105
- # Resolvendo o nome das classes de DTO e Entity
106
- related_dto_class_name = compile_dto_class_name(related_entity_id)
107
- related_entity_class_name = compile_entity_class_name(
108
- related_entity_id
109
- )
110
-
111
- # Resolvendo o caminho do import
112
111
  related_entity_key = external_match.group(0)
113
112
 
114
- related_entity = entity_models.get(related_entity_key)
115
- if not related_entity:
116
- raise Exception(
117
- f"Entidade '{entity_model.id}' possui uma referência externa para uma entidade inexistente: '{related_entity_key}', por meio da propriedade: '{pkey}'."
118
- )
119
-
120
- tenant = related_entity.tenant
121
- grupo_empresarial = related_entity.grupo_empresarial
122
- grupo_key, tenant_key, default_key = compile_namespace_keys(
123
- tenant, grupo_empresarial
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
+ ast_entity_attributes,
121
+ related_imports,
122
+ relations_dependencies,
123
+ pkey,
124
+ prop,
124
125
  )
125
126
 
126
- if (
127
- tenant
128
- and tenant != 0
129
- and grupo_empresarial
130
- and grupo_empresarial != "00000000-0000-0000-0000-000000000000"
131
- ):
132
- related_import = grupo_key
133
- elif tenant and tenant != 0:
134
- related_import = tenant_key
135
- else:
136
- related_import = default_key
137
-
138
- related_imports.append(
139
- (
140
- related_import,
141
- related_dto_class_name,
142
- related_entity_class_name,
143
- )
144
- )
145
-
146
- # Gravando a dependência de relacionamento
147
- relation_dependency = RelationDependency()
148
- relation_dependency.entity_resource = related_entity.api.resource
149
- relation_dependency.entity_scope = related_entity.escopo
150
- relation_dependency.tenant = tenant
151
- relation_dependency.grupo_empresarial = grupo_empresarial
152
- relations_dependencies.append(relation_dependency)
153
-
154
- # Instanciando o ast
155
- if prop.cardinality == CardinalityTypes.C1_N:
156
- # Para relacionamentos 1_N
157
- keywords = [
158
- ast.keyword(
159
- arg="dto_type",
160
- value=ast.Name(
161
- id=related_dto_class_name, ctx=ast.Load()
162
- ),
163
- ),
164
- ast.keyword(
165
- arg="entity_type",
166
- value=ast.Name(
167
- id=related_entity_class_name, ctx=ast.Load()
168
- ),
169
- ),
170
- ]
171
-
172
- # Resolvendo a coluna usada no relacionamento
173
- if (
174
- not properties_structure.entity_properties
175
- or pkey not in properties_structure.entity_properties
176
- or not properties_structure.entity_properties[
177
- pkey
178
- ].relation_column
179
- ):
180
- raise Exception(
181
- f"Propriedade '{pkey}' possui um relacionamento, mas nenhuma coluna de relacioanamento foi apontada na propriedade correspondente no repository."
182
- )
183
-
184
- relation_column = properties_structure.entity_properties[
185
- pkey
186
- ].relation_column
187
-
188
- keywords.append(
189
- ast.keyword(
190
- arg="related_entity_field",
191
- value=ast.Constant(value=relation_column),
192
- )
193
- )
194
-
195
- ast_attr = ast.AnnAssign(
196
- target=ast.Name(
197
- id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()
198
- ),
199
- annotation=ast.Name(
200
- id="list",
201
- ctx=ast.Load(),
202
- ),
203
- value=ast.Call(
204
- func=ast.Name(id="DTOListField", ctx=ast.Load()),
205
- args=[],
206
- keywords=keywords,
207
- ),
208
- simple=1,
209
- )
210
-
211
- ast_dto_attributes.append(ast_attr)
212
- else:
213
- # TODO
214
- pass
215
-
216
- elif re.match(REGEX_INTERNAL_REF, prop.type):
127
+ elif internal_match:
217
128
  # TODO
218
129
  pass
219
130
  else:
220
- raise Exception(f"Tipo de propriedade não suportado: {prop.type}")
131
+ raise Exception(
132
+ f"Tipo da propriedade '{pkey}' não suportado: {prop.type}"
133
+ )
134
+
135
+ for pkey in properties_structure.trait_properties:
136
+ prop = properties_structure.trait_properties[pkey]
137
+
138
+ self._compile_trait_property(
139
+ properties_structure,
140
+ map_unique_by_property,
141
+ pkey,
142
+ prop,
143
+ ast_dto_attributes,
144
+ ast_entity_attributes,
145
+ fixed_filters,
146
+ entity_model,
147
+ enum_classes,
148
+ )
221
149
 
222
150
  return (
223
151
  ast_dto_attributes,
@@ -226,9 +154,470 @@ class EDLPropertyCompiler:
226
154
  enum_classes,
227
155
  related_imports,
228
156
  relations_dependencies,
157
+ fixed_filters,
229
158
  )
230
159
 
231
- def compile_simple_property(
160
+ def _compile_trait_property(
161
+ self,
162
+ properties_structure: PropertiesCompilerStructure,
163
+ map_unique_by_property: dict[str, IndexCompilerStructure],
164
+ pkey: str,
165
+ prop: TraitPropertyMetaModel,
166
+ ast_dto_attributes: list[ast.stmt],
167
+ ast_entity_attributes: list[ast.stmt],
168
+ fixed_filters: list[tuple[str, BasicTypes]],
169
+ entity_model: EntityModel,
170
+ enum_classes: list[ast.stmt],
171
+ ):
172
+ enum_class_name = None
173
+ keywords = []
174
+
175
+ if (
176
+ properties_structure.main_properties
177
+ and pkey in properties_structure.main_properties
178
+ ):
179
+ keywords.append(ast.keyword(arg="resume", value=ast.Constant(True)))
180
+
181
+ if properties_structure.required and pkey in properties_structure.required:
182
+ keywords.append(ast.keyword(arg="not_null", value=ast.Constant(True)))
183
+
184
+ if (
185
+ properties_structure.partition_data
186
+ and pkey in properties_structure.partition_data
187
+ ):
188
+ keywords.append(ast.keyword(arg="partition_data", value=ast.Constant(True)))
189
+
190
+ if pkey in map_unique_by_property:
191
+ unique = map_unique_by_property[pkey].index_model
192
+ keywords.append(
193
+ ast.keyword(
194
+ arg="unique",
195
+ value=ast.Constant(unique.name),
196
+ )
197
+ )
198
+
199
+ if (
200
+ properties_structure.search_properties
201
+ and pkey in properties_structure.search_properties
202
+ ):
203
+ keywords.append(ast.keyword(arg="search", value=ast.Constant(True)))
204
+ else:
205
+ keywords.append(ast.keyword(arg="search", value=ast.Constant(False)))
206
+
207
+ if (
208
+ properties_structure.metric_label
209
+ and pkey in properties_structure.metric_label
210
+ ):
211
+ keywords.append(ast.keyword(arg="metric_label", value=ast.Constant(True)))
212
+
213
+ if prop.type == PrimitiveTypes.CPF:
214
+ keywords.append(
215
+ ast.keyword(
216
+ arg="validator",
217
+ value=ast.Attribute(
218
+ value=ast.Call(
219
+ func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
220
+ args=[],
221
+ keywords=[],
222
+ ),
223
+ attr="validate_cpf",
224
+ ctx=ast.Load(),
225
+ ),
226
+ )
227
+ )
228
+ elif prop.type == PrimitiveTypes.CNPJ:
229
+ keywords.append(
230
+ ast.keyword(
231
+ arg="validator",
232
+ value=ast.Attribute(
233
+ value=ast.Call(
234
+ func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
235
+ args=[],
236
+ keywords=[],
237
+ ),
238
+ attr="validate_cnpj",
239
+ ctx=ast.Load(),
240
+ ),
241
+ )
242
+ )
243
+ elif prop.type == PrimitiveTypes.CPF_CNPJ:
244
+ keywords.append(
245
+ ast.keyword(
246
+ arg="validator",
247
+ value=ast.Attribute(
248
+ value=ast.Call(
249
+ func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
250
+ args=[],
251
+ keywords=[],
252
+ ),
253
+ attr="validate_cpf_or_cnpj",
254
+ ctx=ast.Load(),
255
+ ),
256
+ )
257
+ )
258
+ elif prop.type == PrimitiveTypes.EMAIL:
259
+ keywords.append(
260
+ ast.keyword(
261
+ arg="validator",
262
+ value=ast.Attribute(
263
+ value=ast.Call(
264
+ func=ast.Name(id="DTOFieldValidators", ctx=ast.Load()),
265
+ args=[],
266
+ keywords=[],
267
+ ),
268
+ attr="validate_email",
269
+ ctx=ast.Load(),
270
+ ),
271
+ )
272
+ )
273
+
274
+ # Trtando de uma definição de enum
275
+ if prop.domain_config:
276
+ result = self._compile_domain_config(pkey, prop, entity_model)
277
+ if not result:
278
+ raise Exception(f"Erro desconhecido ao compilar a propriedade {pkey}")
279
+
280
+ enum_class_name, ast_enum_class = result
281
+ enum_classes.append(ast_enum_class)
282
+
283
+ # Resolvendo o nome da propriedade no Entity
284
+ if (
285
+ properties_structure.entity_properties
286
+ and pkey in properties_structure.entity_properties
287
+ ):
288
+ entity_field_name = properties_structure.entity_properties[pkey].column
289
+ else:
290
+ entity_field_name = pkey
291
+
292
+ # Escrevendo, se necessário, o alias para o nome da entity
293
+ if entity_field_name != pkey:
294
+ keywords.append(
295
+ ast.keyword(
296
+ arg="entity_field",
297
+ value=ast.Constant(value=entity_field_name),
298
+ )
299
+ )
300
+
301
+ # Instanciando o atributo AST
302
+ if not isinstance(prop.type, PrimitiveTypes):
303
+ raise Exception(
304
+ f"Tipo da trait_property '{pkey}' não suportado: {prop.type} (deveria ser um Tipo Primitivo)"
305
+ )
306
+
307
+ # Instanciando o atributo AST
308
+ if enum_class_name:
309
+ prop_type = enum_class_name
310
+ else:
311
+ prop_type = TypeUtil.property_type_to_python_type(prop.type)
312
+
313
+ ast_attr = ast.AnnAssign(
314
+ target=ast.Name(id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()),
315
+ annotation=ast.Name(
316
+ id=prop_type,
317
+ ctx=ast.Load(),
318
+ ),
319
+ value=ast.Call(
320
+ func=ast.Name(id="DTOField", ctx=ast.Load()),
321
+ args=[],
322
+ keywords=keywords,
323
+ ),
324
+ simple=1,
325
+ )
326
+
327
+ ast_dto_attributes.append(ast_attr)
328
+
329
+ # Entity
330
+ ast_entity_attr = ast.AnnAssign(
331
+ target=ast.Name(
332
+ id=CompilerStrUtil.to_snake_case(entity_field_name),
333
+ ctx=ast.Store(),
334
+ ),
335
+ annotation=ast.Name(
336
+ id=TypeUtil.property_type_to_python_type(prop.type),
337
+ ctx=ast.Load(),
338
+ ),
339
+ value=ast.Constant(value=None),
340
+ simple=1,
341
+ )
342
+
343
+ ast_entity_attributes.append(ast_entity_attr)
344
+
345
+ # Guardando como um fixed_filter
346
+ # TODO Pernsar em validações para esse value (se está de acordo com o tipo ou enum)
347
+ fixed_filters.append((pkey, prop.value))
348
+
349
+ def _compile_external_relation(
350
+ self,
351
+ related_entity_id: str,
352
+ related_entity_key: str,
353
+ entity_model: EntityModel,
354
+ entity_models: dict[str, EntityModel],
355
+ properties_structure: PropertiesCompilerStructure,
356
+ ast_dto_attributes: list[ast.stmt],
357
+ ast_entity_attributes: list[ast.stmt],
358
+ related_imports: list[tuple[str, str, str]],
359
+ relations_dependencies: list[RelationDependency],
360
+ pkey: str,
361
+ prop: PropertyMetaModel,
362
+ ):
363
+ # Resolvendo o nome das classes de DTO e Entity
364
+ related_dto_class_name = compile_dto_class_name(related_entity_id)
365
+ related_entity_class_name = compile_entity_class_name(related_entity_id)
366
+
367
+ # Resolvendo o caminho do import
368
+ related_entity = entity_models.get(related_entity_key)
369
+ if not related_entity:
370
+ raise Exception(
371
+ f"Entidade '{entity_model.id}' possui uma referência externa para uma entidade inexistente: '{related_entity_key}', por meio da propriedade: '{pkey}'."
372
+ )
373
+
374
+ tenant = related_entity.tenant
375
+ grupo_empresarial = related_entity.grupo_empresarial
376
+ grupo_key, tenant_key, default_key = compile_namespace_keys(
377
+ tenant, grupo_empresarial
378
+ )
379
+
380
+ if (
381
+ tenant
382
+ and tenant != 0
383
+ and grupo_empresarial
384
+ and grupo_empresarial != "00000000-0000-0000-0000-000000000000"
385
+ ):
386
+ related_import = grupo_key
387
+ elif tenant and tenant != 0:
388
+ related_import = tenant_key
389
+ else:
390
+ related_import = default_key
391
+
392
+ related_imports.append(
393
+ (
394
+ related_import,
395
+ related_dto_class_name,
396
+ related_entity_class_name,
397
+ )
398
+ )
399
+
400
+ # Gravando a dependência de relacionamento
401
+ relation_dependency = RelationDependency()
402
+ relation_dependency.entity_resource = related_entity.api.resource
403
+ relation_dependency.entity_scope = related_entity.escopo
404
+ relation_dependency.tenant = tenant
405
+ relation_dependency.grupo_empresarial = grupo_empresarial
406
+ relations_dependencies.append(relation_dependency)
407
+
408
+ # Instanciando o ast
409
+ if prop.cardinality == CardinalityTypes.C1_N:
410
+ # Para relacionamentos 1_N
411
+ self._build_ast_1_N(
412
+ properties_structure,
413
+ ast_dto_attributes,
414
+ pkey,
415
+ related_dto_class_name,
416
+ related_entity_class_name,
417
+ )
418
+
419
+ elif prop.cardinality == CardinalityTypes.C1_1:
420
+ self._build_ast_1_1(
421
+ properties_structure,
422
+ ast_dto_attributes,
423
+ ast_entity_attributes,
424
+ pkey,
425
+ related_dto_class_name,
426
+ related_entity_class_name,
427
+ )
428
+
429
+ elif prop.cardinality == CardinalityTypes.CN_N:
430
+ # TODO
431
+ pass
432
+ else:
433
+ raise Exception(
434
+ f"Propriedade '{pkey}' da entidade '{entity_model.id}' possui cardinalidade inválida ou não suportada: {prop.cardinality}"
435
+ )
436
+
437
+ def _build_ast_1_N(
438
+ self,
439
+ properties_structure: PropertiesCompilerStructure,
440
+ ast_dto_attributes: list[ast.stmt],
441
+ pkey: str,
442
+ related_dto_class_name: str,
443
+ related_entity_class_name: str,
444
+ ):
445
+ # Propriedade do property descriptor
446
+ keywords = [
447
+ ast.keyword(
448
+ arg="dto_type",
449
+ value=ast.Name(id=related_dto_class_name, ctx=ast.Load()),
450
+ ),
451
+ ast.keyword(
452
+ arg="entity_type",
453
+ value=ast.Name(id=related_entity_class_name, ctx=ast.Load()),
454
+ ),
455
+ ]
456
+
457
+ # Resolvendo a coluna usada no relacionamento
458
+ if (
459
+ not properties_structure.entity_properties
460
+ or pkey not in properties_structure.entity_properties
461
+ or not properties_structure.entity_properties[pkey].relation_column
462
+ ):
463
+ raise Exception(
464
+ f"Propriedade '{pkey}' possui um relacionamento, mas nenhuma coluna de relacioanamento foi apontada na propriedade correspondente no repository."
465
+ )
466
+
467
+ relation_column = properties_structure.entity_properties[pkey].relation_column
468
+
469
+ keywords.append(
470
+ ast.keyword(
471
+ arg="related_entity_field",
472
+ value=ast.Constant(value=relation_column),
473
+ )
474
+ )
475
+
476
+ ast_attr = ast.AnnAssign(
477
+ target=ast.Name(id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()),
478
+ annotation=ast.Name(
479
+ id="list",
480
+ ctx=ast.Load(),
481
+ ),
482
+ value=ast.Call(
483
+ func=ast.Name(id="DTOListField", ctx=ast.Load()),
484
+ args=[],
485
+ keywords=keywords,
486
+ ),
487
+ simple=1,
488
+ )
489
+
490
+ ast_dto_attributes.append(ast_attr)
491
+
492
+ def _build_ast_1_1(
493
+ self,
494
+ properties_structure: PropertiesCompilerStructure,
495
+ ast_dto_attributes: list[ast.stmt],
496
+ ast_entity_attributes: list[ast.stmt],
497
+ pkey: str,
498
+ related_dto_class_name: str,
499
+ related_entity_class_name: str,
500
+ ):
501
+ # Propriedade do property descriptor
502
+ keywords = [
503
+ ast.keyword(
504
+ arg="entity_type",
505
+ value=ast.Name(id=related_entity_class_name, ctx=ast.Load()),
506
+ ),
507
+ ]
508
+
509
+ # Resolvendo a coluna usada no relacionamento
510
+ if (
511
+ not properties_structure.entity_properties
512
+ or pkey not in properties_structure.entity_properties
513
+ or not properties_structure.entity_properties[pkey].relation_column
514
+ ):
515
+ raise Exception(
516
+ f"Propriedade '{pkey}' possui um relacionamento, mas nenhuma coluna de relacioanamento foi apontada na propriedade correspondente no repository."
517
+ )
518
+
519
+ relation_column = str(
520
+ properties_structure.entity_properties[pkey].relation_column
521
+ )
522
+
523
+ owner_relation = False
524
+ if "/" in relation_column:
525
+ owner_relation = True
526
+ relation_column = relation_column.split("/")[-1]
527
+
528
+ keywords.append(
529
+ ast.keyword(
530
+ arg="relation_field",
531
+ value=ast.Constant(value=relation_column),
532
+ )
533
+ )
534
+
535
+ if not owner_relation:
536
+ keywords.append(
537
+ ast.keyword(
538
+ arg="entity_relation_owner",
539
+ value=ast.Attribute(
540
+ value=ast.Name(id="EntityRelationOwner", ctx=ast.Load()),
541
+ attr="OTHER",
542
+ ctx=ast.Load(),
543
+ ),
544
+ )
545
+ )
546
+ else:
547
+ # Adicionando propriedade, para o campo de relação, no DTO (quando for o dono da relação)
548
+ ast_dto_attributes.append(
549
+ self._build_dto_property_ast(relation_column, PrimitiveTypes.UUID)
550
+ )
551
+
552
+ # Adicionando propriedade, para o campo de relação, no Entity (quando for o dono da relação)
553
+ ast_entity_attributes.append(
554
+ self._build_entity_property_ast(relation_column, PrimitiveTypes.UUID)
555
+ )
556
+
557
+ # Adicionando a propriedade em si do relacionamento, no DTO
558
+ ast_attr = ast.AnnAssign(
559
+ target=ast.Name(id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()),
560
+ annotation=ast.Name(
561
+ id=related_dto_class_name,
562
+ ctx=ast.Load(),
563
+ ),
564
+ value=ast.Call(
565
+ func=ast.Name(id="DTOObjectField", ctx=ast.Load()),
566
+ args=[],
567
+ keywords=keywords,
568
+ ),
569
+ simple=1,
570
+ )
571
+
572
+ ast_dto_attributes.append(ast_attr)
573
+
574
+ def _build_dto_property_ast(
575
+ self,
576
+ name: str,
577
+ type: PrimitiveTypes | str,
578
+ keywords: list[ast.keyword] = [],
579
+ ):
580
+ if isinstance(type, PrimitiveTypes):
581
+ type_str = TypeUtil.property_type_to_python_type(type)
582
+ else:
583
+ type_str = type
584
+
585
+ return ast.AnnAssign(
586
+ target=ast.Name(
587
+ id=CompilerStrUtil.to_snake_case(name),
588
+ ctx=ast.Store(),
589
+ ),
590
+ annotation=ast.Name(
591
+ id=type_str,
592
+ ctx=ast.Load(),
593
+ ),
594
+ value=ast.Call(
595
+ func=ast.Name(id="DTOField", ctx=ast.Load()),
596
+ args=[],
597
+ keywords=keywords,
598
+ ),
599
+ simple=1,
600
+ )
601
+
602
+ def _build_entity_property_ast(
603
+ self,
604
+ name: str,
605
+ type: PrimitiveTypes,
606
+ ):
607
+ return ast.AnnAssign(
608
+ target=ast.Name(
609
+ id=CompilerStrUtil.to_snake_case(name),
610
+ ctx=ast.Store(),
611
+ ),
612
+ annotation=ast.Name(
613
+ id=TypeUtil.property_type_to_python_type(type),
614
+ ctx=ast.Load(),
615
+ ),
616
+ value=ast.Constant(value=None),
617
+ simple=1,
618
+ )
619
+
620
+ def _compile_simple_property(
232
621
  self,
233
622
  properties_structure,
234
623
  map_unique_by_property,
@@ -438,42 +827,18 @@ class EDLPropertyCompiler:
438
827
  else:
439
828
  prop_type = TypeUtil.property_type_to_python_type(prop.type)
440
829
 
441
- ast_attr = ast.AnnAssign(
442
- target=ast.Name(id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()),
443
- annotation=ast.Name(
444
- id=prop_type,
445
- ctx=ast.Load(),
446
- ),
447
- value=ast.Call(
448
- func=ast.Name(id="DTOField", ctx=ast.Load()),
449
- args=[],
450
- keywords=keywords,
451
- ),
452
- simple=1,
453
- )
454
-
830
+ ast_attr = self._build_dto_property_ast(pkey, prop_type, keywords)
455
831
  ast_dto_attributes.append(ast_attr)
456
832
 
457
833
  # Entity
458
- ast_entity_attr = ast.AnnAssign(
459
- target=ast.Name(
460
- id=CompilerStrUtil.to_snake_case(entity_field_name),
461
- ctx=ast.Store(),
462
- ),
463
- annotation=ast.Name(
464
- id=TypeUtil.property_type_to_python_type(prop.type),
465
- ctx=ast.Load(),
466
- ),
467
- value=ast.Constant(value=None),
468
- simple=1,
469
- )
834
+ ast_entity_attr = self._build_entity_property_ast(entity_field_name, prop.type)
470
835
 
471
836
  ast_entity_attributes.append(ast_entity_attr)
472
837
 
473
838
  def _compile_domain_config(
474
839
  self,
475
840
  pkey: str,
476
- prop: PropertyMetaModel,
841
+ prop: PropertyMetaModel | TraitPropertyMetaModel,
477
842
  entity_model: EntityModel,
478
843
  ) -> tuple[str, ast.stmt] | None:
479
844
  if not prop.domain_config:
@@ -47,7 +47,7 @@ class EntityLoader:
47
47
  entity_resource: str,
48
48
  tenant: str | None,
49
49
  grupo_empresarial: str | None,
50
- scope: str = ESCOPO_RESTLIB2,
50
+ escopo: str = ESCOPO_RESTLIB2,
51
51
  ) -> tuple[str, str, dict, bool, list[str]]:
52
52
  # Montando as chaves dos namespaces
53
53
  grupo_key, tenant_key, default_key = compile_namespace_keys(
@@ -103,6 +103,7 @@ class EntityLoader:
103
103
  tenant_key,
104
104
  default_key,
105
105
  entity_config_key,
106
+ escopo=escopo,
106
107
  )
107
108
 
108
109
  # Se não achar no redis, usa o que estava em memória
@@ -162,7 +163,12 @@ class EntityLoader:
162
163
 
163
164
  # Se não conseguir recuperar a entidade, procura no redis:
164
165
  loaded_config = self._load_entity_config_from_redis(
165
- entity_resource, grupo_key, tenant_key, default_key, None
166
+ entity_resource,
167
+ grupo_key,
168
+ tenant_key,
169
+ default_key,
170
+ None,
171
+ escopo=escopo,
166
172
  )
167
173
 
168
174
  # Se também não achar no redis, lanca exceção
@@ -341,30 +347,31 @@ class EntityLoader:
341
347
  tenant_key: str,
342
348
  default_key: str,
343
349
  entity_config_key: str | None,
350
+ escopo: str,
344
351
  ) -> tuple[str, str] | None:
345
352
  get_logger().debug(
346
- 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}"
347
354
  )
348
355
 
349
356
  if entity_config_key is not None:
350
357
  entity_config_str = get_redis(
351
- "entity_config", ESCOPO_RESTLIB2, entity_config_key, entity_resource
358
+ "entity_config", escopo, entity_config_key, entity_resource
352
359
  )
353
360
 
354
361
  else:
355
362
  entity_config_key = grupo_key
356
363
  entity_config_str = get_redis(
357
- "entity_config", ESCOPO_RESTLIB2, grupo_key, entity_resource
364
+ "entity_config", escopo, grupo_key, entity_resource
358
365
  )
359
366
  if entity_config_str is None:
360
367
  entity_config_key = tenant_key
361
368
  entity_config_str = get_redis(
362
- "entity_config", ESCOPO_RESTLIB2, tenant_key, entity_resource
369
+ "entity_config", escopo, tenant_key, entity_resource
363
370
  )
364
371
  if entity_config_str is None:
365
372
  entity_config_key = default_key
366
373
  entity_config_str = get_redis(
367
- "entity_config", ESCOPO_RESTLIB2, default_key, entity_resource
374
+ "entity_config", escopo, default_key, entity_resource
368
375
  )
369
376
 
370
377
  # Se não encontrar no redis, retorna None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nsj_rest_lib2
3
- Version: 0.0.11
3
+ Version: 0.0.13
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,22 +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=bn780zjNHaopmhOzi0olMhwdh89uFJUKiCDRQActKGI,12243
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=GAKWFvks0Duqs2EsEr1-BFx2-Kny72jJMbl9ZyIEDXw,4125
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
11
  nsj_rest_lib2/compiler/model.py,sha256=QDBoM26qoZdiNcykl1nvXCrFDhg-6Q__QzVq6uY1QzE,1460
12
- nsj_rest_lib2/compiler/property_compiler.py,sha256=xVwql97vPdxln0z3zdigruYIujCA6978LfxGsLi6QhY,19527
12
+ nsj_rest_lib2/compiler/property_compiler.py,sha256=AvJYY5vbmlodGjgyuCx6u17x0Qv3nEsAdMmBcSQP2f4,31153
13
13
  nsj_rest_lib2/compiler/edl_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py,sha256=664QBDcOgVnyfwtUOXO1W7AKaZhueBG335x5DuogruY,7644
15
15
  nsj_rest_lib2/compiler/edl_model/api_model.py,sha256=pH0Uiq_64AGvkHqwY44TrulWWZXbi6M0EKJWUhSqKj0,837
16
- nsj_rest_lib2/compiler/edl_model/column_meta_model.py,sha256=3OLsRwEz66Cktzew6Hie3HZXK9u20GXlWUU0HtFtwfk,709
16
+ nsj_rest_lib2/compiler/edl_model/column_meta_model.py,sha256=s0sEVkoW1hV2_hto1mws4XhzKGH_b4NzhaOiwFH25Ks,694
17
17
  nsj_rest_lib2/compiler/edl_model/entity_model.py,sha256=sXVfC30P3-q2-fQ3XB_-3vpNjqFPIK5oBIVbwkXNFLU,3662
18
18
  nsj_rest_lib2/compiler/edl_model/index_model.py,sha256=cXWlu0hxtro5vvYoirkDW4R3PCnBW5oCCWjRJ6AX5zE,508
19
19
  nsj_rest_lib2/compiler/edl_model/primitives.py,sha256=cWEys87xDpgotyRUXkzvFvY4LHeawzBEEyz0Xed18AQ,1454
20
20
  nsj_rest_lib2/compiler/edl_model/property_meta_model.py,sha256=x2SApvI-5MZTErAHeOXnR6qfjflhSs8r6Y9KMtCykV0,3960
21
21
  nsj_rest_lib2/compiler/edl_model/repository_model.py,sha256=Vt1HxlaoifP4w5ij1laKDkD1-COBihE8EX1HkdEDUSo,977
22
- nsj_rest_lib2/compiler/edl_model/trait_property_meta_model.py,sha256=ZC2oTvc9Y2Oiy4NLNHQLiMOLRWDAOdF8GJxOw4nqHdk,354
22
+ nsj_rest_lib2/compiler/edl_model/trait_property_meta_model.py,sha256=SBSfiu4v0PMsWRsGDySR3P2tkabLbDZxx_FFy_3rGXA,605
23
23
  nsj_rest_lib2/compiler/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  nsj_rest_lib2/compiler/util/str_util.py,sha256=lVP1yHhj1pOd6ULtTnkcfX6Gqrpe4yCBratHUhBNGcI,843
25
25
  nsj_rest_lib2/compiler/util/type_naming_util.py,sha256=sahlxtYUPcksqlX1hygaoTF7vuD8tY8eosgOR04YLAs,612
@@ -27,8 +27,8 @@ nsj_rest_lib2/compiler/util/type_util.py,sha256=HTKOH4uRTOY0YgoM8oUv_6cEcReE_bgK
27
27
  nsj_rest_lib2/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  nsj_rest_lib2/controller/dynamic_controller.py,sha256=XMqxe1NW-NE5XwomXb4pSNdALQHpP74Hc26R4fnmXqg,15194
29
29
  nsj_rest_lib2/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- nsj_rest_lib2/service/entity_loader.py,sha256=es8qWyI0UNGf1wdEFnAmTYo8eW-XMIi7Ar_SgTfjQNQ,15224
31
- nsj_rest_lib2-0.0.11.dist-info/METADATA,sha256=xQRuH1m7gLxd3oW6Mh_e5iWRTSs660KlkSP7bes91FM,1361
32
- nsj_rest_lib2-0.0.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- nsj_rest_lib2-0.0.11.dist-info/top_level.txt,sha256=L6zh0EfH8_rur7OJ8_V-El-XEMf4qg3bkF8ADgqLVIA,14
34
- nsj_rest_lib2-0.0.11.dist-info/RECORD,,
30
+ nsj_rest_lib2/service/entity_loader.py,sha256=KVLFQSqj4DL-K-T29ksJE2or9QkekFmyAGUIKjQX6Qk,15372
31
+ nsj_rest_lib2-0.0.13.dist-info/METADATA,sha256=mR2ZDZ5jbP18qsS288vSwD0tWDPOhibp_iyP-CrQ0Hk,1361
32
+ nsj_rest_lib2-0.0.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
+ nsj_rest_lib2-0.0.13.dist-info/top_level.txt,sha256=L6zh0EfH8_rur7OJ8_V-El-XEMf4qg3bkF8ADgqLVIA,14
34
+ nsj_rest_lib2-0.0.13.dist-info/RECORD,,