sumo-wrapper-python 1.0.26__tar.gz → 1.0.28__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.
Potentially problematic release.
This version of sumo-wrapper-python might be problematic. Click here for more details.
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/PKG-INFO +3 -2
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_auth_provider.py +17 -4
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_logging.py +3 -3
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_retry_strategy.py +2 -2
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_version.py +2 -2
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/sumo_client.py +34 -24
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo_wrapper_python.egg-info/PKG-INFO +3 -2
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.github/workflows/build_docs.yaml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.github/workflows/linting.yml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.github/workflows/publish_release.yml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.github/workflows/pytest.yml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.gitignore +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.pre-commit-config.yaml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.readthedocs.yaml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/CONTRIBUTING.md +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/LICENSE +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/README.md +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/SECURITY.md +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/Makefile +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/_static/equinor-logo.png +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/_static/equinor-logo2.jpg +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/_static/equinor_logo.jpg +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/_static/equinor_logo_only.jpg +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/_templates/layout.html +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/api.rst +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/conf.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/index.rst +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/make.bat +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/sumo-wrapper-python.rst +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/pyproject.toml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/setup.cfg +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/__init__.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/__init__.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_blob_client.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_decorators.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/config.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/login.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo_wrapper_python.egg-info/SOURCES.txt +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo_wrapper_python.egg-info/dependency_links.txt +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo_wrapper_python.egg-info/entry_points.txt +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo_wrapper_python.egg-info/requires.txt +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo_wrapper_python.egg-info/top_level.txt +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/tests/conftest.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/tests/test_sumo_thin_client.py +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/tests/testdata/case.yml +0 -0
- {sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/tests/testdata/surface.yml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: sumo-wrapper-python
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.28
|
|
4
4
|
Summary: Python wrapper for the Sumo API
|
|
5
5
|
Author: Equinor
|
|
6
6
|
License: Apache License
|
|
@@ -229,6 +229,7 @@ Requires-Dist: sphinxcontrib-apidoc; extra == "docs"
|
|
|
229
229
|
Provides-Extra: dev
|
|
230
230
|
Requires-Dist: ruff; extra == "dev"
|
|
231
231
|
Requires-Dist: pre-commit; extra == "dev"
|
|
232
|
+
Dynamic: license-file
|
|
232
233
|
|
|
233
234
|
# sumo-wrapper-python
|
|
234
235
|
|
{sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_auth_provider.py
RENAMED
|
@@ -7,6 +7,7 @@ import sys
|
|
|
7
7
|
import time
|
|
8
8
|
from datetime import datetime, timedelta, timezone
|
|
9
9
|
from pathlib import Path
|
|
10
|
+
from typing import Dict
|
|
10
11
|
from urllib.parse import parse_qs
|
|
11
12
|
|
|
12
13
|
import jwt
|
|
@@ -76,10 +77,10 @@ class AuthProvider:
|
|
|
76
77
|
# ELSE
|
|
77
78
|
return result["access_token"]
|
|
78
79
|
|
|
79
|
-
def get_authorization(self):
|
|
80
|
+
def get_authorization(self) -> Dict:
|
|
80
81
|
token = self.get_token()
|
|
81
82
|
if token is None:
|
|
82
|
-
return
|
|
83
|
+
return {}
|
|
83
84
|
|
|
84
85
|
return {"Authorization": "Bearer " + token}
|
|
85
86
|
|
|
@@ -101,6 +102,13 @@ class AuthProvider:
|
|
|
101
102
|
pass
|
|
102
103
|
|
|
103
104
|
|
|
105
|
+
class AuthProviderNone(AuthProvider):
|
|
106
|
+
def get_token(self):
|
|
107
|
+
raise Exception("No valid authorization provider found.")
|
|
108
|
+
|
|
109
|
+
pass
|
|
110
|
+
|
|
111
|
+
|
|
104
112
|
class AuthProviderSilent(AuthProvider):
|
|
105
113
|
def __init__(self, client_id, authority, resource_id):
|
|
106
114
|
super().__init__(resource_id)
|
|
@@ -423,7 +431,7 @@ def get_auth_provider(
|
|
|
423
431
|
refresh_token=None,
|
|
424
432
|
devicecode=False,
|
|
425
433
|
case_uuid=None,
|
|
426
|
-
):
|
|
434
|
+
) -> AuthProvider:
|
|
427
435
|
if refresh_token:
|
|
428
436
|
return AuthProviderRefreshToken(
|
|
429
437
|
refresh_token, client_id, authority, resource_id
|
|
@@ -435,6 +443,9 @@ def get_auth_provider(
|
|
|
435
443
|
if os.path.exists(get_token_path(resource_id, ".sharedkey", case_uuid)):
|
|
436
444
|
return AuthProviderSumoToken(resource_id, case_uuid)
|
|
437
445
|
# ELSE
|
|
446
|
+
if os.path.exists(get_token_path(resource_id, ".sharedkey")):
|
|
447
|
+
return AuthProviderSumoToken(resource_id)
|
|
448
|
+
# ELSE
|
|
438
449
|
if os.path.exists(get_token_path(resource_id, ".token")):
|
|
439
450
|
auth_silent = AuthProviderSilent(client_id, authority, resource_id)
|
|
440
451
|
token = auth_silent.get_token()
|
|
@@ -472,6 +483,8 @@ def get_auth_provider(
|
|
|
472
483
|
]
|
|
473
484
|
):
|
|
474
485
|
return AuthProviderManaged(resource_id)
|
|
486
|
+
# ELSE
|
|
487
|
+
return AuthProviderNone(resource_id)
|
|
475
488
|
|
|
476
489
|
|
|
477
490
|
def cleanup_shared_keys():
|
|
@@ -481,7 +494,7 @@ def cleanup_shared_keys():
|
|
|
481
494
|
for f in os.listdir(tokendir):
|
|
482
495
|
ff = os.path.join(tokendir, f)
|
|
483
496
|
if os.path.isfile(ff):
|
|
484
|
-
(
|
|
497
|
+
(_, ext) = os.path.splitext(ff)
|
|
485
498
|
if ext.lower() == ".sharedkey":
|
|
486
499
|
try:
|
|
487
500
|
with open(ff, "r") as file:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from datetime import datetime
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class LogHandlerSumo(logging.Handler):
|
|
@@ -11,8 +11,8 @@ class LogHandlerSumo(logging.Handler):
|
|
|
11
11
|
def emit(self, record):
|
|
12
12
|
try:
|
|
13
13
|
dt = (
|
|
14
|
-
datetime.now(
|
|
15
|
-
.replace(microsecond=0)
|
|
14
|
+
datetime.now(timezone.utc)
|
|
15
|
+
.replace(microsecond=0, tzinfo=None)
|
|
16
16
|
.isoformat()
|
|
17
17
|
+ "Z"
|
|
18
18
|
)
|
{sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo/wrapper/_retry_strategy.py
RENAMED
|
@@ -44,7 +44,7 @@ class RetryStrategy:
|
|
|
44
44
|
self._exp_base = exp_base
|
|
45
45
|
return
|
|
46
46
|
|
|
47
|
-
def make_retryer(self):
|
|
47
|
+
def make_retryer(self) -> tn.Retrying:
|
|
48
48
|
return tn.Retrying(
|
|
49
49
|
stop=tn.stop_after_attempt(self._stop_after),
|
|
50
50
|
retry=(
|
|
@@ -63,7 +63,7 @@ class RetryStrategy:
|
|
|
63
63
|
before_sleep=_log_retry_info,
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
-
def make_retryer_async(self):
|
|
66
|
+
def make_retryer_async(self) -> tn.AsyncRetrying:
|
|
67
67
|
return tn.AsyncRetrying(
|
|
68
68
|
stop=tn.stop_after_attempt(self._stop_after),
|
|
69
69
|
retry=(
|
|
@@ -3,6 +3,7 @@ import contextlib
|
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
5
|
import time
|
|
6
|
+
from typing import Dict, Optional, Tuple
|
|
6
7
|
|
|
7
8
|
import httpx
|
|
8
9
|
import jwt
|
|
@@ -25,11 +26,14 @@ DEFAULT_TIMEOUT = httpx.Timeout(30.0)
|
|
|
25
26
|
class SumoClient:
|
|
26
27
|
"""Authenticate and perform requests to the Sumo API."""
|
|
27
28
|
|
|
29
|
+
_client: httpx.Client
|
|
30
|
+
_async_client: httpx.AsyncClient
|
|
31
|
+
|
|
28
32
|
def __init__(
|
|
29
33
|
self,
|
|
30
34
|
env: str,
|
|
31
|
-
token: str = None,
|
|
32
|
-
interactive: bool =
|
|
35
|
+
token: Optional[str] = None,
|
|
36
|
+
interactive: bool = True,
|
|
33
37
|
devicecode: bool = False,
|
|
34
38
|
verbosity: str = "CRITICAL",
|
|
35
39
|
retry_strategy=RetryStrategy(),
|
|
@@ -119,26 +123,23 @@ class SumoClient:
|
|
|
119
123
|
def __enter__(self):
|
|
120
124
|
return self
|
|
121
125
|
|
|
122
|
-
def __exit__(self,
|
|
126
|
+
def __exit__(self, *_):
|
|
123
127
|
if not self._borrowed_client:
|
|
124
128
|
self._client.close()
|
|
125
|
-
self._client = None
|
|
126
129
|
return False
|
|
127
130
|
|
|
128
131
|
async def __aenter__(self):
|
|
129
132
|
return self
|
|
130
133
|
|
|
131
|
-
async def __aexit__(self,
|
|
134
|
+
async def __aexit__(self, *_):
|
|
132
135
|
if not self._borrowed_async_client:
|
|
133
136
|
await self._async_client.aclose()
|
|
134
|
-
self._async_client = None
|
|
135
137
|
return False
|
|
136
138
|
|
|
137
139
|
def __del__(self):
|
|
138
140
|
if self._client is not None and not self._borrowed_client:
|
|
139
141
|
self._client.close()
|
|
140
142
|
pass
|
|
141
|
-
self._client = None
|
|
142
143
|
if self._async_client is not None and not self._borrowed_async_client:
|
|
143
144
|
|
|
144
145
|
async def closeit(client):
|
|
@@ -151,7 +152,6 @@ class SumoClient:
|
|
|
151
152
|
except RuntimeError:
|
|
152
153
|
pass
|
|
153
154
|
pass
|
|
154
|
-
self._async_client = None
|
|
155
155
|
|
|
156
156
|
def authenticate(self):
|
|
157
157
|
if self.auth is None:
|
|
@@ -186,7 +186,7 @@ class SumoClient:
|
|
|
186
186
|
)
|
|
187
187
|
|
|
188
188
|
@raise_for_status
|
|
189
|
-
def get(self, path: str, params:
|
|
189
|
+
def get(self, path: str, params: Optional[Dict] = None) -> httpx.Response:
|
|
190
190
|
"""Performs a GET-request to the Sumo API.
|
|
191
191
|
|
|
192
192
|
Args:
|
|
@@ -247,9 +247,9 @@ class SumoClient:
|
|
|
247
247
|
def post(
|
|
248
248
|
self,
|
|
249
249
|
path: str,
|
|
250
|
-
blob: bytes = None,
|
|
251
|
-
json: dict = None,
|
|
252
|
-
params: dict = None,
|
|
250
|
+
blob: Optional[bytes] = None,
|
|
251
|
+
json: Optional[dict] = None,
|
|
252
|
+
params: Optional[dict] = None,
|
|
253
253
|
) -> httpx.Response:
|
|
254
254
|
"""Performs a POST-request to the Sumo API.
|
|
255
255
|
|
|
@@ -320,7 +320,10 @@ class SumoClient:
|
|
|
320
320
|
|
|
321
321
|
@raise_for_status
|
|
322
322
|
def put(
|
|
323
|
-
self,
|
|
323
|
+
self,
|
|
324
|
+
path: str,
|
|
325
|
+
blob: Optional[bytes] = None,
|
|
326
|
+
json: Optional[dict] = None,
|
|
324
327
|
) -> httpx.Response:
|
|
325
328
|
"""Performs a PUT-request to the Sumo API.
|
|
326
329
|
|
|
@@ -365,7 +368,9 @@ class SumoClient:
|
|
|
365
368
|
return retryer(_put)
|
|
366
369
|
|
|
367
370
|
@raise_for_status
|
|
368
|
-
def delete(
|
|
371
|
+
def delete(
|
|
372
|
+
self, path: str, params: Optional[dict] = None
|
|
373
|
+
) -> httpx.Response:
|
|
369
374
|
"""Performs a DELETE-request to the Sumo API.
|
|
370
375
|
|
|
371
376
|
Args:
|
|
@@ -402,12 +407,12 @@ class SumoClient:
|
|
|
402
407
|
|
|
403
408
|
return retryer(_delete)
|
|
404
409
|
|
|
405
|
-
def _get_retry_details(self, response_in):
|
|
410
|
+
def _get_retry_details(self, response_in) -> Tuple[str, int]:
|
|
406
411
|
assert response_in.status_code == 202, (
|
|
407
412
|
"Incorrect status code; expcted 202"
|
|
408
413
|
)
|
|
409
414
|
headers = response_in.headers
|
|
410
|
-
location = headers.get("location")
|
|
415
|
+
location: str = headers.get("location")
|
|
411
416
|
assert location is not None, "Missing header: Location"
|
|
412
417
|
assert location.startswith(self.base_url)
|
|
413
418
|
retry_after = headers.get("retry-after")
|
|
@@ -440,7 +445,6 @@ class SumoClient:
|
|
|
440
445
|
)
|
|
441
446
|
location, retry_after = self._get_retry_details(response)
|
|
442
447
|
pass
|
|
443
|
-
return None # should never get here.
|
|
444
448
|
|
|
445
449
|
def getLogger(self, name):
|
|
446
450
|
"""Gets a logger object that sends log objects into the message_log
|
|
@@ -495,7 +499,9 @@ class SumoClient:
|
|
|
495
499
|
return self
|
|
496
500
|
|
|
497
501
|
@raise_for_status_async
|
|
498
|
-
async def get_async(
|
|
502
|
+
async def get_async(
|
|
503
|
+
self, path: str, params: Optional[dict] = None
|
|
504
|
+
) -> httpx.Response:
|
|
499
505
|
"""Performs an async GET-request to the Sumo API.
|
|
500
506
|
|
|
501
507
|
Args:
|
|
@@ -556,9 +562,9 @@ class SumoClient:
|
|
|
556
562
|
async def post_async(
|
|
557
563
|
self,
|
|
558
564
|
path: str,
|
|
559
|
-
blob: bytes = None,
|
|
560
|
-
json: dict = None,
|
|
561
|
-
params: dict = None,
|
|
565
|
+
blob: Optional[bytes] = None,
|
|
566
|
+
json: Optional[dict] = None,
|
|
567
|
+
params: Optional[dict] = None,
|
|
562
568
|
) -> httpx.Response:
|
|
563
569
|
"""Performs an async POST-request to the Sumo API.
|
|
564
570
|
|
|
@@ -630,7 +636,10 @@ class SumoClient:
|
|
|
630
636
|
|
|
631
637
|
@raise_for_status_async
|
|
632
638
|
async def put_async(
|
|
633
|
-
self,
|
|
639
|
+
self,
|
|
640
|
+
path: str,
|
|
641
|
+
blob: Optional[bytes] = None,
|
|
642
|
+
json: Optional[dict] = None,
|
|
634
643
|
) -> httpx.Response:
|
|
635
644
|
"""Performs an async PUT-request to the Sumo API.
|
|
636
645
|
|
|
@@ -675,7 +684,9 @@ class SumoClient:
|
|
|
675
684
|
return await retryer(_put)
|
|
676
685
|
|
|
677
686
|
@raise_for_status_async
|
|
678
|
-
async def delete_async(
|
|
687
|
+
async def delete_async(
|
|
688
|
+
self, path: str, params: Optional[dict] = None
|
|
689
|
+
) -> httpx.Response:
|
|
679
690
|
"""Performs an async DELETE-request to the Sumo API.
|
|
680
691
|
|
|
681
692
|
Args:
|
|
@@ -736,4 +747,3 @@ class SumoClient:
|
|
|
736
747
|
)
|
|
737
748
|
location, retry_after = self._get_retry_details(response)
|
|
738
749
|
pass
|
|
739
|
-
return None # should never get here.
|
{sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/src/sumo_wrapper_python.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: sumo-wrapper-python
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.28
|
|
4
4
|
Summary: Python wrapper for the Sumo API
|
|
5
5
|
Author: Equinor
|
|
6
6
|
License: Apache License
|
|
@@ -229,6 +229,7 @@ Requires-Dist: sphinxcontrib-apidoc; extra == "docs"
|
|
|
229
229
|
Provides-Extra: dev
|
|
230
230
|
Requires-Dist: ruff; extra == "dev"
|
|
231
231
|
Requires-Dist: pre-commit; extra == "dev"
|
|
232
|
+
Dynamic: license-file
|
|
232
233
|
|
|
233
234
|
# sumo-wrapper-python
|
|
234
235
|
|
|
File without changes
|
|
File without changes
|
{sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/.github/workflows/publish_release.yml
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sumo_wrapper_python-1.0.26 → sumo_wrapper_python-1.0.28}/docs/_static/equinor_logo_only.jpg
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|