nia-etl-utils 0.2.1__py3-none-any.whl → 0.2.2__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.
- nia_etl_utils/__init__.py +32 -31
- nia_etl_utils/exceptions.py +25 -182
- nia_etl_utils/ocr.py +12 -86
- {nia_etl_utils-0.2.1.dist-info → nia_etl_utils-0.2.2.dist-info}/METADATA +4 -5
- {nia_etl_utils-0.2.1.dist-info → nia_etl_utils-0.2.2.dist-info}/RECORD +7 -7
- {nia_etl_utils-0.2.1.dist-info → nia_etl_utils-0.2.2.dist-info}/WHEEL +0 -0
- {nia_etl_utils-0.2.1.dist-info → nia_etl_utils-0.2.2.dist-info}/top_level.txt +0 -0
nia_etl_utils/__init__.py
CHANGED
|
@@ -20,8 +20,9 @@ Exemplo de uso:
|
|
|
20
20
|
conectar_postgresql_nia,
|
|
21
21
|
exportar_para_csv,
|
|
22
22
|
PostgresConfig,
|
|
23
|
+
ConexaoError,
|
|
24
|
+
OcrError,
|
|
23
25
|
)
|
|
24
|
-
from nia_etl_utils.exceptions import ConexaoError, ExtracaoVaziaError
|
|
25
26
|
|
|
26
27
|
# Configuração
|
|
27
28
|
configurar_logger_padrao_nia("meu_pipeline")
|
|
@@ -33,39 +34,25 @@ Exemplo de uso:
|
|
|
33
34
|
dados = conn.cursor.fetchall()
|
|
34
35
|
except ConexaoError as e:
|
|
35
36
|
logger.error(f"Falha na conexão: {e}")
|
|
36
|
-
sys.exit(1)
|
|
37
|
-
|
|
38
|
-
# Ou com configuração explícita (para testes)
|
|
39
|
-
config = PostgresConfig(
|
|
40
|
-
host="localhost",
|
|
41
|
-
port="5432",
|
|
42
|
-
database="teste",
|
|
43
|
-
user="user",
|
|
44
|
-
password="pass"
|
|
45
|
-
)
|
|
46
|
-
with conectar_postgresql(config) as conn:
|
|
47
|
-
# ...
|
|
37
|
+
sys.exit(1)
|
|
48
38
|
|
|
49
39
|
Exemplo de OCR:
|
|
50
40
|
|
|
51
|
-
from nia_etl_utils import executar_ocr
|
|
52
|
-
from nia_etl_utils.ocr import OcrError
|
|
41
|
+
from nia_etl_utils import executar_ocr, OcrError, OcrTimeoutError
|
|
53
42
|
|
|
54
43
|
try:
|
|
55
44
|
resultado = executar_ocr(blob_bytes, url_base="INTELLIDOC_URL")
|
|
56
45
|
texto = resultado["full_text"]
|
|
57
46
|
qualidade = resultado["overall_quality"]
|
|
47
|
+
except OcrTimeoutError as e:
|
|
48
|
+
logger.error(f"Timeout no OCR: {e}")
|
|
58
49
|
except OcrError as e:
|
|
59
50
|
logger.error(f"Falha no OCR: {e}")
|
|
60
51
|
"""
|
|
61
52
|
|
|
62
|
-
__version__ = "0.2.
|
|
53
|
+
__version__ = "0.2.2"
|
|
63
54
|
__author__ = "Nícolas Galdino Esmael"
|
|
64
55
|
|
|
65
|
-
# =============================================================================
|
|
66
|
-
# EXCEÇÕES - Importar primeiro para uso em type hints
|
|
67
|
-
# =============================================================================
|
|
68
|
-
|
|
69
56
|
# =============================================================================
|
|
70
57
|
# CONFIGURAÇÕES (Dataclasses)
|
|
71
58
|
# =============================================================================
|
|
@@ -76,8 +63,9 @@ from .config import (
|
|
|
76
63
|
SmtpConfig,
|
|
77
64
|
)
|
|
78
65
|
|
|
79
|
-
#
|
|
80
|
-
#
|
|
66
|
+
# =============================================================================
|
|
67
|
+
# DATABASE
|
|
68
|
+
# =============================================================================
|
|
81
69
|
from .database import (
|
|
82
70
|
conectar_oracle,
|
|
83
71
|
conectar_oracle_ouvidorias,
|
|
@@ -89,7 +77,9 @@ from .database import (
|
|
|
89
77
|
obter_engine_postgresql_opengeo,
|
|
90
78
|
)
|
|
91
79
|
|
|
92
|
-
#
|
|
80
|
+
# =============================================================================
|
|
81
|
+
# EMAIL
|
|
82
|
+
# =============================================================================
|
|
93
83
|
from .email_smtp import (
|
|
94
84
|
enviar_email,
|
|
95
85
|
enviar_email_smtp,
|
|
@@ -99,13 +89,16 @@ from .email_smtp import (
|
|
|
99
89
|
# =============================================================================
|
|
100
90
|
# FUNÇÕES UTILITÁRIAS
|
|
101
91
|
# =============================================================================
|
|
102
|
-
# Configuração de ambiente
|
|
103
92
|
from .env_config import (
|
|
104
93
|
obter_variavel_env,
|
|
105
94
|
obter_variavel_env_bool,
|
|
106
95
|
obter_variavel_env_int,
|
|
107
96
|
obter_variavel_env_lista,
|
|
108
97
|
)
|
|
98
|
+
|
|
99
|
+
# =============================================================================
|
|
100
|
+
# EXCEÇÕES
|
|
101
|
+
# =============================================================================
|
|
109
102
|
from .exceptions import (
|
|
110
103
|
# Arquivos
|
|
111
104
|
ArquivoError,
|
|
@@ -125,41 +118,44 @@ from .exceptions import (
|
|
|
125
118
|
LeituraArquivoError,
|
|
126
119
|
# Base
|
|
127
120
|
NiaEtlError,
|
|
121
|
+
# OCR
|
|
122
|
+
OcrError,
|
|
123
|
+
OcrProcessamentoError,
|
|
124
|
+
OcrSubmissaoError,
|
|
125
|
+
OcrTimeoutError,
|
|
128
126
|
ProcessamentoError,
|
|
129
127
|
SmtpError,
|
|
130
128
|
# Validação
|
|
131
129
|
ValidacaoError,
|
|
132
130
|
VariavelAmbienteError,
|
|
133
131
|
)
|
|
134
|
-
|
|
135
|
-
# Manipulação de arquivos
|
|
136
132
|
from .limpeza_pastas import (
|
|
137
133
|
criar_pasta_se_nao_existir,
|
|
138
134
|
limpar_pasta,
|
|
139
135
|
listar_arquivos,
|
|
140
136
|
remover_pasta_recursivamente,
|
|
141
137
|
)
|
|
142
|
-
|
|
143
|
-
# Logging
|
|
144
138
|
from .logger_config import (
|
|
145
139
|
configurar_logger,
|
|
146
140
|
configurar_logger_padrao_nia,
|
|
147
141
|
remover_handlers_existentes,
|
|
148
142
|
)
|
|
149
143
|
|
|
144
|
+
# =============================================================================
|
|
150
145
|
# OCR
|
|
146
|
+
# =============================================================================
|
|
151
147
|
from .ocr import (
|
|
152
148
|
executar_ocr,
|
|
153
149
|
)
|
|
154
150
|
|
|
155
|
-
#
|
|
151
|
+
# =============================================================================
|
|
152
|
+
# CSV
|
|
153
|
+
# =============================================================================
|
|
156
154
|
from .processa_csv import (
|
|
157
155
|
exportar_multiplos_csv,
|
|
158
156
|
exportar_para_csv,
|
|
159
157
|
extrair_e_exportar_csv,
|
|
160
158
|
)
|
|
161
|
-
|
|
162
|
-
# Processamento CSV Paralelo
|
|
163
159
|
from .processa_csv_paralelo import (
|
|
164
160
|
calcular_chunksize,
|
|
165
161
|
processar_csv_paralelo,
|
|
@@ -204,6 +200,11 @@ __all__ = [
|
|
|
204
200
|
"EmailError",
|
|
205
201
|
"DestinatarioError",
|
|
206
202
|
"SmtpError",
|
|
203
|
+
# Exceções - OCR
|
|
204
|
+
"OcrError",
|
|
205
|
+
"OcrSubmissaoError",
|
|
206
|
+
"OcrProcessamentoError",
|
|
207
|
+
"OcrTimeoutError",
|
|
207
208
|
# Exceções - Validação
|
|
208
209
|
"ValidacaoError",
|
|
209
210
|
# Configurações
|
nia_etl_utils/exceptions.py
CHANGED
|
@@ -27,23 +27,22 @@ Hierarquia:
|
|
|
27
27
|
Examples:
|
|
28
28
|
Capturando erros específicos:
|
|
29
29
|
|
|
30
|
-
>>> from nia_etl_utils
|
|
30
|
+
>>> from nia_etl_utils import ConexaoError, OcrTimeoutError
|
|
31
31
|
>>>
|
|
32
32
|
>>> try:
|
|
33
|
-
...
|
|
34
|
-
... except
|
|
35
|
-
... logger.error(f"
|
|
36
|
-
... # tratamento específico
|
|
33
|
+
... resultado = executar_ocr(documento)
|
|
34
|
+
... except OcrTimeoutError as e:
|
|
35
|
+
... logger.error(f"Timeout no OCR: {e}")
|
|
37
36
|
|
|
38
37
|
Capturando qualquer erro do pacote:
|
|
39
38
|
|
|
40
|
-
>>> from nia_etl_utils
|
|
39
|
+
>>> from nia_etl_utils import NiaEtlError
|
|
41
40
|
>>>
|
|
42
41
|
>>> try:
|
|
43
42
|
... executar_pipeline()
|
|
44
43
|
... except NiaEtlError as e:
|
|
45
44
|
... logger.error(f"Erro no pipeline: {e}")
|
|
46
|
-
... sys.exit(1)
|
|
45
|
+
... sys.exit(1)
|
|
47
46
|
"""
|
|
48
47
|
|
|
49
48
|
|
|
@@ -84,30 +83,13 @@ class NiaEtlError(Exception):
|
|
|
84
83
|
|
|
85
84
|
|
|
86
85
|
class ConfiguracaoError(NiaEtlError):
|
|
87
|
-
"""Erro de configuração do sistema.
|
|
88
|
-
|
|
89
|
-
Levantado quando há problemas com configurações necessárias
|
|
90
|
-
para o funcionamento do pacote.
|
|
91
|
-
|
|
92
|
-
Examples:
|
|
93
|
-
>>> raise ConfiguracaoError("Configuração inválida para conexão")
|
|
94
|
-
"""
|
|
86
|
+
"""Erro de configuração do sistema."""
|
|
95
87
|
|
|
96
88
|
pass
|
|
97
89
|
|
|
98
90
|
|
|
99
91
|
class VariavelAmbienteError(ConfiguracaoError):
|
|
100
|
-
"""Variável de ambiente ausente ou inválida.
|
|
101
|
-
|
|
102
|
-
Levantado quando uma variável de ambiente obrigatória não está
|
|
103
|
-
definida e nenhum valor padrão foi fornecido.
|
|
104
|
-
|
|
105
|
-
Attributes:
|
|
106
|
-
nome_variavel: Nome da variável de ambiente que causou o erro.
|
|
107
|
-
|
|
108
|
-
Examples:
|
|
109
|
-
>>> raise VariavelAmbienteError("DB_HOST")
|
|
110
|
-
"""
|
|
92
|
+
"""Variável de ambiente ausente ou inválida."""
|
|
111
93
|
|
|
112
94
|
def __init__(self, nome_variavel: str):
|
|
113
95
|
self.nome_variavel = nome_variavel
|
|
@@ -124,28 +106,13 @@ class VariavelAmbienteError(ConfiguracaoError):
|
|
|
124
106
|
|
|
125
107
|
|
|
126
108
|
class DatabaseError(NiaEtlError):
|
|
127
|
-
"""Erro base para operações de banco de dados.
|
|
128
|
-
|
|
129
|
-
Examples:
|
|
130
|
-
>>> raise DatabaseError("Falha na operação de banco de dados")
|
|
131
|
-
"""
|
|
109
|
+
"""Erro base para operações de banco de dados."""
|
|
132
110
|
|
|
133
111
|
pass
|
|
134
112
|
|
|
135
113
|
|
|
136
114
|
class ConexaoError(DatabaseError):
|
|
137
|
-
"""Falha ao estabelecer conexão com banco de dados.
|
|
138
|
-
|
|
139
|
-
Levantado quando não é possível conectar ao banco de dados,
|
|
140
|
-
seja por credenciais inválidas, host inacessível ou outros
|
|
141
|
-
problemas de conectividade.
|
|
142
|
-
|
|
143
|
-
Examples:
|
|
144
|
-
>>> raise ConexaoError(
|
|
145
|
-
... "Timeout ao conectar",
|
|
146
|
-
... details={"host": "localhost", "port": 5432}
|
|
147
|
-
... )
|
|
148
|
-
"""
|
|
115
|
+
"""Falha ao estabelecer conexão com banco de dados."""
|
|
149
116
|
|
|
150
117
|
pass
|
|
151
118
|
|
|
@@ -156,59 +123,25 @@ class ConexaoError(DatabaseError):
|
|
|
156
123
|
|
|
157
124
|
|
|
158
125
|
class ArquivoError(NiaEtlError):
|
|
159
|
-
"""Erro base para operações de arquivo e diretório.
|
|
160
|
-
|
|
161
|
-
Examples:
|
|
162
|
-
>>> raise ArquivoError("Operação de arquivo falhou")
|
|
163
|
-
"""
|
|
126
|
+
"""Erro base para operações de arquivo e diretório."""
|
|
164
127
|
|
|
165
128
|
pass
|
|
166
129
|
|
|
167
130
|
|
|
168
131
|
class EscritaArquivoError(ArquivoError):
|
|
169
|
-
"""Falha ao escrever arquivo.
|
|
170
|
-
|
|
171
|
-
Levantado quando não é possível criar ou escrever em um arquivo,
|
|
172
|
-
seja por falta de permissão, disco cheio ou caminho inválido.
|
|
173
|
-
|
|
174
|
-
Examples:
|
|
175
|
-
>>> raise EscritaArquivoError(
|
|
176
|
-
... "Sem permissão para escrita",
|
|
177
|
-
... details={"caminho": "/etc/arquivo.csv"}
|
|
178
|
-
... )
|
|
179
|
-
"""
|
|
132
|
+
"""Falha ao escrever arquivo."""
|
|
180
133
|
|
|
181
134
|
pass
|
|
182
135
|
|
|
183
136
|
|
|
184
137
|
class LeituraArquivoError(ArquivoError):
|
|
185
|
-
"""Falha ao ler arquivo.
|
|
186
|
-
|
|
187
|
-
Levantado quando não é possível ler um arquivo, seja porque
|
|
188
|
-
ele não existe, não há permissão ou está corrompido.
|
|
189
|
-
|
|
190
|
-
Examples:
|
|
191
|
-
>>> raise LeituraArquivoError(
|
|
192
|
-
... "Arquivo não encontrado",
|
|
193
|
-
... details={"caminho": "/tmp/dados.csv"}
|
|
194
|
-
... )
|
|
195
|
-
"""
|
|
138
|
+
"""Falha ao ler arquivo."""
|
|
196
139
|
|
|
197
140
|
pass
|
|
198
141
|
|
|
199
142
|
|
|
200
143
|
class DiretorioError(ArquivoError):
|
|
201
|
-
"""Falha em operação de diretório.
|
|
202
|
-
|
|
203
|
-
Levantado quando não é possível criar, limpar ou remover
|
|
204
|
-
um diretório.
|
|
205
|
-
|
|
206
|
-
Examples:
|
|
207
|
-
>>> raise DiretorioError(
|
|
208
|
-
... "Sem permissão para criar diretório",
|
|
209
|
-
... details={"caminho": "/root/dados"}
|
|
210
|
-
... )
|
|
211
|
-
"""
|
|
144
|
+
"""Falha em operação de diretório."""
|
|
212
145
|
|
|
213
146
|
pass
|
|
214
147
|
|
|
@@ -219,28 +152,13 @@ class DiretorioError(ArquivoError):
|
|
|
219
152
|
|
|
220
153
|
|
|
221
154
|
class ExtracaoError(NiaEtlError):
|
|
222
|
-
"""Erro base para operações de extração de dados.
|
|
223
|
-
|
|
224
|
-
Examples:
|
|
225
|
-
>>> raise ExtracaoError("Falha na extração de dados")
|
|
226
|
-
"""
|
|
155
|
+
"""Erro base para operações de extração de dados."""
|
|
227
156
|
|
|
228
157
|
pass
|
|
229
158
|
|
|
230
159
|
|
|
231
160
|
class ExtracaoVaziaError(ExtracaoError):
|
|
232
|
-
"""Extração retornou DataFrame vazio ou None.
|
|
233
|
-
|
|
234
|
-
Levantado quando uma função de extração não retorna dados.
|
|
235
|
-
Pode ser esperado em alguns contextos (extração incremental
|
|
236
|
-
sem novos dados) ou indicar um problema.
|
|
237
|
-
|
|
238
|
-
Attributes:
|
|
239
|
-
nome_extracao: Identificador da extração que falhou.
|
|
240
|
-
|
|
241
|
-
Examples:
|
|
242
|
-
>>> raise ExtracaoVaziaError("clientes_novos")
|
|
243
|
-
"""
|
|
161
|
+
"""Extração retornou DataFrame vazio ou None."""
|
|
244
162
|
|
|
245
163
|
def __init__(self, nome_extracao: str):
|
|
246
164
|
self.nome_extracao = nome_extracao
|
|
@@ -251,17 +169,7 @@ class ExtracaoVaziaError(ExtracaoError):
|
|
|
251
169
|
|
|
252
170
|
|
|
253
171
|
class ProcessamentoError(ExtracaoError):
|
|
254
|
-
"""Erro durante processamento de dados.
|
|
255
|
-
|
|
256
|
-
Levantado quando há falha durante transformação ou
|
|
257
|
-
processamento de dados.
|
|
258
|
-
|
|
259
|
-
Examples:
|
|
260
|
-
>>> raise ProcessamentoError(
|
|
261
|
-
... "Falha ao processar chunk",
|
|
262
|
-
... details={"chunk": 5, "erro": "memória insuficiente"}
|
|
263
|
-
... )
|
|
264
|
-
"""
|
|
172
|
+
"""Erro durante processamento de dados."""
|
|
265
173
|
|
|
266
174
|
pass
|
|
267
175
|
|
|
@@ -272,40 +180,19 @@ class ProcessamentoError(ExtracaoError):
|
|
|
272
180
|
|
|
273
181
|
|
|
274
182
|
class EmailError(NiaEtlError):
|
|
275
|
-
"""Erro base para operações de email.
|
|
276
|
-
|
|
277
|
-
Examples:
|
|
278
|
-
>>> raise EmailError("Falha no envio de email")
|
|
279
|
-
"""
|
|
183
|
+
"""Erro base para operações de email."""
|
|
280
184
|
|
|
281
185
|
pass
|
|
282
186
|
|
|
283
187
|
|
|
284
188
|
class DestinatarioError(EmailError):
|
|
285
|
-
"""Erro relacionado a destinatários de email.
|
|
286
|
-
|
|
287
|
-
Levantado quando não há destinatários configurados ou
|
|
288
|
-
quando os destinatários são inválidos.
|
|
289
|
-
|
|
290
|
-
Examples:
|
|
291
|
-
>>> raise DestinatarioError("Nenhum destinatário configurado")
|
|
292
|
-
"""
|
|
189
|
+
"""Erro relacionado a destinatários de email."""
|
|
293
190
|
|
|
294
191
|
pass
|
|
295
192
|
|
|
296
193
|
|
|
297
194
|
class SmtpError(EmailError):
|
|
298
|
-
"""Erro de comunicação com servidor SMTP.
|
|
299
|
-
|
|
300
|
-
Levantado quando há falha na conexão ou comunicação
|
|
301
|
-
com o servidor de email.
|
|
302
|
-
|
|
303
|
-
Examples:
|
|
304
|
-
>>> raise SmtpError(
|
|
305
|
-
... "Conexão recusada",
|
|
306
|
-
... details={"servidor": "smtp.empresa.com", "porta": 587}
|
|
307
|
-
... )
|
|
308
|
-
"""
|
|
195
|
+
"""Erro de comunicação com servidor SMTP."""
|
|
309
196
|
|
|
310
197
|
pass
|
|
311
198
|
|
|
@@ -316,59 +203,25 @@ class SmtpError(EmailError):
|
|
|
316
203
|
|
|
317
204
|
|
|
318
205
|
class OcrError(NiaEtlError):
|
|
319
|
-
"""Erro base para operações de OCR.
|
|
320
|
-
|
|
321
|
-
Examples:
|
|
322
|
-
>>> raise OcrError("Falha no processamento OCR")
|
|
323
|
-
"""
|
|
206
|
+
"""Erro base para operações de OCR."""
|
|
324
207
|
|
|
325
208
|
pass
|
|
326
209
|
|
|
327
210
|
|
|
328
211
|
class OcrSubmissaoError(OcrError):
|
|
329
|
-
"""Falha ao submeter documento para OCR.
|
|
330
|
-
|
|
331
|
-
Levantado quando não é possível enviar o documento para a API,
|
|
332
|
-
seja por problemas de rede, timeout ou resposta inválida.
|
|
333
|
-
|
|
334
|
-
Examples:
|
|
335
|
-
>>> raise OcrSubmissaoError(
|
|
336
|
-
... "Timeout ao submeter documento",
|
|
337
|
-
... details={"tentativas": 3, "status": 504}
|
|
338
|
-
... )
|
|
339
|
-
"""
|
|
212
|
+
"""Falha ao submeter documento para OCR."""
|
|
340
213
|
|
|
341
214
|
pass
|
|
342
215
|
|
|
343
216
|
|
|
344
217
|
class OcrProcessamentoError(OcrError):
|
|
345
|
-
"""Falha no processamento do documento pela API.
|
|
346
|
-
|
|
347
|
-
Levantado quando a API retorna status FAILURE ou REVOKED,
|
|
348
|
-
indicando que o documento não pôde ser processado.
|
|
349
|
-
|
|
350
|
-
Examples:
|
|
351
|
-
>>> raise OcrProcessamentoError(
|
|
352
|
-
... "Documento corrompido",
|
|
353
|
-
... details={"document_id": "abc-123", "erro_api": "invalid format"}
|
|
354
|
-
... )
|
|
355
|
-
"""
|
|
218
|
+
"""Falha no processamento do documento pela API."""
|
|
356
219
|
|
|
357
220
|
pass
|
|
358
221
|
|
|
359
222
|
|
|
360
223
|
class OcrTimeoutError(OcrError):
|
|
361
|
-
"""Timeout aguardando resultado do OCR.
|
|
362
|
-
|
|
363
|
-
Levantado quando o tempo máximo de polling é atingido
|
|
364
|
-
sem que a API retorne um resultado final.
|
|
365
|
-
|
|
366
|
-
Examples:
|
|
367
|
-
>>> raise OcrTimeoutError(
|
|
368
|
-
... "Timeout após 300s",
|
|
369
|
-
... details={"document_id": "abc-123", "ultimo_status": "PENDING"}
|
|
370
|
-
... )
|
|
371
|
-
"""
|
|
224
|
+
"""Timeout aguardando resultado do OCR."""
|
|
372
225
|
|
|
373
226
|
pass
|
|
374
227
|
|
|
@@ -379,16 +232,6 @@ class OcrTimeoutError(OcrError):
|
|
|
379
232
|
|
|
380
233
|
|
|
381
234
|
class ValidacaoError(NiaEtlError):
|
|
382
|
-
"""Erro de validação de parâmetros ou dados.
|
|
383
|
-
|
|
384
|
-
Levantado quando parâmetros fornecidos são inválidos
|
|
385
|
-
ou não atendem aos requisitos esperados.
|
|
386
|
-
|
|
387
|
-
Examples:
|
|
388
|
-
>>> raise ValidacaoError(
|
|
389
|
-
... "Nome do arquivo não pode ser vazio",
|
|
390
|
-
... details={"parametro": "nome_arquivo", "valor": ""}
|
|
391
|
-
... )
|
|
392
|
-
"""
|
|
235
|
+
"""Erro de validação de parâmetros ou dados."""
|
|
393
236
|
|
|
394
237
|
pass
|
nia_etl_utils/ocr.py
CHANGED
|
@@ -10,23 +10,13 @@ A API IntelliDoc processa documentos de forma assíncrona:
|
|
|
10
10
|
Example:
|
|
11
11
|
Uso básico com variável de ambiente:
|
|
12
12
|
|
|
13
|
-
>>> from nia_etl_utils
|
|
13
|
+
>>> from nia_etl_utils import executar_ocr, OcrError
|
|
14
14
|
>>>
|
|
15
|
-
>>>
|
|
16
|
-
... resultado = executar_ocr(
|
|
17
|
-
...
|
|
18
|
-
...
|
|
19
|
-
... )
|
|
20
|
-
>>> print(resultado["full_text"])
|
|
21
|
-
|
|
22
|
-
Uso com URL direta e configurações customizadas:
|
|
23
|
-
|
|
24
|
-
>>> resultado = executar_ocr(
|
|
25
|
-
... conteudo=blob_bytes,
|
|
26
|
-
... url_base="http://google.com",
|
|
27
|
-
... timeout_polling=600,
|
|
28
|
-
... max_tentativas=5,
|
|
29
|
-
... )
|
|
15
|
+
>>> try:
|
|
16
|
+
... resultado = executar_ocr(blob_bytes, url_base="INTELLIDOC_URL")
|
|
17
|
+
... print(resultado["full_text"])
|
|
18
|
+
... except OcrError as e:
|
|
19
|
+
... logger.error(f"Falha no OCR: {e}")
|
|
30
20
|
"""
|
|
31
21
|
|
|
32
22
|
import time
|
|
@@ -35,70 +25,11 @@ import requests
|
|
|
35
25
|
from loguru import logger
|
|
36
26
|
|
|
37
27
|
from .env_config import obter_variavel_env
|
|
38
|
-
from .exceptions import
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class OcrError(NiaEtlError):
|
|
46
|
-
"""Erro base para operações de OCR.
|
|
47
|
-
|
|
48
|
-
Examples:
|
|
49
|
-
>>> raise OcrError("Falha no processamento OCR")
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
pass
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class OcrSubmissaoError(OcrError):
|
|
56
|
-
"""Falha ao submeter documento para OCR.
|
|
57
|
-
|
|
58
|
-
Levantado quando não é possível enviar o documento para a API,
|
|
59
|
-
seja por problemas de rede, timeout ou resposta inválida.
|
|
60
|
-
|
|
61
|
-
Examples:
|
|
62
|
-
>>> raise OcrSubmissaoError(
|
|
63
|
-
... "Timeout ao submeter documento",
|
|
64
|
-
... details={"tentativas": 3, "status": 504}
|
|
65
|
-
... )
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
pass
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class OcrProcessamentoError(OcrError):
|
|
72
|
-
"""Falha no processamento do documento pela API.
|
|
73
|
-
|
|
74
|
-
Levantado quando a API retorna status FAILURE ou REVOKED,
|
|
75
|
-
indicando que o documento não pôde ser processado.
|
|
76
|
-
|
|
77
|
-
Examples:
|
|
78
|
-
>>> raise OcrProcessamentoError(
|
|
79
|
-
... "Documento corrompido",
|
|
80
|
-
... details={"document_id": "abc-123", "erro_api": "invalid format"}
|
|
81
|
-
... )
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
pass
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
class OcrTimeoutError(OcrError):
|
|
88
|
-
"""Timeout aguardando resultado do OCR.
|
|
89
|
-
|
|
90
|
-
Levantado quando o tempo máximo de polling é atingido
|
|
91
|
-
sem que a API retorne um resultado final.
|
|
92
|
-
|
|
93
|
-
Examples:
|
|
94
|
-
>>> raise OcrTimeoutError(
|
|
95
|
-
... "Timeout após 300s",
|
|
96
|
-
... details={"document_id": "abc-123", "ultimo_status": "PENDING"}
|
|
97
|
-
... )
|
|
98
|
-
"""
|
|
99
|
-
|
|
100
|
-
pass
|
|
101
|
-
|
|
28
|
+
from .exceptions import (
|
|
29
|
+
OcrProcessamentoError,
|
|
30
|
+
OcrSubmissaoError,
|
|
31
|
+
OcrTimeoutError,
|
|
32
|
+
)
|
|
102
33
|
|
|
103
34
|
# =============================================================================
|
|
104
35
|
# CONSTANTES
|
|
@@ -369,15 +300,10 @@ def executar_ocr(
|
|
|
369
300
|
|
|
370
301
|
>>> resultado = executar_ocr(
|
|
371
302
|
... conteudo=pdf_bytes,
|
|
372
|
-
... url_base="http://
|
|
303
|
+
... url_base="http://intellidoc.mprj.mp.br",
|
|
373
304
|
... timeout_polling=600,
|
|
374
305
|
... )
|
|
375
306
|
>>> print(f"Qualidade: {resultado['overall_quality']}")
|
|
376
|
-
|
|
377
|
-
Acessando detalhes das páginas:
|
|
378
|
-
|
|
379
|
-
>>> for page in resultado["pages"]:
|
|
380
|
-
... print(f"Página {page['page_number']}: {page['extraction_method']}")
|
|
381
307
|
"""
|
|
382
308
|
conteudo_bytes = _normalizar_para_bytes(conteudo)
|
|
383
309
|
extensao = _detectar_extensao(conteudo_bytes)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nia-etl-utils
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Utilitários compartilhados para pipelines ETL do NIA/MPRJ
|
|
5
5
|
Author-email: Nícolas Esmael <nicolas.esmael@mprj.mp.br>
|
|
6
6
|
License: MIT
|
|
@@ -51,7 +51,7 @@ Desenvolvida para eliminar duplicação de código, padronizar boas práticas e
|
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
## Novidades da v0.2.
|
|
54
|
+
## Novidades da v0.2.2
|
|
55
55
|
|
|
56
56
|
- **Módulo OCR** (`executar_ocr`) — processamento de OCR via API IntelliDoc com suporte a PDF, imagens e detecção automática de formato
|
|
57
57
|
- **Exceções de OCR** (`OcrError`, `OcrSubmissaoError`, `OcrProcessamentoError`, `OcrTimeoutError`) — tratamento granular de erros de OCR
|
|
@@ -444,8 +444,7 @@ A API processa documentos de forma assíncrona:
|
|
|
444
444
|
**Formatos suportados:** PDF, JPG, PNG, GIF, BMP, TIFF (detecção automática via magic bytes)
|
|
445
445
|
|
|
446
446
|
```python
|
|
447
|
-
from nia_etl_utils import executar_ocr
|
|
448
|
-
from nia_etl_utils.ocr import OcrError, OcrTimeoutError
|
|
447
|
+
from nia_etl_utils import executar_ocr, OcrError, OcrTimeoutError
|
|
449
448
|
|
|
450
449
|
# Uso básico com variável de ambiente
|
|
451
450
|
with open("documento.pdf", "rb") as f:
|
|
@@ -683,7 +682,7 @@ Este projeto usa [Semantic Versioning](https://semver.org/):
|
|
|
683
682
|
- **MINOR**: Novas funcionalidades (retrocompatíveis)
|
|
684
683
|
- **PATCH**: Correções de bugs
|
|
685
684
|
|
|
686
|
-
**Versão atual:** `v0.2.
|
|
685
|
+
**Versão atual:** `v0.2.2`
|
|
687
686
|
|
|
688
687
|
---
|
|
689
688
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
nia_etl_utils/__init__.py,sha256=
|
|
1
|
+
nia_etl_utils/__init__.py,sha256=a6KmJVa5UKpjfXir1xpI3y9d2DFDKcC8PzRVmRsP1YQ,7000
|
|
2
2
|
nia_etl_utils/config.py,sha256=ITgG-BxmCOKGsyxTJnsQYqQJv5TeM2ng9JlGtUxz0Sw,11842
|
|
3
3
|
nia_etl_utils/database.py,sha256=Ggn9EqSb7SyIRUpumx_DIO3bLN-9-ZrgwkKmuqfIKS0,10789
|
|
4
4
|
nia_etl_utils/email_smtp.py,sha256=F4eVeVmNFnzK-4HU7bKijgPzMzWOWOWXTlFF_1fFdFc,8339
|
|
5
5
|
nia_etl_utils/env_config.py,sha256=LH1FCpaAlo2nVx4SIuL9RGKchkgYP8jJurPe_3_IHEA,5506
|
|
6
|
-
nia_etl_utils/exceptions.py,sha256=
|
|
6
|
+
nia_etl_utils/exceptions.py,sha256=Bp_wC2JhF1KIcpQbAJyNXj6-y1NppeyxxKrCs25zWpA,5936
|
|
7
7
|
nia_etl_utils/limpeza_pastas.py,sha256=OuiSCp7Hxpby0WRgox2Ak-B3ATFpyj08uidmBMwV434,7906
|
|
8
8
|
nia_etl_utils/logger_config.py,sha256=Thhv7uwuhvXMKxef6_2M7lTwE1MfN_LAxWuTHjbLPd0,6787
|
|
9
|
-
nia_etl_utils/ocr.py,sha256=
|
|
9
|
+
nia_etl_utils/ocr.py,sha256=u88Gp6syJoHUb4Xe2LvpqiWeBkDU21vYEDtVQ-GVeHA,10482
|
|
10
10
|
nia_etl_utils/processa_csv.py,sha256=BzgN6UUq2mGXjqKdnOaimLOLTXWu9H1SYdE1tJSWZ3M,11834
|
|
11
11
|
nia_etl_utils/processa_csv_paralelo.py,sha256=0tQwsbHzi6UYEc2fp6o2E3pl23XOTvKhCShwCdcqrW0,8859
|
|
12
12
|
nia_etl_utils/results.py,sha256=ah0ZaIymjdDi-4lO24EYiBeZTQpm289_ZHmUpoNQEVs,9156
|
|
13
|
-
nia_etl_utils-0.2.
|
|
14
|
-
nia_etl_utils-0.2.
|
|
15
|
-
nia_etl_utils-0.2.
|
|
16
|
-
nia_etl_utils-0.2.
|
|
13
|
+
nia_etl_utils-0.2.2.dist-info/METADATA,sha256=fueKq-dWiMmGL07xqMxw6UpAjF5O2lzZSO6jC87Kfeo,20256
|
|
14
|
+
nia_etl_utils-0.2.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
15
|
+
nia_etl_utils-0.2.2.dist-info/top_level.txt,sha256=LYLtk9Gh-GaiyyQkwpVs1CoOtnn1G9t8_ijxcFHyjfY,14
|
|
16
|
+
nia_etl_utils-0.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|