lbxtoolkit 2.2.7__tar.gz → 2.2.9__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.
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/PKG-INFO +8 -6
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/README.md +7 -5
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/api_rest.py +60 -4
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/postgresql.py +2 -2
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/pyproject.toml +1 -1
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/__init__.py +0 -0
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/auth_entra_id.py +0 -0
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/config_manager.py +0 -0
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/lbx_logger.py +0 -0
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/misc.py +0 -0
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/service.py +0 -0
- {lbxtoolkit-2.2.7 → lbxtoolkit-2.2.9}/lbxtoolkit/service_windows.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lbxtoolkit
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.9
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Cristiano P. Ferrari
|
|
6
6
|
Author-email: cristiano.ferrari@lbx.com.br
|
|
@@ -60,7 +60,7 @@ Interage com o banco de dados PostgreSQL
|
|
|
60
60
|
Interage com APIs RESTfull, especialmente providas para a plataforma Sienge
|
|
61
61
|
- `auth_base` Autentica (HTTPBasicAuth) sessão na API
|
|
62
62
|
- `auth_bearer` Autentica sessão na API pelos métodos: OAuth, JWT, Bearer
|
|
63
|
-
- `endpoint_json` Realizad chama ao endpoint. Payload em formato `json`
|
|
63
|
+
- `endpoint_json` Realizad chama ao endpoint. Aceita opcionalmente Payload em formato `json` ou arquivo binário.
|
|
64
64
|
- `trata_erro_sienge` Retorna a mensagem de erro do Sienge caso código de retorno seja diferente de 200.
|
|
65
65
|
- `close` Encerra a sessão autenticada
|
|
66
66
|
|
|
@@ -145,7 +145,7 @@ São nessários 2 parâmetros posicionais obrigatórios, e 5 parametros nominais
|
|
|
145
145
|
- `cadencia` Número máximo de chamadas *por segudo* à API
|
|
146
146
|
- `timeout` Tempo máximo (segundos) para aguardar retorno à chamada. Padrão 6s, se omisso.
|
|
147
147
|
- `logger` O objeto _log handler_ para lidar com as informações de saída. Se não informado, todas as saídas serão direcionadas para a stdout.
|
|
148
|
-
- `headers` Cabeçalhos _http_ para a requisição à API.
|
|
148
|
+
- `headers` Cabeçalhos _http_ para a requisição à API. Se não fornecido, será incluida implicitamente a chave `Content-Type` com valor `application/json`.
|
|
149
149
|
- `verify` Verifica a validade do certificado SSL do servidor de destino da requisição.
|
|
150
150
|
|
|
151
151
|
Quanto às credenciais de autenticação, assim como a classe de interação com o PostgreSQL, elas precisam ser fornecidas na forma de um *dicionário*.
|
|
@@ -162,12 +162,14 @@ Caso a autenticação seja pelo método `api_rest.aut_bearer()`, o dicionário d
|
|
|
162
162
|
A classe possui 3 métodos:
|
|
163
163
|
- `api_rest.auth_basic()`: instanciamento da sessão autenticando pelo método HTTPBasicAuth
|
|
164
164
|
- `api_rest.auth_bearer()`: instanciamento da sessão autenticando pelos métodos OAuth, JWT, Bearer
|
|
165
|
-
- `api_rest.endpoint_json([endereço], [método], payload=None)`: para a chamada ao endpoint
|
|
165
|
+
- `api_rest.endpoint_json([endereço], [método], payload=None, files=None)`: para a chamada ao endpoint
|
|
166
166
|
- `close()` para encerra a instância/sessão
|
|
167
167
|
|
|
168
|
-
O consumo é feito pelo método `api_rest.endpoint_json` que suporta
|
|
168
|
+
O consumo é feito pelo método `api_rest.endpoint_json` que suporta APIs cujo payload (opcional) seja aceito no formato JSON ou binario (files).
|
|
169
169
|
|
|
170
|
-
Esse método espera 2 parametros posicionais obrigatórios: o endereço do endpoint e o verbo (get, post, patch ou put), tendo parametro opcional o objeto de 'payload' (json).
|
|
170
|
+
Esse método espera 2 parametros posicionais obrigatórios: o endereço do endpoint e o verbo (get, post, patch ou put), tendo parametro opcional o objeto de 'payload' (json) ou 'files' (binário).
|
|
171
|
+
O método define no `headers` a chavee `Content-Type` implicita e automaticamente com o valor `application/json`, independente de ser ou não fornecido payload.
|
|
172
|
+
Se a carga for do tipo binário, é necessário informar o Content-Type correto (`multipart/form-data`) ou repassar um dicionario vazio (`{}`) para o parametro `headers` no instanciamento da classe `api_rest`
|
|
171
173
|
Note que o endereço do endpoint deve ser informado completo. A URL informada no instanciamento da classe corresponde apenas ao endereço de autenticação.
|
|
172
174
|
|
|
173
175
|
O tempo, em segundos, transcorrido entre a chamada a atual e a chamada anterior ao endpoint pode ser consultado pelo argumento `.Intervalo` no objeto recebido do retorno à chamada ao método `.endpoint_json`.
|
|
@@ -38,7 +38,7 @@ Interage com o banco de dados PostgreSQL
|
|
|
38
38
|
Interage com APIs RESTfull, especialmente providas para a plataforma Sienge
|
|
39
39
|
- `auth_base` Autentica (HTTPBasicAuth) sessão na API
|
|
40
40
|
- `auth_bearer` Autentica sessão na API pelos métodos: OAuth, JWT, Bearer
|
|
41
|
-
- `endpoint_json` Realizad chama ao endpoint. Payload em formato `json`
|
|
41
|
+
- `endpoint_json` Realizad chama ao endpoint. Aceita opcionalmente Payload em formato `json` ou arquivo binário.
|
|
42
42
|
- `trata_erro_sienge` Retorna a mensagem de erro do Sienge caso código de retorno seja diferente de 200.
|
|
43
43
|
- `close` Encerra a sessão autenticada
|
|
44
44
|
|
|
@@ -123,7 +123,7 @@ São nessários 2 parâmetros posicionais obrigatórios, e 5 parametros nominais
|
|
|
123
123
|
- `cadencia` Número máximo de chamadas *por segudo* à API
|
|
124
124
|
- `timeout` Tempo máximo (segundos) para aguardar retorno à chamada. Padrão 6s, se omisso.
|
|
125
125
|
- `logger` O objeto _log handler_ para lidar com as informações de saída. Se não informado, todas as saídas serão direcionadas para a stdout.
|
|
126
|
-
- `headers` Cabeçalhos _http_ para a requisição à API.
|
|
126
|
+
- `headers` Cabeçalhos _http_ para a requisição à API. Se não fornecido, será incluida implicitamente a chave `Content-Type` com valor `application/json`.
|
|
127
127
|
- `verify` Verifica a validade do certificado SSL do servidor de destino da requisição.
|
|
128
128
|
|
|
129
129
|
Quanto às credenciais de autenticação, assim como a classe de interação com o PostgreSQL, elas precisam ser fornecidas na forma de um *dicionário*.
|
|
@@ -140,12 +140,14 @@ Caso a autenticação seja pelo método `api_rest.aut_bearer()`, o dicionário d
|
|
|
140
140
|
A classe possui 3 métodos:
|
|
141
141
|
- `api_rest.auth_basic()`: instanciamento da sessão autenticando pelo método HTTPBasicAuth
|
|
142
142
|
- `api_rest.auth_bearer()`: instanciamento da sessão autenticando pelos métodos OAuth, JWT, Bearer
|
|
143
|
-
- `api_rest.endpoint_json([endereço], [método], payload=None)`: para a chamada ao endpoint
|
|
143
|
+
- `api_rest.endpoint_json([endereço], [método], payload=None, files=None)`: para a chamada ao endpoint
|
|
144
144
|
- `close()` para encerra a instância/sessão
|
|
145
145
|
|
|
146
|
-
O consumo é feito pelo método `api_rest.endpoint_json` que suporta
|
|
146
|
+
O consumo é feito pelo método `api_rest.endpoint_json` que suporta APIs cujo payload (opcional) seja aceito no formato JSON ou binario (files).
|
|
147
147
|
|
|
148
|
-
Esse método espera 2 parametros posicionais obrigatórios: o endereço do endpoint e o verbo (get, post, patch ou put), tendo parametro opcional o objeto de 'payload' (json).
|
|
148
|
+
Esse método espera 2 parametros posicionais obrigatórios: o endereço do endpoint e o verbo (get, post, patch ou put), tendo parametro opcional o objeto de 'payload' (json) ou 'files' (binário).
|
|
149
|
+
O método define no `headers` a chavee `Content-Type` implicita e automaticamente com o valor `application/json`, independente de ser ou não fornecido payload.
|
|
150
|
+
Se a carga for do tipo binário, é necessário informar o Content-Type correto (`multipart/form-data`) ou repassar um dicionario vazio (`{}`) para o parametro `headers` no instanciamento da classe `api_rest`
|
|
149
151
|
Note que o endereço do endpoint deve ser informado completo. A URL informada no instanciamento da classe corresponde apenas ao endereço de autenticação.
|
|
150
152
|
|
|
151
153
|
O tempo, em segundos, transcorrido entre a chamada a atual e a chamada anterior ao endpoint pode ser consultado pelo argumento `.Intervalo` no objeto recebido do retorno à chamada ao método `.endpoint_json`.
|
|
@@ -166,23 +166,79 @@ Para uso em APIs com autenticação JWT (JSON Web Token), OAuth, Bearer Token Au
|
|
|
166
166
|
return Err
|
|
167
167
|
#
|
|
168
168
|
#
|
|
169
|
-
def
|
|
169
|
+
def auth_token(self): # Autentica e abre sessão na API
|
|
170
|
+
if self.Credenciais['token']:
|
|
171
|
+
Token = self.Credenciais['token']
|
|
172
|
+
self.Headers.update({"UserAuthorization": f"token {Token}"})
|
|
173
|
+
else:
|
|
174
|
+
self.logger.critico(f'Falha de requisição api_rest.auth_token: Token não fornecido no dicionário de credenciais! Necessário informar chave da API em dicionário com chave "token" no instanciamento da classe', exit=1)
|
|
175
|
+
|
|
176
|
+
try:
|
|
177
|
+
self.Sessao = requests.Session()
|
|
178
|
+
Auth = self.Sessao.post(self.Url, headers=self.Headers, verify=self.Verify)
|
|
179
|
+
|
|
180
|
+
if 200 <= Auth.status_code <= 299:
|
|
181
|
+
self.Sessao.status_code = Auth.status_code
|
|
182
|
+
return self.Sessao
|
|
183
|
+
else:
|
|
184
|
+
self.logger.critico(f"Erro ao autenticar API: {self.Sessao.status_code} - {self.Sessao.text}")
|
|
185
|
+
raise Exception
|
|
186
|
+
except Exception as Err:
|
|
187
|
+
self.logger.critico(f"Falha ao autenticar API: {Err}. URL: {self.Url}")
|
|
188
|
+
return Err
|
|
189
|
+
#
|
|
190
|
+
#
|
|
191
|
+
def url_request(self, metodo, payload=None): # Efetua chamada diretamente à URL e não a EndPoint específico
|
|
192
|
+
self.ult_tempo_req = time()
|
|
193
|
+
self.Metodo = metodo.lower()
|
|
194
|
+
self.EndPoint = self.Url
|
|
195
|
+
self.Payload = payload
|
|
196
|
+
MetodosAceitos = ['post', 'get', 'patch', 'put']
|
|
197
|
+
if not any(element in self.Metodo for element in MetodosAceitos):
|
|
198
|
+
self.logger.critico(f'Método {self.Metodo} não previsto. Abortando chamada!', exit=1)
|
|
199
|
+
else:
|
|
200
|
+
ChamadaApi = f'self.Sessao.{self.Metodo}(self.Url, timeout=self.Timeout, headers=self.Headers, verify=self.Verify)' if self.Payload is None else f'self.Sessao.{self.Metodo}(self.Url, timeout=self.Timeout, headers=self.Headers, verify=self.Verify, data=self.Payload)'
|
|
201
|
+
self.controla_cadencia()
|
|
202
|
+
self.TempoUltReq = time()
|
|
203
|
+
try:
|
|
204
|
+
self.RetEndPoint = eval(ChamadaApi)
|
|
205
|
+
if self.RetEndPoint.status_code >= 500:
|
|
206
|
+
self.logger.critico(f'Erro [{self.RetEndPoint.status_code}] no lado servidor na resposta à requisição')
|
|
207
|
+
raise Exception
|
|
208
|
+
self.RetEndPoint.Espera = self.Espera ## adiona o tempo de espera ao retorno da API
|
|
209
|
+
self.RetEndPoint.Intervalo = self.Intervalo ## adiciona o intervalo entre chamada ao retorno da API
|
|
210
|
+
return self.RetEndPoint
|
|
211
|
+
except requests.exceptions.ReadTimeout as Err:
|
|
212
|
+
self.logger.critico(f'Excedido tempo limite {self.Timeout} para retorno do endpoint: {Err}\nEndpoint: {self.EndPoint}')
|
|
213
|
+
return Err
|
|
214
|
+
except Exception as Err:
|
|
215
|
+
self.logger.critico(f'Falha na chamada do endpoint: {Err}\nEndpoint: {self.EndPoint}\nCodigo retorno: {self.RetEndPoint.status_code}\nResposta:{self.RetEndPoint.text}')
|
|
216
|
+
return self.RetEndPoint
|
|
217
|
+
#
|
|
218
|
+
#
|
|
219
|
+
def endpoint_json(self, endpoint, metodo, payload=None, file=None): # Interage com End Point
|
|
170
220
|
self.ult_tempo_req = time()
|
|
171
221
|
self.Metodo = metodo.lower()
|
|
172
222
|
#self.EndPoint = self.Url + endpoint
|
|
173
223
|
self.EndPoint = endpoint
|
|
174
224
|
self.Payload = payload
|
|
225
|
+
self.File = file
|
|
226
|
+
|
|
175
227
|
MetodosAceitos = ['post', 'get', 'patch', 'put']
|
|
176
228
|
if not any(element in self.Metodo for element in MetodosAceitos):
|
|
177
229
|
self.logger.critico(f'Método {self.Metodo} não previsto. Abortando chamada!', exit=1)
|
|
178
230
|
else:
|
|
179
|
-
ChamadaApi = f'self.Sessao.{self.Metodo}(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify)' if self.Payload is None
|
|
231
|
+
ChamadaApi = f'self.Sessao.{self.Metodo}(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify)' if self.Payload is None and self.File is None else \
|
|
232
|
+
f'self.Sessao.{self.Metodo}(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify, json=self.Payload)' if self.Payload and self.File is None else \
|
|
233
|
+
f'self.Sessao.{self.Metodo}(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify, files=self.File)' if self.Payload is None and self.File else \
|
|
234
|
+
f'self.Sessao.{self.Metodo}(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify, json=self.Payload, files=self.File)'
|
|
235
|
+
|
|
180
236
|
self.controla_cadencia()
|
|
181
237
|
self.TempoUltReq = time()
|
|
182
238
|
try:
|
|
183
239
|
self.RetEndPoint = eval(ChamadaApi)
|
|
184
240
|
if self.RetEndPoint.status_code >= 500:
|
|
185
|
-
self.logger.critico(f'Erro {self.RetEndPoint.status_code}
|
|
241
|
+
self.logger.critico(f'Erro [{self.RetEndPoint.status_code}] no lado servidor na resposta à requisição')
|
|
186
242
|
raise Exception
|
|
187
243
|
self.RetEndPoint.Espera = self.Espera ## adiona o tempo de espera ao retorno da API
|
|
188
244
|
self.RetEndPoint.Intervalo = self.Intervalo ## adiciona o intervalo entre chamada ao retorno da API
|
|
@@ -192,7 +248,7 @@ Para uso em APIs com autenticação JWT (JSON Web Token), OAuth, Bearer Token Au
|
|
|
192
248
|
return Err
|
|
193
249
|
except Exception as Err:
|
|
194
250
|
self.logger.critico(f'Falha na chamada do endpoint: {Err}\nEndpoint: {self.EndPoint}\nCodigo retorno: {self.RetEndPoint.status_code}\nResposta:{self.RetEndPoint.text}')
|
|
195
|
-
return
|
|
251
|
+
return self.RetEndPoint
|
|
196
252
|
#
|
|
197
253
|
#
|
|
198
254
|
def trata_erro_sienge(CodRet, Retorno):
|
|
@@ -208,10 +208,10 @@ conexao.close()
|
|
|
208
208
|
#
|
|
209
209
|
def db_update(self, Query): # Retorna um cursor à partir de um select
|
|
210
210
|
UpdRows = 0
|
|
211
|
-
BlackList = ['INSERT ', '
|
|
211
|
+
BlackList = ['INSERT ', 'SELECT ', 'CREATE ', 'DROP ', 'MERGE ', 'REPLACE ', 'CALL ', 'EXECUTE ']
|
|
212
212
|
if any(element in Query.upper() for element in BlackList):
|
|
213
213
|
BlackListed = [element for element in BlackList if element in Query.upper()]
|
|
214
|
-
self.logger.erro(f'{__name__}: Este método permite apenas updates. A query informada possui as seguintes palavras reservadas não aceitas: {BlackListed} e não foi executada!')
|
|
214
|
+
self.logger.erro(f'{__name__}: Este método permite apenas updates e deletes. A query informada possui as seguintes palavras reservadas não aceitas: {BlackListed} e não foi executada!')
|
|
215
215
|
return None
|
|
216
216
|
else:
|
|
217
217
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|