plugadvpl 0.4.0__tar.gz → 0.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/PKG-INFO +1 -1
  2. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/_version.py +2 -2
  3. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/cli.py +211 -0
  4. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/db.py +1 -1
  5. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/ingest.py +97 -0
  6. plugadvpl-0.4.2/plugadvpl/lookups/execauto_routines.json +260 -0
  7. plugadvpl-0.4.2/plugadvpl/migrations/006_universo3_execauto_calls.sql +24 -0
  8. plugadvpl-0.4.2/plugadvpl/migrations/007_universo3_protheus_docs.sql +39 -0
  9. plugadvpl-0.4.2/plugadvpl/parsing/execauto.py +221 -0
  10. plugadvpl-0.4.2/plugadvpl/parsing/protheus_doc.py +380 -0
  11. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/query.py +317 -0
  12. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/integration/test_cli.py +318 -0
  13. plugadvpl-0.4.2/tests/unit/test_execauto.py +287 -0
  14. plugadvpl-0.4.2/tests/unit/test_protheus_doc.py +331 -0
  15. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/.gitignore +0 -0
  16. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/README.md +0 -0
  17. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/__init__.py +0 -0
  18. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/__main__.py +0 -0
  19. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/ingest_sx.py +0 -0
  20. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/lookups/.gitkeep +0 -0
  21. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/lookups/funcoes_nativas.json +0 -0
  22. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/lookups/funcoes_restritas.json +0 -0
  23. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/lookups/lint_rules.json +0 -0
  24. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/lookups/modulos_erp.json +0 -0
  25. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/lookups/pontos_entrada_padrao.json +0 -0
  26. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/lookups/sql_macros.json +0 -0
  27. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/migrations/001_initial.sql +0 -0
  28. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/migrations/002_universo2_sx.sql +0 -0
  29. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/migrations/003_lint_rules_status.sql +0 -0
  30. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/migrations/004_consultas_pk_with_tipo.sql +0 -0
  31. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/migrations/005_universo3_execution_triggers.sql +0 -0
  32. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/output.py +0 -0
  33. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/parsing/.gitkeep +0 -0
  34. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/parsing/__init__.py +0 -0
  35. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/parsing/lint.py +0 -0
  36. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/parsing/parser.py +0 -0
  37. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/parsing/stripper.py +0 -0
  38. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/parsing/sx_csv.py +0 -0
  39. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/parsing/triggers.py +0 -0
  40. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/plugadvpl/scan.py +0 -0
  41. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/pyproject.toml +0 -0
  42. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/__init__.py +0 -0
  43. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/bench/.gitkeep +0 -0
  44. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/bench/__init__.py +0 -0
  45. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/bench/test_ingest_perf.py +0 -0
  46. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/bench/test_sx_ingest_perf.py +0 -0
  47. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/e2e_local/.gitkeep +0 -0
  48. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/e2e_local/__init__.py +0 -0
  49. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/e2e_local/test_e2e_local_ingest.py +0 -0
  50. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/e2e_local/test_ingest_sx_real.py +0 -0
  51. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/expected/.gitkeep +0 -0
  52. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/six.csv +0 -0
  53. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sx1.csv +0 -0
  54. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sx2.csv +0 -0
  55. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sx3.csv +0 -0
  56. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sx5.csv +0 -0
  57. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sx6.csv +0 -0
  58. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sx7.csv +0 -0
  59. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sx9.csv +0 -0
  60. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sxa.csv +0 -0
  61. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sxb.csv +0 -0
  62. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sxb_with_collisions.csv +0 -0
  63. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/sx_synthetic/sxg.csv +0 -0
  64. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/.gitkeep +0 -0
  65. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/_generate.py +0 -0
  66. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/classic_browse.prw +0 -0
  67. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/corrupted.bak +0 -0
  68. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/empty.prw +0 -0
  69. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/encoding_cp1252.prw +0 -0
  70. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/encoding_utf8.prw +0 -0
  71. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/exec_auto.prw +0 -0
  72. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/http_outbound.prw +0 -0
  73. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/huge.prw +0 -0
  74. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/job_rpc.prw +0 -0
  75. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/multi_filial.prw +0 -0
  76. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/mvc_complete.prw +0 -0
  77. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/mvc_hooks.prw +0 -0
  78. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/pe_paramixb.prw +0 -0
  79. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/pe_simple.prw +0 -0
  80. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/pubvars.prw +0 -0
  81. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/reclock_alias_dup_trigger.prw +0 -0
  82. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/reclock_pattern.prw +0 -0
  83. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/reclock_unbalanced.prw +0 -0
  84. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/sql_embedded.prw +0 -0
  85. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/tlpp_namespace.tlpp +0 -0
  86. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/ws_rest.tlpp +0 -0
  87. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/ws_restful_classic.prw +0 -0
  88. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/fixtures/synthetic/ws_soap.prw +0 -0
  89. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/integration/.gitkeep +0 -0
  90. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/integration/__init__.py +0 -0
  91. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/integration/test_ingest.py +0 -0
  92. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/integration/test_ingest_sx.py +0 -0
  93. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/.gitkeep +0 -0
  94. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/__snapshots__/test_parser_snapshots.ambr +0 -0
  95. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_db.py +0 -0
  96. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_lint.py +0 -0
  97. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_lint_catalog_consistency.py +0 -0
  98. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_output.py +0 -0
  99. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_parser.py +0 -0
  100. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_parser_snapshots.py +0 -0
  101. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_query.py +0 -0
  102. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_scan.py +0 -0
  103. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_stripper.py +0 -0
  104. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/tests/unit/test_triggers.py +0 -0
  105. {plugadvpl-0.4.0 → plugadvpl-0.4.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugadvpl
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: CLI que indexa fontes ADVPL/Protheus em SQLite com FTS5 para análise por LLM (companheiro do plugin Claude Code plugadvpl)
5
5
  Project-URL: Homepage, https://github.com/JoniPraia/plugadvpl
6
6
  Project-URL: Issues, https://github.com/JoniPraia/plugadvpl/issues
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.4.0'
22
- __version_tuple__ = version_tuple = (0, 4, 0)
21
+ __version__ = version = '0.4.2'
22
+ __version_tuple__ = version_tuple = (0, 4, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -57,8 +57,13 @@ from plugadvpl.query import (
57
57
  )
58
58
  from plugadvpl.query import (
59
59
  doctor_diagnostics,
60
+ execauto_calls_query,
60
61
  execution_triggers_query,
61
62
  find_any,
63
+ protheus_doc_show,
64
+ protheus_docs_orphans,
65
+ protheus_docs_query,
66
+ render_pdoc_markdown,
62
67
  gatilho_query,
63
68
  grep_fts,
64
69
  impacto_query,
@@ -1165,6 +1170,212 @@ def workflow(
1165
1170
  )
1166
1171
 
1167
1172
 
1173
+ # ---------------------------------------------------------------------------
1174
+ # v0.4.1 — Universo 3 (Rastreabilidade) Feature B: execauto
1175
+ # ---------------------------------------------------------------------------
1176
+
1177
+
1178
+ @app.command()
1179
+ def execauto(
1180
+ ctx: typer.Context,
1181
+ routine: Annotated[
1182
+ str | None,
1183
+ typer.Option("--routine", "-r", help="Filtra por rotina TOTVS (MATA410, FINA050, ...)."),
1184
+ ] = None,
1185
+ modulo: Annotated[
1186
+ str | None,
1187
+ typer.Option("--modulo", "-m", help="Filtra por módulo (SIGAFAT, SIGACOM, SIGAFIN, ...)."),
1188
+ ] = None,
1189
+ arquivo: Annotated[
1190
+ str | None,
1191
+ typer.Option("--arquivo", "-a", help="Filtra por arquivo (basename, case-insensitive)."),
1192
+ ] = None,
1193
+ op: Annotated[
1194
+ str | None,
1195
+ typer.Option("--op", "-o", help="Filtra por operação: inc|alt|exc (op_code 3/4/5)."),
1196
+ ] = None,
1197
+ dynamic: Annotated[
1198
+ bool | None,
1199
+ typer.Option(
1200
+ "--dynamic/--no-dynamic",
1201
+ help="--dynamic só não-resolvíveis; --no-dynamic só resolvidas; default: ambos.",
1202
+ ),
1203
+ ] = None,
1204
+ ) -> None:
1205
+ """Lista chamadas MsExecAuto resolvidas (Universo 3 / Feature B).
1206
+
1207
+ Resolve a indireção do codeblock ``{|args| Rotina(args)}`` e cruza com o
1208
+ catálogo TOTVS pra inferir tabelas tocadas, módulo, e tipo de operação
1209
+ (inclusão/alteração/exclusão).
1210
+
1211
+ Sem filtros: lista todas as chamadas. Use ``--routine MATA410`` pra ver
1212
+ quem inclui Pedido de Venda; ``--dynamic`` pra revisar calls não-resolvíveis.
1213
+ """
1214
+ from plugadvpl.parsing.execauto import load_execauto_catalog # lazy
1215
+ rows = _with_ro_db(
1216
+ ctx,
1217
+ lambda c: execauto_calls_query(
1218
+ c, routine=routine, modulo=modulo, arquivo=arquivo, op=op, dynamic=dynamic,
1219
+ ),
1220
+ )
1221
+ display_rows = [
1222
+ {
1223
+ "arquivo": r["arquivo"],
1224
+ "funcao": r["funcao"],
1225
+ "linha": r["linha"],
1226
+ "routine": r["routine"] or "(dynamic)",
1227
+ "module": r["module"] or "",
1228
+ "op": r["op_label"] or (str(r["op_code"]) if r["op_code"] is not None else ""),
1229
+ "tabelas": ",".join(r["tables_resolved"]),
1230
+ "snippet": (r["snippet"] or "")[:80],
1231
+ }
1232
+ for r in rows
1233
+ ]
1234
+ _render_from_ctx(
1235
+ ctx,
1236
+ display_rows,
1237
+ columns=["arquivo", "funcao", "linha", "routine", "module", "op", "tabelas", "snippet"],
1238
+ title=(
1239
+ f"ExecAuto calls"
1240
+ + (f" (routine={routine})" if routine else "")
1241
+ + (f" (modulo={modulo})" if modulo else "")
1242
+ + (f" (arquivo={arquivo})" if arquivo else "")
1243
+ + (f" (op={op})" if op else "")
1244
+ + (" (dynamic)" if dynamic else "")
1245
+ ),
1246
+ next_steps=(
1247
+ [
1248
+ f"plugadvpl arch {arq}"
1249
+ for arq in {r["arquivo"] for r in rows[:3]}
1250
+ ]
1251
+ if rows
1252
+ else [
1253
+ "plugadvpl ingest --no-incremental # se esperava findings",
1254
+ "plugadvpl execauto --dynamic # ver calls não-resolvíveis",
1255
+ ]
1256
+ ),
1257
+ )
1258
+
1259
+
1260
+ # ---------------------------------------------------------------------------
1261
+ # v0.4.2 — Universo 3 (Rastreabilidade) Feature C: docs
1262
+ # ---------------------------------------------------------------------------
1263
+
1264
+
1265
+ @app.command()
1266
+ def docs(
1267
+ ctx: typer.Context,
1268
+ modulo: Annotated[
1269
+ str | None,
1270
+ typer.Argument(help="Módulo TOTVS pra filtrar (SIGAFAT, SIGACOM, ...). Sem valor: lista tudo."),
1271
+ ] = None,
1272
+ author: Annotated[
1273
+ str | None,
1274
+ typer.Option("--author", help="Filtra por autor (LIKE %valor%, case-insensitive)."),
1275
+ ] = None,
1276
+ funcao: Annotated[
1277
+ str | None,
1278
+ typer.Option("--funcao", "-f", help="Filtra por nome de função (exact match)."),
1279
+ ] = None,
1280
+ arquivo: Annotated[
1281
+ str | None,
1282
+ typer.Option("--arquivo", "-a", help="Filtra por arquivo (basename)."),
1283
+ ] = None,
1284
+ deprecated: Annotated[
1285
+ bool | None,
1286
+ typer.Option("--deprecated/--no-deprecated", help="Só @deprecated / só ativos / ambos."),
1287
+ ] = None,
1288
+ tipo: Annotated[
1289
+ str | None,
1290
+ typer.Option("--tipo", "-t", help="Filtra por @type (function, method, class, ...)."),
1291
+ ] = None,
1292
+ show: Annotated[
1293
+ str | None,
1294
+ typer.Option("--show", help="Mostra doc completo de uma função em Markdown estruturado."),
1295
+ ] = None,
1296
+ orphans: Annotated[
1297
+ bool,
1298
+ typer.Option("--orphans", help="Lista funções SEM Protheus.doc (cross-ref BP-007 do lint)."),
1299
+ ] = False,
1300
+ ) -> None:
1301
+ """Catálogo de Protheus.doc agregado (Universo 3 / Feature C).
1302
+
1303
+ Sem args: lista todos os blocos indexados. Com ``[modulo]``: filtra por
1304
+ módulo (path-inferido). Use ``--show <funcao>`` pra ver o bloco completo
1305
+ formatado em Markdown. Use ``--orphans`` pra ver funções sem header.
1306
+ """
1307
+ if show:
1308
+ d = _with_ro_db(ctx, lambda c: protheus_doc_show(c, show))
1309
+ if d is None:
1310
+ typer.echo(f"Nenhum Protheus.doc encontrado pra função '{show}'.", err=True)
1311
+ raise typer.Exit(code=1)
1312
+ typer.echo(render_pdoc_markdown(d))
1313
+ return
1314
+
1315
+ if orphans:
1316
+ rows = _with_ro_db(ctx, lambda c: protheus_docs_orphans(c))
1317
+ _render_from_ctx(
1318
+ ctx,
1319
+ rows,
1320
+ columns=["arquivo", "funcao", "linha", "snippet"],
1321
+ title="Funções sem Protheus.doc (BP-007)",
1322
+ next_steps=(
1323
+ [f"plugadvpl find {r['funcao']}" for r in rows[:3] if r.get("funcao")]
1324
+ if rows
1325
+ else ["plugadvpl lint --regra BP-007 # ver findings raw"]
1326
+ ),
1327
+ )
1328
+ return
1329
+
1330
+ rows = _with_ro_db(
1331
+ ctx,
1332
+ lambda c: protheus_docs_query(
1333
+ c,
1334
+ modulo=modulo,
1335
+ author=author,
1336
+ funcao=funcao,
1337
+ arquivo=arquivo,
1338
+ deprecated=deprecated,
1339
+ tipo=tipo,
1340
+ ),
1341
+ )
1342
+ display_rows = [
1343
+ {
1344
+ "arquivo": r["arquivo"],
1345
+ "funcao": r["funcao"] or r["funcao_id"] or "",
1346
+ "modulo": r["module_inferido"] or "",
1347
+ "tipo": r["tipo"] or "",
1348
+ "author": r["author"] or "",
1349
+ "since": r["since"] or "",
1350
+ "deprecated": "sim" if r["deprecated"] else "",
1351
+ "summary": (r["summary"] or "").replace("\n", " ")[:80],
1352
+ }
1353
+ for r in rows
1354
+ ]
1355
+ _render_from_ctx(
1356
+ ctx,
1357
+ display_rows,
1358
+ columns=["arquivo", "funcao", "modulo", "tipo", "author", "since", "deprecated", "summary"],
1359
+ title=(
1360
+ "Protheus.doc"
1361
+ + (f" (modulo={modulo})" if modulo else "")
1362
+ + (f" (author={author})" if author else "")
1363
+ + (f" (deprecated)" if deprecated else "")
1364
+ ),
1365
+ next_steps=(
1366
+ [
1367
+ f"plugadvpl docs --show {r['funcao']}"
1368
+ for r in rows[:3] if r.get("funcao")
1369
+ ]
1370
+ if rows
1371
+ else [
1372
+ "plugadvpl docs --orphans # funções sem header",
1373
+ "plugadvpl ingest --no-incremental # se esperava docs",
1374
+ ]
1375
+ ),
1376
+ )
1377
+
1378
+
1168
1379
  # ---------------------------------------------------------------------------
1169
1380
  # entry point
1170
1381
  # ---------------------------------------------------------------------------
@@ -11,7 +11,7 @@ from typing import TYPE_CHECKING
11
11
  if TYPE_CHECKING:
12
12
  from pathlib import Path
13
13
 
14
- SCHEMA_VERSION = "5"
14
+ SCHEMA_VERSION = "7"
15
15
 
16
16
 
17
17
  # Mapeamento {filename JSON -> (tabela, colunas em ordem)}.
@@ -36,6 +36,14 @@ from plugadvpl.db import (
36
36
  )
37
37
  from plugadvpl.parsing import lint as lint_module
38
38
  from plugadvpl.parsing.parser import _PE_NAME_RE, parse_source
39
+ from plugadvpl.parsing.execauto import (
40
+ extract_execauto_calls,
41
+ serialize_tables as serialize_execauto_tables,
42
+ )
43
+ from plugadvpl.parsing.protheus_doc import (
44
+ extract_protheus_docs,
45
+ serialize_json as serialize_pdoc_json,
46
+ )
39
47
  from plugadvpl.parsing.triggers import (
40
48
  extract_execution_triggers,
41
49
  serialize_metadata as serialize_trigger_metadata,
@@ -150,6 +158,8 @@ def _delete_dependents(conn: sqlite3.Connection, arquivo: str) -> None:
150
158
  "defines",
151
159
  "lint_findings",
152
160
  "execution_triggers", # v0.4.0 — Universo 3 Feature A
161
+ "execauto_calls", # v0.4.1 — Universo 3 Feature B
162
+ "protheus_docs", # v0.4.2 — Universo 3 Feature C
153
163
  ):
154
164
  conn.execute(f"DELETE FROM {table} WHERE arquivo=?", (arquivo,))
155
165
  conn.execute(
@@ -606,6 +616,89 @@ def _write_parsed( # noqa: PLR0912, PLR0915 — escrita verbosa: 12 tabelas dep
606
616
  )
607
617
  counters["execution_triggers"] = counters.get("execution_triggers", 0) + len(trigger_rows)
608
618
 
619
+ # v0.4.1 (Universo 3 Feature B): execauto_calls
620
+ execauto = extract_execauto_calls(content)
621
+ if execauto:
622
+ execauto_rows: list[tuple[Any, ...]] = []
623
+ for c in execauto:
624
+ linha = int(c.get("linha", 0))
625
+ funcao = _resolve_funcao_origem(linha)
626
+ execauto_rows.append((
627
+ arquivo,
628
+ funcao,
629
+ linha,
630
+ c.get("routine"),
631
+ c.get("module"),
632
+ c.get("routine_type"),
633
+ c.get("op_code"),
634
+ c.get("op_label"),
635
+ serialize_execauto_tables(c.get("tables_resolved", []) or []),
636
+ 1 if c.get("dynamic_call") else 0,
637
+ c.get("arg_count"),
638
+ (c.get("snippet", "") or "")[:500],
639
+ ))
640
+ conn.executemany(
641
+ """
642
+ INSERT INTO execauto_calls (
643
+ arquivo, funcao, linha, routine, module, routine_type,
644
+ op_code, op_label, tables_resolved_json, dynamic_call,
645
+ arg_count, snippet
646
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
647
+ """,
648
+ execauto_rows,
649
+ )
650
+ counters["execauto_calls"] = counters.get("execauto_calls", 0) + len(execauto_rows)
651
+
652
+ # v0.4.2 (Universo 3 Feature C): protheus_docs
653
+ # Usa o caminho relativo pra inferência de módulo (path-based regex).
654
+ pdocs = extract_protheus_docs(content, arquivo=caminho_relativo)
655
+ if pdocs:
656
+ pdoc_rows: list[tuple[Any, ...]] = []
657
+ for d in pdocs:
658
+ pdoc_rows.append((
659
+ arquivo,
660
+ d.get("funcao"),
661
+ d.get("funcao_id"),
662
+ d.get("tipo"),
663
+ d.get("module_inferido"),
664
+ int(d.get("linha_bloco_inicio") or 0),
665
+ int(d.get("linha_bloco_fim") or 0),
666
+ d.get("linha_funcao"),
667
+ d.get("summary"),
668
+ d.get("description"),
669
+ d.get("author"),
670
+ d.get("since"),
671
+ d.get("version"),
672
+ 1 if d.get("deprecated") else 0,
673
+ d.get("deprecated_reason"),
674
+ d.get("language"),
675
+ serialize_pdoc_json(d.get("params")),
676
+ serialize_pdoc_json(d.get("returns")),
677
+ serialize_pdoc_json(d.get("examples")),
678
+ serialize_pdoc_json(d.get("history")),
679
+ serialize_pdoc_json(d.get("see")),
680
+ serialize_pdoc_json(d.get("tables")),
681
+ serialize_pdoc_json(d.get("todos")),
682
+ serialize_pdoc_json(d.get("obs")),
683
+ serialize_pdoc_json(d.get("links")),
684
+ serialize_pdoc_json(d.get("raw_tags")),
685
+ ))
686
+ conn.executemany(
687
+ """
688
+ INSERT INTO protheus_docs (
689
+ arquivo, funcao, funcao_id, tipo, module_inferido,
690
+ linha_bloco_inicio, linha_bloco_fim, linha_funcao,
691
+ summary, description, author, since, version,
692
+ deprecated, deprecated_reason, language,
693
+ params_json, returns_json, examples_json, history_json,
694
+ see_json, tables_json, todos_json, obs_json, links_json,
695
+ raw_tags_json
696
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
697
+ """,
698
+ pdoc_rows,
699
+ )
700
+ counters["protheus_docs"] = counters.get("protheus_docs", 0) + len(pdoc_rows)
701
+
609
702
  counters["arquivos_ok"] += 1
610
703
 
611
704
 
@@ -760,6 +853,8 @@ def ingest(
760
853
  "params": 0,
761
854
  "lint_findings": 0,
762
855
  "execution_triggers": 0, # v0.4.0
856
+ "execauto_calls": 0, # v0.4.1
857
+ "protheus_docs": 0, # v0.4.2
763
858
  "duration_ms": 0,
764
859
  # v0.3.13: caller (CLI) usa esses campos pra detectar a pegadinha do
765
860
  # `--incremental` após `uv tool upgrade` — quando lookup_bundle muda
@@ -797,6 +892,8 @@ def ingest(
797
892
  ("chamadas_funcao", "total_chamadas"),
798
893
  ("lint_findings", "total_lint_findings"),
799
894
  ("execution_triggers", "total_execution_triggers"), # v0.4.0
895
+ ("execauto_calls", "total_execauto_calls"), # v0.4.1
896
+ ("protheus_docs", "total_protheus_docs"), # v0.4.2
800
897
  ):
801
898
  n = conn.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
802
899
  set_meta(conn, key, str(n))
@@ -0,0 +1,260 @@
1
+ {
2
+ "schema_version": 1,
3
+ "_meta": {
4
+ "description": "Catalogo de rotinas TOTVS canonicas chamadas via MsExecAuto. Usado por parsing/execauto.py pra resolver tabelas tocadas indiretamente.",
5
+ "verified_legend": "true=fonte oficial TOTVS conferida; false=fonte secundaria/comunidade, conferir via PR",
6
+ "expansion_policy": "Adicionar rotinas via PR conforme demanda. Rotinas faltantes sao detectadas mas com module=null e tables_resolved=[]."
7
+ },
8
+ "routines": [
9
+ {
10
+ "routine": "MATA010",
11
+ "module": "SIGAEST",
12
+ "type": "cadastro",
13
+ "label": "Cadastro de Produtos",
14
+ "tables_primary": ["SB1"],
15
+ "tables_secondary": [],
16
+ "source_url": "https://tdn.totvs.com",
17
+ "verified": true
18
+ },
19
+ {
20
+ "routine": "MATA030",
21
+ "module": "SIGAFIN",
22
+ "type": "cadastro",
23
+ "label": "Cadastro de Clientes",
24
+ "tables_primary": ["SA1"],
25
+ "tables_secondary": [],
26
+ "source_url": "https://tdn.totvs.com",
27
+ "verified": true
28
+ },
29
+ {
30
+ "routine": "MATA050",
31
+ "module": "SIGAFAT",
32
+ "type": "cadastro",
33
+ "label": "Cadastro de Transportadoras",
34
+ "tables_primary": ["SA4"],
35
+ "tables_secondary": [],
36
+ "source_url": "https://centraldeatendimento.totvs.com/hc/pt-br/articles/8058455139479",
37
+ "verified": true
38
+ },
39
+ {
40
+ "routine": "MATA075",
41
+ "module": "SIGAEST",
42
+ "type": "movimento",
43
+ "label": "Movimento de Lote",
44
+ "tables_primary": ["SB8"],
45
+ "tables_secondary": [],
46
+ "source_url": "https://tdn.totvs.com",
47
+ "verified": false
48
+ },
49
+ {
50
+ "routine": "MATA103",
51
+ "module": "SIGACOM",
52
+ "type": "movimento",
53
+ "label": "Documento de Entrada (NF Compra)",
54
+ "tables_primary": ["SF1", "SD1"],
55
+ "tables_secondary": ["SF4", "SE2"],
56
+ "source_url": "https://mastersiga.tomticket.com/kb/compras/sigacom-documento-de-entrada-rotina-automatica-mata103-execauto",
57
+ "verified": true
58
+ },
59
+ {
60
+ "routine": "MATA110",
61
+ "module": "SIGACOM",
62
+ "type": "movimento",
63
+ "label": "Solicitacao de Compra",
64
+ "tables_primary": ["SC1"],
65
+ "tables_secondary": [],
66
+ "source_url": "https://tdn.totvs.com/pages/viewpage.action?pageId=318605213",
67
+ "verified": true
68
+ },
69
+ {
70
+ "routine": "MATA120",
71
+ "module": "SIGACOM",
72
+ "type": "movimento",
73
+ "label": "Pedido de Compra",
74
+ "tables_primary": ["SC7"],
75
+ "tables_secondary": [],
76
+ "source_url": "https://tdn.totvs.com",
77
+ "verified": true
78
+ },
79
+ {
80
+ "routine": "MATA125",
81
+ "module": "SIGACOM",
82
+ "type": "movimento",
83
+ "label": "Autorizacao de Entrega",
84
+ "tables_primary": ["SCA", "SCB"],
85
+ "tables_secondary": [],
86
+ "source_url": "https://tdn.totvs.com",
87
+ "verified": false
88
+ },
89
+ {
90
+ "routine": "MATA150",
91
+ "module": "SIGACOM",
92
+ "type": "movimento",
93
+ "label": "Cotacao de Compra",
94
+ "tables_primary": ["SC8"],
95
+ "tables_secondary": [],
96
+ "source_url": "https://tdn.totvs.com",
97
+ "verified": true
98
+ },
99
+ {
100
+ "routine": "MATA180",
101
+ "module": "SIGAEST",
102
+ "type": "cadastro",
103
+ "label": "Complemento de Produto",
104
+ "tables_primary": ["SB5"],
105
+ "tables_secondary": [],
106
+ "source_url": "https://tdn.totvs.com/pages/releaseview.action?pageId=358453385",
107
+ "verified": true
108
+ },
109
+ {
110
+ "routine": "MATA220",
111
+ "module": "SIGAEST",
112
+ "type": "cadastro",
113
+ "label": "Estrutura de Produto",
114
+ "tables_primary": ["SG1"],
115
+ "tables_secondary": [],
116
+ "source_url": "https://tdn.totvs.com",
117
+ "verified": false
118
+ },
119
+ {
120
+ "routine": "MATA242",
121
+ "module": "SIGAPCP",
122
+ "type": "movimento",
123
+ "label": "Desmontagem de Produtos",
124
+ "tables_primary": ["SD3"],
125
+ "tables_secondary": [],
126
+ "source_url": "https://tdn.totvs.com/pages/viewpage.action?pageId=393362555",
127
+ "verified": true
128
+ },
129
+ {
130
+ "routine": "MATA261",
131
+ "module": "SIGAEST",
132
+ "type": "movimento",
133
+ "label": "Transferencia Multipla",
134
+ "tables_primary": ["SD3"],
135
+ "tables_secondary": [],
136
+ "source_url": "https://tdn.totvs.com/pages/viewpage.action?pageId=379292916",
137
+ "verified": true
138
+ },
139
+ {
140
+ "routine": "MATA310",
141
+ "module": "SIGAEST",
142
+ "type": "movimento",
143
+ "label": "Movimento Interno - Saida",
144
+ "tables_primary": ["SD3"],
145
+ "tables_secondary": [],
146
+ "source_url": "https://tdn.totvs.com",
147
+ "verified": true
148
+ },
149
+ {
150
+ "routine": "MATA311",
151
+ "module": "SIGAEST",
152
+ "type": "movimento",
153
+ "label": "Movimento Interno - Entrada",
154
+ "tables_primary": ["SD3"],
155
+ "tables_secondary": [],
156
+ "source_url": "https://tdn.totvs.com",
157
+ "verified": true
158
+ },
159
+ {
160
+ "routine": "MATA410",
161
+ "module": "SIGAFAT",
162
+ "type": "movimento",
163
+ "label": "Pedido de Venda",
164
+ "tables_primary": ["SC5", "SC6"],
165
+ "tables_secondary": ["SF4", "SB1"],
166
+ "source_url": "https://tdn.totvs.com/pages/releaseview.action?pageId=6784012",
167
+ "verified": true
168
+ },
169
+ {
170
+ "routine": "MATA460",
171
+ "module": "SIGAFAT",
172
+ "type": "movimento",
173
+ "label": "Documento de Saida (NF) - Geracao",
174
+ "tables_primary": ["SF2", "SD2"],
175
+ "tables_secondary": [],
176
+ "source_url": "https://centraldeatendimento.totvs.com",
177
+ "verified": true
178
+ },
179
+ {
180
+ "routine": "MATA461",
181
+ "module": "SIGAFAT",
182
+ "type": "movimento",
183
+ "label": "Documento de Saida (NF) - Manutencao",
184
+ "tables_primary": ["SF2", "SD2"],
185
+ "tables_secondary": [],
186
+ "source_url": "https://centraldeatendimento.totvs.com",
187
+ "verified": true
188
+ },
189
+ {
190
+ "routine": "FINA040",
191
+ "module": "SIGAFIN",
192
+ "type": "movimento",
193
+ "label": "Contas a Receber - Inclusao Titulo",
194
+ "tables_primary": ["SE1"],
195
+ "tables_secondary": [],
196
+ "source_url": "https://tdn.totvs.com",
197
+ "verified": true
198
+ },
199
+ {
200
+ "routine": "FINA050",
201
+ "module": "SIGAFIN",
202
+ "type": "movimento",
203
+ "label": "Contas a Pagar - Inclusao Titulo",
204
+ "tables_primary": ["SE2"],
205
+ "tables_secondary": [],
206
+ "source_url": "https://protheusadvpl.com.br/execauto-fina050/",
207
+ "verified": true
208
+ },
209
+ {
210
+ "routine": "FINA070",
211
+ "module": "SIGAFIN",
212
+ "type": "movimento",
213
+ "label": "Baixa de Contas a Receber",
214
+ "tables_primary": ["SE1", "SE5"],
215
+ "tables_secondary": [],
216
+ "source_url": "https://tdn.totvs.com",
217
+ "verified": true
218
+ },
219
+ {
220
+ "routine": "FINA080",
221
+ "module": "SIGAFIN",
222
+ "type": "movimento",
223
+ "label": "Baixa de Contas a Pagar",
224
+ "tables_primary": ["SE2", "SE5"],
225
+ "tables_secondary": [],
226
+ "source_url": "https://tdn.totvs.com",
227
+ "verified": true
228
+ },
229
+ {
230
+ "routine": "CTBA102",
231
+ "module": "SIGACTB",
232
+ "type": "movimento",
233
+ "label": "Lancamento Contabil",
234
+ "tables_primary": ["CT2"],
235
+ "tables_secondary": [],
236
+ "source_url": "https://tdn.totvs.com",
237
+ "verified": true
238
+ },
239
+ {
240
+ "routine": "EECAP100",
241
+ "module": "SIGAEEC",
242
+ "type": "movimento",
243
+ "label": "Pedido de Exportacao",
244
+ "tables_primary": ["EEC", "EE7"],
245
+ "tables_secondary": [],
246
+ "source_url": "https://tdn.totvs.com/pages/releaseview.action?pageId=394219396",
247
+ "verified": false
248
+ },
249
+ {
250
+ "routine": "TMSA500",
251
+ "module": "SIGATMS",
252
+ "type": "movimento",
253
+ "label": "Documento de Transporte",
254
+ "tables_primary": ["DT6"],
255
+ "tables_secondary": [],
256
+ "source_url": "https://tdn.totvs.com/display/public/PROT/TUMGXW_DT_MsExecAuto_Manutencao_de_Documentos_de_Transporte_TMSA500",
257
+ "verified": false
258
+ }
259
+ ]
260
+ }
@@ -0,0 +1,24 @@
1
+ -- v0.4.1 — Universo 3 / Feature B: ExecAuto chain expansion.
2
+ -- Indexa chamadas MsExecAuto resolvendo a rotina canonica TOTVS chamada
3
+ -- via codeblock e cruzando com catalogo (execauto_routines.json) pra
4
+ -- inferir tabelas tocadas indiretamente.
5
+
6
+ CREATE TABLE IF NOT EXISTS execauto_calls (
7
+ id INTEGER PRIMARY KEY,
8
+ arquivo TEXT NOT NULL,
9
+ funcao TEXT,
10
+ linha INTEGER NOT NULL,
11
+ routine TEXT, -- MATA410, FINA050, NULL se dynamic
12
+ module TEXT, -- SIGAFAT, NULL se rotina nao no catalogo
13
+ routine_type TEXT, -- cadastro/movimento, NULL se desconhecido
14
+ op_code INTEGER, -- 3/4/5 ou outro literal
15
+ op_label TEXT, -- "inclusao"/"alteracao"/"exclusao"
16
+ tables_resolved_json TEXT, -- JSON array ["SC5","SC6"]
17
+ dynamic_call INTEGER NOT NULL DEFAULT 0, -- 0/1 (bool)
18
+ arg_count INTEGER, -- num args do codeblock
19
+ snippet TEXT NOT NULL
20
+ );
21
+
22
+ CREATE INDEX IF NOT EXISTS idx_execauto_arquivo ON execauto_calls(arquivo);
23
+ CREATE INDEX IF NOT EXISTS idx_execauto_routine ON execauto_calls(routine);
24
+ CREATE INDEX IF NOT EXISTS idx_execauto_module ON execauto_calls(module);