nsj-rest-lib2 0.0.30__py3-none-any.whl → 0.0.32__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,118 @@
1
+ import re
2
+ from dataclasses import dataclass
3
+ from typing import Literal, Sequence
4
+
5
+ from nsj_rest_lib2.compiler.edl_model.entity_model_base import EntityModelBase
6
+ from nsj_rest_lib2.compiler.edl_model.primitives import (
7
+ REGEX_EXTERNAL_COMPONENT_REF,
8
+ REGEX_EXTERNAL_REF,
9
+ REGEX_INTERNAL_REF,
10
+ )
11
+
12
+
13
+ RelationRefType = Literal["internal", "external", "external_component"]
14
+
15
+
16
+ @dataclass
17
+ class RelationRef:
18
+ ref_type: RelationRefType
19
+ scope: str | None
20
+ entity: str
21
+ components: list[str]
22
+
23
+ @property
24
+ def entity_key(self) -> str | None:
25
+ if not self.scope:
26
+ return None
27
+
28
+ return f"{self.scope}/{self.entity}"
29
+
30
+ @property
31
+ def target_id(self) -> str:
32
+ return self.components[-1] if self.components else self.entity
33
+
34
+ @property
35
+ def prefx_class_name(self) -> str:
36
+ if not self.components:
37
+ return ""
38
+
39
+ prefix_parts: list[str] = [self.entity, *self.components[:-1]]
40
+ return f"_{'_'.join(prefix_parts)}"
41
+
42
+ @property
43
+ def is_external(self) -> bool:
44
+ return self.ref_type in {"external", "external_component"}
45
+
46
+ def resolve_model(
47
+ self,
48
+ entity_models: dict[str, EntityModelBase],
49
+ base_model: EntityModelBase | None = None,
50
+ ) -> EntityModelBase | None:
51
+ entity_key = self.entity_key
52
+ resolved_base: EntityModelBase | None = None
53
+
54
+ if entity_key:
55
+ resolved_base = entity_models.get(entity_key)
56
+ elif base_model:
57
+ resolved_base = base_model
58
+
59
+ if not resolved_base:
60
+ return None
61
+
62
+ return RelationRefParser.follow_components(resolved_base, self.components)
63
+
64
+
65
+ class RelationRefParser:
66
+ @staticmethod
67
+ def parse(ref: str) -> RelationRef | None:
68
+ internal_match = re.match(REGEX_INTERNAL_REF, ref)
69
+ if internal_match:
70
+ components = RelationRefParser._split_components(internal_match.group(1))
71
+ if not components:
72
+ return None
73
+ entity = components[0]
74
+ extra_components = components[1:] if len(components) > 1 else []
75
+ return RelationRef("internal", None, entity, extra_components)
76
+
77
+ external_component_match = re.match(REGEX_EXTERNAL_COMPONENT_REF, ref)
78
+ if external_component_match:
79
+ components = RelationRefParser._split_components(
80
+ external_component_match.group(3)
81
+ )
82
+ return RelationRef(
83
+ "external_component",
84
+ external_component_match.group(1),
85
+ external_component_match.group(2),
86
+ components,
87
+ )
88
+
89
+ external_match = re.match(REGEX_EXTERNAL_REF, ref)
90
+ if external_match:
91
+ return RelationRef(
92
+ "external",
93
+ external_match.group(1),
94
+ external_match.group(2),
95
+ [],
96
+ )
97
+
98
+ return None
99
+
100
+ @staticmethod
101
+ def follow_components(
102
+ base_model: EntityModelBase, components: Sequence[str]
103
+ ) -> EntityModelBase | None:
104
+ target_model: EntityModelBase | None = base_model
105
+ for component in components:
106
+ if not target_model or not target_model.components:
107
+ return None
108
+ target_model = target_model.components.get(component)
109
+ if target_model is None:
110
+ return None
111
+
112
+ return target_model
113
+
114
+ @staticmethod
115
+ def _split_components(components_path: str) -> list[str]:
116
+ # Remove marcadores opcionais '#/components/' intermediários
117
+ cleaned = components_path.replace("#/components/", "/").replace("#", "")
118
+ return [part for part in cleaned.split("/") if part]
@@ -33,7 +33,17 @@ def compile_function_class_name(
33
33
  incorporando o caminho dos relacionamentos (quando houver).
34
34
  """
35
35
 
36
- suffix = "InsertType" if operation == "insert" else "UpdateType"
36
+ operation = (operation or "").lower()
37
+ suffix_map = {
38
+ "insert": "InsertType",
39
+ "update": "UpdateType",
40
+ "get": "GetType",
41
+ "list": "ListType",
42
+ "delete": "DeleteType",
43
+ }
44
+ suffix = suffix_map.get(
45
+ operation, f"{CompilerStrUtil.to_pascal_case(operation)}Type"
46
+ )
37
47
  path_suffix = "".join(CompilerStrUtil.to_pascal_case(part) for part in path_parts)
38
48
  return (
39
49
  f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}"
@@ -41,3 +51,30 @@ def compile_function_class_name(
41
51
  f"{path_suffix}"
42
52
  f"{suffix}"
43
53
  )
54
+
55
+
56
+ def compile_function_params_dto_class_name(
57
+ entity_id: str,
58
+ prefx_class_name: str,
59
+ verb: str,
60
+ ) -> str:
61
+ """
62
+ Gera o nome da classe DTO usada como envelope de parâmetros para funções
63
+ de GET, LIST e DELETE.
64
+ """
65
+
66
+ verb = (verb or "").lower()
67
+ if verb == "get":
68
+ suffix = "GetParamsDTO"
69
+ elif verb == "list":
70
+ suffix = "ListParamsDTO"
71
+ elif verb == "delete":
72
+ suffix = "DeleteParamsDTO"
73
+ else:
74
+ suffix = f"{CompilerStrUtil.to_pascal_case(verb)}ParamsDTO"
75
+
76
+ return (
77
+ f"{CompilerStrUtil.to_pascal_case(prefx_class_name)}"
78
+ f"{CompilerStrUtil.to_pascal_case(entity_id)}"
79
+ f"{suffix}"
80
+ )
@@ -96,6 +96,14 @@ def setup_dynamic_routes(
96
96
  api_verbs,
97
97
  _insert_function_class_name,
98
98
  _update_function_class_name,
99
+ _insert_function_name,
100
+ _update_function_name,
101
+ _get_function_name,
102
+ list_function_name,
103
+ _delete_function_name,
104
+ _get_function_type_class_name,
105
+ list_function_type_class_name,
106
+ _delete_function_type_class_name,
99
107
  ) = entity_loader.load_entity_source(
100
108
  entity_resource,
101
109
  tenant,
@@ -115,6 +123,10 @@ def setup_dynamic_routes(
115
123
  dto_class=etities_dict[dto_class_name],
116
124
  entity_class=etities_dict[entity_class_name],
117
125
  injector_factory=injector_factory,
126
+ list_function_name=list_function_name,
127
+ list_function_type_class=etities_dict.get(
128
+ list_function_type_class_name
129
+ ),
118
130
  )
119
131
 
120
132
  return route.handle_request(*args, **kwargs)
@@ -152,6 +164,14 @@ def setup_dynamic_routes(
152
164
  api_verbs,
153
165
  _insert_function_class_name,
154
166
  _update_function_class_name,
167
+ _insert_function_name,
168
+ _update_function_name,
169
+ get_function_name,
170
+ _list_function_name,
171
+ _delete_function_name,
172
+ get_function_type_class_name,
173
+ _list_function_type_class_name,
174
+ _delete_function_type_class_name,
155
175
  ) = entity_loader.load_entity_source(
156
176
  entity_resource,
157
177
  tenant,
@@ -171,6 +191,10 @@ def setup_dynamic_routes(
171
191
  dto_class=etities_dict[dto_class_name],
172
192
  entity_class=etities_dict[entity_class_name],
173
193
  injector_factory=injector_factory,
194
+ get_function_name=get_function_name,
195
+ get_function_type_class=etities_dict.get(
196
+ get_function_type_class_name
197
+ ),
174
198
  )
175
199
 
176
200
  return route.handle_request(*args, **kwargs)
@@ -207,6 +231,14 @@ def setup_dynamic_routes(
207
231
  api_verbs,
208
232
  insert_function_class_name,
209
233
  _update_function_class_name,
234
+ insert_function_name,
235
+ _update_function_name,
236
+ _get_function_name,
237
+ _list_function_name,
238
+ _delete_function_name,
239
+ _get_function_type_class_name,
240
+ _list_function_type_class_name,
241
+ _delete_function_type_class_name,
210
242
  ) = entity_loader.load_entity_source(
211
243
  entity_resource,
212
244
  tenant,
@@ -233,6 +265,7 @@ def setup_dynamic_routes(
233
265
  entity_class=etities_dict[entity_class_name],
234
266
  injector_factory=injector_factory,
235
267
  insert_function_type_class=insert_function_type_class,
268
+ insert_function_name=insert_function_name,
236
269
  )
237
270
 
238
271
  return route.handle_request(*args, **kwargs)
@@ -269,6 +302,14 @@ def setup_dynamic_routes(
269
302
  api_verbs,
270
303
  _insert_function_class_name,
271
304
  update_function_class_name,
305
+ _insert_function_name,
306
+ update_function_name,
307
+ _get_function_name,
308
+ _list_function_name,
309
+ _delete_function_name,
310
+ _get_function_type_class_name,
311
+ _list_function_type_class_name,
312
+ _delete_function_type_class_name,
272
313
  ) = entity_loader.load_entity_source(
273
314
  entity_resource,
274
315
  tenant,
@@ -295,6 +336,7 @@ def setup_dynamic_routes(
295
336
  entity_class=etities_dict[entity_class_name],
296
337
  injector_factory=injector_factory,
297
338
  update_function_type_class=update_function_type_class,
339
+ update_function_name=update_function_name,
298
340
  )
299
341
 
300
342
  return route.handle_request(*args, **kwargs)
@@ -331,6 +373,11 @@ def setup_dynamic_routes(
331
373
  api_verbs,
332
374
  _insert_function_class_name,
333
375
  _update_function_class_name,
376
+ _insert_function_name,
377
+ _update_function_name,
378
+ _get_function_name,
379
+ _list_function_name,
380
+ _delete_function_name,
334
381
  ) = entity_loader.load_entity_source(
335
382
  entity_resource,
336
383
  tenant,
@@ -386,6 +433,14 @@ def setup_dynamic_routes(
386
433
  api_verbs,
387
434
  _insert_function_class_name,
388
435
  _update_function_class_name,
436
+ _insert_function_name,
437
+ _update_function_name,
438
+ _get_function_name,
439
+ _list_function_name,
440
+ delete_function_name,
441
+ _get_function_type_class_name,
442
+ _list_function_type_class_name,
443
+ delete_function_type_class_name,
389
444
  ) = entity_loader.load_entity_source(
390
445
  entity_resource,
391
446
  tenant,
@@ -405,6 +460,10 @@ def setup_dynamic_routes(
405
460
  dto_class=etities_dict[dto_class_name],
406
461
  entity_class=etities_dict[entity_class_name],
407
462
  injector_factory=injector_factory,
463
+ delete_function_name=delete_function_name,
464
+ delete_function_type_class=etities_dict.get(
465
+ delete_function_type_class_name
466
+ ),
408
467
  )
409
468
 
410
469
  return route.handle_request(*args, **kwargs)
@@ -71,9 +71,20 @@ class EntityConfigWriter:
71
71
  "dto_class_name": compiler_result.dto_class_name,
72
72
  "entity_class_name": compiler_result.entity_class_name,
73
73
  "insert_function_class_name": compiler_result.insert_function_class_name,
74
+ "insert_function_name": compiler_result.insert_function_name,
74
75
  "source_insert_function": compiler_result.source_insert_function,
75
76
  "update_function_class_name": compiler_result.update_function_class_name,
77
+ "update_function_name": compiler_result.update_function_name,
76
78
  "source_update_function": compiler_result.source_update_function,
79
+ "get_function_name": compiler_result.get_function_name,
80
+ "list_function_name": compiler_result.list_function_name,
81
+ "delete_function_name": compiler_result.delete_function_name,
82
+ "get_function_type_class_name": compiler_result.get_function_type_class_name,
83
+ "list_function_type_class_name": compiler_result.list_function_type_class_name,
84
+ "delete_function_type_class_name": compiler_result.delete_function_type_class_name,
85
+ "source_get_function_type": compiler_result.source_get_function_type,
86
+ "source_list_function_type": compiler_result.source_list_function_type,
87
+ "source_delete_function_type": compiler_result.source_delete_function_type,
77
88
  "source_dto": compiler_result.dto_code,
78
89
  "source_entity": compiler_result.entity_code,
79
90
  "entity_hash": entity_hash
@@ -120,8 +131,16 @@ class EntityConfigWriter:
120
131
  for content in self._iter_hash_chunks(
121
132
  compiler_result.dto_code,
122
133
  compiler_result.entity_code,
134
+ compiler_result.insert_function_name,
135
+ compiler_result.update_function_name,
136
+ compiler_result.get_function_name,
137
+ compiler_result.list_function_name,
138
+ compiler_result.delete_function_name,
123
139
  compiler_result.source_insert_function,
124
140
  compiler_result.source_update_function,
141
+ compiler_result.source_get_function_type,
142
+ compiler_result.source_list_function_type,
143
+ compiler_result.source_delete_function_type,
125
144
  ):
126
145
  hasher.update(content)
127
146
 
@@ -26,6 +26,14 @@ class LoadedEntity:
26
26
  self.relations_dependencies: list[RelationDependency] = []
27
27
  self.insert_function_class_name: str | None = None
28
28
  self.update_function_class_name: str | None = None
29
+ self.insert_function_name: str | None = None
30
+ self.update_function_name: str | None = None
31
+ self.get_function_name: str | None = None
32
+ self.list_function_name: str | None = None
33
+ self.delete_function_name: str | None = None
34
+ self.get_function_type_class_name: str | None = None
35
+ self.list_function_type_class_name: str | None = None
36
+ self.delete_function_type_class_name: str | None = None
29
37
 
30
38
 
31
39
  class Namespace:
@@ -50,7 +58,23 @@ class EntityLoader:
50
58
  grupo_empresarial: str | None,
51
59
  escopo: str = ESCOPO_RESTLIB2,
52
60
  force_reload: bool = False,
53
- ) -> tuple[str, str, dict, bool, list[str], str | None, str | None]:
61
+ ) -> tuple[
62
+ str,
63
+ str,
64
+ dict,
65
+ bool,
66
+ list[str],
67
+ str | None,
68
+ str | None,
69
+ str | None,
70
+ str | None,
71
+ str | None,
72
+ str | None,
73
+ str | None,
74
+ str | None,
75
+ str | None,
76
+ str | None,
77
+ ]:
54
78
  # Assumind o escopo default se necessário
55
79
  if not escopo:
56
80
  escopo = ESCOPO_RESTLIB2
@@ -81,6 +105,20 @@ class EntityLoader:
81
105
  relations_dependencies = loaded_entity.relations_dependencies
82
106
  insert_function_class_name = loaded_entity.insert_function_class_name
83
107
  update_function_class_name = loaded_entity.update_function_class_name
108
+ insert_function_name = loaded_entity.insert_function_name
109
+ update_function_name = loaded_entity.update_function_name
110
+ get_function_name = loaded_entity.get_function_name
111
+ list_function_name = loaded_entity.list_function_name
112
+ delete_function_name = loaded_entity.delete_function_name
113
+ get_function_type_class_name = (
114
+ loaded_entity.get_function_type_class_name
115
+ )
116
+ list_function_type_class_name = (
117
+ loaded_entity.list_function_type_class_name
118
+ )
119
+ delete_function_type_class_name = (
120
+ loaded_entity.delete_function_type_class_name
121
+ )
84
122
 
85
123
  # Verificando se alguma de suas dependências precisariam ser recarregadas
86
124
  for rd in relations_dependencies:
@@ -128,6 +166,14 @@ class EntityLoader:
128
166
  api_verbs,
129
167
  insert_function_class_name,
130
168
  update_function_class_name,
169
+ insert_function_name,
170
+ update_function_name,
171
+ get_function_name,
172
+ list_function_name,
173
+ delete_function_name,
174
+ get_function_type_class_name,
175
+ list_function_type_class_name,
176
+ delete_function_type_class_name,
131
177
  )
132
178
 
133
179
  # Desempacotando resultado
@@ -151,6 +197,14 @@ class EntityLoader:
151
197
  api_verbs,
152
198
  insert_function_class_name,
153
199
  update_function_class_name,
200
+ insert_function_name,
201
+ update_function_name,
202
+ get_function_name,
203
+ list_function_name,
204
+ delete_function_name,
205
+ get_function_type_class_name,
206
+ list_function_type_class_name,
207
+ delete_function_type_class_name,
154
208
  )
155
209
  else:
156
210
  (
@@ -159,6 +213,16 @@ class EntityLoader:
159
213
  namespace,
160
214
  api_expose,
161
215
  api_verbs,
216
+ insert_function_class_name,
217
+ update_function_class_name,
218
+ insert_function_name,
219
+ update_function_name,
220
+ get_function_name,
221
+ list_function_name,
222
+ delete_function_name,
223
+ get_function_type_class_name,
224
+ list_function_type_class_name,
225
+ delete_function_type_class_name,
162
226
  ) = result_execute
163
227
  return (
164
228
  dto_class_name,
@@ -166,6 +230,16 @@ class EntityLoader:
166
230
  namespace.entities_dict,
167
231
  api_expose,
168
232
  api_verbs,
233
+ insert_function_class_name,
234
+ update_function_class_name,
235
+ insert_function_name,
236
+ update_function_name,
237
+ get_function_name,
238
+ list_function_name,
239
+ delete_function_name,
240
+ get_function_type_class_name,
241
+ list_function_type_class_name,
242
+ delete_function_type_class_name,
169
243
  )
170
244
  else:
171
245
  # Se não deu o intervalo de verificação do refresh, retorna o que está em memória
@@ -177,6 +251,14 @@ class EntityLoader:
177
251
  api_verbs,
178
252
  insert_function_class_name,
179
253
  update_function_class_name,
254
+ insert_function_name,
255
+ update_function_name,
256
+ get_function_name,
257
+ list_function_name,
258
+ delete_function_name,
259
+ get_function_type_class_name,
260
+ list_function_type_class_name,
261
+ delete_function_type_class_name,
180
262
  )
181
263
 
182
264
  # Se não conseguir recuperar a entidade, procura no redis:
@@ -213,6 +295,14 @@ class EntityLoader:
213
295
  api_verbs,
214
296
  insert_function_class_name,
215
297
  update_function_class_name,
298
+ insert_function_name,
299
+ update_function_name,
300
+ get_function_name,
301
+ list_function_name,
302
+ delete_function_name,
303
+ get_function_type_class_name,
304
+ list_function_type_class_name,
305
+ delete_function_type_class_name,
216
306
  ) = result_execute
217
307
 
218
308
  return (
@@ -223,6 +313,14 @@ class EntityLoader:
223
313
  api_verbs,
224
314
  insert_function_class_name,
225
315
  update_function_class_name,
316
+ insert_function_name,
317
+ update_function_name,
318
+ get_function_name,
319
+ list_function_name,
320
+ delete_function_name,
321
+ get_function_type_class_name,
322
+ list_function_type_class_name,
323
+ delete_function_type_class_name,
226
324
  )
227
325
 
228
326
  def clear_namespaces(self):
@@ -253,7 +351,23 @@ class EntityLoader:
253
351
  entity_config_key: str,
254
352
  entity_resource: str,
255
353
  check_refresh: bool = False,
256
- ) -> tuple[str, str, Namespace, bool, list[str], str | None, str | None] | None:
354
+ ) -> tuple[
355
+ str,
356
+ str,
357
+ Namespace,
358
+ bool,
359
+ list[str],
360
+ str | None,
361
+ str | None,
362
+ str | None,
363
+ str | None,
364
+ str | None,
365
+ str | None,
366
+ str | None,
367
+ str | None,
368
+ str | None,
369
+ str | None,
370
+ ] | None:
257
371
  # Interpretando o json de configuração da entidade
258
372
  try:
259
373
  entity_config = json.loads(entity_config_str)
@@ -270,11 +384,28 @@ class EntityLoader:
270
384
  insert_function_class_name = entity_config.get(
271
385
  "insert_function_class_name"
272
386
  )
387
+ insert_function_name = entity_config.get("insert_function_name")
273
388
  insert_function_code = entity_config.get("source_insert_function")
274
389
  update_function_class_name = entity_config.get(
275
390
  "update_function_class_name"
276
391
  )
392
+ update_function_name = entity_config.get("update_function_name")
277
393
  update_function_code = entity_config.get("source_update_function")
394
+ get_function_name = entity_config.get("get_function_name")
395
+ list_function_name = entity_config.get("list_function_name")
396
+ delete_function_name = entity_config.get("delete_function_name")
397
+ get_function_type_class_name = entity_config.get(
398
+ "get_function_type_class_name"
399
+ )
400
+ list_function_type_class_name = entity_config.get(
401
+ "list_function_type_class_name"
402
+ )
403
+ delete_function_type_class_name = entity_config.get(
404
+ "delete_function_type_class_name"
405
+ )
406
+ get_function_code = entity_config.get("source_get_function_type")
407
+ list_function_code = entity_config.get("source_list_function_type")
408
+ delete_function_code = entity_config.get("source_delete_function_type")
278
409
  relations_dependencies = [
279
410
  RelationDependency().from_dict(rd)
280
411
  for rd in entity_config.get("relations_dependencies", [])
@@ -371,6 +502,27 @@ class EntityLoader:
371
502
  "Update Function source",
372
503
  )
373
504
 
505
+ if get_function_code:
506
+ self._safe_exec(
507
+ get_function_code,
508
+ namespace.entities_dict,
509
+ "Get FunctionType source",
510
+ )
511
+
512
+ if list_function_code:
513
+ self._safe_exec(
514
+ list_function_code,
515
+ namespace.entities_dict,
516
+ "List FunctionType source",
517
+ )
518
+
519
+ if delete_function_code:
520
+ self._safe_exec(
521
+ delete_function_code,
522
+ namespace.entities_dict,
523
+ "Delete FunctionType source",
524
+ )
525
+
374
526
  self._safe_exec(source_entity, namespace.entities_dict, "Entity source")
375
527
  self._safe_exec(source_dto, namespace.entities_dict, "DTO source")
376
528
 
@@ -384,6 +536,20 @@ class EntityLoader:
384
536
  loaded_entity.relations_dependencies = relations_dependencies
385
537
  loaded_entity.insert_function_class_name = insert_function_class_name
386
538
  loaded_entity.update_function_class_name = update_function_class_name
539
+ loaded_entity.insert_function_name = insert_function_name
540
+ loaded_entity.update_function_name = update_function_name
541
+ loaded_entity.get_function_name = get_function_name
542
+ loaded_entity.list_function_name = list_function_name
543
+ loaded_entity.delete_function_name = delete_function_name
544
+ loaded_entity.get_function_type_class_name = (
545
+ get_function_type_class_name
546
+ )
547
+ loaded_entity.list_function_type_class_name = (
548
+ list_function_type_class_name
549
+ )
550
+ loaded_entity.delete_function_type_class_name = (
551
+ delete_function_type_class_name
552
+ )
387
553
 
388
554
  namespace.loaded_entities[entity_resource] = loaded_entity
389
555
 
@@ -395,6 +561,14 @@ class EntityLoader:
395
561
  api_verbs,
396
562
  insert_function_class_name,
397
563
  update_function_class_name,
564
+ insert_function_name,
565
+ update_function_name,
566
+ get_function_name,
567
+ list_function_name,
568
+ delete_function_name,
569
+ get_function_type_class_name,
570
+ list_function_type_class_name,
571
+ delete_function_type_class_name,
398
572
  )
399
573
 
400
574
  def _safe_exec(self, source_code, context, description):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nsj_rest_lib2
3
- Version: 0.0.30
3
+ Version: 0.0.32
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