masstack-python-client 0.0.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.
- masstack_python_client/__init__.py +4 -0
- masstack_python_client/auth/__init__.py +0 -0
- masstack_python_client/auth/token.py +11 -0
- masstack_python_client/auth/token_manager.py +86 -0
- masstack_python_client/auth/token_store.py +34 -0
- masstack_python_client/client.py +85 -0
- masstack_python_client/data/data_utils.py +51 -0
- masstack_python_client/data/province_translation.csv +53 -0
- masstack_python_client/data/street_type_translation.csv +91 -0
- masstack_python_client/data/unit_translation.csv +13 -0
- masstack_python_client/exceptions.py +57 -0
- masstack_python_client/resources/__init__.py +0 -0
- masstack_python_client/resources/feasibility.py +267 -0
- masstack_python_client/resources/models/address.py +197 -0
- masstack_python_client-0.0.1.dist-info/METADATA +110 -0
- masstack_python_client-0.0.1.dist-info/RECORD +19 -0
- masstack_python_client-0.0.1.dist-info/WHEEL +5 -0
- masstack_python_client-0.0.1.dist-info/licenses/LICENSE +674 -0
- masstack_python_client-0.0.1.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from datetime import datetime, timedelta
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass(frozen=True)
|
|
6
|
+
class Token:
|
|
7
|
+
access_token: str
|
|
8
|
+
expires_at: datetime
|
|
9
|
+
|
|
10
|
+
def is_expired(self, skew_seconds: int = 60) -> bool:
|
|
11
|
+
return datetime.utcnow() >= self.expires_at - timedelta(seconds=skew_seconds)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import base64
|
|
3
|
+
import requests
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
|
+
from joserfc import jwt
|
|
6
|
+
from joserfc.jwk import RSAKey
|
|
7
|
+
from requests.exceptions import HTTPError
|
|
8
|
+
from ..exceptions import ErrorFetchingToKen
|
|
9
|
+
from .token import Token
|
|
10
|
+
from .token_store import FileTokenStore
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TokenManager:
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self._token_uri = self._token_uri()
|
|
17
|
+
self._client_email = self._client_email()
|
|
18
|
+
self._private_key = self._private_key()
|
|
19
|
+
self._private_key_id = self._private_key_id()
|
|
20
|
+
self._store = FileTokenStore(self._store_path())
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def _token_uri() -> str:
|
|
24
|
+
return os.environ.get("MASSTACK_TOKEN_URI", "")
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def _client_email() -> str:
|
|
28
|
+
return os.environ.get("MASSTACK_CLIENT_EMAIL", "")
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def _private_key() -> str:
|
|
32
|
+
base64_private_key = os.environ.get("MASSTACK_PRIVATE_KEY_BASE64", "").encode(
|
|
33
|
+
"ascii"
|
|
34
|
+
)
|
|
35
|
+
base64_decode_bytes_private_key = base64.b64decode(base64_private_key)
|
|
36
|
+
return base64_decode_bytes_private_key.decode("ascii")
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def _private_key_id() -> str:
|
|
40
|
+
return os.environ.get("MASSTACK_PRIVATE_KEY_ID", "")
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def _store_path() -> str:
|
|
44
|
+
return os.environ.get("MASSTACK_TOKEN_STORE_PATH")
|
|
45
|
+
|
|
46
|
+
def _fetch_token(self) -> Token:
|
|
47
|
+
now = datetime.utcnow()
|
|
48
|
+
claims = {
|
|
49
|
+
"iss": self._client_email,
|
|
50
|
+
"aud": self._token_uri,
|
|
51
|
+
"exp": now + timedelta(hours=1),
|
|
52
|
+
"iat": now,
|
|
53
|
+
}
|
|
54
|
+
jwt_header = {"alg": "RS256", "kid": self._private_key_id}
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
key = RSAKey.import_key(self._private_key)
|
|
58
|
+
assertion = jwt.encode(jwt_header, claims, key)
|
|
59
|
+
response = requests.post(
|
|
60
|
+
self._token_uri,
|
|
61
|
+
data={
|
|
62
|
+
"assertion": assertion,
|
|
63
|
+
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
64
|
+
},
|
|
65
|
+
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
66
|
+
)
|
|
67
|
+
response.raise_for_status()
|
|
68
|
+
except HTTPError:
|
|
69
|
+
raise ErrorFetchingToKen(response.status_code, response.text)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
raise ErrorFetchingToKen(500, str(e))
|
|
72
|
+
data = response.json()
|
|
73
|
+
|
|
74
|
+
return Token(
|
|
75
|
+
access_token=data["access_token"],
|
|
76
|
+
expires_at=datetime.utcnow() + timedelta(seconds=data["expires_in"]),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def get(self) -> str:
|
|
80
|
+
token = self._store.load()
|
|
81
|
+
|
|
82
|
+
if token is None or token.is_expired():
|
|
83
|
+
token = self._fetch_token()
|
|
84
|
+
self._store.save(token)
|
|
85
|
+
|
|
86
|
+
return token.access_token
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
import tempfile
|
|
6
|
+
from .token import Token
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FileTokenStore:
|
|
10
|
+
|
|
11
|
+
def __init__(self, path: Optional[str] = None):
|
|
12
|
+
self.path = Path(
|
|
13
|
+
path if path is not None else Path(tempfile.gettempdir()) / "masstack.token"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
def load(self) -> Optional[Token]:
|
|
17
|
+
if not self.path.exists():
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
data = json.loads(self.path.read_text())
|
|
21
|
+
return Token(
|
|
22
|
+
access_token=data["access_token"],
|
|
23
|
+
expires_at=datetime.fromisoformat(data["expires_at"]),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def save(self, token: Token) -> None:
|
|
27
|
+
self.path.write_text(
|
|
28
|
+
json.dumps(
|
|
29
|
+
{
|
|
30
|
+
"access_token": token.access_token,
|
|
31
|
+
"expires_at": token.expires_at.isoformat(),
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import requests as req
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from masstack_python_client.auth.token_manager import TokenManager
|
|
5
|
+
from masstack_python_client.exceptions import ErrorPostingData, ErrorRetrievingData
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MasstackClient:
|
|
9
|
+
"""Base Masstack API client"""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self._token_manager = TokenManager()
|
|
13
|
+
self.domain = self._domain()
|
|
14
|
+
self.org_id = self._org_id()
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def _org_id() -> str:
|
|
18
|
+
return os.environ.get("MASSTACK_ORG_ID", "")
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def _domain() -> str:
|
|
22
|
+
return os.environ.get("MASSTACK_DOMAIN", "")
|
|
23
|
+
|
|
24
|
+
def _common_header(self) -> dict:
|
|
25
|
+
token = self._token_manager.get()
|
|
26
|
+
return {"Authorization": f"Bearer {token}", "Accept": "application/json"}
|
|
27
|
+
|
|
28
|
+
def get(
|
|
29
|
+
self,
|
|
30
|
+
api: str,
|
|
31
|
+
version: str,
|
|
32
|
+
endpoint: str,
|
|
33
|
+
params: Optional[dict] = None,
|
|
34
|
+
header: Optional[dict] = None,
|
|
35
|
+
data: Optional[dict] = None,
|
|
36
|
+
) -> dict:
|
|
37
|
+
url = self._build_url(api, version, endpoint)
|
|
38
|
+
res = self._send_request("GET", url, extra_headers=header, params=params)
|
|
39
|
+
|
|
40
|
+
if res.status_code >= 400:
|
|
41
|
+
raise ErrorRetrievingData(res.status_code, res.text, params)
|
|
42
|
+
|
|
43
|
+
return res.json()
|
|
44
|
+
|
|
45
|
+
def post(
|
|
46
|
+
self,
|
|
47
|
+
api: str,
|
|
48
|
+
version: str,
|
|
49
|
+
endpoint: str,
|
|
50
|
+
data: Optional[dict],
|
|
51
|
+
header: Optional[dict] = None,
|
|
52
|
+
params: Optional[dict] = None,
|
|
53
|
+
) -> dict:
|
|
54
|
+
url = self._build_url(api, version, endpoint)
|
|
55
|
+
res = self._send_request(
|
|
56
|
+
"POST", url, extra_headers=header, payload=data, params=params
|
|
57
|
+
)
|
|
58
|
+
if res.status_code >= 400:
|
|
59
|
+
raise ErrorPostingData(res.status_code, res.text, data)
|
|
60
|
+
|
|
61
|
+
return res.json()
|
|
62
|
+
|
|
63
|
+
def _send_request(
|
|
64
|
+
self,
|
|
65
|
+
verb: str,
|
|
66
|
+
url: str,
|
|
67
|
+
payload: Optional[dict] = None,
|
|
68
|
+
params: Optional[dict] = None,
|
|
69
|
+
extra_headers: Optional[dict] = None,
|
|
70
|
+
) -> req.Response:
|
|
71
|
+
headers = self._common_header()
|
|
72
|
+
if extra_headers:
|
|
73
|
+
headers.update(extra_headers)
|
|
74
|
+
|
|
75
|
+
return req.request(
|
|
76
|
+
verb.upper(), url, headers=headers, json=payload, params=params
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def _build_url(self, api: str, version: str, endpoint: str) -> str:
|
|
80
|
+
return (
|
|
81
|
+
f"https://{api}.{self.domain}/"
|
|
82
|
+
f"{version.strip('/')}/"
|
|
83
|
+
f"orgs/{self.org_id.strip('/')}/"
|
|
84
|
+
f"{endpoint.lstrip('/')}"
|
|
85
|
+
)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
BASE_DIR = Path(__file__).resolve().parent
|
|
5
|
+
PROVINCE_FILE_PATH = BASE_DIR / "province_translation.csv"
|
|
6
|
+
STREET_TYPE_FILE_PATH = BASE_DIR / "street_type_translation.csv"
|
|
7
|
+
UNIT_TRANSLATION_FILE_PATH = BASE_DIR / "unit_translation.csv"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_province_by_id(
|
|
11
|
+
province_id: str, province: str = "", lang: str = "ca_ES"
|
|
12
|
+
) -> str:
|
|
13
|
+
with open(
|
|
14
|
+
PROVINCE_FILE_PATH,
|
|
15
|
+
newline="",
|
|
16
|
+
encoding="utf-8",
|
|
17
|
+
) as f:
|
|
18
|
+
return _get_by_code(csv.DictReader(f), province_id, lang, province)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_street_type(original_text: str, lang: str = "ca_ES") -> str:
|
|
22
|
+
with open(
|
|
23
|
+
STREET_TYPE_FILE_PATH,
|
|
24
|
+
newline="",
|
|
25
|
+
encoding="utf-8",
|
|
26
|
+
) as f:
|
|
27
|
+
return _get_translation(csv.DictReader(f), original_text, lang)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_unit_translation(original_text: str, lang: str = "ca_ES") -> str:
|
|
31
|
+
with open(
|
|
32
|
+
UNIT_TRANSLATION_FILE_PATH,
|
|
33
|
+
newline="",
|
|
34
|
+
encoding="utf-8",
|
|
35
|
+
) as f:
|
|
36
|
+
return _get_translation(csv.DictReader(f), original_text, lang)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _get_by_code(reader, code, lang, default):
|
|
40
|
+
return next((row[lang] for row in reader if row["code"] == code), default)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _get_translation(reader, text, lang):
|
|
44
|
+
match = {"es": None, "ca": None}
|
|
45
|
+
for row in reader:
|
|
46
|
+
if row["es_ES"] == text:
|
|
47
|
+
match["es"] = row
|
|
48
|
+
if row["ca_ES"] == text:
|
|
49
|
+
match["ca"] = row
|
|
50
|
+
|
|
51
|
+
return ((m := match["es"] or match["ca"]) and m.get(lang)) or text
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
code,es_ES,ca_ES
|
|
2
|
+
1,ALAVA,ALAVA
|
|
3
|
+
2,ALBACETE,ALBACETE
|
|
4
|
+
3,ALICANTE,ALACANT
|
|
5
|
+
4,ALMERIA,ALMERIA
|
|
6
|
+
33,ASTURIAS,ASTURIES
|
|
7
|
+
5,AVILA,AVILA
|
|
8
|
+
6,BADAJOZ,BADAJOZ
|
|
9
|
+
8,BARCELONA,BARCELONA
|
|
10
|
+
9,BURGOS,BURGOS
|
|
11
|
+
10,CACERES,CACERES
|
|
12
|
+
11,CADIZ,CADIZ
|
|
13
|
+
39,CANTABRIA,CANTABRIA
|
|
14
|
+
12,CASTELLON,CASTELLO
|
|
15
|
+
51,CEUTA,CEUTA
|
|
16
|
+
13,CIUDAD REAL,CIUTAT REAL
|
|
17
|
+
14,CORDOBA,CORDOBA
|
|
18
|
+
15,CORU+ANE-A (A),CORUNYA (A)
|
|
19
|
+
16,CUENCA,CUENCA
|
|
20
|
+
17,GERONA,GIRONA
|
|
21
|
+
18,GRANADA,GRANADA
|
|
22
|
+
19,GUADALAJARA,GUADALAJARA
|
|
23
|
+
20,GUIPUZCOA,GIPUSKOA
|
|
24
|
+
21,HUELVA,HUELVA
|
|
25
|
+
22,HUESCA,HUESCA
|
|
26
|
+
7,ILLES BALEARS,ILLES BALEARS
|
|
27
|
+
23,JAEN,JAEN
|
|
28
|
+
24,LEON,LEON
|
|
29
|
+
25,LERIDA,LLEIDA
|
|
30
|
+
27,LUGO,LUGO
|
|
31
|
+
28,MADRID,MADRID
|
|
32
|
+
29,MALAGA,MALAGA
|
|
33
|
+
52,MELILLA,MELILLA
|
|
34
|
+
30,MURCIA,MURCIA
|
|
35
|
+
31,NAVARRA,NAVARRA
|
|
36
|
+
32,OURENSE,ORENSE
|
|
37
|
+
34,PALENCIA,PALENCIA
|
|
38
|
+
35,PALMAS (LAS),PALMES (LES)
|
|
39
|
+
36,PONTEVEDRA,PONTEVEDRA
|
|
40
|
+
26,RIOJA (LA),RIOJA (LA)
|
|
41
|
+
37,SALAMANCA,SALAMANCA
|
|
42
|
+
38,SANTA CRUZ DE TENERIFE,SANTA CRUZ DE TENERIFE
|
|
43
|
+
40,SEGOVIA,SEGOVIA
|
|
44
|
+
41,SEVILLA,SEVILLA
|
|
45
|
+
42,SORIA,SORIA
|
|
46
|
+
43,TARRAGONA,TARRAGONA
|
|
47
|
+
44,TERUEL,TEROL
|
|
48
|
+
45,TOLEDO,TOLEDO
|
|
49
|
+
46,VALENCIA,VALENCIA
|
|
50
|
+
47,VALLADOLID,VALLADOLID
|
|
51
|
+
48,VIZCAYA,BIZKAIA
|
|
52
|
+
49,ZAMORA,ZAMORA
|
|
53
|
+
50,ZARAGOZA,SARAGOSSA
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
code,es_ES,ca_ES
|
|
2
|
+
AL,ALAMEDA,ALAMEDA
|
|
3
|
+
AD,ALDEA,ALDEA
|
|
4
|
+
AP,APARTAMENTOS,APARTAMENTS
|
|
5
|
+
AY,ARROYO,RIEROL
|
|
6
|
+
AV,AVENIDA,AVINGUDA
|
|
7
|
+
BJ,BAJADA,BAIXADA
|
|
8
|
+
BR,BARRANCO,BARRANC
|
|
9
|
+
BO,BARRIO,BARRI
|
|
10
|
+
BL,BLOQUE,BLOC
|
|
11
|
+
CL,CALLE,CARRER
|
|
12
|
+
CJ,CALLEJA,CARRERÓ
|
|
13
|
+
CM,CAMINO,CAMÍ
|
|
14
|
+
CR,CARRETERA,CARRETERA
|
|
15
|
+
CS,CASERIO,CASERIU
|
|
16
|
+
CH,CHALET,XALÉ
|
|
17
|
+
CG,COLEGIO,COL·LEGI
|
|
18
|
+
CO,COLONIA,COLÒNIA
|
|
19
|
+
CN,CONJUNTO,CONJUNT
|
|
20
|
+
CT,CUESTA,COSTA
|
|
21
|
+
ED,EDIFICIO,EDIFICI
|
|
22
|
+
EN,ENTRADA,ENTRADA
|
|
23
|
+
ES,ESCALINATA,ESCALINATA
|
|
24
|
+
EX,EXPLANADA,ESPLANADA
|
|
25
|
+
EM,EXTRAMUROS,EXTRAMURS
|
|
26
|
+
ER,EXTRARRADIO,EXTRARADI
|
|
27
|
+
FC,FERROCARRIL,FERROCARRIL
|
|
28
|
+
GL,GLORIETA,GLORIETA
|
|
29
|
+
GV,GRAN VÍA,GRAN VIA
|
|
30
|
+
GR,GRUPO,GRUP
|
|
31
|
+
HT,HUERTA,HORTA
|
|
32
|
+
JR,JARDINES,JARDINS
|
|
33
|
+
LD,LADO,COSTAT
|
|
34
|
+
LG,LUGAR,LLOC
|
|
35
|
+
MZ,MANZANA,ILLA
|
|
36
|
+
MS,MASÍA,MASIA
|
|
37
|
+
MC,MERCADO,MERCAT
|
|
38
|
+
MT,MONTE,MUNTANYA
|
|
39
|
+
ML,MUELLE,MOLL
|
|
40
|
+
MN,MUNICIPIO,MUNICIPI
|
|
41
|
+
PA,PARCELA,PARCEL·LA
|
|
42
|
+
PQ,PARQUE,PARC
|
|
43
|
+
PI,PARROQUIA,PARRÒQUIA
|
|
44
|
+
PD,PARTIDA,PARTIDA
|
|
45
|
+
PJ,PASAJE,PASSATGE
|
|
46
|
+
PS,PASEO,PASSEIG
|
|
47
|
+
PZ,PLAZA,PLAÇA
|
|
48
|
+
PB,POBLADO,POBLAT
|
|
49
|
+
PG,POLIGONO,POLÍGON
|
|
50
|
+
PR,PROLONGACION,PROLONGACIÓ
|
|
51
|
+
PT,PUENTE,PONT
|
|
52
|
+
PU,PUERTA,PORTA
|
|
53
|
+
QT,QUINTA,QUINTA
|
|
54
|
+
RM,RAMAL,RAMAL
|
|
55
|
+
RB,RAMBLA,RAMBLA
|
|
56
|
+
RP,RAMPA,RAMPA
|
|
57
|
+
RR,RIERA,RIERA
|
|
58
|
+
RC,RINCÓN,RACÓ
|
|
59
|
+
RD,RONDA,RONDA
|
|
60
|
+
RU,RÚA,RUA
|
|
61
|
+
SA,SALIDA,SORTIDA
|
|
62
|
+
SC,SECTOR,SECTOR
|
|
63
|
+
SC,SECCIÓN,SECCIÓ
|
|
64
|
+
SD,SENDA,SENDERA
|
|
65
|
+
SL,SOLAR,SOLAR
|
|
66
|
+
SL,SALÓN,SALÓ
|
|
67
|
+
SB,SUBIDA,PUJADA
|
|
68
|
+
TN,TERRENOS,TERRENYS
|
|
69
|
+
TO,TORRENTE,TORRENT
|
|
70
|
+
TR,TRAVESÍA,TRAVESSERA
|
|
71
|
+
UR,URBANIZACION,URBANITZACIÓ
|
|
72
|
+
VI,VÍA,VIA
|
|
73
|
+
VP,VÍA PÚBLICA,VIA PÚBLICA
|
|
74
|
+
AR,ÁREA,ÀREA
|
|
75
|
+
AR,ARRABAL,RAVAL
|
|
76
|
+
AC,ACCESO,ACCÉS
|
|
77
|
+
VR,ACERA,VORERA
|
|
78
|
+
AQ,ACEQUIA,SÈQUIA
|
|
79
|
+
AF,AFUERA(S),AFORES
|
|
80
|
+
AG,AGRUPACION,AGRUPACIÓ
|
|
81
|
+
AS,ARRABAL(ES),RAVALS
|
|
82
|
+
AV,AUTOPISTA/AUTOVIA,AUTOPISTA/AUTOVIA
|
|
83
|
+
BB,BARRIADA/BAJADA,BARRIADA/BAIXADA
|
|
84
|
+
CC,CASA(S)/CASETA,CASA(ES)/CASETA
|
|
85
|
+
MJ,COMPLEJO,COMPLEXE
|
|
86
|
+
RJ,CORTIJO,MAS
|
|
87
|
+
DM,DISEMINADO(S)/EXTR.,DISSEMINAT(S)/EXTR.
|
|
88
|
+
NO,NUCLEO,NUCLI
|
|
89
|
+
PO,PATIO,PATI
|
|
90
|
+
LA,POBLACIÓN,POBLACIÓ
|
|
91
|
+
RS,RESIDENCIA,RESIDÈNCIA
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MasstackClientException(Exception):
|
|
5
|
+
"""Base exception for Masstack Python Client."""
|
|
6
|
+
|
|
7
|
+
_status_code: Optional[int] = None
|
|
8
|
+
_message: Optional[str] = None
|
|
9
|
+
|
|
10
|
+
def __init__(self, status_code: int, message: str):
|
|
11
|
+
super(Exception, self).__init__(message)
|
|
12
|
+
self._message = message
|
|
13
|
+
self._status_code = status_code
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def status_code(self) -> int:
|
|
17
|
+
"""The status_code property."""
|
|
18
|
+
return self._status_code or 0
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def message(self) -> str:
|
|
22
|
+
"""The error message property."""
|
|
23
|
+
return self._message or ""
|
|
24
|
+
|
|
25
|
+
def _params_to_string(self, params):
|
|
26
|
+
if not params or len(params) == 0:
|
|
27
|
+
return ""
|
|
28
|
+
params_msg = ""
|
|
29
|
+
for key, value in params.items():
|
|
30
|
+
params_msg = params_msg + "{}: {}\n".format(key, value)
|
|
31
|
+
return params_msg
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ErrorFetchingToKen(MasstackClientException):
|
|
35
|
+
def __init__(self, status_code: int, error_msg: str):
|
|
36
|
+
message = "Error fetching token with the next error message: {}".format(
|
|
37
|
+
error_msg
|
|
38
|
+
)
|
|
39
|
+
super(ErrorFetchingToKen, self).__init__(status_code, message)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ErrorRetrievingData(MasstackClientException):
|
|
43
|
+
def __init__(self, status_code: int, error_msg: str, params: Optional[dict] = None):
|
|
44
|
+
message = "Error retrieving data with the next error message: {}\nParameters:\n{}".format(
|
|
45
|
+
error_msg, self._params_to_string(params)
|
|
46
|
+
)
|
|
47
|
+
super(ErrorRetrievingData, self).__init__(status_code, message)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ErrorPostingData(MasstackClientException):
|
|
51
|
+
def __init__(self, status_code: int, error_msg: str, body: dict):
|
|
52
|
+
message = (
|
|
53
|
+
"Error posting data with the next error message: {}\nBody:\n{}".format(
|
|
54
|
+
error_msg, self._params_to_string(body)
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
super(ErrorPostingData, self).__init__(status_code, message)
|
|
File without changes
|