bigdata-corp-api 0.16__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.
- bigdata_corp_api-0.16/LICENSE +28 -0
- bigdata_corp_api-0.16/PKG-INFO +17 -0
- bigdata_corp_api-0.16/README.md +2 -0
- bigdata_corp_api-0.16/pyproject.toml +72 -0
- bigdata_corp_api-0.16/src/bigdatacorp_api/__init__.py +0 -0
- bigdata_corp_api-0.16/src/bigdatacorp_api/data.py +734 -0
- bigdata_corp_api-0.16/src/bigdatacorp_api/exceptions.py +66 -0
- bigdata_corp_api-0.16/src/bigdatacorp_api/tests/test__bigdata_api.py +30 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023, Murabei Data Science
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bigdata-corp-api
|
|
3
|
+
Version: 0.16
|
|
4
|
+
Summary: Python API to facilitate interaction with BigDataCorp end-points
|
|
5
|
+
License: BSD-3-Clause License
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Author: André Andrade Baceti
|
|
8
|
+
Author-email: a.baceti@murabei.com
|
|
9
|
+
Requires-Python: >=3.6
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Dist: requests
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# bigdata-corp-api
|
|
16
|
+
Python API to facilitate interaction with BigDataCorp end-points
|
|
17
|
+
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "bigdata-corp-api"
|
|
3
|
+
version = "0.16"
|
|
4
|
+
description = "Python API to facilitate interaction with BigDataCorp end-points"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.6"
|
|
7
|
+
license = { text = "BSD-3-Clause License" }
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "André Andrade Baceti", email = "a.baceti@murabei.com"}
|
|
10
|
+
]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Programming Language :: Python :: 3",
|
|
13
|
+
"Operating System :: OS Independent",
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"requests"
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[tool.poetry]
|
|
20
|
+
packages = [{include = "bigdatacorp_api", from = "src"}]
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
24
|
+
build-backend = "poetry.core.masonry.api"
|
|
25
|
+
|
|
26
|
+
[tool.ruff]
|
|
27
|
+
line-length = 79 # Quantidade de caracteres que o linter irá considerar na linha
|
|
28
|
+
indent-width = 4
|
|
29
|
+
|
|
30
|
+
# Pastas onde o linter não atuara. Por padrão ele só lê arquivos python e ignora tudo dentro do .gitignore
|
|
31
|
+
exclude = [
|
|
32
|
+
"secrets/",
|
|
33
|
+
"__init__.py",
|
|
34
|
+
"setup_template.py",
|
|
35
|
+
"setup.py"
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
# Lista de linters que serão aplicados. o ruff da suporte a vários e eles podem ser adicionados aqui.
|
|
39
|
+
[tool.ruff.lint]
|
|
40
|
+
select = [
|
|
41
|
+
"F", # Pyflakes - Procura bugs básicos no codigo
|
|
42
|
+
"E", # pycodestyle - Pep8
|
|
43
|
+
"W", # pycodestyle - Pep8
|
|
44
|
+
"D", # pydocstyle - Docstring
|
|
45
|
+
"I", # Isort - Imports
|
|
46
|
+
"PD", # pandas-vet - linter de pandas (não deixa usar inplace nem df como nome de variavel)
|
|
47
|
+
"N", # pep8-naming - nomes seguindo pep8
|
|
48
|
+
"S", # flake8-bandit - linter de vulnerabilidade (nmao deixa usar assert)
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
# Os códigos de erros colocados aqui são ignorados pelo linter. O erro abaixo é em relação ao assert. Está comentado por padrão.
|
|
52
|
+
ignore = [
|
|
53
|
+
# "S101" # Use of `assert` detected
|
|
54
|
+
"E402", "N806", "I001"
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
# ativa um modo plus do ruff
|
|
58
|
+
preview = true
|
|
59
|
+
|
|
60
|
+
[tool.ruff.format]
|
|
61
|
+
indent-style = "space"
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint.pydocstyle]
|
|
64
|
+
convention = "google" # seleciona as docstrings do google como padrão
|
|
65
|
+
|
|
66
|
+
[tool.ruff.lint.isort]
|
|
67
|
+
no-sections = true
|
|
68
|
+
|
|
69
|
+
[dependency-groups]
|
|
70
|
+
docs = [
|
|
71
|
+
"mkdocs (>=1.6.1,<2.0.0)"
|
|
72
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
"""BigDataCorp Python API."""
|
|
2
|
+
import os
|
|
3
|
+
import time
|
|
4
|
+
import json
|
|
5
|
+
import time
|
|
6
|
+
import datetime
|
|
7
|
+
import requests
|
|
8
|
+
from bigdatacorp_api.exceptions import (
|
|
9
|
+
BigDataCorpAPIException, BigDataCorpAPIInvalidDocumentException,
|
|
10
|
+
BigDataCorpAPIMinorDocumentException,
|
|
11
|
+
BigDataCorpAPIInvalidDatabaseException,
|
|
12
|
+
BigDataCorpAPIMaxRetryException,
|
|
13
|
+
BigDataCorpAPIInvalidInputException,
|
|
14
|
+
BigDataCorpAPILoginProblemException,
|
|
15
|
+
BigDataCorpAPIProblemAPIException,
|
|
16
|
+
BigDataCorpAPIOnDemandQueriesException,
|
|
17
|
+
BigDataCorpAPIMonitoringAPIException,
|
|
18
|
+
BigDataCorpAPIUnmappedErrorException,
|
|
19
|
+
BigDataCorpAPIEmptyEnrichedProcessException)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BigDataCorpAPI:
|
|
23
|
+
CPF_DATABASES = [
|
|
24
|
+
"government_debtors",
|
|
25
|
+
"election_candidate_data",
|
|
26
|
+
"circles_college_class",
|
|
27
|
+
"circles_coworkers",
|
|
28
|
+
"circles_household",
|
|
29
|
+
"circles_relatives",
|
|
30
|
+
"circles_lawsuit_parties",
|
|
31
|
+
"circles_partners",
|
|
32
|
+
"circles_neighbors",
|
|
33
|
+
"circles_building",
|
|
34
|
+
"basic_data",
|
|
35
|
+
"occupation_data",
|
|
36
|
+
"electoral_donors",
|
|
37
|
+
"related_people_emails",
|
|
38
|
+
"addresses_extended",
|
|
39
|
+
"related_people_addresses",
|
|
40
|
+
"media_profile_and_exposure",
|
|
41
|
+
"company_group_employed",
|
|
42
|
+
"company_group_family_ownership",
|
|
43
|
+
"company_group_sued",
|
|
44
|
+
"company_group_ownership",
|
|
45
|
+
"historical_basic_data",
|
|
46
|
+
"financial_data",
|
|
47
|
+
"demographic_data",
|
|
48
|
+
"licenses_and_authorizations",
|
|
49
|
+
"life_stages",
|
|
50
|
+
"collections",
|
|
51
|
+
"electoral_providers",
|
|
52
|
+
"indebtedness_question",
|
|
53
|
+
"processes",
|
|
54
|
+
"first_level_relatives_lawsuit_data",
|
|
55
|
+
"business_relationships",
|
|
56
|
+
"related_people",
|
|
57
|
+
"phones_extended",
|
|
58
|
+
"related_people_phones",
|
|
59
|
+
"vehicles",
|
|
60
|
+
"registration_data"]
|
|
61
|
+
|
|
62
|
+
CNPJ_DATABASES = [
|
|
63
|
+
"partner_murabei_credit_score_company",
|
|
64
|
+
"government_debtors",
|
|
65
|
+
"syndicate_agreements",
|
|
66
|
+
"investment_fund_data",
|
|
67
|
+
'electoral_donors',
|
|
68
|
+
'owners_electoral_donors',
|
|
69
|
+
'company_evolution',
|
|
70
|
+
'activity_indicators',
|
|
71
|
+
'interests_and_behaviors',
|
|
72
|
+
'licenses_and_authorizations',
|
|
73
|
+
"financial_market",
|
|
74
|
+
'electoral_providers',
|
|
75
|
+
'industrial_property',
|
|
76
|
+
'employees_industrial_property',
|
|
77
|
+
'owners_industrial_property',
|
|
78
|
+
'domains',
|
|
79
|
+
'domains_extended',
|
|
80
|
+
'emails_extended',
|
|
81
|
+
'related_people_emails',
|
|
82
|
+
'addresses_extended',
|
|
83
|
+
'related_people_addresses',
|
|
84
|
+
'phones_extended',
|
|
85
|
+
'related_people_phones',
|
|
86
|
+
'basic_data',
|
|
87
|
+
'history_basic_data',
|
|
88
|
+
'media_profile_and_exposure',
|
|
89
|
+
'kyc_dtec_flex_news',
|
|
90
|
+
'kyc',
|
|
91
|
+
'economic_group_kyc',
|
|
92
|
+
'employees_kyc',
|
|
93
|
+
'owners_kyc',
|
|
94
|
+
'online_ads',
|
|
95
|
+
'marketplace_data',
|
|
96
|
+
'apps_networks_and_platforms',
|
|
97
|
+
'collections',
|
|
98
|
+
'owners_lawsuits',
|
|
99
|
+
'processes',
|
|
100
|
+
'reputations_and_reviews',
|
|
101
|
+
"social_conscience",
|
|
102
|
+
"awards_and_certifications",
|
|
103
|
+
'circles_employees',
|
|
104
|
+
'circles_legal_representatives',
|
|
105
|
+
'circles_first_level_owners',
|
|
106
|
+
'economic_group_full_extended',
|
|
107
|
+
'economic_group_first_level_extended',
|
|
108
|
+
'economic_group_second_level_extended',
|
|
109
|
+
'economic_group_third_level_extended',
|
|
110
|
+
'company_group_household_activity',
|
|
111
|
+
'company_group_rfcontact',
|
|
112
|
+
'company_group_household',
|
|
113
|
+
'company_group_tradename',
|
|
114
|
+
'company_group_tradename_city',
|
|
115
|
+
'company_group_building',
|
|
116
|
+
'company_group_documentroot',
|
|
117
|
+
'company_group_officialname',
|
|
118
|
+
'company_group_legal_representative',
|
|
119
|
+
'company_group_owners',
|
|
120
|
+
'company_group_household_owners_surname',
|
|
121
|
+
'relationships',
|
|
122
|
+
'economic_group_relationships',
|
|
123
|
+
"registration_data"]
|
|
124
|
+
|
|
125
|
+
MARKETPLACE_DATABASES = [
|
|
126
|
+
"partner_murabei_credit_score_company"
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
PROCESS_DATABASES = [
|
|
130
|
+
'basic_data',
|
|
131
|
+
'cade_processes_data'
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
def __init__(self, bigdata_auth_token: str):
|
|
135
|
+
"""
|
|
136
|
+
__init__.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
bigdata_auth_token [str]: Authentication token for BigData API.
|
|
140
|
+
"""
|
|
141
|
+
self._bigdata_auth_token = bigdata_auth_token
|
|
142
|
+
|
|
143
|
+
def list_cpf_dataset(self) -> list:
|
|
144
|
+
"""
|
|
145
|
+
Return avaiable BigData CPF Datasets.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
No Args
|
|
149
|
+
Kwargs:
|
|
150
|
+
No Kwargs
|
|
151
|
+
Return:
|
|
152
|
+
Return a list with avaiable datasets.
|
|
153
|
+
"""
|
|
154
|
+
return self.CPF_DATABASES
|
|
155
|
+
|
|
156
|
+
def list_cnpj_dataset(self) -> list:
|
|
157
|
+
"""
|
|
158
|
+
Return avaiable BigData CNPJ Datasets.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
No Args
|
|
162
|
+
Kwargs:
|
|
163
|
+
No Kwargs
|
|
164
|
+
Return:
|
|
165
|
+
Return a list with avaiable datasets.
|
|
166
|
+
"""
|
|
167
|
+
return self.CNPJ_DATABASES
|
|
168
|
+
|
|
169
|
+
def list_process_dataset(self) -> list:
|
|
170
|
+
"""
|
|
171
|
+
Return avaiable BigData process Datasets.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
No Args
|
|
175
|
+
Kwargs:
|
|
176
|
+
No Kwargs
|
|
177
|
+
Return:
|
|
178
|
+
Return a list with avaiable datasets.
|
|
179
|
+
"""
|
|
180
|
+
return self.PROCESS_DATABASES
|
|
181
|
+
|
|
182
|
+
def get_cpf_dataset(self, cpf: str, dataset: str) -> dict:
|
|
183
|
+
"""
|
|
184
|
+
Call BigData API to fecth a database for a CPF.
|
|
185
|
+
|
|
186
|
+
Retry for 5 times sleeping 1 second when errors are raised.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
cpf [str]: Person's CPF.
|
|
190
|
+
dataset [str]: Dataset on BigData that user should be fetched.
|
|
191
|
+
Return [dict]:
|
|
192
|
+
Information avaiable on BigData.
|
|
193
|
+
Raise:
|
|
194
|
+
BigDataCorpAPIException: Raise if errors in API occour.
|
|
195
|
+
"""
|
|
196
|
+
if dataset not in self.CPF_DATABASES:
|
|
197
|
+
msg = (
|
|
198
|
+
"dataset [{dataset}] not avaiable on bigboost for CPF, "
|
|
199
|
+
"avaiable datasets:\n{datasets}").format(
|
|
200
|
+
dataset=dataset, datasets=", ".join(self.CPF_DATABASES))
|
|
201
|
+
raise BigDataCorpAPIException(msg)
|
|
202
|
+
|
|
203
|
+
url = "https://bigboost.bigdatacorp.com.br/peoplev2"
|
|
204
|
+
payload = {
|
|
205
|
+
"Datasets": dataset,
|
|
206
|
+
"q": "doc{" + cpf + "}",
|
|
207
|
+
"Limit": 1}
|
|
208
|
+
headers = {
|
|
209
|
+
"accept": "application/json",
|
|
210
|
+
"content-type": "application/json",
|
|
211
|
+
"AccessToken": self._bigdata_auth_token}
|
|
212
|
+
|
|
213
|
+
error_msgs = []
|
|
214
|
+
for i in range(5):
|
|
215
|
+
try:
|
|
216
|
+
response = requests.post(url, json=payload, headers=headers)
|
|
217
|
+
response.raise_for_status()
|
|
218
|
+
response_json = response.json()
|
|
219
|
+
status_data = response_json['Status']
|
|
220
|
+
|
|
221
|
+
# Treat minor validation error
|
|
222
|
+
birth_validation = status_data.get('date_of_birth_validation')
|
|
223
|
+
if birth_validation is not None:
|
|
224
|
+
raise BigDataCorpAPIMinorDocumentException(
|
|
225
|
+
message="this cpf belongs to a minor",
|
|
226
|
+
payload=birth_validation[0])
|
|
227
|
+
|
|
228
|
+
login_entry = status_data.get("login")
|
|
229
|
+
if login_entry is not None:
|
|
230
|
+
login_return = login_entry[0]
|
|
231
|
+
if login_return["Code"] == -101:
|
|
232
|
+
msg = "BigBoost user has expired"
|
|
233
|
+
raise BigDataCorpAPILoginProblemException(msg)
|
|
234
|
+
|
|
235
|
+
# Check if the CPF has a match
|
|
236
|
+
status = status_data[dataset][0]
|
|
237
|
+
if status['Code'] == 0:
|
|
238
|
+
return response.json()
|
|
239
|
+
|
|
240
|
+
elif status['Code'] >= -202 and status['Code'] <= -100:
|
|
241
|
+
raise BigDataCorpAPIInvalidInputException(
|
|
242
|
+
message="error related to input data",
|
|
243
|
+
payload={
|
|
244
|
+
'bigdata_status': status,
|
|
245
|
+
'cpf': cpf,
|
|
246
|
+
'dataset': dataset})
|
|
247
|
+
|
|
248
|
+
elif status['Code'] >= -1002 and status['Code'] <= -1000:
|
|
249
|
+
raise BigDataCorpAPILoginProblemException(
|
|
250
|
+
message="error related to login problem",
|
|
251
|
+
payload={
|
|
252
|
+
'bigdata_status': status,
|
|
253
|
+
'cpf': cpf,
|
|
254
|
+
'dataset': dataset
|
|
255
|
+
})
|
|
256
|
+
elif status['Code'] >= -2999 and status['Code'] <= -2000:
|
|
257
|
+
raise BigDataCorpAPIProblemAPIException(
|
|
258
|
+
message="error related to internal problems in APIs "
|
|
259
|
+
"or services",
|
|
260
|
+
payload={
|
|
261
|
+
'bigdata_status': status,
|
|
262
|
+
'cpf': cpf,
|
|
263
|
+
'dataset': dataset
|
|
264
|
+
})
|
|
265
|
+
elif status['Code'] >= -1999 and status['Code'] <= -1200:
|
|
266
|
+
raise BigDataCorpAPIOnDemandQueriesException(
|
|
267
|
+
message="error related to on-demand queries",
|
|
268
|
+
payload={
|
|
269
|
+
'bigdata_status': status,
|
|
270
|
+
'cpf': cpf,
|
|
271
|
+
'dataset': dataset
|
|
272
|
+
})
|
|
273
|
+
elif status['Code'] <= -3000:
|
|
274
|
+
raise BigDataCorpAPIMonitoringAPIException(
|
|
275
|
+
message="error related to problems in the Monitoring "
|
|
276
|
+
"API or Asynchronous Calls",
|
|
277
|
+
payload={
|
|
278
|
+
'bigdata_status': status,
|
|
279
|
+
'cpf': cpf,
|
|
280
|
+
'dataset': dataset
|
|
281
|
+
})
|
|
282
|
+
else:
|
|
283
|
+
raise BigDataCorpAPIUnmappedErrorException(
|
|
284
|
+
message="unmapped error",
|
|
285
|
+
payload={
|
|
286
|
+
'bigdata_status': status,
|
|
287
|
+
'cpf': cpf,
|
|
288
|
+
'dataset': dataset
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
# Raise if document is invalid
|
|
292
|
+
except BigDataCorpAPIException as e:
|
|
293
|
+
raise e
|
|
294
|
+
|
|
295
|
+
# Raise if document is invalid
|
|
296
|
+
except BigDataCorpAPILoginProblemException as e:
|
|
297
|
+
raise e
|
|
298
|
+
|
|
299
|
+
# Raise if document is from an under age (age < 18)
|
|
300
|
+
except BigDataCorpAPIMinorDocumentException as e:
|
|
301
|
+
raise e
|
|
302
|
+
|
|
303
|
+
except Exception as e:
|
|
304
|
+
error_msgs.append(str(e))
|
|
305
|
+
print("!!Error fetching BigData API:", str(e))
|
|
306
|
+
|
|
307
|
+
msg = (
|
|
308
|
+
"Untreated error on API with max 5 retries:{}\n".format(
|
|
309
|
+
"\n".join(error_msgs)))
|
|
310
|
+
raise BigDataCorpAPIMaxRetryException(
|
|
311
|
+
message=msg, payload={"errors": error_msgs})
|
|
312
|
+
|
|
313
|
+
def get_cnpj_dataset(self, cnpj: str, dataset: str) -> dict:
|
|
314
|
+
"""
|
|
315
|
+
Call BigData API to fecth a database for a CNPJ.
|
|
316
|
+
|
|
317
|
+
Retry for 5 times sleeping 1 second when errors are raised.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
cnpj [str]: Company CNPJ.
|
|
321
|
+
dataset [str]: Dataset on BigData that user should be fetched.
|
|
322
|
+
Return [dict]:
|
|
323
|
+
Information avaiable on BigData.
|
|
324
|
+
Raise:
|
|
325
|
+
BigDataCorpAPIException: Raise if errors in API occour.
|
|
326
|
+
"""
|
|
327
|
+
if dataset not in self.CNPJ_DATABASES:
|
|
328
|
+
msg = (
|
|
329
|
+
"dataset [{dataset}] not avaiable on bigboost for CNPJ, "
|
|
330
|
+
"avaiable datasets:\n{datasets}").format(
|
|
331
|
+
dataset=dataset, datasets=", ".join(self.CNPJ_DATABASES))
|
|
332
|
+
raise BigDataCorpAPIException(msg)
|
|
333
|
+
|
|
334
|
+
if dataset in self.MARKETPLACE_DATABASES:
|
|
335
|
+
url = "https://plataforma.bigdatacorp.com.br/marketplace"
|
|
336
|
+
else:
|
|
337
|
+
url = "https://bigboost.bigdatacorp.com.br/companies"
|
|
338
|
+
|
|
339
|
+
payload = {
|
|
340
|
+
"Datasets": dataset,
|
|
341
|
+
"q": "doc{" + cnpj + "}",
|
|
342
|
+
"Limit": 1}
|
|
343
|
+
headers = {
|
|
344
|
+
"accept": "application/json",
|
|
345
|
+
"content-type": "application/json",
|
|
346
|
+
"AccessToken": self._bigdata_auth_token}
|
|
347
|
+
|
|
348
|
+
error_msgs = []
|
|
349
|
+
for i in range(5):
|
|
350
|
+
try:
|
|
351
|
+
response = requests.post(url, json=payload, headers=headers)
|
|
352
|
+
response.raise_for_status()
|
|
353
|
+
response_json = response.json()
|
|
354
|
+
status_data = response_json['Status']
|
|
355
|
+
|
|
356
|
+
login_entry = status_data.get("login")
|
|
357
|
+
if login_entry is not None:
|
|
358
|
+
login_return = login_entry[0]
|
|
359
|
+
if login_return["Code"] == -101:
|
|
360
|
+
msg = "BigBoost user has expired"
|
|
361
|
+
raise BigDataCorpAPILoginProblemException(msg)
|
|
362
|
+
|
|
363
|
+
# Check if the CNPJ has a match
|
|
364
|
+
status = status_data[dataset][0]
|
|
365
|
+
if status['Code'] == 0:
|
|
366
|
+
return response.json()
|
|
367
|
+
elif status['Code'] >= -202 and status['Code'] <= -100:
|
|
368
|
+
raise BigDataCorpAPIInvalidInputException(
|
|
369
|
+
message="error related to input data",
|
|
370
|
+
payload={
|
|
371
|
+
'bigdata_status': status,
|
|
372
|
+
'cnpj': cnpj,
|
|
373
|
+
'dataset': dataset
|
|
374
|
+
})
|
|
375
|
+
elif status['Code'] >= -1002 and status['Code'] <= -1000:
|
|
376
|
+
raise BigDataCorpAPILoginProblemException(
|
|
377
|
+
message="error related to login problem",
|
|
378
|
+
payload={
|
|
379
|
+
'bigdata_status': status,
|
|
380
|
+
'cnpj': cnpj,
|
|
381
|
+
'dataset': dataset
|
|
382
|
+
})
|
|
383
|
+
elif status['Code'] >= -2999 and status['Code'] <= -2000:
|
|
384
|
+
raise BigDataCorpAPIProblemAPIException(
|
|
385
|
+
message="error related to internal problems in APIs "
|
|
386
|
+
"or services",
|
|
387
|
+
payload={
|
|
388
|
+
'bigdata_status': status,
|
|
389
|
+
'cnpj': cnpj,
|
|
390
|
+
'dataset': dataset
|
|
391
|
+
})
|
|
392
|
+
elif status['Code'] >= -1999 and status['Code'] <= -1200:
|
|
393
|
+
raise BigDataCorpAPIOnDemandQueriesException(
|
|
394
|
+
message="error related to on-demand queries",
|
|
395
|
+
payload={
|
|
396
|
+
'bigdata_status': status,
|
|
397
|
+
'cnpj': cnpj,
|
|
398
|
+
'dataset': dataset
|
|
399
|
+
})
|
|
400
|
+
elif status['Code'] <= -3000:
|
|
401
|
+
raise BigDataCorpAPIMonitoringAPIException(
|
|
402
|
+
message="error related to problems in the Monitoring "
|
|
403
|
+
"API or Asynchronous Calls",
|
|
404
|
+
payload={
|
|
405
|
+
'bigdata_status': status,
|
|
406
|
+
'cnpj': cnpj,
|
|
407
|
+
'dataset': dataset
|
|
408
|
+
})
|
|
409
|
+
else:
|
|
410
|
+
raise BigDataCorpAPIUnmappedErrorException(
|
|
411
|
+
message="unmapped error",
|
|
412
|
+
payload={
|
|
413
|
+
'bigdata_status': status,
|
|
414
|
+
'cnpj': cnpj,
|
|
415
|
+
'dataset': dataset
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
# Raise if document is invalid
|
|
419
|
+
except BigDataCorpAPIException as e:
|
|
420
|
+
raise e
|
|
421
|
+
|
|
422
|
+
except Exception as e:
|
|
423
|
+
error_msgs.append(str(e))
|
|
424
|
+
print("!!Error fetching BigData API:", str(e))
|
|
425
|
+
|
|
426
|
+
msg = (
|
|
427
|
+
"Untreated error on API with max 5 retries:{}\n".format(
|
|
428
|
+
"\n".join(error_msgs)))
|
|
429
|
+
raise BigDataCorpAPIMaxRetryException(
|
|
430
|
+
message=msg, payload={"errors": error_msgs})
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def get_process_dataset(self, process: str, dataset: str) -> dict:
|
|
434
|
+
"""Call BigData API to fecth a database for a process.
|
|
435
|
+
|
|
436
|
+
Retry for 5 times sleeping 1 second when errors are raised.
|
|
437
|
+
|
|
438
|
+
Args:
|
|
439
|
+
process [str]: process number.
|
|
440
|
+
dataset [str]: Dataset on BigData that user should be fetched.
|
|
441
|
+
Return [dict]:
|
|
442
|
+
Information avaiable on BigData.
|
|
443
|
+
Raise:
|
|
444
|
+
BigDataCorpAPIException: Raise if errors in API occour.
|
|
445
|
+
"""
|
|
446
|
+
if dataset not in self.PROCESS_DATABASES:
|
|
447
|
+
msg = (
|
|
448
|
+
"dataset [{dataset}] not avaiable on bigboost for process, "
|
|
449
|
+
"avaiable datasets:\n{datasets}").format(
|
|
450
|
+
dataset=dataset, datasets=", ".join(self.PROCESS_DATABASES))
|
|
451
|
+
raise BigDataCorpAPIException(msg)
|
|
452
|
+
|
|
453
|
+
url = "https://plataforma.bigdatacorp.com.br/processos"
|
|
454
|
+
|
|
455
|
+
payload = {
|
|
456
|
+
"Datasets": dataset,
|
|
457
|
+
"q": "processnumber{" + process + "}",
|
|
458
|
+
"Limit": 1}
|
|
459
|
+
headers = {
|
|
460
|
+
"accept": "application/json",
|
|
461
|
+
"content-type": "application/json",
|
|
462
|
+
"AccessToken": self._bigdata_auth_token}
|
|
463
|
+
|
|
464
|
+
error_msgs = []
|
|
465
|
+
for i in range(5):
|
|
466
|
+
try:
|
|
467
|
+
response = requests.post(url, json=payload, headers=headers)
|
|
468
|
+
response.raise_for_status()
|
|
469
|
+
response_json = response.json()
|
|
470
|
+
status_data = response_json['Status']
|
|
471
|
+
result_data = response_json.\
|
|
472
|
+
get('Result', [{}])[0].\
|
|
473
|
+
get('BasicData', {})
|
|
474
|
+
|
|
475
|
+
login_entry = status_data.get("login")
|
|
476
|
+
if login_entry is not None:
|
|
477
|
+
login_return = login_entry[0]
|
|
478
|
+
if login_return["Code"] == -101:
|
|
479
|
+
msg = "BigBoost user has expired"
|
|
480
|
+
raise BigDataCorpAPILoginProblemException(msg)
|
|
481
|
+
|
|
482
|
+
# Check if the process has a match
|
|
483
|
+
status = status_data[dataset][0]
|
|
484
|
+
if status['Code'] == 0 and result_data:
|
|
485
|
+
return response.json()
|
|
486
|
+
elif not result_data:
|
|
487
|
+
raise BigDataCorpAPIEmptyEnrichedProcessException(
|
|
488
|
+
message="no process data returned",
|
|
489
|
+
payload={
|
|
490
|
+
'bigdata_status': status,
|
|
491
|
+
'process_number': process,
|
|
492
|
+
'dataset': dataset
|
|
493
|
+
})
|
|
494
|
+
elif status['Code'] >= -202 and status['Code'] <= -100:
|
|
495
|
+
raise BigDataCorpAPIInvalidInputException(
|
|
496
|
+
message="error related to input data",
|
|
497
|
+
payload={
|
|
498
|
+
'bigdata_status': status,
|
|
499
|
+
'process_number': process,
|
|
500
|
+
'dataset': dataset
|
|
501
|
+
})
|
|
502
|
+
elif status['Code'] >= -1002 and status['Code'] <= -1000:
|
|
503
|
+
raise BigDataCorpAPILoginProblemException(
|
|
504
|
+
message="error related to login problem",
|
|
505
|
+
payload={
|
|
506
|
+
'bigdata_status': status,
|
|
507
|
+
'process_number': process,
|
|
508
|
+
'dataset': dataset
|
|
509
|
+
})
|
|
510
|
+
elif status['Code'] >= -2999 and status['Code'] <= -2000:
|
|
511
|
+
raise BigDataCorpAPIProblemAPIException(
|
|
512
|
+
message="error related to internal problems in APIs "
|
|
513
|
+
"or services",
|
|
514
|
+
payload={
|
|
515
|
+
'bigdata_status': status,
|
|
516
|
+
'process_number': process,
|
|
517
|
+
'dataset': dataset
|
|
518
|
+
})
|
|
519
|
+
elif status['Code'] >= -1999 and status['Code'] <= -1200:
|
|
520
|
+
raise BigDataCorpAPIOnDemandQueriesException(
|
|
521
|
+
message="error related to on-demand queries",
|
|
522
|
+
payload={
|
|
523
|
+
'bigdata_status': status,
|
|
524
|
+
'process_number': process,
|
|
525
|
+
'dataset': dataset
|
|
526
|
+
})
|
|
527
|
+
elif status['Code'] <= -3000:
|
|
528
|
+
raise BigDataCorpAPIMonitoringAPIException(
|
|
529
|
+
message="error related to problems in the Monitoring "
|
|
530
|
+
"API or Asynchronous Calls",
|
|
531
|
+
payload={
|
|
532
|
+
'bigdata_status': status,
|
|
533
|
+
'process_number': process,
|
|
534
|
+
'dataset': dataset
|
|
535
|
+
})
|
|
536
|
+
else:
|
|
537
|
+
raise BigDataCorpAPIUnmappedErrorException(
|
|
538
|
+
message="unmapped error",
|
|
539
|
+
payload={
|
|
540
|
+
'bigdata_status': status,
|
|
541
|
+
'process_number': process,
|
|
542
|
+
'dataset': dataset
|
|
543
|
+
})
|
|
544
|
+
|
|
545
|
+
# Raise if document is invalid
|
|
546
|
+
except BigDataCorpAPIException as e:
|
|
547
|
+
raise e
|
|
548
|
+
|
|
549
|
+
except Exception as e:
|
|
550
|
+
error_msgs.append(str(e))
|
|
551
|
+
print("!!Error fetching BigData API:", str(e))
|
|
552
|
+
|
|
553
|
+
msg = (
|
|
554
|
+
"Untreated error on API with max 5 retries:{}\n".format(
|
|
555
|
+
"\n".join(error_msgs)))
|
|
556
|
+
raise BigDataCorpAPIMaxRetryException(
|
|
557
|
+
message=msg, payload={"errors": error_msgs})
|
|
558
|
+
|
|
559
|
+
def get_cpf_datasets(self, cpf: str, datasets: list,
|
|
560
|
+
verbosity: bool = False) -> dict:
|
|
561
|
+
"""
|
|
562
|
+
Fetch a list of datasets and return a dictionary with all info.
|
|
563
|
+
|
|
564
|
+
Args:
|
|
565
|
+
cpf [str]: Person's CPF.
|
|
566
|
+
datasets [list[str]]: List of all datasets to be fetched.
|
|
567
|
+
Kwargs:
|
|
568
|
+
verbosity [bool]: If set true will print a msg for each dataset
|
|
569
|
+
fetch.
|
|
570
|
+
Returns [dict]:
|
|
571
|
+
Return a dictionary with all dataset information, with keys
|
|
572
|
+
corresponding to dataset name.
|
|
573
|
+
"""
|
|
574
|
+
response_dict = {}
|
|
575
|
+
for db in datasets:
|
|
576
|
+
if verbosity:
|
|
577
|
+
print("Fetching dataset:", db)
|
|
578
|
+
response_dict[db] = self.get_cpf_dataset(
|
|
579
|
+
cpf=cpf, dataset=db)
|
|
580
|
+
return response_dict
|
|
581
|
+
|
|
582
|
+
def get_cnpj_datasets(self, cnpj: str, datasets: list,
|
|
583
|
+
verbosity: bool = False) -> dict:
|
|
584
|
+
"""
|
|
585
|
+
Fetch a list of datasets and return a dictionary with all info.
|
|
586
|
+
|
|
587
|
+
Args:
|
|
588
|
+
cnpj [str]: Company cnpj.
|
|
589
|
+
datasets [list[str]]: List of all datasets to be fetched.
|
|
590
|
+
Kwargs:
|
|
591
|
+
verbosity [bool]: If set true will print a msg for each dataset
|
|
592
|
+
fetch.
|
|
593
|
+
Returns [dict]:
|
|
594
|
+
Return a dictionary with all dataset information, with keys
|
|
595
|
+
corresponding to dataset name.
|
|
596
|
+
"""
|
|
597
|
+
cnpj = cnpj.replace(".", "").replace("/", "").replace("-", "")
|
|
598
|
+
response_dict = {}
|
|
599
|
+
for db in datasets:
|
|
600
|
+
if verbosity:
|
|
601
|
+
print("Fetching dataset:", db)
|
|
602
|
+
response_dict[db] = self.get_cnpj_dataset(
|
|
603
|
+
cnpj=cnpj, dataset=db)
|
|
604
|
+
return response_dict
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def get_process_datasets(self, process: str, datasets: list,
|
|
608
|
+
verbosity: bool = False) -> dict:
|
|
609
|
+
"""Fetch a list of datasets and return a dictionary with all info.
|
|
610
|
+
|
|
611
|
+
Args:
|
|
612
|
+
process [str]: process number.
|
|
613
|
+
datasets [list[str]]: List of all datasets to be fetched.
|
|
614
|
+
Kwargs:
|
|
615
|
+
verbosity [bool]: If set true will print a msg for each dataset
|
|
616
|
+
fetch.
|
|
617
|
+
Returns [dict]:
|
|
618
|
+
Return a dictionary with all dataset information, with keys
|
|
619
|
+
corresponding to dataset name.
|
|
620
|
+
"""
|
|
621
|
+
process = process.replace(".", "").replace("/", "").replace("-", "")
|
|
622
|
+
response_dict = {}
|
|
623
|
+
for db in datasets:
|
|
624
|
+
if verbosity:
|
|
625
|
+
print("Fetching dataset:", db)
|
|
626
|
+
response_dict[db] = self.get_process_dataset(
|
|
627
|
+
process=process, dataset=db)
|
|
628
|
+
return response_dict
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
def get_usage(self, initial_date: str, final_date: str):
|
|
632
|
+
"""
|
|
633
|
+
Retrieves usage data for a specified date range.
|
|
634
|
+
|
|
635
|
+
Parameters:
|
|
636
|
+
- initial_date (str): The initial date of the range in the format
|
|
637
|
+
'yyyy-MM-dd'.
|
|
638
|
+
- final_date (str): The final date of the range in the format
|
|
639
|
+
'yyyy-MM-dd'.
|
|
640
|
+
|
|
641
|
+
Returns:
|
|
642
|
+
- results (list): A list of dictionaries containing the usage data for
|
|
643
|
+
each API and endpoint.
|
|
644
|
+
Each dictionary has the following keys:
|
|
645
|
+
- 'api_type' (str): The type of API ('people' or 'companies').
|
|
646
|
+
- 'end_point' (str): The endpoint of the API.
|
|
647
|
+
- 'successful_requests' (int): The total number of successful
|
|
648
|
+
requests made.
|
|
649
|
+
- 'requests_with_error' (int): The total number of requests
|
|
650
|
+
with errors.
|
|
651
|
+
- 'queries_charged' (int): The total number of queries charged.
|
|
652
|
+
- 'queries_not_charged' (int): The total number of queries
|
|
653
|
+
not charged.
|
|
654
|
+
- 'estimated_price' (float): The total estimated price
|
|
655
|
+
for the usage.
|
|
656
|
+
|
|
657
|
+
"""
|
|
658
|
+
results = []
|
|
659
|
+
url = "https://plataforma.bigdatacorp.com.br/usage"
|
|
660
|
+
|
|
661
|
+
headers = {
|
|
662
|
+
"accept": "application/json",
|
|
663
|
+
"content-type": "application/json",
|
|
664
|
+
"AccessToken": self._bigdata_auth_token,
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
payload = {
|
|
668
|
+
"InitialReferenceDate": initial_date,
|
|
669
|
+
"FinalReferenceDate": final_date,
|
|
670
|
+
"DateFormat": "yyyy-MM-dd"
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
for api in self.CPF_DATABASES:
|
|
674
|
+
payload["Api"] = "people"
|
|
675
|
+
payload["Datasets"] = api
|
|
676
|
+
try:
|
|
677
|
+
response = requests.post(url, headers=headers, json=payload)
|
|
678
|
+
if response.status_code == 500:
|
|
679
|
+
response.raise_for_status()
|
|
680
|
+
|
|
681
|
+
if response.status_code != 200:
|
|
682
|
+
raise BigDataCorpAPIException(
|
|
683
|
+
response.json()['Status']['Message'])
|
|
684
|
+
|
|
685
|
+
results.append({
|
|
686
|
+
'api_type': "people",
|
|
687
|
+
'end_point': api,
|
|
688
|
+
"successful_requests": response.json()["UsageData"]
|
|
689
|
+
["TotalSuccessfulRequests"],
|
|
690
|
+
"requests_with_error": response.json()["UsageData"]
|
|
691
|
+
["TotalRequestsWithError"],
|
|
692
|
+
"queries_charged": response.json()["UsageData"]
|
|
693
|
+
["TotalQueriesCharged"],
|
|
694
|
+
"queries_not_charged": response.json()["UsageData"]
|
|
695
|
+
["TotalQueriesNotCharged"],
|
|
696
|
+
"estimated_price": response.json()["UsageData"]
|
|
697
|
+
["TotalEstimatedPrice"],
|
|
698
|
+
})
|
|
699
|
+
|
|
700
|
+
except Exception as err:
|
|
701
|
+
print(err)
|
|
702
|
+
|
|
703
|
+
for api in self.CNPJ_DATABASES:
|
|
704
|
+
payload["Api"] = "companies"
|
|
705
|
+
payload["Datasets"] = api
|
|
706
|
+
try:
|
|
707
|
+
response = requests.post(url, headers=headers, json=payload)
|
|
708
|
+
|
|
709
|
+
if response.status_code == 500:
|
|
710
|
+
response.raise_for_status()
|
|
711
|
+
|
|
712
|
+
if response.status_code != 200:
|
|
713
|
+
raise BigDataCorpAPIException(
|
|
714
|
+
response.json()['Status']['Message'])
|
|
715
|
+
|
|
716
|
+
results.append({
|
|
717
|
+
'api_type': "companies",
|
|
718
|
+
'end_point': api,
|
|
719
|
+
"successful_requests": response.json()["UsageData"]
|
|
720
|
+
["TotalSuccessfulRequests"],
|
|
721
|
+
"requests_with_error": response.json()["UsageData"]
|
|
722
|
+
["TotalRequestsWithError"],
|
|
723
|
+
"queries_charged": response.json()["UsageData"]
|
|
724
|
+
["TotalQueriesCharged"],
|
|
725
|
+
"queries_not_charged": response.json()["UsageData"]
|
|
726
|
+
["TotalQueriesNotCharged"],
|
|
727
|
+
"estimated_price": response.json()["UsageData"]
|
|
728
|
+
["TotalEstimatedPrice"],
|
|
729
|
+
})
|
|
730
|
+
|
|
731
|
+
except Exception as err:
|
|
732
|
+
print(err)
|
|
733
|
+
|
|
734
|
+
return results
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Custom exceptions for BigDataCorpAPI."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BigDataCorpAPIException(Exception):
|
|
5
|
+
def __repr__(self):
|
|
6
|
+
template = "{class_name}: {message}"
|
|
7
|
+
return template.format(
|
|
8
|
+
class_name=self.__class__.__name__,
|
|
9
|
+
message=self.message)
|
|
10
|
+
|
|
11
|
+
def __str__(self):
|
|
12
|
+
return self.__repr__()
|
|
13
|
+
|
|
14
|
+
def __init__(self, message: str, payload: dict = {}):
|
|
15
|
+
self.message = message
|
|
16
|
+
self.payload = payload
|
|
17
|
+
|
|
18
|
+
def to_dict(self):
|
|
19
|
+
rv = {
|
|
20
|
+
"payload": self.payload,
|
|
21
|
+
"type": self.__class__.__name__,
|
|
22
|
+
"message": self.message}
|
|
23
|
+
return rv
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BigDataCorpAPIInvalidDocumentException(BigDataCorpAPIException):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BigDataCorpAPIInvalidDatabaseException(BigDataCorpAPIException):
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BigDataCorpAPIMinorDocumentException(BigDataCorpAPIException):
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class BigDataCorpAPIMaxRetryException(BigDataCorpAPIException):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class BigDataCorpAPILoginProblemException(BigDataCorpAPIException):
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class BigDataCorpAPIProblemAPIException(BigDataCorpAPIException):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class BigDataCorpAPIOnDemandQueriesException(BigDataCorpAPIException):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class BigDataCorpAPIMonitoringAPIException(BigDataCorpAPIException):
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class BigDataCorpAPIUnmappedErrorException(BigDataCorpAPIException):
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class BigDataCorpAPIInvalidInputException(BigDataCorpAPIException):
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
class BigDataCorpAPIEmptyEnrichedProcessException(BigDataCorpAPIException):
|
|
66
|
+
pass
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Test BigDataCorpAPI."""
|
|
2
|
+
import os
|
|
3
|
+
import unittest
|
|
4
|
+
from bigdatacorp_api.data import BigDataCorpAPI
|
|
5
|
+
from bigdatacorp_api.exceptions import (
|
|
6
|
+
BigDataCorpAPIException, BigDataCorpAPIInvalidDocumentException,
|
|
7
|
+
BigDataCorpAPIMaxRetryException)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
BIGDATA_AUTH_TOKEN = os.environ.get("BIGDATA_AUTH_TOKEN")
|
|
11
|
+
TEST_CPF = os.environ.get("TEST_CPF")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestBigDataCorpAPI(unittest.TestCase):
|
|
15
|
+
"""Test process Calendar input data."""
|
|
16
|
+
|
|
17
|
+
def test__ok(self):
|
|
18
|
+
bigdata_api = BigDataCorpAPI(
|
|
19
|
+
bigdata_auth_token=BIGDATA_AUTH_TOKEN)
|
|
20
|
+
bigdata_api.get_cpf_dataset(
|
|
21
|
+
cpf=TEST_CPF, dataset="basic_data")
|
|
22
|
+
|
|
23
|
+
def test__invalid(self):
|
|
24
|
+
bigdata_api = BigDataCorpAPI(
|
|
25
|
+
bigdata_auth_token=BIGDATA_AUTH_TOKEN)
|
|
26
|
+
with self.assertRaises(
|
|
27
|
+
BigDataCorpAPIInvalidDocumentException) as context:
|
|
28
|
+
bigdata_api.get_cpf_dataset(
|
|
29
|
+
cpf=TEST_CPF + "0", dataset="basic_data")
|
|
30
|
+
self.assertEqual(context.exception.message, 'cpf is invalid')
|