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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lbxtoolkit
3
- Version: 2.2.7
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` opcional.
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 apenas APIs cujo payload (opcional) seja aceito no formato JSON.
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` opcional.
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 apenas APIs cujo payload (opcional) seja aceito no formato JSON.
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 endpoint_json(self, endpoint, metodo, payload=None): # Interage com End Point
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 else f'self.Sessao.{self.Metodo}(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify, json=self.Payload)'
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} na chamada do endpoint: {Err}\nEndpoint: {self.EndPoint}\nResposta: {self.RetEndPoint.text}')
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 Err
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 ', 'DELETE ', 'SELECT ', 'CREATE ', 'DROP ', 'MERGE ', 'REPLACE ', 'CALL ', 'EXECUTE ']
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:
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "lbxtoolkit"
3
- version = "2.2.7"
3
+ version = "2.2.9"
4
4
  description = ""
5
5
  authors = ["Cristiano P. Ferrari <cristiano.ferrari@lbx.com.br>"]
6
6
  readme = "README.md"