nia-etl-utils 0.1.0__py3-none-any.whl → 0.2.1__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 +173 -43
- nia_etl_utils/config.py +391 -0
- nia_etl_utils/database.py +249 -153
- nia_etl_utils/email_smtp.py +201 -67
- nia_etl_utils/env_config.py +137 -15
- nia_etl_utils/exceptions.py +394 -0
- nia_etl_utils/limpeza_pastas.py +192 -59
- nia_etl_utils/logger_config.py +98 -40
- nia_etl_utils/ocr.py +401 -0
- nia_etl_utils/processa_csv.py +257 -114
- nia_etl_utils/processa_csv_paralelo.py +150 -37
- nia_etl_utils/results.py +304 -0
- nia_etl_utils-0.2.1.dist-info/METADATA +723 -0
- nia_etl_utils-0.2.1.dist-info/RECORD +16 -0
- {nia_etl_utils-0.1.0.dist-info → nia_etl_utils-0.2.1.dist-info}/WHEEL +1 -1
- nia_etl_utils-0.1.0.dist-info/METADATA +0 -594
- nia_etl_utils-0.1.0.dist-info/RECORD +0 -12
- {nia_etl_utils-0.1.0.dist-info → nia_etl_utils-0.2.1.dist-info}/top_level.txt +0 -0
nia_etl_utils/__init__.py
CHANGED
|
@@ -2,41 +2,85 @@
|
|
|
2
2
|
|
|
3
3
|
Este pacote fornece funções reutilizáveis para:
|
|
4
4
|
- Configuração de ambiente (env_config)
|
|
5
|
+
- Configurações de conexão e email (config)
|
|
6
|
+
- Exceções customizadas (exceptions)
|
|
7
|
+
- Resultados estruturados (results)
|
|
5
8
|
- Envio de emails via SMTP (email_smtp)
|
|
6
9
|
- Conexões com bancos de dados Oracle e PostgreSQL (database)
|
|
7
10
|
- Configuração de logging padronizado (logger_config)
|
|
8
11
|
- Processamento e exportação de CSV (processa_csv)
|
|
12
|
+
- Processamento paralelo de CSV grandes (processa_csv_paralelo)
|
|
9
13
|
- Manipulação de arquivos e diretórios (limpeza_pastas)
|
|
14
|
+
- Processamento de OCR via API IntelliDoc (ocr)
|
|
10
15
|
|
|
11
16
|
Exemplo de uso:
|
|
12
|
-
|
|
13
|
-
from nia_etl_utils import
|
|
17
|
+
|
|
18
|
+
from nia_etl_utils import (
|
|
19
|
+
configurar_logger_padrao_nia,
|
|
20
|
+
conectar_postgresql_nia,
|
|
21
|
+
exportar_para_csv,
|
|
22
|
+
PostgresConfig,
|
|
23
|
+
)
|
|
24
|
+
from nia_etl_utils.exceptions import ConexaoError, ExtracaoVaziaError
|
|
14
25
|
|
|
15
26
|
# Configuração
|
|
16
27
|
configurar_logger_padrao_nia("meu_pipeline")
|
|
17
|
-
db_host = obter_variavel_env('DB_POSTGRESQL_HOST')
|
|
18
28
|
|
|
19
|
-
# Conexão
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
# Conexão com context manager
|
|
30
|
+
try:
|
|
31
|
+
with conectar_postgresql_nia() as conn:
|
|
32
|
+
conn.cursor.execute("SELECT * FROM tabela")
|
|
33
|
+
dados = conn.cursor.fetchall()
|
|
34
|
+
except ConexaoError as e:
|
|
35
|
+
logger.error(f"Falha na conexão: {e}")
|
|
36
|
+
sys.exit(1) # decisão do CHAMADOR
|
|
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
|
+
# ...
|
|
48
|
+
|
|
49
|
+
Exemplo de OCR:
|
|
50
|
+
|
|
51
|
+
from nia_etl_utils import executar_ocr
|
|
52
|
+
from nia_etl_utils.ocr import OcrError
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
resultado = executar_ocr(blob_bytes, url_base="INTELLIDOC_URL")
|
|
56
|
+
texto = resultado["full_text"]
|
|
57
|
+
qualidade = resultado["overall_quality"]
|
|
58
|
+
except OcrError as e:
|
|
59
|
+
logger.error(f"Falha no OCR: {e}")
|
|
23
60
|
"""
|
|
24
61
|
|
|
25
|
-
__version__ = "0.1
|
|
62
|
+
__version__ = "0.2.1"
|
|
26
63
|
__author__ = "Nícolas Galdino Esmael"
|
|
27
64
|
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
# Configuração de ambiente
|
|
33
|
-
from .env_config import obter_variavel_env
|
|
65
|
+
# =============================================================================
|
|
66
|
+
# EXCEÇÕES - Importar primeiro para uso em type hints
|
|
67
|
+
# =============================================================================
|
|
34
68
|
|
|
35
|
-
#
|
|
36
|
-
|
|
69
|
+
# =============================================================================
|
|
70
|
+
# CONFIGURAÇÕES (Dataclasses)
|
|
71
|
+
# =============================================================================
|
|
72
|
+
from .config import (
|
|
73
|
+
LogConfig,
|
|
74
|
+
OracleConfig,
|
|
75
|
+
PostgresConfig,
|
|
76
|
+
SmtpConfig,
|
|
77
|
+
)
|
|
37
78
|
|
|
38
|
-
# Database -
|
|
79
|
+
# Database - Funções core
|
|
80
|
+
# Database - Wrappers de conveniência
|
|
39
81
|
from .database import (
|
|
82
|
+
conectar_oracle,
|
|
83
|
+
conectar_oracle_ouvidorias,
|
|
40
84
|
conectar_postgresql,
|
|
41
85
|
conectar_postgresql_nia,
|
|
42
86
|
conectar_postgresql_opengeo,
|
|
@@ -45,11 +89,55 @@ from .database import (
|
|
|
45
89
|
obter_engine_postgresql_opengeo,
|
|
46
90
|
)
|
|
47
91
|
|
|
48
|
-
#
|
|
49
|
-
from .
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
92
|
+
# Email
|
|
93
|
+
from .email_smtp import (
|
|
94
|
+
enviar_email,
|
|
95
|
+
enviar_email_smtp,
|
|
96
|
+
obter_destinatarios_padrao,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# =============================================================================
|
|
100
|
+
# FUNÇÕES UTILITÁRIAS
|
|
101
|
+
# =============================================================================
|
|
102
|
+
# Configuração de ambiente
|
|
103
|
+
from .env_config import (
|
|
104
|
+
obter_variavel_env,
|
|
105
|
+
obter_variavel_env_bool,
|
|
106
|
+
obter_variavel_env_int,
|
|
107
|
+
obter_variavel_env_lista,
|
|
108
|
+
)
|
|
109
|
+
from .exceptions import (
|
|
110
|
+
# Arquivos
|
|
111
|
+
ArquivoError,
|
|
112
|
+
ConexaoError,
|
|
113
|
+
# Configuração
|
|
114
|
+
ConfiguracaoError,
|
|
115
|
+
# Database
|
|
116
|
+
DatabaseError,
|
|
117
|
+
DestinatarioError,
|
|
118
|
+
DiretorioError,
|
|
119
|
+
# Email
|
|
120
|
+
EmailError,
|
|
121
|
+
EscritaArquivoError,
|
|
122
|
+
# Extração
|
|
123
|
+
ExtracaoError,
|
|
124
|
+
ExtracaoVaziaError,
|
|
125
|
+
LeituraArquivoError,
|
|
126
|
+
# Base
|
|
127
|
+
NiaEtlError,
|
|
128
|
+
ProcessamentoError,
|
|
129
|
+
SmtpError,
|
|
130
|
+
# Validação
|
|
131
|
+
ValidacaoError,
|
|
132
|
+
VariavelAmbienteError,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Manipulação de arquivos
|
|
136
|
+
from .limpeza_pastas import (
|
|
137
|
+
criar_pasta_se_nao_existir,
|
|
138
|
+
limpar_pasta,
|
|
139
|
+
listar_arquivos,
|
|
140
|
+
remover_pasta_recursivamente,
|
|
53
141
|
)
|
|
54
142
|
|
|
55
143
|
# Logging
|
|
@@ -59,68 +147,110 @@ from .logger_config import (
|
|
|
59
147
|
remover_handlers_existentes,
|
|
60
148
|
)
|
|
61
149
|
|
|
150
|
+
# OCR
|
|
151
|
+
from .ocr import (
|
|
152
|
+
executar_ocr,
|
|
153
|
+
)
|
|
154
|
+
|
|
62
155
|
# Processamento CSV
|
|
63
156
|
from .processa_csv import (
|
|
157
|
+
exportar_multiplos_csv,
|
|
64
158
|
exportar_para_csv,
|
|
65
159
|
extrair_e_exportar_csv,
|
|
66
|
-
exportar_multiplos_csv,
|
|
67
160
|
)
|
|
68
161
|
|
|
69
162
|
# Processamento CSV Paralelo
|
|
70
163
|
from .processa_csv_paralelo import (
|
|
71
|
-
processar_csv_paralelo,
|
|
72
164
|
calcular_chunksize,
|
|
165
|
+
processar_csv_paralelo,
|
|
73
166
|
)
|
|
74
167
|
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
168
|
+
# =============================================================================
|
|
169
|
+
# RESULTADOS (Dataclasses)
|
|
170
|
+
# =============================================================================
|
|
171
|
+
from .results import (
|
|
172
|
+
Conexao,
|
|
173
|
+
ResultadoEmail,
|
|
174
|
+
ResultadoExtracao,
|
|
175
|
+
ResultadoLote,
|
|
80
176
|
)
|
|
81
177
|
|
|
178
|
+
# =============================================================================
|
|
179
|
+
# __all__ - Exportações públicas
|
|
180
|
+
# =============================================================================
|
|
82
181
|
|
|
83
182
|
__all__ = [
|
|
84
183
|
# Metadata
|
|
85
184
|
"__version__",
|
|
86
185
|
"__author__",
|
|
87
|
-
|
|
186
|
+
# Exceções - Base
|
|
187
|
+
"NiaEtlError",
|
|
188
|
+
# Exceções - Configuração
|
|
189
|
+
"ConfiguracaoError",
|
|
190
|
+
"VariavelAmbienteError",
|
|
191
|
+
# Exceções - Database
|
|
192
|
+
"DatabaseError",
|
|
193
|
+
"ConexaoError",
|
|
194
|
+
# Exceções - Arquivos
|
|
195
|
+
"ArquivoError",
|
|
196
|
+
"DiretorioError",
|
|
197
|
+
"EscritaArquivoError",
|
|
198
|
+
"LeituraArquivoError",
|
|
199
|
+
# Exceções - Extração
|
|
200
|
+
"ExtracaoError",
|
|
201
|
+
"ExtracaoVaziaError",
|
|
202
|
+
"ProcessamentoError",
|
|
203
|
+
# Exceções - Email
|
|
204
|
+
"EmailError",
|
|
205
|
+
"DestinatarioError",
|
|
206
|
+
"SmtpError",
|
|
207
|
+
# Exceções - Validação
|
|
208
|
+
"ValidacaoError",
|
|
209
|
+
# Configurações
|
|
210
|
+
"PostgresConfig",
|
|
211
|
+
"OracleConfig",
|
|
212
|
+
"SmtpConfig",
|
|
213
|
+
"LogConfig",
|
|
214
|
+
# Resultados
|
|
215
|
+
"Conexao",
|
|
216
|
+
"ResultadoExtracao",
|
|
217
|
+
"ResultadoLote",
|
|
218
|
+
"ResultadoEmail",
|
|
88
219
|
# Env config
|
|
89
220
|
"obter_variavel_env",
|
|
90
|
-
|
|
221
|
+
"obter_variavel_env_int",
|
|
222
|
+
"obter_variavel_env_bool",
|
|
223
|
+
"obter_variavel_env_lista",
|
|
91
224
|
# Email
|
|
225
|
+
"enviar_email",
|
|
92
226
|
"enviar_email_smtp",
|
|
93
227
|
"obter_destinatarios_padrao",
|
|
94
|
-
|
|
95
|
-
# Database - PostgreSQL
|
|
228
|
+
# Database - Core
|
|
96
229
|
"conectar_postgresql",
|
|
230
|
+
"conectar_oracle",
|
|
231
|
+
"obter_engine_postgresql",
|
|
232
|
+
# Database - Wrappers
|
|
97
233
|
"conectar_postgresql_nia",
|
|
98
234
|
"conectar_postgresql_opengeo",
|
|
99
|
-
"
|
|
235
|
+
"conectar_oracle_ouvidorias",
|
|
100
236
|
"obter_engine_postgresql_nia",
|
|
101
237
|
"obter_engine_postgresql_opengeo",
|
|
102
|
-
|
|
103
|
-
# Database - Oracle
|
|
104
|
-
"conectar_oracle",
|
|
105
|
-
"conectar_oracle_ouvidorias",
|
|
106
|
-
"fechar_conexao",
|
|
107
|
-
|
|
108
238
|
# Logging
|
|
109
239
|
"configurar_logger",
|
|
110
240
|
"configurar_logger_padrao_nia",
|
|
111
241
|
"remover_handlers_existentes",
|
|
112
|
-
|
|
113
242
|
# CSV
|
|
114
243
|
"exportar_para_csv",
|
|
115
244
|
"extrair_e_exportar_csv",
|
|
116
245
|
"exportar_multiplos_csv",
|
|
117
|
-
|
|
118
246
|
# CSV Paralelo
|
|
119
247
|
"processar_csv_paralelo",
|
|
120
248
|
"calcular_chunksize",
|
|
121
|
-
|
|
122
249
|
# Arquivos
|
|
123
250
|
"limpar_pasta",
|
|
124
251
|
"remover_pasta_recursivamente",
|
|
125
252
|
"criar_pasta_se_nao_existir",
|
|
253
|
+
"listar_arquivos",
|
|
254
|
+
# OCR
|
|
255
|
+
"executar_ocr",
|
|
126
256
|
]
|
nia_etl_utils/config.py
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
"""Dataclasses de configuração para o pacote nia_etl_utils.
|
|
2
|
+
|
|
3
|
+
Este módulo define estruturas de dados imutáveis para configuração
|
|
4
|
+
de conexões, email e outras operações do pacote.
|
|
5
|
+
|
|
6
|
+
As configurações podem ser criadas de três formas:
|
|
7
|
+
1. Instanciação direta com valores explícitos
|
|
8
|
+
2. Factory method `from_env()` para carregar de variáveis de ambiente
|
|
9
|
+
3. Wrappers de conveniência para casos comuns
|
|
10
|
+
|
|
11
|
+
Examples:
|
|
12
|
+
Configuração explícita (recomendado para testes):
|
|
13
|
+
|
|
14
|
+
>>> config = PostgresConfig(
|
|
15
|
+
... host="localhost",
|
|
16
|
+
... port="5432",
|
|
17
|
+
... database="teste",
|
|
18
|
+
... user="user",
|
|
19
|
+
... password="pass"
|
|
20
|
+
... )
|
|
21
|
+
|
|
22
|
+
Configuração via ambiente (recomendado para produção):
|
|
23
|
+
|
|
24
|
+
>>> config = PostgresConfig.from_env() # usa variáveis padrão
|
|
25
|
+
>>> config = PostgresConfig.from_env("_OPENGEO") # usa sufixo
|
|
26
|
+
|
|
27
|
+
Uso com funções de conexão:
|
|
28
|
+
|
|
29
|
+
>>> from nia_etl_utils import conectar_postgresql
|
|
30
|
+
>>> with conectar_postgresql(config) as conn:
|
|
31
|
+
... conn.cursor.execute("SELECT 1")
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from dataclasses import dataclass
|
|
35
|
+
from typing import TYPE_CHECKING
|
|
36
|
+
|
|
37
|
+
import cx_Oracle
|
|
38
|
+
|
|
39
|
+
from .exceptions import ConfiguracaoError
|
|
40
|
+
|
|
41
|
+
if TYPE_CHECKING:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class PostgresConfig:
|
|
47
|
+
"""Configuração de conexão PostgreSQL.
|
|
48
|
+
|
|
49
|
+
Dataclass imutável contendo todos os parâmetros necessários
|
|
50
|
+
para estabelecer conexão com um banco PostgreSQL.
|
|
51
|
+
|
|
52
|
+
Attributes:
|
|
53
|
+
host: Endereço do servidor PostgreSQL.
|
|
54
|
+
port: Porta de conexão (geralmente 5432).
|
|
55
|
+
database: Nome do banco de dados.
|
|
56
|
+
user: Usuário de autenticação.
|
|
57
|
+
password: Senha de autenticação.
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
Criação direta:
|
|
61
|
+
|
|
62
|
+
>>> config = PostgresConfig(
|
|
63
|
+
... host="localhost",
|
|
64
|
+
... port="5432",
|
|
65
|
+
... database="meu_banco",
|
|
66
|
+
... user="usuario",
|
|
67
|
+
... password="senha"
|
|
68
|
+
... )
|
|
69
|
+
|
|
70
|
+
A partir de variáveis de ambiente:
|
|
71
|
+
|
|
72
|
+
>>> config = PostgresConfig.from_env()
|
|
73
|
+
>>> config = PostgresConfig.from_env("_OPENGEO")
|
|
74
|
+
|
|
75
|
+
Acessando connection string:
|
|
76
|
+
|
|
77
|
+
>>> config.connection_string
|
|
78
|
+
'postgresql+psycopg2://usuario:senha@localhost:5432/meu_banco'
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
host: str
|
|
82
|
+
port: str
|
|
83
|
+
database: str
|
|
84
|
+
user: str
|
|
85
|
+
password: str
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def from_env(cls, sufixo: str = "") -> "PostgresConfig":
|
|
89
|
+
"""Cria configuração a partir de variáveis de ambiente.
|
|
90
|
+
|
|
91
|
+
Busca as seguintes variáveis (com sufixo opcional):
|
|
92
|
+
- DB_POSTGRESQL_HOST{sufixo}
|
|
93
|
+
- DB_POSTGRESQL_PORT{sufixo}
|
|
94
|
+
- DB_POSTGRESQL_DATABASE{sufixo}
|
|
95
|
+
- DB_POSTGRESQL_USER{sufixo}
|
|
96
|
+
- DB_POSTGRESQL_PASSWORD{sufixo}
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
sufixo: Sufixo das variáveis de ambiente. Use "" para
|
|
100
|
+
variáveis padrão ou "_OPENGEO", "_PROD", etc para
|
|
101
|
+
ambientes específicos.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
PostgresConfig com valores das variáveis de ambiente.
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
ConfiguracaoError: Se alguma variável obrigatória não existir.
|
|
108
|
+
|
|
109
|
+
Examples:
|
|
110
|
+
>>> config = PostgresConfig.from_env()
|
|
111
|
+
>>> config = PostgresConfig.from_env("_OPENGEO")
|
|
112
|
+
"""
|
|
113
|
+
from .env_config import obter_variavel_env
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
return cls(
|
|
117
|
+
host=obter_variavel_env(f"DB_POSTGRESQL_HOST{sufixo}"),
|
|
118
|
+
port=obter_variavel_env(f"DB_POSTGRESQL_PORT{sufixo}"),
|
|
119
|
+
database=obter_variavel_env(f"DB_POSTGRESQL_DATABASE{sufixo}"),
|
|
120
|
+
user=obter_variavel_env(f"DB_POSTGRESQL_USER{sufixo}"),
|
|
121
|
+
password=obter_variavel_env(f"DB_POSTGRESQL_PASSWORD{sufixo}"),
|
|
122
|
+
)
|
|
123
|
+
except Exception as e:
|
|
124
|
+
raise ConfiguracaoError(
|
|
125
|
+
f"Variáveis de ambiente PostgreSQL incompletas (sufixo='{sufixo}')",
|
|
126
|
+
details={"sufixo": sufixo, "erro_original": str(e)}
|
|
127
|
+
) from e
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def connection_string(self) -> str:
|
|
131
|
+
"""String de conexão SQLAlchemy.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
String formatada para uso com SQLAlchemy create_engine().
|
|
135
|
+
|
|
136
|
+
Examples:
|
|
137
|
+
>>> config = PostgresConfig(
|
|
138
|
+
... host="localhost",
|
|
139
|
+
... port="5432",
|
|
140
|
+
... database="teste",
|
|
141
|
+
... user="user",
|
|
142
|
+
... password="pass"
|
|
143
|
+
... )
|
|
144
|
+
>>> config.connection_string
|
|
145
|
+
'postgresql+psycopg2://user:pass@localhost:5432/teste'
|
|
146
|
+
"""
|
|
147
|
+
return (
|
|
148
|
+
f"postgresql+psycopg2://{self.user}:{self.password}"
|
|
149
|
+
f"@{self.host}:{self.port}/{self.database}"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def __repr__(self) -> str:
|
|
153
|
+
"""Representação segura (sem expor senha)."""
|
|
154
|
+
return (
|
|
155
|
+
f"PostgresConfig(host='{self.host}', port='{self.port}', "
|
|
156
|
+
f"database='{self.database}', user='{self.user}', password='***')"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass(frozen=True)
|
|
161
|
+
class OracleConfig:
|
|
162
|
+
"""Configuração de conexão Oracle.
|
|
163
|
+
|
|
164
|
+
Dataclass imutável contendo todos os parâmetros necessários
|
|
165
|
+
para estabelecer conexão com um banco Oracle.
|
|
166
|
+
|
|
167
|
+
Attributes:
|
|
168
|
+
host: Endereço do servidor Oracle.
|
|
169
|
+
port: Porta de conexão (geralmente 1521).
|
|
170
|
+
service_name: Nome do serviço Oracle.
|
|
171
|
+
user: Usuário de autenticação.
|
|
172
|
+
password: Senha de autenticação.
|
|
173
|
+
|
|
174
|
+
Examples:
|
|
175
|
+
Criação direta:
|
|
176
|
+
|
|
177
|
+
>>> config = OracleConfig(
|
|
178
|
+
... host="oracle.empresa.com",
|
|
179
|
+
... port="1521",
|
|
180
|
+
... service_name="PROD",
|
|
181
|
+
... user="usuario",
|
|
182
|
+
... password="senha"
|
|
183
|
+
... )
|
|
184
|
+
|
|
185
|
+
A partir de variáveis de ambiente:
|
|
186
|
+
|
|
187
|
+
>>> config = OracleConfig.from_env()
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
host: str
|
|
191
|
+
port: str
|
|
192
|
+
service_name: str
|
|
193
|
+
user: str
|
|
194
|
+
password: str
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def from_env(cls, sufixo: str = "") -> "OracleConfig":
|
|
198
|
+
"""Cria configuração a partir de variáveis de ambiente.
|
|
199
|
+
|
|
200
|
+
Busca as seguintes variáveis (com sufixo opcional):
|
|
201
|
+
- DB_ORACLE_HOST{sufixo}
|
|
202
|
+
- DB_ORACLE_PORT{sufixo}
|
|
203
|
+
- DB_ORACLE_SERVICE_NAME{sufixo}
|
|
204
|
+
- DB_ORACLE_USER{sufixo}
|
|
205
|
+
- DB_ORACLE_PASSWORD{sufixo}
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
sufixo: Sufixo das variáveis de ambiente.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
OracleConfig com valores das variáveis de ambiente.
|
|
212
|
+
|
|
213
|
+
Raises:
|
|
214
|
+
ConfiguracaoError: Se alguma variável obrigatória não existir.
|
|
215
|
+
|
|
216
|
+
Examples:
|
|
217
|
+
>>> config = OracleConfig.from_env()
|
|
218
|
+
>>> config = OracleConfig.from_env("_PROD")
|
|
219
|
+
"""
|
|
220
|
+
from .env_config import obter_variavel_env
|
|
221
|
+
|
|
222
|
+
try:
|
|
223
|
+
return cls(
|
|
224
|
+
host=obter_variavel_env(f"DB_ORACLE_HOST{sufixo}"),
|
|
225
|
+
port=obter_variavel_env(f"DB_ORACLE_PORT{sufixo}"),
|
|
226
|
+
service_name=obter_variavel_env(f"DB_ORACLE_SERVICE_NAME{sufixo}"),
|
|
227
|
+
user=obter_variavel_env(f"DB_ORACLE_USER{sufixo}"),
|
|
228
|
+
password=obter_variavel_env(f"DB_ORACLE_PASSWORD{sufixo}"),
|
|
229
|
+
)
|
|
230
|
+
except Exception as e:
|
|
231
|
+
raise ConfiguracaoError(
|
|
232
|
+
f"Variáveis de ambiente Oracle incompletas (sufixo='{sufixo}')",
|
|
233
|
+
details={"sufixo": sufixo, "erro_original": str(e)}
|
|
234
|
+
) from e
|
|
235
|
+
|
|
236
|
+
@property
|
|
237
|
+
def dsn(self) -> str:
|
|
238
|
+
"""DSN para conexão cx_Oracle.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
DSN formatado para uso com cx_Oracle.connect().
|
|
242
|
+
|
|
243
|
+
Examples:
|
|
244
|
+
>>> config = OracleConfig(
|
|
245
|
+
... host="oracle.empresa.com",
|
|
246
|
+
... port="1521",
|
|
247
|
+
... service_name="PROD",
|
|
248
|
+
... user="user",
|
|
249
|
+
... password="pass"
|
|
250
|
+
... )
|
|
251
|
+
>>> # dsn é gerado internamente por cx_Oracle.makedsn()
|
|
252
|
+
"""
|
|
253
|
+
return cx_Oracle.makedsn(self.host, self.port, service_name=self.service_name)
|
|
254
|
+
|
|
255
|
+
def __repr__(self) -> str:
|
|
256
|
+
"""Representação segura (sem expor senha)."""
|
|
257
|
+
return (
|
|
258
|
+
f"OracleConfig(host='{self.host}', port='{self.port}', "
|
|
259
|
+
f"service_name='{self.service_name}', user='{self.user}', password='***')"
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@dataclass(frozen=True)
|
|
264
|
+
class SmtpConfig:
|
|
265
|
+
"""Configuração de servidor SMTP para envio de emails.
|
|
266
|
+
|
|
267
|
+
Attributes:
|
|
268
|
+
servidor: Endereço do servidor SMTP.
|
|
269
|
+
porta: Porta de conexão (geralmente 25, 465 ou 587).
|
|
270
|
+
remetente: Endereço de email do remetente.
|
|
271
|
+
destinatarios_padrao: Lista de destinatários padrão.
|
|
272
|
+
cc: Endereço para cópia (opcional).
|
|
273
|
+
|
|
274
|
+
Examples:
|
|
275
|
+
Criação direta:
|
|
276
|
+
|
|
277
|
+
>>> config = SmtpConfig(
|
|
278
|
+
... servidor="smtp.empresa.com",
|
|
279
|
+
... porta=587,
|
|
280
|
+
... remetente="sistema@empresa.com",
|
|
281
|
+
... destinatarios_padrao=["admin@empresa.com"]
|
|
282
|
+
... )
|
|
283
|
+
|
|
284
|
+
A partir de variáveis de ambiente:
|
|
285
|
+
|
|
286
|
+
>>> config = SmtpConfig.from_env()
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
servidor: str
|
|
290
|
+
porta: int
|
|
291
|
+
remetente: str
|
|
292
|
+
destinatarios_padrao: list[str]
|
|
293
|
+
cc: str | None = None
|
|
294
|
+
|
|
295
|
+
@classmethod
|
|
296
|
+
def from_env(cls) -> "SmtpConfig":
|
|
297
|
+
"""Cria configuração a partir de variáveis de ambiente.
|
|
298
|
+
|
|
299
|
+
Busca as seguintes variáveis:
|
|
300
|
+
- MAIL_SMTP_SERVER
|
|
301
|
+
- MAIL_SMTP_PORT
|
|
302
|
+
- MAIL_SENDER
|
|
303
|
+
- EMAIL_DESTINATARIOS (separados por vírgula)
|
|
304
|
+
- MAIL_CC (opcional)
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
SmtpConfig com valores das variáveis de ambiente.
|
|
308
|
+
|
|
309
|
+
Raises:
|
|
310
|
+
ConfiguracaoError: Se alguma variável obrigatória não existir.
|
|
311
|
+
|
|
312
|
+
Examples:
|
|
313
|
+
>>> config = SmtpConfig.from_env()
|
|
314
|
+
"""
|
|
315
|
+
from .env_config import obter_variavel_env
|
|
316
|
+
|
|
317
|
+
try:
|
|
318
|
+
destinatarios_str = obter_variavel_env("EMAIL_DESTINATARIOS").strip()
|
|
319
|
+
destinatarios = [
|
|
320
|
+
email.strip()
|
|
321
|
+
for email in destinatarios_str.split(',')
|
|
322
|
+
if email.strip()
|
|
323
|
+
]
|
|
324
|
+
|
|
325
|
+
import os
|
|
326
|
+
cc = os.getenv("MAIL_CC")
|
|
327
|
+
|
|
328
|
+
return cls(
|
|
329
|
+
servidor=obter_variavel_env("MAIL_SMTP_SERVER"),
|
|
330
|
+
porta=int(obter_variavel_env("MAIL_SMTP_PORT")),
|
|
331
|
+
remetente=obter_variavel_env("MAIL_SENDER"),
|
|
332
|
+
destinatarios_padrao=destinatarios,
|
|
333
|
+
cc=cc,
|
|
334
|
+
)
|
|
335
|
+
except Exception as e:
|
|
336
|
+
raise ConfiguracaoError(
|
|
337
|
+
"Variáveis de ambiente SMTP incompletas",
|
|
338
|
+
details={"erro_original": str(e)}
|
|
339
|
+
) from e
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@dataclass(frozen=True)
|
|
343
|
+
class LogConfig:
|
|
344
|
+
"""Configuração de logging.
|
|
345
|
+
|
|
346
|
+
Attributes:
|
|
347
|
+
prefixo: Nome do módulo/pipeline para identificação.
|
|
348
|
+
pasta_logs: Diretório onde os logs serão salvos.
|
|
349
|
+
rotation: Critério de rotação (tamanho ou tempo).
|
|
350
|
+
retention: Tempo de retenção dos logs.
|
|
351
|
+
level: Nível mínimo de log.
|
|
352
|
+
|
|
353
|
+
Examples:
|
|
354
|
+
>>> config = LogConfig(
|
|
355
|
+
... prefixo="etl_ouvidorias",
|
|
356
|
+
... pasta_logs="/var/log/nia",
|
|
357
|
+
... rotation="50 MB",
|
|
358
|
+
... retention="30 days",
|
|
359
|
+
... level="INFO"
|
|
360
|
+
... )
|
|
361
|
+
"""
|
|
362
|
+
|
|
363
|
+
prefixo: str
|
|
364
|
+
pasta_logs: str = "logs"
|
|
365
|
+
rotation: str = "10 MB"
|
|
366
|
+
retention: str = "7 days"
|
|
367
|
+
level: str = "DEBUG"
|
|
368
|
+
|
|
369
|
+
@classmethod
|
|
370
|
+
def padrao_nia(cls, prefixo: str) -> "LogConfig":
|
|
371
|
+
"""Cria configuração com padrões do NIA.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
prefixo: Nome do pipeline.
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
LogConfig com configurações padrão NIA:
|
|
378
|
+
- Rotação: 50 MB
|
|
379
|
+
- Retenção: 30 dias
|
|
380
|
+
- Nível: INFO
|
|
381
|
+
|
|
382
|
+
Examples:
|
|
383
|
+
>>> config = LogConfig.padrao_nia("ouvidorias_etl")
|
|
384
|
+
"""
|
|
385
|
+
return cls(
|
|
386
|
+
prefixo=prefixo,
|
|
387
|
+
pasta_logs="logs",
|
|
388
|
+
rotation="50 MB",
|
|
389
|
+
retention="30 days",
|
|
390
|
+
level="INFO"
|
|
391
|
+
)
|