sumo-wrapper-python 1.3.0__py3-none-any.whl → 1.5.0__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.
- sumo/wrapper/_auth_provider.py +11 -2
- sumo/wrapper/_decorators.py +8 -4
- sumo/wrapper/_version.py +2 -2
- sumo/wrapper/sumo_client.py +47 -20
- {sumo_wrapper_python-1.3.0.dist-info → sumo_wrapper_python-1.5.0.dist-info}/METADATA +1 -1
- sumo_wrapper_python-1.5.0.dist-info/RECORD +16 -0
- {sumo_wrapper_python-1.3.0.dist-info → sumo_wrapper_python-1.5.0.dist-info}/WHEEL +1 -1
- sumo/wrapper/config.py +0 -26
- sumo_wrapper_python-1.3.0.dist-info/RECORD +0 -17
- {sumo_wrapper_python-1.3.0.dist-info → sumo_wrapper_python-1.5.0.dist-info}/entry_points.txt +0 -0
- {sumo_wrapper_python-1.3.0.dist-info → sumo_wrapper_python-1.5.0.dist-info}/licenses/LICENSE +0 -0
- {sumo_wrapper_python-1.3.0.dist-info → sumo_wrapper_python-1.5.0.dist-info}/top_level.txt +0 -0
sumo/wrapper/_auth_provider.py
CHANGED
|
@@ -99,6 +99,9 @@ class AuthProvider:
|
|
|
99
99
|
get_token_path(self._resource_id, ".sharedkey", case_uuid)
|
|
100
100
|
)
|
|
101
101
|
|
|
102
|
+
def delete_token(self):
|
|
103
|
+
return False
|
|
104
|
+
|
|
102
105
|
pass
|
|
103
106
|
|
|
104
107
|
|
|
@@ -400,9 +403,10 @@ class AuthProviderSumoToken(AuthProvider):
|
|
|
400
403
|
def __init__(self, resource_id, case_uuid=None):
|
|
401
404
|
super().__init__(resource_id)
|
|
402
405
|
protect_token_cache(resource_id, ".sharedkey", case_uuid)
|
|
403
|
-
token_path = get_token_path(resource_id, ".sharedkey", case_uuid)
|
|
404
|
-
with open(token_path, "r") as f:
|
|
406
|
+
self.token_path = get_token_path(resource_id, ".sharedkey", case_uuid)
|
|
407
|
+
with open(self.token_path, "r") as f:
|
|
405
408
|
self._token = f.readline().strip()
|
|
409
|
+
|
|
406
410
|
return
|
|
407
411
|
|
|
408
412
|
def get_token(self):
|
|
@@ -411,6 +415,11 @@ class AuthProviderSumoToken(AuthProvider):
|
|
|
411
415
|
def get_authorization(self):
|
|
412
416
|
return {"X-SUMO-Token": self._token}
|
|
413
417
|
|
|
418
|
+
def delete_token(self):
|
|
419
|
+
if os.path.exists(self.token_path):
|
|
420
|
+
os.unlink(self.token_path)
|
|
421
|
+
return True
|
|
422
|
+
|
|
414
423
|
|
|
415
424
|
@tn.retry(
|
|
416
425
|
retry=tn.retry_if_exception(_maybe_nfs_exception),
|
sumo/wrapper/_decorators.py
CHANGED
|
@@ -4,11 +4,13 @@ from functools import wraps
|
|
|
4
4
|
|
|
5
5
|
def raise_for_status(func):
|
|
6
6
|
@wraps(func)
|
|
7
|
-
def wrapper(*args, **kwargs):
|
|
7
|
+
def wrapper(self, *args, **kwargs):
|
|
8
8
|
# FIXME: in newer versions of httpx, raise_for_status() is chainable,
|
|
9
9
|
# so we could simply write
|
|
10
10
|
# return func(*args, **kwargs).raise_for_status()
|
|
11
|
-
response = func(*args, **kwargs)
|
|
11
|
+
response = func(self, *args, **kwargs)
|
|
12
|
+
if response.status_code == 401:
|
|
13
|
+
self._handle_invalid_shared_key()
|
|
12
14
|
response.raise_for_status()
|
|
13
15
|
return response
|
|
14
16
|
|
|
@@ -17,11 +19,13 @@ def raise_for_status(func):
|
|
|
17
19
|
|
|
18
20
|
def raise_for_status_async(func):
|
|
19
21
|
@wraps(func)
|
|
20
|
-
async def wrapper(*args, **kwargs):
|
|
22
|
+
async def wrapper(self, *args, **kwargs):
|
|
21
23
|
# FIXME: in newer versions of httpx, raise_for_status() is chainable,
|
|
22
24
|
# so we could simply write
|
|
23
25
|
# return func(*args, **kwargs).raise_for_status()
|
|
24
|
-
response = await func(*args, **kwargs)
|
|
26
|
+
response = await func(self, *args, **kwargs)
|
|
27
|
+
if response.status_code == 401:
|
|
28
|
+
self._handle_invalid_shared_key()
|
|
25
29
|
response.raise_for_status()
|
|
26
30
|
return response
|
|
27
31
|
|
sumo/wrapper/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.
|
|
32
|
-
__version_tuple__ = version_tuple = (1,
|
|
31
|
+
__version__ = version = '1.5.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 5, 0)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
sumo/wrapper/sumo_client.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import contextlib
|
|
3
3
|
import logging
|
|
4
|
+
import os
|
|
4
5
|
import re
|
|
5
6
|
import time
|
|
6
7
|
from typing import Dict, Optional, Tuple
|
|
@@ -16,12 +17,15 @@ from ._decorators import (
|
|
|
16
17
|
)
|
|
17
18
|
from ._logging import LogHandlerSumo
|
|
18
19
|
from ._retry_strategy import RetryStrategy
|
|
19
|
-
from .config import APP_REGISTRATION, AUTHORITY_HOST_URI, TENANT_ID
|
|
20
20
|
|
|
21
21
|
logger = logging.getLogger("sumo.wrapper")
|
|
22
22
|
|
|
23
23
|
DEFAULT_TIMEOUT = httpx.Timeout(30.0)
|
|
24
24
|
|
|
25
|
+
WELL_KNOWN = os.environ.get(
|
|
26
|
+
"SUMOCONNECTIONINFO", "https://api.sumo.equinor.com/well-known"
|
|
27
|
+
)
|
|
28
|
+
|
|
25
29
|
|
|
26
30
|
class SumoClient:
|
|
27
31
|
"""Authenticate and perform requests to the Sumo API."""
|
|
@@ -31,7 +35,7 @@ class SumoClient:
|
|
|
31
35
|
|
|
32
36
|
def __init__(
|
|
33
37
|
self,
|
|
34
|
-
env: str,
|
|
38
|
+
env: str = "prod",
|
|
35
39
|
token: Optional[str] = None,
|
|
36
40
|
interactive: bool = True,
|
|
37
41
|
devicecode: bool = False,
|
|
@@ -41,22 +45,46 @@ class SumoClient:
|
|
|
41
45
|
case_uuid=None,
|
|
42
46
|
http_client=None,
|
|
43
47
|
async_http_client=None,
|
|
48
|
+
client_id: Optional[str] = None,
|
|
44
49
|
):
|
|
45
50
|
"""Initialize a new Sumo object
|
|
46
51
|
|
|
47
52
|
Args:
|
|
48
|
-
env: Sumo environment
|
|
49
|
-
token: Access token or refresh token.
|
|
50
|
-
interactive: Enable interactive authentication (in browser).
|
|
51
|
-
If not enabled, code grant flow will be used.
|
|
52
|
-
|
|
53
|
+
env (str): Sumo environment. Defaults to "prod".
|
|
54
|
+
token (Optional[str]): Access token or refresh token. Defaults to None.
|
|
55
|
+
interactive (bool): Enable interactive authentication (in browser).
|
|
56
|
+
If not enabled, code grant flow will be used. Defaults to True.
|
|
57
|
+
devicecode (bool): Enable device code flow. Defaults to False.
|
|
58
|
+
verbosity (str): Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL).
|
|
59
|
+
Defaults to "CRITICAL".
|
|
60
|
+
retry_strategy (RetryStrategy): Retry strategy for HTTP requests.
|
|
61
|
+
Defaults to RetryStrategy().
|
|
62
|
+
timeout (int): Timeout for HTTP requests. Defaults to DEFAULT_TIMEOUT.
|
|
63
|
+
case_uuid (Optional[str]): Case UUID for authentication. Defaults to None.
|
|
64
|
+
http_client (Optional[httpx.Client]): HTTP client for synchronous requests.
|
|
65
|
+
Defaults to None.
|
|
66
|
+
async_http_client (Optional[httpx.AsyncClient]): HTTP client for asynchronous requests.
|
|
67
|
+
Defaults to None.
|
|
68
|
+
client_id (Optional[str]): Client ID for authentication. If None, will use
|
|
69
|
+
AZURE_CLIENT_ID from environment variables or the config. Defaults to None.
|
|
53
70
|
"""
|
|
54
71
|
|
|
55
72
|
logger.setLevel(verbosity)
|
|
56
73
|
|
|
57
|
-
|
|
74
|
+
well_known = httpx.get(WELL_KNOWN).json()
|
|
75
|
+
if env not in well_known["envs"]:
|
|
58
76
|
raise ValueError(f"Invalid environment: {env}")
|
|
59
77
|
|
|
78
|
+
tenant_id = well_known["tenant_id"]
|
|
79
|
+
authority_host = well_known["authority"]
|
|
80
|
+
config = well_known["envs"][env]
|
|
81
|
+
resource_id = config["resource_id"]
|
|
82
|
+
base_url = config["base_url"]
|
|
83
|
+
self.client_id = (
|
|
84
|
+
client_id
|
|
85
|
+
or os.environ.get("AZURE_CLIENT_ID")
|
|
86
|
+
or config["client_id"]
|
|
87
|
+
)
|
|
60
88
|
self.env = env
|
|
61
89
|
self._verbosity = verbosity
|
|
62
90
|
|
|
@@ -101,11 +129,10 @@ class SumoClient:
|
|
|
101
129
|
pass
|
|
102
130
|
|
|
103
131
|
cleanup_shared_keys()
|
|
104
|
-
|
|
105
132
|
self.auth = get_auth_provider(
|
|
106
|
-
client_id=
|
|
107
|
-
authority=f"{
|
|
108
|
-
resource_id=
|
|
133
|
+
client_id=self.client_id,
|
|
134
|
+
authority=f"{authority_host}{tenant_id}",
|
|
135
|
+
resource_id=resource_id,
|
|
109
136
|
interactive=interactive,
|
|
110
137
|
refresh_token=refresh_token,
|
|
111
138
|
access_token=access_token,
|
|
@@ -113,14 +140,7 @@ class SumoClient:
|
|
|
113
140
|
case_uuid=case_uuid,
|
|
114
141
|
)
|
|
115
142
|
|
|
116
|
-
|
|
117
|
-
self.base_url = "https://api.sumo.equinor.com/api/v1"
|
|
118
|
-
elif env == "localhost":
|
|
119
|
-
self.base_url = "http://localhost:8084/api/v1"
|
|
120
|
-
else:
|
|
121
|
-
self.base_url = (
|
|
122
|
-
f"https://main-sumo-core-{env}.c3.radix.equinor.com/api/v1"
|
|
123
|
-
)
|
|
143
|
+
self.base_url = base_url
|
|
124
144
|
return
|
|
125
145
|
|
|
126
146
|
def __enter__(self):
|
|
@@ -188,6 +208,13 @@ class SumoClient:
|
|
|
188
208
|
self._retry_strategy,
|
|
189
209
|
)
|
|
190
210
|
|
|
211
|
+
def _handle_invalid_shared_key(self):
|
|
212
|
+
"""Handle the invalid shared key by deleting it."""
|
|
213
|
+
if self.auth.delete_token():
|
|
214
|
+
print(
|
|
215
|
+
"Invalid shared key detected and deleted, run again to reset automatically"
|
|
216
|
+
)
|
|
217
|
+
|
|
191
218
|
@raise_for_status
|
|
192
219
|
def get(self, path: str, params: Optional[Dict] = None) -> httpx.Response:
|
|
193
220
|
"""Performs a GET-request to the Sumo API.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
sumo/__init__.py,sha256=ftS-xRPSH-vU7fIHlnZQaCTWbNvs4owJivNW65kzsIM,85
|
|
2
|
+
sumo/wrapper/__init__.py,sha256=JK6iMAy2Fdrc7iaIHTn60fHPdRvsgNjZwWD6DJtGUYQ,235
|
|
3
|
+
sumo/wrapper/_auth_provider.py,sha256=SJRu8lRkSryFPI6Nevveny_QMFfGfhQwzk9ef5TmMNE,16665
|
|
4
|
+
sumo/wrapper/_blob_client.py,sha256=SyfyFZ1hHVWKU4lmgUqSjl5TaK_OJNQ__0wDETrp-ag,1623
|
|
5
|
+
sumo/wrapper/_decorators.py,sha256=ZwyrWkfAXiGNSgYsQSEXA13D-WIQM2XPf0v2z9N8HyQ,1002
|
|
6
|
+
sumo/wrapper/_logging.py,sha256=WAGrjPmK2_JC9w1IxT5onq1iEAreEsyzmm95pXBe0dA,1074
|
|
7
|
+
sumo/wrapper/_retry_strategy.py,sha256=JSXy-ki5vWI_N4D52LpK9EoAmPrnT3H6OG0aBLsJRMk,2525
|
|
8
|
+
sumo/wrapper/_version.py,sha256=sfeo6QRBwy3wEFaKhAEbFPpF98FLjoe4Car1c6NnghQ,704
|
|
9
|
+
sumo/wrapper/login.py,sha256=Bp5IgSrsgjWcgOQIQIQ5aJrCBWdK3khS-CnTmB63Rjk,1951
|
|
10
|
+
sumo/wrapper/sumo_client.py,sha256=W1s-ENTRXHgP7GPocuJu1KSpdAzA7bGecS9lQt5T-W0,23028
|
|
11
|
+
sumo_wrapper_python-1.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
12
|
+
sumo_wrapper_python-1.5.0.dist-info/METADATA,sha256=LFC9vB8mBHjF6LBTUl_v582ScotGLsJzmJfTKEk609w,14615
|
|
13
|
+
sumo_wrapper_python-1.5.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
|
|
14
|
+
sumo_wrapper_python-1.5.0.dist-info/entry_points.txt,sha256=V_vGky2C3He5vohJAxnBdvpt_fqfUDFj5irUm9HtoFc,55
|
|
15
|
+
sumo_wrapper_python-1.5.0.dist-info/top_level.txt,sha256=rLbKyH9rWgCj3PoLeR7fvC5X8vCaUc5LF8-Y_GBWZL0,5
|
|
16
|
+
sumo_wrapper_python-1.5.0.dist-info/RECORD,,
|
sumo/wrapper/config.py
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
APP_REGISTRATION = {
|
|
2
|
-
"prod": {
|
|
3
|
-
"CLIENT_ID": "d57a8f87-4e28-4391-84d6-34356d5876a2",
|
|
4
|
-
"RESOURCE_ID": "9e5443dd-3431-4690-9617-31eed61cb55a",
|
|
5
|
-
},
|
|
6
|
-
"test": {
|
|
7
|
-
"CLIENT_ID": "d57a8f87-4e28-4391-84d6-34356d5876a2",
|
|
8
|
-
"RESOURCE_ID": "9e5443dd-3431-4690-9617-31eed61cb55a",
|
|
9
|
-
},
|
|
10
|
-
"dev": {
|
|
11
|
-
"CLIENT_ID": "1826bd7c-582f-4838-880d-5b4da5c3eea2",
|
|
12
|
-
"RESOURCE_ID": "88d2b022-3539-4dda-9e66-853801334a86",
|
|
13
|
-
},
|
|
14
|
-
"preview": {
|
|
15
|
-
"CLIENT_ID": "1826bd7c-582f-4838-880d-5b4da5c3eea2",
|
|
16
|
-
"RESOURCE_ID": "88d2b022-3539-4dda-9e66-853801334a86",
|
|
17
|
-
},
|
|
18
|
-
"localhost": {
|
|
19
|
-
"CLIENT_ID": "1826bd7c-582f-4838-880d-5b4da5c3eea2",
|
|
20
|
-
"RESOURCE_ID": "88d2b022-3539-4dda-9e66-853801334a86",
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
TENANT_ID = "3aa4a235-b6e2-48d5-9195-7fcf05b459b0"
|
|
25
|
-
|
|
26
|
-
AUTHORITY_HOST_URI = "https://login.microsoftonline.com"
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
sumo/__init__.py,sha256=ftS-xRPSH-vU7fIHlnZQaCTWbNvs4owJivNW65kzsIM,85
|
|
2
|
-
sumo/wrapper/__init__.py,sha256=JK6iMAy2Fdrc7iaIHTn60fHPdRvsgNjZwWD6DJtGUYQ,235
|
|
3
|
-
sumo/wrapper/_auth_provider.py,sha256=du15SjkJ7eDEITbAJXdx6y1L4RALpSpsDrw9zE9E3fI,16472
|
|
4
|
-
sumo/wrapper/_blob_client.py,sha256=SyfyFZ1hHVWKU4lmgUqSjl5TaK_OJNQ__0wDETrp-ag,1623
|
|
5
|
-
sumo/wrapper/_decorators.py,sha256=3IEi6GXVkkDACHoo8dOeDoBtZh5TlJ6Tw0qlpOVHqLQ,806
|
|
6
|
-
sumo/wrapper/_logging.py,sha256=WAGrjPmK2_JC9w1IxT5onq1iEAreEsyzmm95pXBe0dA,1074
|
|
7
|
-
sumo/wrapper/_retry_strategy.py,sha256=JSXy-ki5vWI_N4D52LpK9EoAmPrnT3H6OG0aBLsJRMk,2525
|
|
8
|
-
sumo/wrapper/_version.py,sha256=0Oc4EBzGTJOvXX0Vym4evglW1NQPpe8RLn8TdxsKzfs,704
|
|
9
|
-
sumo/wrapper/config.py,sha256=6t7qqjrrmd11m4VMlRryiMYw2JDU_R51305woAP1TAs,865
|
|
10
|
-
sumo/wrapper/login.py,sha256=Bp5IgSrsgjWcgOQIQIQ5aJrCBWdK3khS-CnTmB63Rjk,1951
|
|
11
|
-
sumo/wrapper/sumo_client.py,sha256=toWsk_5yrVYWfVF1SgmF-lKN-NQ3YNszikZk1xeS8wE,21660
|
|
12
|
-
sumo_wrapper_python-1.3.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
13
|
-
sumo_wrapper_python-1.3.0.dist-info/METADATA,sha256=S6VEoUsqpP3Z1VFL-mnKmZ1Dqw6i0Ft3oPuXcgU1Ujk,14615
|
|
14
|
-
sumo_wrapper_python-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
15
|
-
sumo_wrapper_python-1.3.0.dist-info/entry_points.txt,sha256=V_vGky2C3He5vohJAxnBdvpt_fqfUDFj5irUm9HtoFc,55
|
|
16
|
-
sumo_wrapper_python-1.3.0.dist-info/top_level.txt,sha256=rLbKyH9rWgCj3PoLeR7fvC5X8vCaUc5LF8-Y_GBWZL0,5
|
|
17
|
-
sumo_wrapper_python-1.3.0.dist-info/RECORD,,
|
{sumo_wrapper_python-1.3.0.dist-info → sumo_wrapper_python-1.5.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{sumo_wrapper_python-1.3.0.dist-info → sumo_wrapper_python-1.5.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|