biatoolkit 1.2.3__tar.gz → 1.2.4__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.
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/PKG-INFO +101 -94
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/sankhya_call.py +2 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit.egg-info/PKG-INFO +101 -94
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit.egg-info/SOURCES.txt +1 -4
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/setup.py +1 -1
- biatoolkit-1.2.3/biatoolkit/validation/__init__.py +0 -0
- biatoolkit-1.2.3/biatoolkit/validation/coercion.py +0 -175
- biatoolkit-1.2.3/biatoolkit/validation/validation.py +0 -135
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/README.md +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/__init__.py +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/basic_client.py +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/schema/__init__.py +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/schema/header.py +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/settings.py +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/test_sankhya.py +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit/util.py +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit.egg-info/dependency_links.txt +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/biatoolkit.egg-info/top_level.txt +0 -0
- {biatoolkit-1.2.3 → biatoolkit-1.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: biatoolkit
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: Biblioteca para desenvolvedores que utilizam o BiaAgentBuilder
|
|
5
5
|
Author: Bia Platform Team
|
|
6
6
|
Author-email: data.platform@sankhya.com.br
|
|
@@ -37,7 +37,6 @@ A classe `BiaClient` encapsula um cliente HTTP assíncrono para comunicação co
|
|
|
37
37
|
(Model Context Protocol).
|
|
38
38
|
|
|
39
39
|
Ela esconde toda a complexidade de:
|
|
40
|
-
- Conexão HTTP streamable
|
|
41
40
|
- Inicialização de sessões MCP
|
|
42
41
|
- Execução de tools
|
|
43
42
|
|
|
@@ -49,7 +48,6 @@ Ela esconde toda a complexidade de:
|
|
|
49
48
|
- **call_tool(tool_name, params=None)**
|
|
50
49
|
- Executa uma ferramenta específica disponível no servidor MCP.
|
|
51
50
|
|
|
52
|
-
---
|
|
53
51
|
|
|
54
52
|
### BiaUtil
|
|
55
53
|
|
|
@@ -64,7 +62,6 @@ permitindo acesso fácil a:
|
|
|
64
62
|
- Recebe uma instância de `FastMCP` para acessar o contexto da requisição atual.
|
|
65
63
|
|
|
66
64
|
- **get_header()**
|
|
67
|
-
- Extrai e retorna os headers customizados do runtime.
|
|
68
65
|
- Retorna um objeto `Header` com os campos:
|
|
69
66
|
- `current_host`: Host do ERP no qual o copilot está em execução.
|
|
70
67
|
- `user_email`: Email do usuário autenticado.
|
|
@@ -75,7 +72,6 @@ permitindo acesso fácil a:
|
|
|
75
72
|
- `iam_user_id`: ID do usuário do BIA IAM.
|
|
76
73
|
- `gateway_token`: Token primário do Sankhya API Gateway.
|
|
77
74
|
|
|
78
|
-
- **get_parameter(parameter_name)**
|
|
79
75
|
- Recupera parâmetros sensíveis seguindo a ordem:
|
|
80
76
|
1. Variáveis de ambiente do sistema
|
|
81
77
|
2. AWS SSM Parameter Store (fallback)
|
|
@@ -84,7 +80,6 @@ permitindo acesso fácil a:
|
|
|
84
80
|
- O SSM só é consultado se o parâmetro **não existir** nas variáveis de ambiente.
|
|
85
81
|
- Em produção, a busca no SSM depende do header
|
|
86
82
|
`X-Amzn-Bedrock-AgentCore-Runtime-Custom-prefix`.
|
|
87
|
-
- Se esse header não estiver presente, o método retorna `None`.
|
|
88
83
|
|
|
89
84
|
---
|
|
90
85
|
|
|
@@ -95,7 +90,6 @@ Nesta seção você encontrará uma breve descrição de como utilizar os princi
|
|
|
95
90
|
### **Criando um MCP Server**
|
|
96
91
|
|
|
97
92
|
Primeiro, instale os pacotes **MCP** e **Bia Toolkit**.
|
|
98
|
-
|
|
99
93
|
```bash
|
|
100
94
|
pip install mcp biatoolkit
|
|
101
95
|
```
|
|
@@ -108,9 +102,107 @@ import json
|
|
|
108
102
|
|
|
109
103
|
mcp = FastMCP(host="0.0.0.0", stateless_http=True)
|
|
110
104
|
|
|
111
|
-
@mcp.tool()
|
|
112
105
|
def listar() -> str:
|
|
113
|
-
|
|
106
|
+
|
|
107
|
+
O Bia Toolkit oferece integração pronta para consumo de serviços HTTP da plataforma Sankhya (ou gateway), com autenticação via JSESSIONID e configuração de timeouts/retries via variáveis de ambiente.
|
|
108
|
+
|
|
109
|
+
### Objetivo
|
|
110
|
+
|
|
111
|
+
- Facilitar chamadas autenticadas a serviços Sankhya sem que o desenvolvedor precise lidar com autenticação, headers ou gerenciamento de sessão HTTP.
|
|
112
|
+
- Fornecer métodos prontos para chamadas genéricas (`call_json`) e para consultas a views (`load_view`).
|
|
113
|
+
- Permitir uso estático compatível com scaffolds legados via `Sankhya.Call(...)`.
|
|
114
|
+
|
|
115
|
+
### Configuração
|
|
116
|
+
|
|
117
|
+
- O caminho do serviço (`/mge/service.sbr`) é fixo no toolkit.
|
|
118
|
+
- O parâmetro `base_url` é obrigatório e pode ser passado explicitamente ou extraído automaticamente do header do runtime (`current_host` via `BiaUtil`).
|
|
119
|
+
- Não existe mais configuração via variável de ambiente para base_url ou service_path.
|
|
120
|
+
- As variáveis de ambiente opcionais são apenas para timeout, retries e SSL:
|
|
121
|
+
- `SANKHYA_TIMEOUT_CONNECT`: timeout de conexão (default: 3.05)
|
|
122
|
+
- `SANKHYA_TIMEOUT_READ`: timeout de leitura (default: 12)
|
|
123
|
+
- `SANKHYA_RETRIES_TOTAL`: número de tentativas em falha (default: 3)
|
|
124
|
+
- `SANKHYA_RETRY_BACKOFF`: backoff entre tentativas (default: 0.5)
|
|
125
|
+
- `SANKHYA_VERIFY_SSL`: se valida SSL (default: "1")
|
|
126
|
+
|
|
127
|
+
### Principais classes e métodos
|
|
128
|
+
|
|
129
|
+
- **SankhyaSettings**: Dataclass de configuração de timeouts/retries/SSL. Use `SankhyaSettings.from_env()` para obter as configurações do ambiente.
|
|
130
|
+
- **Sankhya**: Classe principal de integração. Permite instanciar com contexto MCP (`FastMCP`) ou usar métodos estáticos.
|
|
131
|
+
- `call_json(...)`: Realiza chamada HTTP autenticada, retorna JSON. Veja detalhes dos parâmetros abaixo.
|
|
132
|
+
- `load_view(...)`: Helper para consultas a views Sankhya (`CRUDServiceProvider.loadView`). Veja detalhes dos parâmetros abaixo.
|
|
133
|
+
- `Call(...)`: Método estático compatível com scaffolds legados. Veja detalhes dos parâmetros abaixo.
|
|
134
|
+
### Parâmetros dos métodos principais
|
|
135
|
+
|
|
136
|
+
#### `call_json`
|
|
137
|
+
|
|
138
|
+
| Parâmetro | Obrigatório | Descrição |
|
|
139
|
+
|-------------------|-------------|-----------|
|
|
140
|
+
| payload | Não | Dicionário enviado como corpo da requisição (POST). Pode ser None. |
|
|
141
|
+
| jsessionid | Não | Token de sessão JSESSIONID. Se não informado, tenta extrair do header do runtime (via MCP/BiaUtil). |
|
|
142
|
+
| url | Não | URL completa para chamada. Se informado, ignora base_url. |
|
|
143
|
+
| base_url | Sim* | Base URL do serviço Sankhya (ex: https://meu.sankhya.com.br). Obrigatório se não estiver em contexto MCP (header). |
|
|
144
|
+
| query | Não | Querystring adicional (ex: serviceName=...&outputType=json). |
|
|
145
|
+
| method | Não | "POST" (default) ou "GET". |
|
|
146
|
+
| extra_headers | Não | Dicionário de headers adicionais. |
|
|
147
|
+
| timeout | Não | Tupla (connect, read) para sobrescrever timeout padrão. |
|
|
148
|
+
| raise_for_http_error | Não | Se True (default), lança SankhyaHTTPError em erro HTTP. |
|
|
149
|
+
|
|
150
|
+
*Se não passar base_url, o método tentará extrair automaticamente do header do runtime (MCP) se disponível. Caso contrário, será obrigatório.
|
|
151
|
+
|
|
152
|
+
#### `load_view`
|
|
153
|
+
|
|
154
|
+
| Parâmetro | Obrigatório | Descrição |
|
|
155
|
+
|-------------------|-------------|-----------|
|
|
156
|
+
| view_name | Sim | Nome da view no Sankhya. |
|
|
157
|
+
| where_sql | Sim | Cláusula WHERE (string). |
|
|
158
|
+
| fields | Não | Campos a retornar (string). Default: "*". |
|
|
159
|
+
| jsessionid | Não | Token de sessão JSESSIONID. Se não informado, tenta extrair do header do runtime (via MCP/BiaUtil). |
|
|
160
|
+
| url | Não | URL completa opcional (override). |
|
|
161
|
+
| base_url | Não* | Base URL do serviço Sankhya. Se não informado, tenta extrair do header do runtime (current_host). |
|
|
162
|
+
| output_type | Não | "json" (default). |
|
|
163
|
+
| extra_headers | Não | Dicionário de headers adicionais. |
|
|
164
|
+
|
|
165
|
+
*Se não passar base_url, o método tentará extrair automaticamente do header do runtime (MCP) via BiaUtil. Caso não consiga, lança erro.
|
|
166
|
+
|
|
167
|
+
#### `Call`
|
|
168
|
+
|
|
169
|
+
| Parâmetro | Obrigatório | Descrição |
|
|
170
|
+
|-------------------|-------------|-----------|
|
|
171
|
+
| jsessionID | Não | Token de sessão JSESSIONID. Se não informado, tenta extrair do header do runtime (via MCP/BiaUtil). |
|
|
172
|
+
| payload | Não | Dicionário enviado como corpo da requisição. |
|
|
173
|
+
| mcp | Não | Instância opcional do FastMCP para contexto do runtime. |
|
|
174
|
+
| url | Não | URL completa (opcional). |
|
|
175
|
+
| base_url | Sim* | Base URL do serviço Sankhya. Obrigatório se não estiver em contexto MCP (header). |
|
|
176
|
+
| query | Não | Querystring adicional (opcional). |
|
|
177
|
+
| method | Não | "POST" (default) ou "GET". |
|
|
178
|
+
| extra_headers | Não | Dicionário de headers adicionais. |
|
|
179
|
+
|
|
180
|
+
*Se não passar base_url, o método tentará extrair automaticamente do header do runtime (MCP) se disponível. Caso contrário, será obrigatório.
|
|
181
|
+
|
|
182
|
+
**Resumo:** Sempre que possível, o toolkit resolve automaticamente base_url e jsessionid do contexto MCP (headers). Se não estiver rodando em MCP, passe base_url explicitamente.
|
|
183
|
+
- **SankhyaHTTPError**: Exceção lançada em caso de erro HTTP (status != 200), contendo status_code e response_text.
|
|
184
|
+
|
|
185
|
+
### Exemplo de uso (instanciado)
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
from biatoolkit.sankhya_call import Sankhya
|
|
189
|
+
sk = Sankhya(mcp=mcp)
|
|
190
|
+
result = sk.load_view("BIA_VW_MB_RULES", "CODPROD_A = 123", fields="*")
|
|
191
|
+
# O base_url será extraído automaticamente do header do runtime (current_host)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Exemplo de uso (estático)
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
from biatoolkit.sankhya_call import Sankhya
|
|
198
|
+
result = Sankhya.Call(jsessionID="...", payload={...}, base_url="https://meu.sankhya.com.br", query="serviceName=...&outputType=json")
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Observações
|
|
202
|
+
|
|
203
|
+
- O JSESSIONID pode ser passado explicitamente ou extraído automaticamente do header do runtime (se rodando em MCP Server).
|
|
204
|
+
- O método `load_view` facilita consultas a views Sankhya, montando o payload e a querystring automaticamente, e resolve o base_url do header se não for passado.
|
|
205
|
+
- O método `call_json` permite chamadas genéricas a qualquer serviço Sankhya, com controle total sobre headers, método HTTP, payload e querystring, mas exige base_url explícito se não estiver em contexto MCP.
|
|
114
206
|
exemplo = {
|
|
115
207
|
"itens": [
|
|
116
208
|
{"id": 1, "nome": "Item 1"},
|
|
@@ -348,91 +440,6 @@ O método `get_parameter(parameter_name: str)` busca o parâmetro informado em d
|
|
|
348
440
|
- Um arquivo `.env` para testes locais.
|
|
349
441
|
- No cofre de segredos do Bia Agent Builder para usar em ambiente produtivo.
|
|
350
442
|
|
|
351
|
-
|
|
352
|
-
---
|
|
353
|
-
|
|
354
|
-
## Validação e Coerção de Dados
|
|
355
|
-
|
|
356
|
-
O Bia Toolkit oferece funções utilitárias para normalização, sanitização e coerção de dados, facilitando o consumo seguro de entradas vindas de APIs, headers, payloads e integrações legadas.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
### Validação de Dados (`biatoolkit.validation.validation`)
|
|
360
|
-
|
|
361
|
-
Utilize a classe **BiaValidation** para acessar as funções de validação de forma padronizada:
|
|
362
|
-
|
|
363
|
-
- **BiaValidation.parse_int_list(value, dedupe=True, keep_order=True)**
|
|
364
|
-
- Normaliza um valor arbitrário em uma lista de inteiros.
|
|
365
|
-
- Suporta: None, int, str (extrai números), list/tuple (recursivo).
|
|
366
|
-
- Ignora valores inválidos.
|
|
367
|
-
- Deduplica e mantém ordem por padrão.
|
|
368
|
-
- Exemplo:
|
|
369
|
-
```python
|
|
370
|
-
from biatoolkit.validation.validation import BiaValidation
|
|
371
|
-
BiaValidation.parse_int_list("SKU=300231 x2") # [300231, 2]
|
|
372
|
-
BiaValidation.parse_int_list([1, 2, 1, 3], dedupe=False) # [1, 2, 1, 3]
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
- **BiaValidation.sanitize_like(value, max_len=80, upper=True)**
|
|
376
|
-
- Sanitiza texto para uso seguro em filtros LIKE/search SQL.
|
|
377
|
-
- Remove caracteres fora da allowlist, limita tamanho, escapa aspas simples, %, _ e normaliza espaços.
|
|
378
|
-
- Converte para maiúsculas por padrão.
|
|
379
|
-
- Exemplo:
|
|
380
|
-
```python
|
|
381
|
-
from biatoolkit.validation.validation import BiaValidation
|
|
382
|
-
BiaValidation.sanitize_like("O'Reilly") # "O''REILLY"
|
|
383
|
-
BiaValidation.sanitize_like("100%_OK") # "100\\%\\_OK"
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
### Coerção de Dados (`biatoolkit.validation.coercion`)
|
|
388
|
-
|
|
389
|
-
Utilize a classe **BiaCoercion** para acessar as funções de coerção de forma padronizada:
|
|
390
|
-
|
|
391
|
-
- **BiaCoercion.ensure_list(value)**
|
|
392
|
-
- Garante que o valor seja retornado como lista.
|
|
393
|
-
- None → [], list → list, tuple/set → list, dict → [dict], outro → [valor].
|
|
394
|
-
- Exemplo:
|
|
395
|
-
```python
|
|
396
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
397
|
-
BiaCoercion.ensure_list(None) # []
|
|
398
|
-
BiaCoercion.ensure_list({"a": 1}) # [{"a": 1}]
|
|
399
|
-
BiaCoercion.ensure_list(5) # [5]
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
- **BiaCoercion.unwrap_dollar_value(value)**
|
|
403
|
-
- Desembrulha valores no formato {"$": ...} (comum em integrações legadas).
|
|
404
|
-
- Exemplo:
|
|
405
|
-
```python
|
|
406
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
407
|
-
BiaCoercion.unwrap_dollar_value({"$": 123}) # 123
|
|
408
|
-
BiaCoercion.unwrap_dollar_value("abc") # "abc"
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
- **BiaCoercion.to_int(value, default=0)**
|
|
412
|
-
- Converte valor para int de forma segura.
|
|
413
|
-
- None, "", bool, NaN/inf → default.
|
|
414
|
-
- Aceita strings numéricas, floats (trunca), etc.
|
|
415
|
-
- Exemplo:
|
|
416
|
-
```python
|
|
417
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
418
|
-
BiaCoercion.to_int(" 42 ") # 42
|
|
419
|
-
BiaCoercion.to_int(None, default=-1) # -1
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
- **BiaCoercion.to_float(value, default=0.0)**
|
|
423
|
-
- Converte valor para float de forma segura.
|
|
424
|
-
- None, "", bool, NaN/inf → default.
|
|
425
|
-
- Aceita strings com vírgula decimal.
|
|
426
|
-
- Exemplo:
|
|
427
|
-
```python
|
|
428
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
429
|
-
BiaCoercion.to_float("12,34") # 12.34
|
|
430
|
-
BiaCoercion.to_float("abc", default=-1.0) # -1.0
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
Essas funções são úteis para garantir robustez e previsibilidade ao tratar dados vindos de múltiplas fontes, reduzindo erros e if/else espalhados pelo código.
|
|
435
|
-
|
|
436
443
|
---
|
|
437
444
|
|
|
438
445
|
## Integração com Sankhya (`biatoolkit.sankhya_call`)
|
|
@@ -271,6 +271,7 @@ class Sankhya:
|
|
|
271
271
|
|
|
272
272
|
# Resolve o token de sessão (JSESSIONID)
|
|
273
273
|
sid = self._resolve_jsessionid(jsessionid)
|
|
274
|
+
|
|
274
275
|
# Para mgeSession na query, usar só a primeira parte antes do ponto
|
|
275
276
|
sid_query = sid.split(".", 1)[0] if "." in sid else sid
|
|
276
277
|
|
|
@@ -281,6 +282,7 @@ class Sankhya:
|
|
|
281
282
|
query_parts.append(f"mgeSession={sid_query}")
|
|
282
283
|
final_query = "&".join(query_parts)
|
|
283
284
|
|
|
285
|
+
|
|
284
286
|
# Monta a URL final da requisição
|
|
285
287
|
final_url = build_url(url=url, query=final_query, base_url=base_url)
|
|
286
288
|
print("FINAL URL:", final_url)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: biatoolkit
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.4
|
|
4
4
|
Summary: Biblioteca para desenvolvedores que utilizam o BiaAgentBuilder
|
|
5
5
|
Author: Bia Platform Team
|
|
6
6
|
Author-email: data.platform@sankhya.com.br
|
|
@@ -37,7 +37,6 @@ A classe `BiaClient` encapsula um cliente HTTP assíncrono para comunicação co
|
|
|
37
37
|
(Model Context Protocol).
|
|
38
38
|
|
|
39
39
|
Ela esconde toda a complexidade de:
|
|
40
|
-
- Conexão HTTP streamable
|
|
41
40
|
- Inicialização de sessões MCP
|
|
42
41
|
- Execução de tools
|
|
43
42
|
|
|
@@ -49,7 +48,6 @@ Ela esconde toda a complexidade de:
|
|
|
49
48
|
- **call_tool(tool_name, params=None)**
|
|
50
49
|
- Executa uma ferramenta específica disponível no servidor MCP.
|
|
51
50
|
|
|
52
|
-
---
|
|
53
51
|
|
|
54
52
|
### BiaUtil
|
|
55
53
|
|
|
@@ -64,7 +62,6 @@ permitindo acesso fácil a:
|
|
|
64
62
|
- Recebe uma instância de `FastMCP` para acessar o contexto da requisição atual.
|
|
65
63
|
|
|
66
64
|
- **get_header()**
|
|
67
|
-
- Extrai e retorna os headers customizados do runtime.
|
|
68
65
|
- Retorna um objeto `Header` com os campos:
|
|
69
66
|
- `current_host`: Host do ERP no qual o copilot está em execução.
|
|
70
67
|
- `user_email`: Email do usuário autenticado.
|
|
@@ -75,7 +72,6 @@ permitindo acesso fácil a:
|
|
|
75
72
|
- `iam_user_id`: ID do usuário do BIA IAM.
|
|
76
73
|
- `gateway_token`: Token primário do Sankhya API Gateway.
|
|
77
74
|
|
|
78
|
-
- **get_parameter(parameter_name)**
|
|
79
75
|
- Recupera parâmetros sensíveis seguindo a ordem:
|
|
80
76
|
1. Variáveis de ambiente do sistema
|
|
81
77
|
2. AWS SSM Parameter Store (fallback)
|
|
@@ -84,7 +80,6 @@ permitindo acesso fácil a:
|
|
|
84
80
|
- O SSM só é consultado se o parâmetro **não existir** nas variáveis de ambiente.
|
|
85
81
|
- Em produção, a busca no SSM depende do header
|
|
86
82
|
`X-Amzn-Bedrock-AgentCore-Runtime-Custom-prefix`.
|
|
87
|
-
- Se esse header não estiver presente, o método retorna `None`.
|
|
88
83
|
|
|
89
84
|
---
|
|
90
85
|
|
|
@@ -95,7 +90,6 @@ Nesta seção você encontrará uma breve descrição de como utilizar os princi
|
|
|
95
90
|
### **Criando um MCP Server**
|
|
96
91
|
|
|
97
92
|
Primeiro, instale os pacotes **MCP** e **Bia Toolkit**.
|
|
98
|
-
|
|
99
93
|
```bash
|
|
100
94
|
pip install mcp biatoolkit
|
|
101
95
|
```
|
|
@@ -108,9 +102,107 @@ import json
|
|
|
108
102
|
|
|
109
103
|
mcp = FastMCP(host="0.0.0.0", stateless_http=True)
|
|
110
104
|
|
|
111
|
-
@mcp.tool()
|
|
112
105
|
def listar() -> str:
|
|
113
|
-
|
|
106
|
+
|
|
107
|
+
O Bia Toolkit oferece integração pronta para consumo de serviços HTTP da plataforma Sankhya (ou gateway), com autenticação via JSESSIONID e configuração de timeouts/retries via variáveis de ambiente.
|
|
108
|
+
|
|
109
|
+
### Objetivo
|
|
110
|
+
|
|
111
|
+
- Facilitar chamadas autenticadas a serviços Sankhya sem que o desenvolvedor precise lidar com autenticação, headers ou gerenciamento de sessão HTTP.
|
|
112
|
+
- Fornecer métodos prontos para chamadas genéricas (`call_json`) e para consultas a views (`load_view`).
|
|
113
|
+
- Permitir uso estático compatível com scaffolds legados via `Sankhya.Call(...)`.
|
|
114
|
+
|
|
115
|
+
### Configuração
|
|
116
|
+
|
|
117
|
+
- O caminho do serviço (`/mge/service.sbr`) é fixo no toolkit.
|
|
118
|
+
- O parâmetro `base_url` é obrigatório e pode ser passado explicitamente ou extraído automaticamente do header do runtime (`current_host` via `BiaUtil`).
|
|
119
|
+
- Não existe mais configuração via variável de ambiente para base_url ou service_path.
|
|
120
|
+
- As variáveis de ambiente opcionais são apenas para timeout, retries e SSL:
|
|
121
|
+
- `SANKHYA_TIMEOUT_CONNECT`: timeout de conexão (default: 3.05)
|
|
122
|
+
- `SANKHYA_TIMEOUT_READ`: timeout de leitura (default: 12)
|
|
123
|
+
- `SANKHYA_RETRIES_TOTAL`: número de tentativas em falha (default: 3)
|
|
124
|
+
- `SANKHYA_RETRY_BACKOFF`: backoff entre tentativas (default: 0.5)
|
|
125
|
+
- `SANKHYA_VERIFY_SSL`: se valida SSL (default: "1")
|
|
126
|
+
|
|
127
|
+
### Principais classes e métodos
|
|
128
|
+
|
|
129
|
+
- **SankhyaSettings**: Dataclass de configuração de timeouts/retries/SSL. Use `SankhyaSettings.from_env()` para obter as configurações do ambiente.
|
|
130
|
+
- **Sankhya**: Classe principal de integração. Permite instanciar com contexto MCP (`FastMCP`) ou usar métodos estáticos.
|
|
131
|
+
- `call_json(...)`: Realiza chamada HTTP autenticada, retorna JSON. Veja detalhes dos parâmetros abaixo.
|
|
132
|
+
- `load_view(...)`: Helper para consultas a views Sankhya (`CRUDServiceProvider.loadView`). Veja detalhes dos parâmetros abaixo.
|
|
133
|
+
- `Call(...)`: Método estático compatível com scaffolds legados. Veja detalhes dos parâmetros abaixo.
|
|
134
|
+
### Parâmetros dos métodos principais
|
|
135
|
+
|
|
136
|
+
#### `call_json`
|
|
137
|
+
|
|
138
|
+
| Parâmetro | Obrigatório | Descrição |
|
|
139
|
+
|-------------------|-------------|-----------|
|
|
140
|
+
| payload | Não | Dicionário enviado como corpo da requisição (POST). Pode ser None. |
|
|
141
|
+
| jsessionid | Não | Token de sessão JSESSIONID. Se não informado, tenta extrair do header do runtime (via MCP/BiaUtil). |
|
|
142
|
+
| url | Não | URL completa para chamada. Se informado, ignora base_url. |
|
|
143
|
+
| base_url | Sim* | Base URL do serviço Sankhya (ex: https://meu.sankhya.com.br). Obrigatório se não estiver em contexto MCP (header). |
|
|
144
|
+
| query | Não | Querystring adicional (ex: serviceName=...&outputType=json). |
|
|
145
|
+
| method | Não | "POST" (default) ou "GET". |
|
|
146
|
+
| extra_headers | Não | Dicionário de headers adicionais. |
|
|
147
|
+
| timeout | Não | Tupla (connect, read) para sobrescrever timeout padrão. |
|
|
148
|
+
| raise_for_http_error | Não | Se True (default), lança SankhyaHTTPError em erro HTTP. |
|
|
149
|
+
|
|
150
|
+
*Se não passar base_url, o método tentará extrair automaticamente do header do runtime (MCP) se disponível. Caso contrário, será obrigatório.
|
|
151
|
+
|
|
152
|
+
#### `load_view`
|
|
153
|
+
|
|
154
|
+
| Parâmetro | Obrigatório | Descrição |
|
|
155
|
+
|-------------------|-------------|-----------|
|
|
156
|
+
| view_name | Sim | Nome da view no Sankhya. |
|
|
157
|
+
| where_sql | Sim | Cláusula WHERE (string). |
|
|
158
|
+
| fields | Não | Campos a retornar (string). Default: "*". |
|
|
159
|
+
| jsessionid | Não | Token de sessão JSESSIONID. Se não informado, tenta extrair do header do runtime (via MCP/BiaUtil). |
|
|
160
|
+
| url | Não | URL completa opcional (override). |
|
|
161
|
+
| base_url | Não* | Base URL do serviço Sankhya. Se não informado, tenta extrair do header do runtime (current_host). |
|
|
162
|
+
| output_type | Não | "json" (default). |
|
|
163
|
+
| extra_headers | Não | Dicionário de headers adicionais. |
|
|
164
|
+
|
|
165
|
+
*Se não passar base_url, o método tentará extrair automaticamente do header do runtime (MCP) via BiaUtil. Caso não consiga, lança erro.
|
|
166
|
+
|
|
167
|
+
#### `Call`
|
|
168
|
+
|
|
169
|
+
| Parâmetro | Obrigatório | Descrição |
|
|
170
|
+
|-------------------|-------------|-----------|
|
|
171
|
+
| jsessionID | Não | Token de sessão JSESSIONID. Se não informado, tenta extrair do header do runtime (via MCP/BiaUtil). |
|
|
172
|
+
| payload | Não | Dicionário enviado como corpo da requisição. |
|
|
173
|
+
| mcp | Não | Instância opcional do FastMCP para contexto do runtime. |
|
|
174
|
+
| url | Não | URL completa (opcional). |
|
|
175
|
+
| base_url | Sim* | Base URL do serviço Sankhya. Obrigatório se não estiver em contexto MCP (header). |
|
|
176
|
+
| query | Não | Querystring adicional (opcional). |
|
|
177
|
+
| method | Não | "POST" (default) ou "GET". |
|
|
178
|
+
| extra_headers | Não | Dicionário de headers adicionais. |
|
|
179
|
+
|
|
180
|
+
*Se não passar base_url, o método tentará extrair automaticamente do header do runtime (MCP) se disponível. Caso contrário, será obrigatório.
|
|
181
|
+
|
|
182
|
+
**Resumo:** Sempre que possível, o toolkit resolve automaticamente base_url e jsessionid do contexto MCP (headers). Se não estiver rodando em MCP, passe base_url explicitamente.
|
|
183
|
+
- **SankhyaHTTPError**: Exceção lançada em caso de erro HTTP (status != 200), contendo status_code e response_text.
|
|
184
|
+
|
|
185
|
+
### Exemplo de uso (instanciado)
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
from biatoolkit.sankhya_call import Sankhya
|
|
189
|
+
sk = Sankhya(mcp=mcp)
|
|
190
|
+
result = sk.load_view("BIA_VW_MB_RULES", "CODPROD_A = 123", fields="*")
|
|
191
|
+
# O base_url será extraído automaticamente do header do runtime (current_host)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Exemplo de uso (estático)
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
from biatoolkit.sankhya_call import Sankhya
|
|
198
|
+
result = Sankhya.Call(jsessionID="...", payload={...}, base_url="https://meu.sankhya.com.br", query="serviceName=...&outputType=json")
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Observações
|
|
202
|
+
|
|
203
|
+
- O JSESSIONID pode ser passado explicitamente ou extraído automaticamente do header do runtime (se rodando em MCP Server).
|
|
204
|
+
- O método `load_view` facilita consultas a views Sankhya, montando o payload e a querystring automaticamente, e resolve o base_url do header se não for passado.
|
|
205
|
+
- O método `call_json` permite chamadas genéricas a qualquer serviço Sankhya, com controle total sobre headers, método HTTP, payload e querystring, mas exige base_url explícito se não estiver em contexto MCP.
|
|
114
206
|
exemplo = {
|
|
115
207
|
"itens": [
|
|
116
208
|
{"id": 1, "nome": "Item 1"},
|
|
@@ -348,91 +440,6 @@ O método `get_parameter(parameter_name: str)` busca o parâmetro informado em d
|
|
|
348
440
|
- Um arquivo `.env` para testes locais.
|
|
349
441
|
- No cofre de segredos do Bia Agent Builder para usar em ambiente produtivo.
|
|
350
442
|
|
|
351
|
-
|
|
352
|
-
---
|
|
353
|
-
|
|
354
|
-
## Validação e Coerção de Dados
|
|
355
|
-
|
|
356
|
-
O Bia Toolkit oferece funções utilitárias para normalização, sanitização e coerção de dados, facilitando o consumo seguro de entradas vindas de APIs, headers, payloads e integrações legadas.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
### Validação de Dados (`biatoolkit.validation.validation`)
|
|
360
|
-
|
|
361
|
-
Utilize a classe **BiaValidation** para acessar as funções de validação de forma padronizada:
|
|
362
|
-
|
|
363
|
-
- **BiaValidation.parse_int_list(value, dedupe=True, keep_order=True)**
|
|
364
|
-
- Normaliza um valor arbitrário em uma lista de inteiros.
|
|
365
|
-
- Suporta: None, int, str (extrai números), list/tuple (recursivo).
|
|
366
|
-
- Ignora valores inválidos.
|
|
367
|
-
- Deduplica e mantém ordem por padrão.
|
|
368
|
-
- Exemplo:
|
|
369
|
-
```python
|
|
370
|
-
from biatoolkit.validation.validation import BiaValidation
|
|
371
|
-
BiaValidation.parse_int_list("SKU=300231 x2") # [300231, 2]
|
|
372
|
-
BiaValidation.parse_int_list([1, 2, 1, 3], dedupe=False) # [1, 2, 1, 3]
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
- **BiaValidation.sanitize_like(value, max_len=80, upper=True)**
|
|
376
|
-
- Sanitiza texto para uso seguro em filtros LIKE/search SQL.
|
|
377
|
-
- Remove caracteres fora da allowlist, limita tamanho, escapa aspas simples, %, _ e normaliza espaços.
|
|
378
|
-
- Converte para maiúsculas por padrão.
|
|
379
|
-
- Exemplo:
|
|
380
|
-
```python
|
|
381
|
-
from biatoolkit.validation.validation import BiaValidation
|
|
382
|
-
BiaValidation.sanitize_like("O'Reilly") # "O''REILLY"
|
|
383
|
-
BiaValidation.sanitize_like("100%_OK") # "100\\%\\_OK"
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
### Coerção de Dados (`biatoolkit.validation.coercion`)
|
|
388
|
-
|
|
389
|
-
Utilize a classe **BiaCoercion** para acessar as funções de coerção de forma padronizada:
|
|
390
|
-
|
|
391
|
-
- **BiaCoercion.ensure_list(value)**
|
|
392
|
-
- Garante que o valor seja retornado como lista.
|
|
393
|
-
- None → [], list → list, tuple/set → list, dict → [dict], outro → [valor].
|
|
394
|
-
- Exemplo:
|
|
395
|
-
```python
|
|
396
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
397
|
-
BiaCoercion.ensure_list(None) # []
|
|
398
|
-
BiaCoercion.ensure_list({"a": 1}) # [{"a": 1}]
|
|
399
|
-
BiaCoercion.ensure_list(5) # [5]
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
- **BiaCoercion.unwrap_dollar_value(value)**
|
|
403
|
-
- Desembrulha valores no formato {"$": ...} (comum em integrações legadas).
|
|
404
|
-
- Exemplo:
|
|
405
|
-
```python
|
|
406
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
407
|
-
BiaCoercion.unwrap_dollar_value({"$": 123}) # 123
|
|
408
|
-
BiaCoercion.unwrap_dollar_value("abc") # "abc"
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
- **BiaCoercion.to_int(value, default=0)**
|
|
412
|
-
- Converte valor para int de forma segura.
|
|
413
|
-
- None, "", bool, NaN/inf → default.
|
|
414
|
-
- Aceita strings numéricas, floats (trunca), etc.
|
|
415
|
-
- Exemplo:
|
|
416
|
-
```python
|
|
417
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
418
|
-
BiaCoercion.to_int(" 42 ") # 42
|
|
419
|
-
BiaCoercion.to_int(None, default=-1) # -1
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
- **BiaCoercion.to_float(value, default=0.0)**
|
|
423
|
-
- Converte valor para float de forma segura.
|
|
424
|
-
- None, "", bool, NaN/inf → default.
|
|
425
|
-
- Aceita strings com vírgula decimal.
|
|
426
|
-
- Exemplo:
|
|
427
|
-
```python
|
|
428
|
-
from biatoolkit.validation.coercion import BiaCoercion
|
|
429
|
-
BiaCoercion.to_float("12,34") # 12.34
|
|
430
|
-
BiaCoercion.to_float("abc", default=-1.0) # -1.0
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
Essas funções são úteis para garantir robustez e previsibilidade ao tratar dados vindos de múltiplas fontes, reduzindo erros e if/else espalhados pelo código.
|
|
435
|
-
|
|
436
443
|
---
|
|
437
444
|
|
|
438
445
|
## Integração com Sankhya (`biatoolkit.sankhya_call`)
|
|
@@ -11,7 +11,4 @@ biatoolkit.egg-info/SOURCES.txt
|
|
|
11
11
|
biatoolkit.egg-info/dependency_links.txt
|
|
12
12
|
biatoolkit.egg-info/top_level.txt
|
|
13
13
|
biatoolkit/schema/__init__.py
|
|
14
|
-
biatoolkit/schema/header.py
|
|
15
|
-
biatoolkit/validation/__init__.py
|
|
16
|
-
biatoolkit/validation/coercion.py
|
|
17
|
-
biatoolkit/validation/validation.py
|
|
14
|
+
biatoolkit/schema/header.py
|
|
File without changes
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
# biatoolkit/validation/coercion.py
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import Any, Iterable, Mapping, Optional
|
|
6
|
-
import math
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def ensure_list(value: Any) -> list:
|
|
10
|
-
"""
|
|
11
|
-
Normaliza um valor para sempre retornar uma lista.
|
|
12
|
-
|
|
13
|
-
Regras:
|
|
14
|
-
- None -> []
|
|
15
|
-
- list -> a própria lista
|
|
16
|
-
- tuple/set -> list(value)
|
|
17
|
-
- dict (ou Mapping) -> [value] (não "explode" dict em chaves)
|
|
18
|
-
- qualquer outro -> [value]
|
|
19
|
-
|
|
20
|
-
Por que existe:
|
|
21
|
-
- Muitas APIs retornam ora um item único (dict), ora uma lista.
|
|
22
|
-
- Este helper padroniza o consumo e reduz if/else espalhado.
|
|
23
|
-
|
|
24
|
-
Args:
|
|
25
|
-
value: qualquer valor.
|
|
26
|
-
|
|
27
|
-
Returns:
|
|
28
|
-
list: lista normalizada.
|
|
29
|
-
"""
|
|
30
|
-
if value is None:
|
|
31
|
-
return []
|
|
32
|
-
|
|
33
|
-
if isinstance(value, list):
|
|
34
|
-
return value
|
|
35
|
-
|
|
36
|
-
if isinstance(value, (tuple, set)):
|
|
37
|
-
return list(value)
|
|
38
|
-
|
|
39
|
-
# Dict/Mapping deve ser tratado como item único, não iterável de chaves.
|
|
40
|
-
if isinstance(value, Mapping):
|
|
41
|
-
return [value]
|
|
42
|
-
|
|
43
|
-
return [value]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def unwrap_dollar_value(value: Any) -> Any:
|
|
47
|
-
"""
|
|
48
|
-
"Desembrulha" valores no formato {"$": "..."} (comum em integrações legadas).
|
|
49
|
-
|
|
50
|
-
Exemplo:
|
|
51
|
-
{"$": "123"} -> "123"
|
|
52
|
-
{"$": 123} -> 123
|
|
53
|
-
|
|
54
|
-
Se não for dict com a chave "$", retorna o valor original.
|
|
55
|
-
|
|
56
|
-
Args:
|
|
57
|
-
value: valor de entrada.
|
|
58
|
-
|
|
59
|
-
Returns:
|
|
60
|
-
Any: valor desembrulhado ou original.
|
|
61
|
-
"""
|
|
62
|
-
if isinstance(value, dict) and "$" in value:
|
|
63
|
-
return value.get("$")
|
|
64
|
-
return value
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def to_int(value: Any, default: int = 0) -> int:
|
|
68
|
-
"""
|
|
69
|
-
Converte um valor para int de forma segura.
|
|
70
|
-
|
|
71
|
-
Regras:
|
|
72
|
-
- None / "" -> default
|
|
73
|
-
- strings com espaços são aceitas (" 12 ")
|
|
74
|
-
- strings numéricas com sinal são aceitas ("-3")
|
|
75
|
-
- floats numéricos -> int(value) (trunca)
|
|
76
|
-
- NaN/inf -> default
|
|
77
|
-
|
|
78
|
-
Obs:
|
|
79
|
-
- Não tenta "extrair número do meio do texto" (isso é responsabilidade
|
|
80
|
-
de parse específico, ex: parse_int_list).
|
|
81
|
-
|
|
82
|
-
Args:
|
|
83
|
-
value: valor a converter.
|
|
84
|
-
default: fallback.
|
|
85
|
-
|
|
86
|
-
Returns:
|
|
87
|
-
int: convertido ou default.
|
|
88
|
-
"""
|
|
89
|
-
try:
|
|
90
|
-
if value is None:
|
|
91
|
-
return default
|
|
92
|
-
|
|
93
|
-
if isinstance(value, bool):
|
|
94
|
-
# Evita True->1 / False->0 de forma "surpresa"
|
|
95
|
-
return default
|
|
96
|
-
|
|
97
|
-
if isinstance(value, str):
|
|
98
|
-
s = value.strip()
|
|
99
|
-
if s == "":
|
|
100
|
-
return default
|
|
101
|
-
return int(s)
|
|
102
|
-
|
|
103
|
-
if isinstance(value, float):
|
|
104
|
-
if math.isnan(value) or math.isinf(value):
|
|
105
|
-
return default
|
|
106
|
-
return int(value)
|
|
107
|
-
|
|
108
|
-
return int(value)
|
|
109
|
-
except (TypeError, ValueError):
|
|
110
|
-
return default
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
def to_float(value: Any, default: float = 0.0) -> float:
|
|
114
|
-
"""
|
|
115
|
-
Converte um valor para float de forma segura.
|
|
116
|
-
|
|
117
|
-
Regras:
|
|
118
|
-
- None / "" -> default
|
|
119
|
-
- aceita strings com vírgula decimal ("12,34")
|
|
120
|
-
- NaN/inf -> default
|
|
121
|
-
|
|
122
|
-
Args:
|
|
123
|
-
value: valor a converter.
|
|
124
|
-
default: fallback.
|
|
125
|
-
|
|
126
|
-
Returns:
|
|
127
|
-
float: convertido ou default.
|
|
128
|
-
"""
|
|
129
|
-
try:
|
|
130
|
-
if value is None:
|
|
131
|
-
return default
|
|
132
|
-
|
|
133
|
-
if isinstance(value, bool):
|
|
134
|
-
return default
|
|
135
|
-
|
|
136
|
-
if isinstance(value, str):
|
|
137
|
-
s = value.strip()
|
|
138
|
-
if s == "":
|
|
139
|
-
return default
|
|
140
|
-
s = s.replace(",", ".")
|
|
141
|
-
v = float(s)
|
|
142
|
-
else:
|
|
143
|
-
v = float(value)
|
|
144
|
-
|
|
145
|
-
if math.isnan(v) or math.isinf(v):
|
|
146
|
-
return default
|
|
147
|
-
|
|
148
|
-
return v
|
|
149
|
-
except (TypeError, ValueError):
|
|
150
|
-
return default
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
# Classe fachada para coerção
|
|
156
|
-
class BiaCoercion:
|
|
157
|
-
"""
|
|
158
|
-
Fachada estática para funções de coerção do Bia Toolkit.
|
|
159
|
-
Permite referenciar e utilizar as utilidades de coerção de forma padronizada.
|
|
160
|
-
"""
|
|
161
|
-
@staticmethod
|
|
162
|
-
def ensure_list(*args, **kwargs):
|
|
163
|
-
return ensure_list(*args, **kwargs)
|
|
164
|
-
|
|
165
|
-
@staticmethod
|
|
166
|
-
def unwrap_dollar_value(*args, **kwargs):
|
|
167
|
-
return unwrap_dollar_value(*args, **kwargs)
|
|
168
|
-
|
|
169
|
-
@staticmethod
|
|
170
|
-
def to_int(*args, **kwargs):
|
|
171
|
-
return to_int(*args, **kwargs)
|
|
172
|
-
|
|
173
|
-
@staticmethod
|
|
174
|
-
def to_float(*args, **kwargs):
|
|
175
|
-
return to_float(*args, **kwargs)
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# biatoolkit/validation.py
|
|
2
|
-
|
|
3
|
-
from typing import Any, Iterable
|
|
4
|
-
import re
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def parse_int_list(
|
|
8
|
-
value: Any,
|
|
9
|
-
*,
|
|
10
|
-
dedupe: bool = True,
|
|
11
|
-
keep_order: bool = True,
|
|
12
|
-
) -> list[int]:
|
|
13
|
-
"""
|
|
14
|
-
Normaliza um valor arbitrário em uma lista de inteiros.
|
|
15
|
-
|
|
16
|
-
Casos suportados:
|
|
17
|
-
- None -> []
|
|
18
|
-
- int -> [int]
|
|
19
|
-
- str -> extrai números (ex: "100, 200" / "SKU=300231 x2")
|
|
20
|
-
- list/tuple -> processa cada item recursivamente
|
|
21
|
-
|
|
22
|
-
Comportamento:
|
|
23
|
-
- Ignora valores inválidos
|
|
24
|
-
- Deduplica por padrão
|
|
25
|
-
- Mantém a ordem de aparição por padrão
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
value: Valor de entrada (None, int, str, list, etc.)
|
|
29
|
-
dedupe: Remove valores duplicados.
|
|
30
|
-
keep_order: Mantém a ordem original dos valores.
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
list[int]: Lista normalizada de inteiros.
|
|
34
|
-
"""
|
|
35
|
-
if value is None:
|
|
36
|
-
return []
|
|
37
|
-
|
|
38
|
-
# Normaliza para iterável
|
|
39
|
-
if isinstance(value, (list, tuple, set)):
|
|
40
|
-
raw: Iterable[Any] = value
|
|
41
|
-
else:
|
|
42
|
-
raw = [value]
|
|
43
|
-
|
|
44
|
-
numbers: list[int] = []
|
|
45
|
-
|
|
46
|
-
for item in raw:
|
|
47
|
-
if item is None:
|
|
48
|
-
continue
|
|
49
|
-
|
|
50
|
-
# Inteiro direto
|
|
51
|
-
if isinstance(item, int):
|
|
52
|
-
numbers.append(item)
|
|
53
|
-
continue
|
|
54
|
-
|
|
55
|
-
# String ou outros tipos
|
|
56
|
-
text = str(item)
|
|
57
|
-
matches = re.findall(r"\d+", text)
|
|
58
|
-
for m in matches:
|
|
59
|
-
try:
|
|
60
|
-
numbers.append(int(m))
|
|
61
|
-
except ValueError:
|
|
62
|
-
continue
|
|
63
|
-
|
|
64
|
-
if not dedupe:
|
|
65
|
-
return numbers
|
|
66
|
-
|
|
67
|
-
if keep_order:
|
|
68
|
-
seen = set()
|
|
69
|
-
ordered: list[int] = []
|
|
70
|
-
for n in numbers:
|
|
71
|
-
if n not in seen:
|
|
72
|
-
seen.add(n)
|
|
73
|
-
ordered.append(n)
|
|
74
|
-
return ordered
|
|
75
|
-
|
|
76
|
-
return list(set(numbers))
|
|
77
|
-
|
|
78
|
-
def sanitize_like(
|
|
79
|
-
value: str,
|
|
80
|
-
*,
|
|
81
|
-
max_len: int = 80,
|
|
82
|
-
upper: bool = True,
|
|
83
|
-
) -> str:
|
|
84
|
-
"""
|
|
85
|
-
Sanitiza um texto para uso seguro em filtros do tipo LIKE/search.
|
|
86
|
-
|
|
87
|
-
Regras aplicadas:
|
|
88
|
-
- Remove caracteres fora de uma allowlist básica
|
|
89
|
-
- Limita o tamanho do texto
|
|
90
|
-
- Escapa aspas simples
|
|
91
|
-
- Escapa curingas comuns (% e _)
|
|
92
|
-
- Converte para UPPER por padrão
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
value: Texto de entrada.
|
|
96
|
-
max_len: Tamanho máximo permitido.
|
|
97
|
-
upper: Converte o texto final para maiúsculas.
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
str: Texto sanitizado.
|
|
101
|
-
"""
|
|
102
|
-
if not value:
|
|
103
|
-
return ""
|
|
104
|
-
|
|
105
|
-
# Normaliza e corta tamanho
|
|
106
|
-
text = str(value).strip()[:max_len]
|
|
107
|
-
|
|
108
|
-
# Allowlist simples (letras, números, acentos, espaço e alguns símbolos, incluindo ', %, _)
|
|
109
|
-
# Mantém ', %, _ para escapá-los depois
|
|
110
|
-
text = re.sub(r"[^0-9A-Za-zÀ-ÿ\s\-\(\)\./'_%]", " ", text)
|
|
111
|
-
|
|
112
|
-
# Escapes básicos
|
|
113
|
-
text = text.replace("'", "''")
|
|
114
|
-
text = text.replace("%", r"\%" ).replace("_", r"\_")
|
|
115
|
-
|
|
116
|
-
# Normaliza espaços
|
|
117
|
-
text = re.sub(r"\s+", " ", text).strip()
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return text.upper() if upper else text
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
# Classe fachada para validação
|
|
124
|
-
class BiaValidation:
|
|
125
|
-
"""
|
|
126
|
-
Fachada estática para funções de validação do Bia Toolkit.
|
|
127
|
-
Permite referenciar e utilizar as utilidades de validação de forma padronizada.
|
|
128
|
-
"""
|
|
129
|
-
@staticmethod
|
|
130
|
-
def parse_int_list(*args, **kwargs):
|
|
131
|
-
return parse_int_list(*args, **kwargs)
|
|
132
|
-
|
|
133
|
-
@staticmethod
|
|
134
|
-
def sanitize_like(*args, **kwargs):
|
|
135
|
-
return sanitize_like(*args, **kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|