Skip to content

Commit 17ed752

Browse files
authored
Breaking changes (#154)
* Breaking changes: - SumoClient .get() and .delete() no longer decodes the response; instead, the response object is returned. - Instead of keyword parameters, SumoClient .get() takes the parameter 'params', which is a dict. - The parameter 'params' is also added to a few other methods. In particular, it is now possible to pass a '$pit' parameter to the DELETE handler for 'pit'. * (reformatted with black. --------- Co-authored-by: Raymond Wiker <rayw@equinor.com>
1 parent b8fc568 commit 17ed752

2 files changed

Lines changed: 48 additions & 60 deletions

File tree

src/sumo/wrapper/sumo_client.py

Lines changed: 23 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from ._auth_provider import get_auth_provider
1010
from .config import APP_REGISTRATION, TENANT_ID, AUTHORITY_HOST_URI
1111

12-
from ._decorators import http_unpack, raise_for_status, http_retry
12+
from ._decorators import raise_for_status, http_retry
1313

1414
logger = logging.getLogger("sumo.wrapper")
1515

@@ -47,7 +47,14 @@ def __init__(
4747
refresh_token = None
4848
if token:
4949
logger.debug("Token provided")
50-
payload = self.__decode_token(token)
50+
51+
payload = None
52+
try:
53+
payload = jwt.decode(
54+
token, options={"verify_signature": False}
55+
)
56+
except jwt.InvalidTokenError:
57+
pass
5158

5259
if payload:
5360
logger.debug(f"Token decoded as JWT, payload: {payload}")
@@ -101,49 +108,14 @@ def blob_client(self) -> BlobClient:
101108

102109
return self._blob_client
103110

104-
def __decode_token(self, token: str) -> dict:
105-
"""
106-
Decodes a Json Web Token, returns the payload as a dictionary.
107-
108-
Args:
109-
token: Token to decode
110-
111-
Returns:
112-
Decoded Json Web Token (None if token can't be decoded)
113-
"""
114-
115-
try:
116-
payload = jwt.decode(token, options={"verify_signature": False})
117-
return payload
118-
except jwt.InvalidTokenError:
119-
return None
120-
121-
def _process_params(self, params_dict: dict) -> dict:
122-
"""Convert a dictionary of query parameters to Sumo friendly format.
123-
124-
Args:
125-
params_dict: Dictionary of query parameters
126-
127-
Returns:
128-
Dictionary of processed parameters
129-
"""
130-
131-
prefixed_params = {}
132-
133-
for param_key in params_dict:
134-
prefixed_params[f"${param_key}"] = params_dict[param_key]
135-
136-
return None if prefixed_params == {} else prefixed_params
137-
138-
@http_unpack
139111
@raise_for_status
140112
@http_retry
141-
def get(self, path: str, **params) -> dict:
113+
def get(self, path: str, params: dict = None) -> dict:
142114
"""Performs a GET-request to the Sumo API.
143115
144116
Args:
145117
path: Path to a Sumo endpoint
146-
params: Keyword arguments treated as query parameters
118+
params: query parameters, as dictionary
147119
148120
Returns:
149121
Sumo JSON response as a dictionary
@@ -175,7 +147,7 @@ def get(self, path: str, **params) -> dict:
175147

176148
response = httpx.get(
177149
f"{self.base_url}{path}",
178-
params=self._process_params(params),
150+
params=params,
179151
headers=headers,
180152
follow_redirects=True,
181153
timeout=DEFAULT_TIMEOUT,
@@ -201,6 +173,7 @@ def post(
201173
path: Path to a Sumo endpoint
202174
blob: Blob payload
203175
json: Json payload
176+
params: query parameters, as dictionary
204177
205178
Returns:
206179
Sumo response object
@@ -300,14 +273,14 @@ def put(
300273

301274
return response
302275

303-
@http_unpack
304276
@raise_for_status
305277
@http_retry
306-
def delete(self, path: str) -> dict:
278+
def delete(self, path: str, params: dict = None) -> dict:
307279
"""Performs a DELETE-request to the Sumo API.
308280
309281
Args:
310282
path: Path to a Sumo endpoint
283+
params: query parameters, as dictionary
311284
312285
Returns:
313286
Sumo JSON resposne as a dictionary
@@ -331,6 +304,7 @@ def delete(self, path: str) -> dict:
331304
response = httpx.delete(
332305
f"{self.base_url}{path}",
333306
headers=headers,
307+
params=params,
334308
timeout=DEFAULT_TIMEOUT,
335309
)
336310

@@ -354,15 +328,14 @@ def getLogger(self, name):
354328
logger.addHandler(handler)
355329
return logger
356330

357-
@http_unpack
358331
@raise_for_status
359332
@http_retry
360-
async def get_async(self, path: str, **params):
333+
async def get_async(self, path: str, params: dict = None):
361334
"""Performs an async GET-request to the Sumo API.
362335
363336
Args:
364337
path: Path to a Sumo endpoint
365-
params: Keyword arguments treated as query parameters
338+
params: query parameters, as dictionary
366339
367340
Returns:
368341
Sumo JSON response as a dictionary
@@ -394,7 +367,7 @@ async def get_async(self, path: str, **params):
394367
async with httpx.AsyncClient() as client:
395368
response = await client.get(
396369
f"{self.base_url}{path}",
397-
params=self._process_params(params),
370+
params=params,
398371
headers=headers,
399372
timeout=DEFAULT_TIMEOUT,
400373
)
@@ -419,6 +392,7 @@ async def post_async(
419392
path: Path to a Sumo endpoint
420393
blob: Blob payload
421394
json: Json payload
395+
params: query parameters, as dictionary
422396
423397
Returns:
424398
Sumo response object
@@ -522,14 +496,14 @@ async def put_async(
522496

523497
return response
524498

525-
@http_unpack
526499
@raise_for_status
527500
@http_retry
528-
async def delete_async(self, path: str) -> dict:
501+
async def delete_async(self, path: str, params: dict = None) -> dict:
529502
"""Performs an async DELETE-request to the Sumo API.
530503
531504
Args:
532505
path: Path to a Sumo endpoint
506+
params: query parameters, as dictionary
533507
534508
Returns:
535509
Sumo JSON resposne as a dictionary
@@ -554,6 +528,7 @@ async def delete_async(self, path: str) -> dict:
554528
response = await client.delete(
555529
url=f"{self.base_url}{path}",
556530
headers=headers,
531+
params=params,
557532
timeout=DEFAULT_TIMEOUT,
558533
)
559534

tests/test_sumo_thin_client.py

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def _get_blob_uri(C, object_id):
4747

4848

4949
def _download_object(C, object_id):
50-
json = C.api.get(f"/objects('{object_id}')")
50+
json = C.api.get(f"/objects('{object_id}')").json()
5151

5252
return json
5353

@@ -56,12 +56,14 @@ def _upload_child_level_json(C, parent_id, json):
5656
response = C.api.post(f"/objects('{parent_id}')", json=json)
5757

5858
if not 200 <= response.status_code < 202:
59-
raise Exception(f"Response: {response.status_code}, Text: {response.text}")
59+
raise Exception(
60+
f"Response: {response.status_code}, Text: {response.text}"
61+
)
6062
return response
6163

6264

6365
def _delete_object(C, object_id):
64-
response = C.api.delete(f"/objects('{object_id}')")
66+
response = C.api.delete(f"/objects('{object_id}')").json()
6567

6668
return response
6769

@@ -111,7 +113,9 @@ def test_upload_search_delete_ensemble_child(token):
111113

112114
fmu_surface_metadata["fmu"]["case"]["uuid"] = case_uuid
113115

114-
fmu_surface_id = fmu_surface_metadata.get("fmu").get("realization").get("id")
116+
fmu_surface_id = (
117+
fmu_surface_metadata.get("fmu").get("realization").get("id")
118+
)
115119
response_surface = _upload_child_level_json(
116120
C=C, parent_id=case_id, json=fmu_surface_metadata
117121
)
@@ -123,22 +127,28 @@ def test_upload_search_delete_ensemble_child(token):
123127
blob_url = response_surface.json().get("blob_url")
124128

125129
# Upload BLOB
126-
response_blob = _upload_blob(C=C, blob=B, url=blob_url, object_id=surface_id)
130+
response_blob = _upload_blob(
131+
C=C, blob=B, url=blob_url, object_id=surface_id
132+
)
127133
assert 200 <= response_blob.status_code <= 202
128134

129135
sleep(4)
130136

131137
# Search for ensemble
132138
query = f"fmu.case.uuid:{case_uuid}"
133139

134-
search_results = C.api.get("/searchroot", query=query, select=["_source"])
140+
search_results = C.api.get(
141+
"/searchroot", params={"$query": query, "$select": ["_source"]}
142+
).json()
135143

136144
hits = search_results.get("hits").get("hits")
137145
assert len(hits) == 1
138146
assert hits[0].get("_id") == case_id
139147

140148
# Search for child object
141-
search_results = C.api.get("/search", query=query, select=["_source"])
149+
search_results = C.api.get(
150+
"/search", {"$query": query, "$select": ["_source"]}
151+
).json()
142152

143153
total = search_results.get("hits").get("total").get("value")
144154
assert total == 2
@@ -147,7 +157,7 @@ def test_upload_search_delete_ensemble_child(token):
147157
assert get_result["_id"] == surface_id
148158

149159
# Search for blob
150-
bin_obj = C.api.get(f"/objects('{surface_id}')/blob")
160+
bin_obj = C.api.get(f"/objects('{surface_id}')/blob").content
151161
assert bin_obj == B
152162

153163
# Delete Ensemble
@@ -157,14 +167,18 @@ def test_upload_search_delete_ensemble_child(token):
157167
sleep(40)
158168

159169
# Search for ensemble
160-
search_results = C.api.get("/searchroot", query=query, select=["_source"])
170+
search_results = C.api.get(
171+
"/searchroot", {"$query": query, "$select": ["_source"]}
172+
).json()
161173

162174
hits = search_results.get("hits").get("hits")
163175

164176
assert len(hits) == 0
165177

166178
# Search for child object
167-
search_results = C.api.get("/search", query=query, select=["_source"])
179+
search_results = C.api.get(
180+
"/search", {"$query": query, "$select": ["_source"]}
181+
).json()
168182
total = search_results.get("hits").get("total").get("value")
169183
assert total == 0
170184

@@ -189,12 +203,11 @@ def test_upload_duplicate_ensemble(token):
189203

190204
with open("tests/testdata/case.yml", "r") as stream:
191205
fmu_metadata2 = yaml.safe_load(stream)
192-
206+
193207
case_uuid = str(uuid.uuid4())
194208
fmu_metadata1["fmu"]["case"]["uuid"] = case_uuid
195209
fmu_metadata2["fmu"]["case"]["uuid"] = case_uuid
196210

197-
198211
# upload case metadata, get object_id
199212
response1 = _upload_parent_object(C=C, json=fmu_metadata1)
200213
assert 200 <= response1.status_code <= 202

0 commit comments

Comments
 (0)