nsj-rest-lib2 0.0.3__py3-none-any.whl → 0.0.4__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.
@@ -0,0 +1,359 @@
1
+ import ast
2
+
3
+ from nsj_rest_lib2.compiler.compiler_structures import (
4
+ IndexCompilerStructure,
5
+ PropertiesCompilerStructure,
6
+ )
7
+ from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
8
+ from nsj_rest_lib2.compiler.edl_model.primitives import PrimitiveTypes
9
+ from nsj_rest_lib2.compiler.edl_model.property_meta_model import PropertyMetaModel
10
+ from nsj_rest_lib2.compiler.util.str_util import CompilerStrUtil
11
+ from nsj_rest_lib2.compiler.util.type_util import TypeUtil
12
+
13
+ # TODO pattern
14
+ # TODO lowercase
15
+ # TODO uppercase
16
+ # TODO Adicionar o nome da entidade, no nome das classes de enum (para evitar conflitos no caso das traits)
17
+
18
+
19
+ class EDLPropertyCompiler:
20
+ def compile(
21
+ self,
22
+ properties_structure: PropertiesCompilerStructure,
23
+ map_unique_by_property: dict[str, IndexCompilerStructure],
24
+ entity_model: EntityModel,
25
+ ) -> tuple[list[ast.stmt], list[ast.stmt], list[str], list[ast.stmt]]:
26
+
27
+ # TODO Criar opção de campo calculado?
28
+
29
+ ast_dto_attributes = []
30
+ ast_entity_attributes = []
31
+ props_pk = []
32
+ enum_classes = []
33
+
34
+ if properties_structure.properties is None:
35
+ return (ast_dto_attributes, ast_entity_attributes, props_pk, enum_classes)
36
+
37
+ for pkey in properties_structure.properties:
38
+ prop = properties_structure.properties[pkey]
39
+ enum_class_name = None
40
+
41
+ # DTO
42
+ ## Tratando propriedade simples (não array, não object)
43
+ if prop.type not in [PrimitiveTypes.ARRAY, PrimitiveTypes.OBJECT]:
44
+ keywords = []
45
+
46
+ if prop.pk:
47
+ keywords.append(ast.keyword(arg="pk", value=ast.Constant(True)))
48
+ props_pk.append(pkey)
49
+
50
+ if prop.key_alternative:
51
+ keywords.append(
52
+ ast.keyword(arg="candidate_key", value=ast.Constant(True))
53
+ )
54
+
55
+ if (
56
+ properties_structure.main_properties
57
+ and pkey in properties_structure.main_properties
58
+ ):
59
+ keywords.append(ast.keyword(arg="resume", value=ast.Constant(True)))
60
+
61
+ if (
62
+ properties_structure.required
63
+ and pkey in properties_structure.required
64
+ ):
65
+ keywords.append(
66
+ ast.keyword(arg="not_null", value=ast.Constant(True))
67
+ )
68
+
69
+ if (
70
+ properties_structure.partition_data
71
+ and pkey in properties_structure.partition_data
72
+ ):
73
+ keywords.append(
74
+ ast.keyword(arg="partition_data", value=ast.Constant(True))
75
+ )
76
+
77
+ if pkey in map_unique_by_property:
78
+ unique = map_unique_by_property[pkey].index_model
79
+ keywords.append(
80
+ ast.keyword(
81
+ arg="unique",
82
+ value=ast.Constant(unique.name),
83
+ )
84
+ )
85
+
86
+ if (
87
+ prop.default
88
+ ): # TODO Verificar esse modo de tratar valores default (principalmente expressões)
89
+ keywords.append(
90
+ ast.keyword(
91
+ arg="default_value",
92
+ value=ast.Name(str(prop.default), ctx=ast.Load()),
93
+ )
94
+ )
95
+
96
+ if prop.trim:
97
+ keywords.append(ast.keyword(arg="strip", value=ast.Constant(True)))
98
+
99
+ max = None
100
+ min = None
101
+ if prop.type in [PrimitiveTypes.STRING, PrimitiveTypes.EMAIL]:
102
+ if prop.max_length:
103
+ max = prop.max_length
104
+ elif prop.min_length:
105
+ min = prop.min_length
106
+ elif prop.type in [PrimitiveTypes.INTEGER, PrimitiveTypes.NUMBER]:
107
+ if prop.minimum:
108
+ min = prop.minimum
109
+ elif prop.maximum:
110
+ max = prop.maximum
111
+
112
+ if max:
113
+ keywords.append(
114
+ ast.keyword(arg="max", value=ast.Constant(prop.max_length))
115
+ )
116
+ if min:
117
+ keywords.append(
118
+ ast.keyword(arg="min", value=ast.Constant(prop.min_length))
119
+ )
120
+
121
+ if (
122
+ properties_structure.search_properties
123
+ and pkey in properties_structure.search_properties
124
+ ):
125
+ keywords.append(ast.keyword(arg="search", value=ast.Constant(True)))
126
+ else:
127
+ keywords.append(
128
+ ast.keyword(arg="search", value=ast.Constant(False))
129
+ )
130
+
131
+ if (
132
+ properties_structure.metric_label
133
+ and pkey in properties_structure.metric_label
134
+ ):
135
+ keywords.append(
136
+ ast.keyword(arg="metric_label", value=ast.Constant(True))
137
+ )
138
+
139
+ if prop.type == PrimitiveTypes.CPF and not prop.validator:
140
+ keywords.append(
141
+ ast.keyword(
142
+ arg="validator",
143
+ value=ast.Attribute(
144
+ value=ast.Call(
145
+ func=ast.Name(
146
+ id="DTOFieldValidators", ctx=ast.Load()
147
+ ),
148
+ args=[],
149
+ keywords=[],
150
+ ),
151
+ attr="validate_cpf",
152
+ ctx=ast.Load(),
153
+ ),
154
+ )
155
+ )
156
+ elif prop.type == PrimitiveTypes.CNPJ and not prop.validator:
157
+ keywords.append(
158
+ ast.keyword(
159
+ arg="validator",
160
+ value=ast.Attribute(
161
+ value=ast.Call(
162
+ func=ast.Name(
163
+ id="DTOFieldValidators", ctx=ast.Load()
164
+ ),
165
+ args=[],
166
+ keywords=[],
167
+ ),
168
+ attr="validate_cnpj",
169
+ ctx=ast.Load(),
170
+ ),
171
+ )
172
+ )
173
+ elif prop.type == PrimitiveTypes.CPF_CNPJ and not prop.validator:
174
+ keywords.append(
175
+ ast.keyword(
176
+ arg="validator",
177
+ value=ast.Attribute(
178
+ value=ast.Call(
179
+ func=ast.Name(
180
+ id="DTOFieldValidators", ctx=ast.Load()
181
+ ),
182
+ args=[],
183
+ keywords=[],
184
+ ),
185
+ attr="validate_cpf_or_cnpj",
186
+ ctx=ast.Load(),
187
+ ),
188
+ )
189
+ )
190
+ elif prop.type == PrimitiveTypes.EMAIL and not prop.validator:
191
+ keywords.append(
192
+ ast.keyword(
193
+ arg="validator",
194
+ value=ast.Attribute(
195
+ value=ast.Call(
196
+ func=ast.Name(
197
+ id="DTOFieldValidators", ctx=ast.Load()
198
+ ),
199
+ args=[],
200
+ keywords=[],
201
+ ),
202
+ attr="validate_email",
203
+ ctx=ast.Load(),
204
+ ),
205
+ )
206
+ )
207
+ elif prop.validator:
208
+ keywords.append(
209
+ ast.keyword(
210
+ arg="validator",
211
+ value=ast.Name(prop.validator, ctx=ast.Load()),
212
+ )
213
+ )
214
+
215
+ if prop.immutable:
216
+ keywords.append(
217
+ ast.keyword(arg="read_only", value=ast.Constant(True))
218
+ )
219
+
220
+ if prop.on_save:
221
+ keywords.append(
222
+ ast.keyword(
223
+ arg="convert_to_entity",
224
+ value=ast.Name(prop.on_save, ctx=ast.Load()),
225
+ )
226
+ )
227
+
228
+ if prop.on_retrieve:
229
+ keywords.append(
230
+ ast.keyword(
231
+ arg="convert_from_entity",
232
+ value=ast.Name(id=prop.on_retrieve, ctx=ast.Load()),
233
+ )
234
+ )
235
+
236
+ if prop.domain_config:
237
+ result = self._compile_domain_config(pkey, prop, entity_model)
238
+ if not result:
239
+ raise Exception(
240
+ f"Erro desconhecido ao compilar a propriedade {pkey}"
241
+ )
242
+
243
+ enum_class_name, ast_enum_class = result
244
+ enum_classes.append(ast_enum_class)
245
+
246
+ # Instanciando o atributo AST
247
+ if enum_class_name:
248
+ prop_type = enum_class_name
249
+ else:
250
+ prop_type = TypeUtil.property_type_to_python_type(prop.type)
251
+
252
+ ast_attr = ast.AnnAssign(
253
+ target=ast.Name(
254
+ id=CompilerStrUtil.to_snake_case(pkey), ctx=ast.Store()
255
+ ),
256
+ annotation=ast.Name(
257
+ id=prop_type,
258
+ ctx=ast.Load(),
259
+ ),
260
+ value=ast.Call(
261
+ func=ast.Name(id="DTOField", ctx=ast.Load()),
262
+ args=[],
263
+ keywords=keywords,
264
+ ),
265
+ simple=1,
266
+ )
267
+
268
+ ast_dto_attributes.append(ast_attr)
269
+
270
+ # Entity
271
+ if (
272
+ properties_structure.entity_properties
273
+ and pkey in properties_structure.entity_properties
274
+ ):
275
+ entity_field_name = properties_structure.entity_properties[
276
+ pkey
277
+ ].column
278
+ else:
279
+ entity_field_name = pkey
280
+
281
+ ast_entity_attr = ast.AnnAssign(
282
+ target=ast.Name(
283
+ id=CompilerStrUtil.to_snake_case(entity_field_name),
284
+ ctx=ast.Store(),
285
+ ),
286
+ annotation=ast.Name(
287
+ id=TypeUtil.property_type_to_python_type(prop.type),
288
+ ctx=ast.Load(),
289
+ ),
290
+ value=ast.Constant(value=None),
291
+ simple=1,
292
+ )
293
+
294
+ ast_entity_attributes.append(ast_entity_attr)
295
+
296
+ return ast_dto_attributes, ast_entity_attributes, props_pk, enum_classes
297
+
298
+ def _compile_domain_config(
299
+ self,
300
+ pkey: str,
301
+ prop: PropertyMetaModel,
302
+ entity_model: EntityModel,
303
+ ) -> tuple[str, ast.stmt] | None:
304
+ if not prop.domain_config:
305
+ return None
306
+
307
+ # Verificando se deveria usar o mapped_value
308
+ use_mapped_value = False
309
+ for value in prop.domain_config:
310
+ if value.mapped_value:
311
+ use_mapped_value = True
312
+ break
313
+
314
+ # Compilando as opções do enum
315
+ ast_values = []
316
+ for value in prop.domain_config:
317
+ value_name = CompilerStrUtil.to_snake_case(value.value).upper()
318
+
319
+ if use_mapped_value and value.mapped_value is None:
320
+ raise Exception(
321
+ f"Propriedade '{pkey}' possui domain_config com value '{value.value}' mas sem mapped_value"
322
+ )
323
+
324
+ if value.mapped_value is not None:
325
+ ast_value = ast.Assign(
326
+ targets=[ast.Name(id=value_name, ctx=ast.Store())],
327
+ value=ast.Tuple(
328
+ elts=[
329
+ ast.Constant(value=value.value),
330
+ ast.Constant(value=value.mapped_value),
331
+ ],
332
+ ctx=ast.Load(),
333
+ ),
334
+ )
335
+ else:
336
+ ast_value = ast.Assign(
337
+ targets=[ast.Name(id=value_name, ctx=ast.Store())],
338
+ value=ast.Constant(value=value.value),
339
+ )
340
+
341
+ ast_values.append(ast_value)
342
+
343
+ # Instanciando o atributo AST
344
+ enum_class_name = f"{CompilerStrUtil.to_pascal_case(entity_model.escopo)}{CompilerStrUtil.to_pascal_case(entity_model.id)}{CompilerStrUtil.to_pascal_case(pkey)}Enum"
345
+ ast_enum_class = ast.ClassDef(
346
+ name=enum_class_name,
347
+ bases=[
348
+ ast.Attribute(
349
+ value=ast.Name(id="enum", ctx=ast.Load()),
350
+ attr="Enum",
351
+ ctx=ast.Load(),
352
+ )
353
+ ],
354
+ keywords=[],
355
+ decorator_list=[],
356
+ body=ast_values,
357
+ )
358
+
359
+ return enum_class_name, ast_enum_class
@@ -11,6 +11,7 @@ from nsj_rest_lib2.redis_config import get_redis
11
11
  from nsj_rest_lib2.settings import ESCOPO_RESTLIB2, MIN_TIME_SOURCE_REFRESH
12
12
 
13
13
 
14
+ # TODO Verificar se está atualizando o loaded_at, quando o hash não muda
14
15
  class LoadedEntity:
15
16
  def __init__(self):
16
17
  self.dto_class_name: str = ""
nsj_rest_lib2/settings.py CHANGED
@@ -1,6 +1,8 @@
1
+ import logging
1
2
  import os
2
3
 
3
4
  ESCOPO_RESTLIB2 = os.environ["ESCOPO_RESTLIB2"]
5
+ APP_NAME = os.getenv("APP_NAME", "nsj_rest_lib2")
4
6
 
5
7
  ENV = os.getenv("ENV", "dev").lower()
6
8
 
@@ -8,3 +10,7 @@ if ENV in ("dev", "local"):
8
10
  MIN_TIME_SOURCE_REFRESH = 0
9
11
  else:
10
12
  MIN_TIME_SOURCE_REFRESH = int(os.getenv("MIN_TIME_SOURCE_REFRESH", "15"))
13
+
14
+
15
+ def get_logger():
16
+ return logging.getLogger(APP_NAME)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nsj_rest_lib2
3
- Version: 0.0.3
3
+ Version: 0.0.4
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
@@ -0,0 +1,29 @@
1
+ nsj_rest_lib2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ nsj_rest_lib2/exception.py,sha256=E9uMUdoCCQOVQfc8f6gD9b5Pxurf3Q4SytDCcqSlkZ8,56
3
+ nsj_rest_lib2/redis_config.py,sha256=4KLcvYS3nJO7PMQgF6F9_j6r-TyqcS7TBbd3LEQuKDU,629
4
+ nsj_rest_lib2/settings.py,sha256=Hn_o1HZmievnYb8D1kNT2Nq-OEjxbyNjOiOpbnFsMwE,367
5
+ nsj_rest_lib2/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ nsj_rest_lib2/compiler/ai_compiler.py,sha256=shAtN4T0ai_52qh15L3mK1QbeC6glHOR6C3J3gj14II,9029
7
+ nsj_rest_lib2/compiler/compiler.py,sha256=Zo9gMaUaHhiGS-5lm0hHSdTn4wRW89OV_xrQPxlezOI,9945
8
+ nsj_rest_lib2/compiler/compiler_structures.py,sha256=2bM4_7lG1fytDGxJl6SU9pLsbspiNV36gVn9-O-23Q8,1009
9
+ nsj_rest_lib2/compiler/dto_compiler.py,sha256=hVmy9WLBl8217zmNSBBTpmSmdzXU6NXy7TJym6eRd-Q,2615
10
+ nsj_rest_lib2/compiler/entity_compiler.py,sha256=ytcS-RPQTJtf56z4HqT3xQLBYzbd6UUPGsaGB1pj_EA,4240
11
+ nsj_rest_lib2/compiler/property_compiler.py,sha256=NwQd3hVypT7CYgy8rK506XTRaz5oxiWUtkZEpGyolRs,13969
12
+ nsj_rest_lib2/compiler/edl_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py,sha256=664QBDcOgVnyfwtUOXO1W7AKaZhueBG335x5DuogruY,7644
14
+ 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=V1VI0LslSDO6oB2cOQrTcBijBnWIPL7s4xNbI2Wb8Kk,195
16
+ nsj_rest_lib2/compiler/edl_model/entity_model.py,sha256=mn19nIuzDdzo7N2K4ElYwKpk8T9tb3pNU4CudkblblI,3375
17
+ nsj_rest_lib2/compiler/edl_model/index_model.py,sha256=cXWlu0hxtro5vvYoirkDW4R3PCnBW5oCCWjRJ6AX5zE,508
18
+ nsj_rest_lib2/compiler/edl_model/primitives.py,sha256=VAzTbpkQAZWkeTdpoXL4FSaO1KEMTPXOxl6WxIJMWHk,1104
19
+ nsj_rest_lib2/compiler/edl_model/property_meta_model.py,sha256=i7lu-JFvPzUDBdsHB6kspGUyCkqf_GuTRmKfpIZj-K0,3444
20
+ 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=NA8eRh5rA0boFmFd-0sHLrilOoOQSeN-amN_4TXcGiA,358
22
+ nsj_rest_lib2/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ nsj_rest_lib2/controller/dynamic_controller.py,sha256=4HS1__ton8cQ1LSvMoZUv93BQEnGV5f2gE-jW5lD510,13448
24
+ nsj_rest_lib2/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ nsj_rest_lib2/service/entity_loader.py,sha256=E--DbswAMIn3Ic6LOMotRTcUN4PsArA9oSFAVzadnAQ,10713
26
+ nsj_rest_lib2-0.0.4.dist-info/METADATA,sha256=WUKrR5K1gPeEDjFP0WP_lhb5gDBlyHdPfW0Hnnk_zy8,1196
27
+ nsj_rest_lib2-0.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ nsj_rest_lib2-0.0.4.dist-info/top_level.txt,sha256=L6zh0EfH8_rur7OJ8_V-El-XEMf4qg3bkF8ADgqLVIA,14
29
+ nsj_rest_lib2-0.0.4.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- nsj_rest_lib2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- nsj_rest_lib2/exception.py,sha256=E9uMUdoCCQOVQfc8f6gD9b5Pxurf3Q4SytDCcqSlkZ8,56
3
- nsj_rest_lib2/redis_config.py,sha256=4KLcvYS3nJO7PMQgF6F9_j6r-TyqcS7TBbd3LEQuKDU,629
4
- nsj_rest_lib2/settings.py,sha256=f_jqFEv1rkhfEfyvCtTduUEwc4dwiiLnP00VM7gvWPw,243
5
- nsj_rest_lib2/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- nsj_rest_lib2/controller/dynamic_controller.py,sha256=4HS1__ton8cQ1LSvMoZUv93BQEnGV5f2gE-jW5lD510,13448
7
- nsj_rest_lib2/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- nsj_rest_lib2/service/entity_loader.py,sha256=1_NhcO_7g7CWC3WTKHCYkblH2luO3AbPRyE2uCQ2zXw,10638
9
- nsj_rest_lib2-0.0.3.dist-info/METADATA,sha256=wkUs-y8kYkmSQYVt2pi4QHR28ECogJkjez3VcsGpcMY,1196
10
- nsj_rest_lib2-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
- nsj_rest_lib2-0.0.3.dist-info/top_level.txt,sha256=L6zh0EfH8_rur7OJ8_V-El-XEMf4qg3bkF8ADgqLVIA,14
12
- nsj_rest_lib2-0.0.3.dist-info/RECORD,,