sumo-wrapper-python 1.0.8__py3-none-any.whl → 1.0.9__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.
Potentially problematic release.
This version of sumo-wrapper-python might be problematic. Click here for more details.
- sumo/wrapper/_auth_provider.py +60 -20
- sumo/wrapper/_decorators.py +6 -0
- sumo/wrapper/_logging.py +3 -0
- sumo/wrapper/_version.py +2 -2
- sumo/wrapper/login.py +5 -0
- sumo/wrapper/sumo_client.py +21 -0
- {sumo_wrapper_python-1.0.8.dist-info → sumo_wrapper_python-1.0.9.dist-info}/METADATA +9 -154
- sumo_wrapper_python-1.0.9.dist-info/RECORD +17 -0
- {sumo_wrapper_python-1.0.8.dist-info → sumo_wrapper_python-1.0.9.dist-info}/WHEEL +1 -1
- sumo_wrapper_python-1.0.8.dist-info/RECORD +0 -17
- {sumo_wrapper_python-1.0.8.dist-info → sumo_wrapper_python-1.0.9.dist-info}/LICENSE +0 -0
- {sumo_wrapper_python-1.0.8.dist-info → sumo_wrapper_python-1.0.9.dist-info}/entry_points.txt +0 -0
- {sumo_wrapper_python-1.0.8.dist-info → sumo_wrapper_python-1.0.9.dist-info}/top_level.txt +0 -0
sumo/wrapper/_auth_provider.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
from pathlib import Path
|
|
1
3
|
import msal
|
|
2
4
|
import os
|
|
3
5
|
from datetime import datetime, timedelta
|
|
@@ -34,6 +36,9 @@ class AuthProvider:
|
|
|
34
36
|
self._resource_id = resource_id
|
|
35
37
|
self._scope = scope_for_resource(resource_id)
|
|
36
38
|
self._app = None
|
|
39
|
+
self._login_timeout_minutes = 5
|
|
40
|
+
os.system("") # Ensure color init on all platforms (win10)
|
|
41
|
+
|
|
37
42
|
return
|
|
38
43
|
|
|
39
44
|
@tn.retry(
|
|
@@ -57,7 +62,11 @@ class AuthProvider:
|
|
|
57
62
|
return result["access_token"]
|
|
58
63
|
|
|
59
64
|
def get_authorization(self):
|
|
60
|
-
|
|
65
|
+
token = self.get_token()
|
|
66
|
+
if token is None:
|
|
67
|
+
return ""
|
|
68
|
+
|
|
69
|
+
return {"Authorization": "Bearer " + token}
|
|
61
70
|
|
|
62
71
|
pass
|
|
63
72
|
|
|
@@ -195,25 +204,24 @@ class AuthProviderInteractive(AuthProvider):
|
|
|
195
204
|
)
|
|
196
205
|
def login(self):
|
|
197
206
|
scopes = [self._scope + " offline_access"]
|
|
198
|
-
login_timeout_minutes = 7
|
|
199
|
-
os.system("") # Ensure color init on all platforms (win10)
|
|
200
207
|
print(
|
|
201
208
|
"\n\n \033[31m NOTE! \033[0m"
|
|
202
209
|
+ " Please login to Equinor Azure to enable Sumo access: "
|
|
203
|
-
+ "we
|
|
210
|
+
+ "we are opening a login web-page for you in your browser."
|
|
204
211
|
+ "\nYou should complete your login within "
|
|
205
|
-
+ str(
|
|
212
|
+
+ str(self._login_timeout_minutes)
|
|
206
213
|
+ " minutes, "
|
|
207
214
|
+ "that is before "
|
|
208
215
|
+ str(
|
|
209
216
|
(
|
|
210
|
-
datetime.now()
|
|
217
|
+
datetime.now()
|
|
218
|
+
+ timedelta(minutes=self._login_timeout_minutes)
|
|
211
219
|
).strftime("%H:%M:%S")
|
|
212
220
|
)
|
|
213
221
|
)
|
|
214
222
|
try:
|
|
215
223
|
result = self._app.acquire_token_interactive(
|
|
216
|
-
scopes, timeout=(
|
|
224
|
+
scopes, timeout=(self._login_timeout_minutes * 60)
|
|
217
225
|
)
|
|
218
226
|
if "error" in result:
|
|
219
227
|
print(
|
|
@@ -230,7 +238,9 @@ class AuthProviderInteractive(AuthProvider):
|
|
|
230
238
|
return
|
|
231
239
|
|
|
232
240
|
protect_token_cache(self._resource_id, ".token")
|
|
233
|
-
print(
|
|
241
|
+
print(
|
|
242
|
+
"Equinor Azure login for Sumo access was successful (interactive)"
|
|
243
|
+
)
|
|
234
244
|
return
|
|
235
245
|
|
|
236
246
|
pass
|
|
@@ -261,24 +271,47 @@ class AuthProviderDeviceCode(AuthProvider):
|
|
|
261
271
|
before_sleep=_log_retry_info,
|
|
262
272
|
)
|
|
263
273
|
def login(self):
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
274
|
+
try:
|
|
275
|
+
scopes = [self._scope + " offline_access"]
|
|
276
|
+
flow = self._app.initiate_device_flow(scopes)
|
|
277
|
+
if "error" in flow:
|
|
278
|
+
print(
|
|
279
|
+
"\n\n \033[31m"
|
|
280
|
+
+ "Failed to initiate device-code login. Err: %s"
|
|
281
|
+
+ "\033[0m" % json.dumps(flow, indent=4)
|
|
282
|
+
)
|
|
283
|
+
return
|
|
284
|
+
flow["expires_at"] = (
|
|
285
|
+
int(time.time()) + self._login_timeout_minutes * 60
|
|
270
286
|
)
|
|
271
287
|
|
|
272
|
-
|
|
273
|
-
|
|
288
|
+
print(
|
|
289
|
+
"\033[31m"
|
|
290
|
+
+ " NOTE! Please login to Equinor Azure to enable Sumo access:"
|
|
291
|
+
+ flow["message"]
|
|
292
|
+
+ " \033[0m"
|
|
293
|
+
+ "\nYou should complete your login within a few minutes"
|
|
294
|
+
)
|
|
295
|
+
result = self._app.acquire_token_by_device_flow(flow)
|
|
274
296
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
297
|
+
if "error" in result:
|
|
298
|
+
print(
|
|
299
|
+
"\n\n \033[31m Error during Equinor Azure login "
|
|
300
|
+
"for Sumo access: \033[0m"
|
|
301
|
+
)
|
|
302
|
+
print("Err: ", json.dumps(result, indent=4))
|
|
303
|
+
return
|
|
304
|
+
except Exception:
|
|
305
|
+
print(
|
|
306
|
+
"\n\n \033[31m Failed Equinor Azure login for Sumo access, "
|
|
307
|
+
"one possible reason is timeout \033[0m"
|
|
279
308
|
)
|
|
309
|
+
return
|
|
280
310
|
|
|
281
311
|
protect_token_cache(self._resource_id, ".token")
|
|
312
|
+
print(
|
|
313
|
+
"Equinor Azure login for Sumo access was successful (device-code)"
|
|
314
|
+
)
|
|
282
315
|
|
|
283
316
|
return
|
|
284
317
|
|
|
@@ -384,4 +417,11 @@ def get_auth_provider(
|
|
|
384
417
|
):
|
|
385
418
|
return AuthProviderManaged(resource_id)
|
|
386
419
|
# ELSE
|
|
420
|
+
lockfile_path = Path.home() / ".config/chromium/SingletonLock"
|
|
421
|
+
if Path(lockfile_path).is_symlink() and not str(
|
|
422
|
+
Path(lockfile_path).resolve()
|
|
423
|
+
).__contains__(platform.node()):
|
|
424
|
+
# https://github.com/equinor/sumo-wrapper-python/issues/193
|
|
425
|
+
return AuthProviderDeviceCode(client_id, authority, resource_id)
|
|
426
|
+
# ELSE
|
|
387
427
|
return AuthProviderInteractive(client_id, authority, resource_id)
|
sumo/wrapper/_decorators.py
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
# For sphinx:
|
|
2
|
+
from functools import wraps
|
|
3
|
+
|
|
4
|
+
|
|
1
5
|
def raise_for_status(func):
|
|
6
|
+
@wraps(func)
|
|
2
7
|
def wrapper(*args, **kwargs):
|
|
3
8
|
# FIXME: in newer versions of httpx, raise_for_status() is chainable,
|
|
4
9
|
# so we could simply write
|
|
@@ -11,6 +16,7 @@ def raise_for_status(func):
|
|
|
11
16
|
|
|
12
17
|
|
|
13
18
|
def raise_for_status_async(func):
|
|
19
|
+
@wraps(func)
|
|
14
20
|
async def wrapper(*args, **kwargs):
|
|
15
21
|
# FIXME: in newer versions of httpx, raise_for_status() is chainable,
|
|
16
22
|
# so we could simply write
|
sumo/wrapper/_logging.py
CHANGED
|
@@ -20,6 +20,9 @@ class LogHandlerSumo(logging.Handler):
|
|
|
20
20
|
"funcname": record.funcName,
|
|
21
21
|
"linenumber": record.lineno,
|
|
22
22
|
}
|
|
23
|
+
if "objectUuid" in record.__dict__.keys():
|
|
24
|
+
json["objectUuid"] = record.__dict__.get("objectUuid")
|
|
25
|
+
|
|
23
26
|
self._sumoClient.post("/message-log/new", json=json)
|
|
24
27
|
except Exception:
|
|
25
28
|
# Never fail on logging
|
sumo/wrapper/_version.py
CHANGED
sumo/wrapper/login.py
CHANGED
|
@@ -74,6 +74,11 @@ def main():
|
|
|
74
74
|
if args.print_token:
|
|
75
75
|
print(f"TOKEN: {token}")
|
|
76
76
|
|
|
77
|
+
if token is not None:
|
|
78
|
+
print("Successfully logged in to Sumo environment: " + env)
|
|
79
|
+
else:
|
|
80
|
+
print("Failed login to Sumo environment: " + env)
|
|
81
|
+
|
|
77
82
|
|
|
78
83
|
if __name__ == "__main__":
|
|
79
84
|
main()
|
sumo/wrapper/sumo_client.py
CHANGED
|
@@ -84,6 +84,27 @@ class SumoClient:
|
|
|
84
84
|
access_token=access_token,
|
|
85
85
|
devicecode=devicecode,
|
|
86
86
|
)
|
|
87
|
+
if (
|
|
88
|
+
self.auth.get_token() is None
|
|
89
|
+
and refresh_token is None
|
|
90
|
+
and access_token is None
|
|
91
|
+
):
|
|
92
|
+
print("\n \033[31m !!! Falling back to device-code login:\033[0m")
|
|
93
|
+
self.auth = get_auth_provider(
|
|
94
|
+
client_id=APP_REGISTRATION[env]["CLIENT_ID"],
|
|
95
|
+
authority=f"{AUTHORITY_HOST_URI}/{TENANT_ID}",
|
|
96
|
+
resource_id=APP_REGISTRATION[env]["RESOURCE_ID"],
|
|
97
|
+
interactive=False,
|
|
98
|
+
refresh_token=None,
|
|
99
|
+
access_token=None,
|
|
100
|
+
devicecode=True,
|
|
101
|
+
)
|
|
102
|
+
if self.auth.get_token() is None:
|
|
103
|
+
print(
|
|
104
|
+
"\n\n \033[31m "
|
|
105
|
+
+ "NOTE! Login failed/timed out. Giving up."
|
|
106
|
+
+ "\033[0m"
|
|
107
|
+
)
|
|
87
108
|
|
|
88
109
|
if env == "localhost":
|
|
89
110
|
self.base_url = "http://localhost:8084/api/v1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sumo-wrapper-python
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.9
|
|
4
4
|
Summary: Python wrapper for the Sumo API
|
|
5
5
|
Author: Equinor
|
|
6
6
|
License: Apache License
|
|
@@ -220,165 +220,20 @@ Requires-Dist: azure-identity >=1.13.0
|
|
|
220
220
|
Provides-Extra: docs
|
|
221
221
|
Requires-Dist: sphinx ; extra == 'docs'
|
|
222
222
|
Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
|
|
223
|
+
Requires-Dist: autoapi ; extra == 'docs'
|
|
224
|
+
Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
|
|
225
|
+
Requires-Dist: sphinxcontrib-apidoc ; extra == 'docs'
|
|
223
226
|
Provides-Extra: test
|
|
224
227
|
Requires-Dist: pytest ; extra == 'test'
|
|
225
228
|
Requires-Dist: PyYAML ; extra == 'test'
|
|
226
229
|
|
|
227
230
|
# sumo-wrapper-python
|
|
228
231
|
|
|
229
|
-
|
|
232
|
+
[](https://sumo-wrapper-python.readthedocs.io/en/latest/?badge=latest)
|
|
230
233
|
|
|
231
|
-
|
|
234
|
+
## Documentation and guidelines
|
|
235
|
+
[sumo-wrapper-python documentation](https://sumo-wrapper-python.readthedocs.io/en/latest/)
|
|
232
236
|
|
|
233
|
-
##
|
|
237
|
+
## Contribute
|
|
238
|
+
[Contribution guidelines](./CONTRIBUTING.md)
|
|
234
239
|
|
|
235
|
-
pip install sumo-wrapper-python
|
|
236
|
-
|
|
237
|
-
For internal Equinor users, this package is available through the Komodo
|
|
238
|
-
distribution.
|
|
239
|
-
|
|
240
|
-
# Table of contents
|
|
241
|
-
|
|
242
|
-
- [sumo-wrapper-python](#sumo-wrapper-python)
|
|
243
|
-
- [Install:](#install)
|
|
244
|
-
- [Table of contents](#table-of-contents)
|
|
245
|
-
- [SumoClient](#sumoclient)
|
|
246
|
-
- [Initialization](#initialization)
|
|
247
|
-
- [Parameters](#parameters)
|
|
248
|
-
- [`token` logic](#token-logic)
|
|
249
|
-
- [Methods](#methods)
|
|
250
|
-
- [get(path, \*\*params)](#getpath-params)
|
|
251
|
-
- [post(path, json, blob, params)](#postpath-json-blob-params)
|
|
252
|
-
- [put(path, json, blob)](#putpath-json-blob)
|
|
253
|
-
- [delete(path)](#deletepath)
|
|
254
|
-
- [Async methods](#async-methods)
|
|
255
|
-
|
|
256
|
-
# SumoClient
|
|
257
|
-
|
|
258
|
-
A thin wrapper class for the Sumo API.
|
|
259
|
-
|
|
260
|
-
### Initialization
|
|
261
|
-
|
|
262
|
-
```python
|
|
263
|
-
from sumo.wrapper import SumoClient
|
|
264
|
-
|
|
265
|
-
sumo = SumoClient(env="dev")
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
### Parameters
|
|
269
|
-
|
|
270
|
-
```python
|
|
271
|
-
class SumoClient:
|
|
272
|
-
def __init__(
|
|
273
|
-
self,
|
|
274
|
-
env:str,
|
|
275
|
-
token:str=None,
|
|
276
|
-
interactive:bool=False,
|
|
277
|
-
verbosity:str="CRITICAL"
|
|
278
|
-
):
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
- `env`: sumo environment
|
|
282
|
-
- `token`: bearer token or refresh token
|
|
283
|
-
- `interactive`: use interactive flow when authenticating
|
|
284
|
-
- `verbosity`: "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
|
|
285
|
-
|
|
286
|
-
###### `token` logic
|
|
287
|
-
|
|
288
|
-
If an access token is provided in the `token` parameter, it will be used as long
|
|
289
|
-
as it's valid. An error will be raised when it expires.
|
|
290
|
-
|
|
291
|
-
If we are unable to decode the provided `token` as a JWT, we treat it as a
|
|
292
|
-
refresh token and attempt to use it to retrieve an access token.
|
|
293
|
-
|
|
294
|
-
If no `token` is provided, an authentication code flow/interactive flow is
|
|
295
|
-
triggered to retrieve a token.
|
|
296
|
-
|
|
297
|
-
## Methods
|
|
298
|
-
|
|
299
|
-
`SumoClient` has one method for each HTTP-method that is used in the sumo-core
|
|
300
|
-
API. See examples of how to use these methods below.
|
|
301
|
-
|
|
302
|
-
All methods accepts a path argument. Path parameters can be interpolated into
|
|
303
|
-
the path string. Example:
|
|
304
|
-
|
|
305
|
-
```python
|
|
306
|
-
object_id = "1234"
|
|
307
|
-
|
|
308
|
-
# GET/objects('{obejctid}')
|
|
309
|
-
sumo.get(f"/objects('{object_id}')")
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### get(path, \*\*params)
|
|
313
|
-
|
|
314
|
-
Performs a GET-request to sumo-core. Accepts query parameters as keyword
|
|
315
|
-
arguments.
|
|
316
|
-
|
|
317
|
-
```python
|
|
318
|
-
# Retrieve userdata
|
|
319
|
-
user_data = sumo.get("/userdata")
|
|
320
|
-
|
|
321
|
-
# Search for objects
|
|
322
|
-
results = sumo.get("/search",
|
|
323
|
-
query="class:surface",
|
|
324
|
-
size:3,
|
|
325
|
-
select=["_id"]
|
|
326
|
-
)
|
|
327
|
-
|
|
328
|
-
# Get object by id
|
|
329
|
-
object_id = "159405ba-0046-b321-55ce-542f383ba5c7"
|
|
330
|
-
|
|
331
|
-
obj = sumo.get(f"/objects('{object_id}')")
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
### post(path, json, blob, params)
|
|
335
|
-
|
|
336
|
-
Performs a POST-request to sumo-core. Accepts json and blob, but not both at the
|
|
337
|
-
same time.
|
|
338
|
-
|
|
339
|
-
```python
|
|
340
|
-
# Upload new parent object
|
|
341
|
-
parent_object = sumo.post("/objects", json=parent_meta_data)
|
|
342
|
-
|
|
343
|
-
# Upload child object
|
|
344
|
-
parent_id = parent_object["_id"]
|
|
345
|
-
|
|
346
|
-
child_object = sumo.post(f"/objects('{parent_id}')", json=child_meta_data)
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
### put(path, json, blob)
|
|
350
|
-
|
|
351
|
-
Performs a PUT-request to sumo-core. Accepts json and blob, but not both at the
|
|
352
|
-
same time.
|
|
353
|
-
|
|
354
|
-
```python
|
|
355
|
-
# Upload blob to child object
|
|
356
|
-
child_id = child_object["_id"]
|
|
357
|
-
|
|
358
|
-
sumo.put(f"/objects('{child_id}')/blob", blob=blob)
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
### delete(path)
|
|
362
|
-
|
|
363
|
-
Performs a DELETE-request to sumo-core.
|
|
364
|
-
|
|
365
|
-
```python
|
|
366
|
-
# Delete blob
|
|
367
|
-
sumo.delete(f"/objects('{child_id}')/blob")
|
|
368
|
-
|
|
369
|
-
# Delete child object
|
|
370
|
-
sumo.delete(f"/objects('{child_id}')")
|
|
371
|
-
|
|
372
|
-
# Delete parent object
|
|
373
|
-
sumo.delete(f"/objects('{parent_id}')")
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
## Async methods
|
|
377
|
-
|
|
378
|
-
`SumoClient` also has *async* alternatives `get_async`, `post_async`, `put_async` and `delete_async`.
|
|
379
|
-
These accept the same parameters as their synchronous counterparts, but have to be *awaited*.
|
|
380
|
-
|
|
381
|
-
```python
|
|
382
|
-
# Retrieve userdata
|
|
383
|
-
user_data = await sumo.get_async("/userdata")
|
|
384
|
-
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
sumo/__init__.py,sha256=ftS-xRPSH-vU7fIHlnZQaCTWbNvs4owJivNW65kzsIM,85
|
|
2
|
+
sumo/wrapper/__init__.py,sha256=wW7Bjl0btCgK9_exGVrfJsnFmTOybIdyeCudz0LueQM,235
|
|
3
|
+
sumo/wrapper/_auth_provider.py,sha256=HieseMcqT9lMBqgyzwL5Pr6CCyk-eFjKyYhJQx8UKRw,13494
|
|
4
|
+
sumo/wrapper/_blob_client.py,sha256=y15_TThJ4ENFtEAF37mgju6Htc8D3ZyzcYCqsYQZo7Y,1495
|
|
5
|
+
sumo/wrapper/_decorators.py,sha256=3IEi6GXVkkDACHoo8dOeDoBtZh5TlJ6Tw0qlpOVHqLQ,806
|
|
6
|
+
sumo/wrapper/_logging.py,sha256=lnhjn6oQna33jZpzeZ7IeBya2uKNfrzXr_C3nw7txo0,965
|
|
7
|
+
sumo/wrapper/_retry_strategy.py,sha256=9PjOT0hOhLbCHrJu02thUkGdY39NpB2rqa_XUODoguw,2415
|
|
8
|
+
sumo/wrapper/_version.py,sha256=29gfaFnVGHlO4YwJu6vgvQjCQwPqDmuCvkEOYMZyflo,411
|
|
9
|
+
sumo/wrapper/config.py,sha256=6t7qqjrrmd11m4VMlRryiMYw2JDU_R51305woAP1TAs,865
|
|
10
|
+
sumo/wrapper/login.py,sha256=HY3CLu3u0RZtgSbitpdyk2T0P-M9ttZ6LRDsGO4BwRM,1773
|
|
11
|
+
sumo/wrapper/sumo_client.py,sha256=Mjco-nFF28GgmjXgDmGmXmFXr7LJI50M54zL0zt3CJs,15545
|
|
12
|
+
sumo_wrapper_python-1.0.9.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
13
|
+
sumo_wrapper_python-1.0.9.dist-info/METADATA,sha256=pmewZzDIe8sALypH6d9EVNxBr5qiuoCFlW5MfBjytSg,14267
|
|
14
|
+
sumo_wrapper_python-1.0.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
15
|
+
sumo_wrapper_python-1.0.9.dist-info/entry_points.txt,sha256=V_vGky2C3He5vohJAxnBdvpt_fqfUDFj5irUm9HtoFc,55
|
|
16
|
+
sumo_wrapper_python-1.0.9.dist-info/top_level.txt,sha256=rLbKyH9rWgCj3PoLeR7fvC5X8vCaUc5LF8-Y_GBWZL0,5
|
|
17
|
+
sumo_wrapper_python-1.0.9.dist-info/RECORD,,
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
sumo/__init__.py,sha256=ftS-xRPSH-vU7fIHlnZQaCTWbNvs4owJivNW65kzsIM,85
|
|
2
|
-
sumo/wrapper/__init__.py,sha256=wW7Bjl0btCgK9_exGVrfJsnFmTOybIdyeCudz0LueQM,235
|
|
3
|
-
sumo/wrapper/_auth_provider.py,sha256=jxhLxaImD0PMKZDy6YNcBOn-ogF7G5F5Fvh4oDwW40g,12023
|
|
4
|
-
sumo/wrapper/_blob_client.py,sha256=y15_TThJ4ENFtEAF37mgju6Htc8D3ZyzcYCqsYQZo7Y,1495
|
|
5
|
-
sumo/wrapper/_decorators.py,sha256=FSorPaTEBpq2N0qrqfdTt0jMToe_0PpOYlsL6vZSbIg,728
|
|
6
|
-
sumo/wrapper/_logging.py,sha256=XgXcOAEoVw0aqij7V7EPTiP3ALqa8xNDgJgKyWOxeok,838
|
|
7
|
-
sumo/wrapper/_retry_strategy.py,sha256=9PjOT0hOhLbCHrJu02thUkGdY39NpB2rqa_XUODoguw,2415
|
|
8
|
-
sumo/wrapper/_version.py,sha256=vy0P95Si-KzUl6NsixjrWEHfr5xcmkA_oO_S3bQRmvE,411
|
|
9
|
-
sumo/wrapper/config.py,sha256=6t7qqjrrmd11m4VMlRryiMYw2JDU_R51305woAP1TAs,865
|
|
10
|
-
sumo/wrapper/login.py,sha256=HB_USKw6pR4j5EyNevaFVJGQjQ3t_8F__ZBaR29XLf4,1610
|
|
11
|
-
sumo/wrapper/sumo_client.py,sha256=q5k6qP_oSgzmfFf1Bc2zw8L2KK85GFXg99Ro8GT3GZA,14741
|
|
12
|
-
sumo_wrapper_python-1.0.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
13
|
-
sumo_wrapper_python-1.0.8.dist-info/METADATA,sha256=CVL2k02sgRkHOJk1EvXcED6XHZbcxS75ZVrXejy9mB8,17407
|
|
14
|
-
sumo_wrapper_python-1.0.8.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
15
|
-
sumo_wrapper_python-1.0.8.dist-info/entry_points.txt,sha256=V_vGky2C3He5vohJAxnBdvpt_fqfUDFj5irUm9HtoFc,55
|
|
16
|
-
sumo_wrapper_python-1.0.8.dist-info/top_level.txt,sha256=rLbKyH9rWgCj3PoLeR7fvC5X8vCaUc5LF8-Y_GBWZL0,5
|
|
17
|
-
sumo_wrapper_python-1.0.8.dist-info/RECORD,,
|
|
File without changes
|
{sumo_wrapper_python-1.0.8.dist-info → sumo_wrapper_python-1.0.9.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|