bb_api 0.5.0__tar.gz → 0.5.1__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.
- {bb_api-0.5.0 → bb_api-0.5.1}/PKG-INFO +1 -1
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api/__init__.py +13 -2
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api/accountability.py +70 -2
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api.egg-info/PKG-INFO +1 -1
- {bb_api-0.5.0 → bb_api-0.5.1}/pyproject.toml +1 -1
- {bb_api-0.5.0 → bb_api-0.5.1}/LICENSE +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/README.md +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api/common.py +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api/gestao_agil.py +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api/sia.py +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api.egg-info/SOURCES.txt +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api.egg-info/dependency_links.txt +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api.egg-info/requires.txt +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/bb_api.egg-info/top_level.txt +0 -0
- {bb_api-0.5.0 → bb_api-0.5.1}/setup.cfg +0 -0
|
@@ -4,11 +4,18 @@ from importlib.metadata import PackageNotFoundError, version
|
|
|
4
4
|
try:
|
|
5
5
|
__version__ = version("bb_api")
|
|
6
6
|
except PackageNotFoundError:
|
|
7
|
-
__version__ = "0.5.
|
|
7
|
+
__version__ = "0.5.1"
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
from .common import Ambiente
|
|
11
|
-
from .accountability import
|
|
11
|
+
from .accountability import (
|
|
12
|
+
MAX_DIAS_EXTRATO,
|
|
13
|
+
AccountabilityV3RepasseAPI,
|
|
14
|
+
AccountabilityV3ControleAPI,
|
|
15
|
+
ExtratoError,
|
|
16
|
+
IntervaloLongoDemaisError,
|
|
17
|
+
SemLancamentosError,
|
|
18
|
+
)
|
|
12
19
|
from .sia import (
|
|
13
20
|
BBSiaAPI,
|
|
14
21
|
CredenciaisNecessariasError,
|
|
@@ -21,11 +28,15 @@ from .gestao_agil import (
|
|
|
21
28
|
)
|
|
22
29
|
|
|
23
30
|
__all__ = [
|
|
31
|
+
"MAX_DIAS_EXTRATO",
|
|
24
32
|
"Ambiente",
|
|
25
33
|
"AccountabilityV3RepasseAPI",
|
|
26
34
|
"AccountabilityV3ControleAPI",
|
|
27
35
|
"BBSiaAPI",
|
|
28
36
|
"CredenciaisNecessariasError",
|
|
37
|
+
"ExtratoError",
|
|
38
|
+
"IntervaloLongoDemaisError",
|
|
39
|
+
"SemLancamentosError",
|
|
29
40
|
"FalhaDownload",
|
|
30
41
|
"ResultadoDownloads",
|
|
31
42
|
"parse_retorno_abertura_massificada",
|
|
@@ -9,6 +9,74 @@ import requests
|
|
|
9
9
|
import bb_api.common as common
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
MAX_DIAS_EXTRATO = 31
|
|
13
|
+
"""Maior intervalo, em dias corridos, aceito numa consulta de extrato.
|
|
14
|
+
|
|
15
|
+
``startDate`` e ``endDate`` podem distar no máximo esse tanto: 31 dias passam,
|
|
16
|
+
32 devolvem ``400``. Períodos maiores precisam ser fatiados pelo chamador.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
_ERRO_SEM_LANCAMENTOS = "não existem lançamentos"
|
|
20
|
+
_ERRO_INTERVALO_LONGO = "maior do que 31 dias"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ExtratoError(Exception):
|
|
24
|
+
"""Erro devolvido pela API ao consultar o extrato do órgão repassador.
|
|
25
|
+
|
|
26
|
+
Carrega o status HTTP e a mensagem originais do Banco do Brasil, porque a
|
|
27
|
+
API usa ``400`` tanto para falha de verdade quanto para situações normais.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
status_code: int
|
|
31
|
+
mensagem: str
|
|
32
|
+
|
|
33
|
+
def __init__(self, status_code: int, mensagem: str) -> None:
|
|
34
|
+
detalhe = f"(HTTP {status_code}): {mensagem}"
|
|
35
|
+
super().__init__(f"Não foi possível reaver o extrato do órgão repassador {detalhe}")
|
|
36
|
+
self.status_code = status_code
|
|
37
|
+
self.mensagem = mensagem
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class SemLancamentosError(ExtratoError):
|
|
41
|
+
"""A conta não tem lançamento nenhum no período consultado.
|
|
42
|
+
|
|
43
|
+
A API responde ``400`` nesse caso, e não ``200`` com uma lista vazia, então
|
|
44
|
+
esse resultado normal chega como erro e precisa ser separado de uma falha —
|
|
45
|
+
senão uma conta parada vira indistinguível de uma consulta quebrada.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class IntervaloLongoDemaisError(ExtratoError):
|
|
50
|
+
"""O intervalo pedido passa dos ``MAX_DIAS_EXTRATO`` dias corridos."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _mensagem_de_erro(res: requests.Response) -> str:
|
|
54
|
+
try:
|
|
55
|
+
corpo = cast("object", res.json())
|
|
56
|
+
except ValueError:
|
|
57
|
+
return res.text.strip()
|
|
58
|
+
|
|
59
|
+
if not isinstance(corpo, dict):
|
|
60
|
+
return res.text.strip()
|
|
61
|
+
|
|
62
|
+
campos = cast("dict[str, object]", corpo)
|
|
63
|
+
for chave in ("error", "message", "mensagem", "erro"):
|
|
64
|
+
valor = campos.get(chave)
|
|
65
|
+
if isinstance(valor, str) and valor:
|
|
66
|
+
return valor
|
|
67
|
+
return res.text.strip()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _erro_extrato(res: requests.Response) -> ExtratoError:
|
|
71
|
+
mensagem = _mensagem_de_erro(res)
|
|
72
|
+
normalizada = mensagem.casefold()
|
|
73
|
+
if _ERRO_SEM_LANCAMENTOS in normalizada:
|
|
74
|
+
return SemLancamentosError(res.status_code, mensagem)
|
|
75
|
+
if _ERRO_INTERVALO_LONGO in normalizada:
|
|
76
|
+
return IntervaloLongoDemaisError(res.status_code, mensagem)
|
|
77
|
+
return ExtratoError(res.status_code, mensagem)
|
|
78
|
+
|
|
79
|
+
|
|
12
80
|
class _AccountabilityV3BaseAPI:
|
|
13
81
|
_app_key: str
|
|
14
82
|
_client_id: str
|
|
@@ -224,7 +292,7 @@ class AccountabilityV3RepasseAPI(_AccountabilityV3BaseAPI):
|
|
|
224
292
|
)
|
|
225
293
|
|
|
226
294
|
if res.status_code != 200:
|
|
227
|
-
raise
|
|
295
|
+
raise _erro_extrato(res)
|
|
228
296
|
|
|
229
297
|
res = common.parse_json_object(res)
|
|
230
298
|
|
|
@@ -1233,7 +1301,7 @@ class AccountabilityV3ControleAPI(_AccountabilityV3BaseAPI):
|
|
|
1233
1301
|
)
|
|
1234
1302
|
|
|
1235
1303
|
if res.status_code != 200:
|
|
1236
|
-
raise
|
|
1304
|
+
raise _erro_extrato(res)
|
|
1237
1305
|
|
|
1238
1306
|
res = common.parse_json_object(res)
|
|
1239
1307
|
|
|
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
|