osducli 0.0.42__py3-none-any.whl → 0.0.44__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.
- osducli/__init__.py +1 -1
- osducli/cliclient.py +38 -10
- osducli/commands/storage/add.py +45 -29
- osducli/commands/storage/delete.py +6 -5
- osducli/util/file.py +18 -0
- {osducli-0.0.42.dist-info → osducli-0.0.44.dist-info}/METADATA +17 -2
- {osducli-0.0.42.dist-info → osducli-0.0.44.dist-info}/RECORD +11 -11
- {osducli-0.0.42.dist-info → osducli-0.0.44.dist-info}/LICENSE.md +0 -0
- {osducli-0.0.42.dist-info → osducli-0.0.44.dist-info}/WHEEL +0 -0
- {osducli-0.0.42.dist-info → osducli-0.0.44.dist-info}/entry_points.txt +0 -0
- {osducli-0.0.42.dist-info → osducli-0.0.44.dist-info}/top_level.txt +0 -0
osducli/__init__.py
CHANGED
osducli/cliclient.py
CHANGED
|
@@ -157,12 +157,14 @@ class CliOsduClient(BaseClient):
|
|
|
157
157
|
return url
|
|
158
158
|
|
|
159
159
|
def check_status_code(self, response: requests.Response, ok_status_codes: list = None):
|
|
160
|
+
"""Check the status code of the response and raise an exception if not in the list of ok status codes"""
|
|
160
161
|
if ok_status_codes is None:
|
|
161
162
|
ok_status_codes = [200]
|
|
162
163
|
if response.status_code not in ok_status_codes:
|
|
163
164
|
raise HTTPError(response=response)
|
|
164
165
|
|
|
165
166
|
def get_search_client(self) -> SearchClient:
|
|
167
|
+
"""Get a client for the search service"""
|
|
166
168
|
search_url = self.url_from_config(CONFIG_SEARCH_URL, "")
|
|
167
169
|
if search_url.endswith("/"):
|
|
168
170
|
search_url = search_url[:-1]
|
|
@@ -174,6 +176,7 @@ class CliOsduClient(BaseClient):
|
|
|
174
176
|
)
|
|
175
177
|
|
|
176
178
|
def get_storage_record_client(self) -> RecordClient:
|
|
179
|
+
"""Get a client for the storage record service"""
|
|
177
180
|
storage_url = self.url_from_config(CONFIG_STORAGE_URL, "")
|
|
178
181
|
if storage_url.endswith("/"):
|
|
179
182
|
storage_url = storage_url[:-1]
|
|
@@ -185,6 +188,7 @@ class CliOsduClient(BaseClient):
|
|
|
185
188
|
)
|
|
186
189
|
|
|
187
190
|
def get_entitlements_client(self) -> EntitlementsClient:
|
|
191
|
+
"""Get a client for the entitlements service"""
|
|
188
192
|
entitlements_url = self.url_from_config(CONFIG_ENTITLEMENTS_URL, "")
|
|
189
193
|
if entitlements_url.endswith("/"):
|
|
190
194
|
entitlements_url = entitlements_url[:-1]
|
|
@@ -195,7 +199,15 @@ class CliOsduClient(BaseClient):
|
|
|
195
199
|
token_refresher=self.token_refresher
|
|
196
200
|
)
|
|
197
201
|
|
|
198
|
-
def get_wellbore_ddms_client(
|
|
202
|
+
def get_wellbore_ddms_client(
|
|
203
|
+
self,
|
|
204
|
+
url_extra_path: str
|
|
205
|
+
) -> WellboreDdmsClient:
|
|
206
|
+
"""Get a client for the wellbore ddms service
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
url_extra_path (str): extra path to add to the base path
|
|
210
|
+
"""
|
|
199
211
|
wellbore_ddms_url = self.url_from_config(CONFIG_WELLBORE_DDMS_URL, url_extra_path)
|
|
200
212
|
return WellboreDdmsClient(
|
|
201
213
|
wellbore_ddms_url=wellbore_ddms_url,
|
|
@@ -205,9 +217,12 @@ class CliOsduClient(BaseClient):
|
|
|
205
217
|
)
|
|
206
218
|
|
|
207
219
|
def cli_get(
|
|
208
|
-
self,
|
|
220
|
+
self,
|
|
221
|
+
config_url_key: str,
|
|
222
|
+
url_extra_path: str,
|
|
223
|
+
ok_status_codes: list = None
|
|
209
224
|
) -> requests.Response:
|
|
210
|
-
"""
|
|
225
|
+
"""Basic GET call to the given url, returning the response object.
|
|
211
226
|
|
|
212
227
|
Args:
|
|
213
228
|
config_url_key (str): key in configuration for the base path
|
|
@@ -220,9 +235,12 @@ class CliOsduClient(BaseClient):
|
|
|
220
235
|
return response
|
|
221
236
|
|
|
222
237
|
def cli_get_returning_json(
|
|
223
|
-
self,
|
|
238
|
+
self,
|
|
239
|
+
config_url_key: str,
|
|
240
|
+
url_extra_path: str,
|
|
241
|
+
ok_status_codes: list = None
|
|
224
242
|
) -> dict:
|
|
225
|
-
"""
|
|
243
|
+
"""Basic GET call to the given url, returning the json.
|
|
226
244
|
|
|
227
245
|
Args:
|
|
228
246
|
config_url_key (str): key in configuration for the base path
|
|
@@ -241,7 +259,7 @@ class CliOsduClient(BaseClient):
|
|
|
241
259
|
data: str | dict,
|
|
242
260
|
ok_status_codes: list = None,
|
|
243
261
|
) -> dict:
|
|
244
|
-
"""
|
|
262
|
+
"""Basic POST call to the given url, returning the json.
|
|
245
263
|
|
|
246
264
|
Args:
|
|
247
265
|
config_url_key (str): key in configuration for the base path
|
|
@@ -253,6 +271,8 @@ class CliOsduClient(BaseClient):
|
|
|
253
271
|
dict: returned json
|
|
254
272
|
"""
|
|
255
273
|
url = self.url_from_config(config_url_key, url_extra_path)
|
|
274
|
+
if isinstance(data, dict):
|
|
275
|
+
data = json.dumps(data)
|
|
256
276
|
response = self.make_request(method=HttpMethod.POST, url=url, data=data)
|
|
257
277
|
self.check_status_code(response, ok_status_codes)
|
|
258
278
|
return response.json()
|
|
@@ -263,7 +283,7 @@ class CliOsduClient(BaseClient):
|
|
|
263
283
|
url_extra_path: str,
|
|
264
284
|
ok_status_codes: list = None,
|
|
265
285
|
) -> requests.Response:
|
|
266
|
-
"""
|
|
286
|
+
"""Basic DELETE call to the given url.
|
|
267
287
|
|
|
268
288
|
Args:
|
|
269
289
|
config_url_key (str): key in configuration for the base path
|
|
@@ -274,7 +294,11 @@ class CliOsduClient(BaseClient):
|
|
|
274
294
|
requests.Response: Response object from the HTTP call
|
|
275
295
|
"""
|
|
276
296
|
url = self.url_from_config(config_url_key, url_extra_path)
|
|
277
|
-
|
|
297
|
+
|
|
298
|
+
# TODO: Fix bug in SDK for DELETE. Workaround is to give bearer_token
|
|
299
|
+
response = self.make_request(method=HttpMethod.DELETE, url=url,
|
|
300
|
+
bearer_token=self.token_refresher.refresh_token())
|
|
301
|
+
|
|
278
302
|
self.check_status_code(response, ok_status_codes)
|
|
279
303
|
return response
|
|
280
304
|
|
|
@@ -285,7 +309,7 @@ class CliOsduClient(BaseClient):
|
|
|
285
309
|
data: str | dict,
|
|
286
310
|
ok_status_codes: list = None,
|
|
287
311
|
) -> requests.Response:
|
|
288
|
-
"""
|
|
312
|
+
"""Basic PUT call to the given url.
|
|
289
313
|
|
|
290
314
|
Args:
|
|
291
315
|
config_url_key (str): key in configuration for the base path
|
|
@@ -294,6 +318,8 @@ class CliOsduClient(BaseClient):
|
|
|
294
318
|
ok_status_codes (list, optional): Optional status codes to check for successful call.
|
|
295
319
|
"""
|
|
296
320
|
url = self.url_from_config(config_url_key, url_extra_path)
|
|
321
|
+
if isinstance(data, dict):
|
|
322
|
+
data = json.dumps(data)
|
|
297
323
|
response = self.make_request(method=HttpMethod.PUT, url=url, data=data)
|
|
298
324
|
self.check_status_code(response, ok_status_codes)
|
|
299
325
|
return response
|
|
@@ -305,7 +331,7 @@ class CliOsduClient(BaseClient):
|
|
|
305
331
|
data: str | dict,
|
|
306
332
|
ok_status_codes: list = None,
|
|
307
333
|
) -> dict:
|
|
308
|
-
"""PUT
|
|
334
|
+
"""Basic PUT call to the given url, returning the json.
|
|
309
335
|
|
|
310
336
|
Args:
|
|
311
337
|
config_url_key (str): key in configuration for the base path
|
|
@@ -317,6 +343,8 @@ class CliOsduClient(BaseClient):
|
|
|
317
343
|
dict: returned json
|
|
318
344
|
"""
|
|
319
345
|
url = self.url_from_config(config_url_key, url_extra_path)
|
|
346
|
+
if isinstance(data, dict):
|
|
347
|
+
data = json.dumps(data)
|
|
320
348
|
response = self.make_request(method=HttpMethod.PUT, url=url, data=data)
|
|
321
349
|
self.check_status_code(response, ok_status_codes)
|
|
322
350
|
return response.json()
|
osducli/commands/storage/add.py
CHANGED
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
import json
|
|
16
16
|
|
|
17
17
|
import click
|
|
18
|
+
from osdu_api.model.storage.record import Record
|
|
18
19
|
|
|
19
20
|
from osducli.click_cli import CustomClickCommand, State, command_with_output
|
|
20
21
|
from osducli.cliclient import CliOsduClient, handle_cli_exceptions
|
|
21
|
-
from osducli.config import CONFIG_STORAGE_URL
|
|
22
22
|
from osducli.log import get_logger
|
|
23
|
-
from osducli.util.file import
|
|
23
|
+
from osducli.util.file import get_files_from_path_with_suffix
|
|
24
24
|
|
|
25
25
|
logger = get_logger(__name__)
|
|
26
26
|
|
|
@@ -51,41 +51,57 @@ def _click_command(state: State, path: str, batch: int):
|
|
|
51
51
|
return add_records(state, path, batch)
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
def add_records(state: State, path: str, batch: int
|
|
54
|
+
def add_records(state: State, path: str, batch: int = None):
|
|
55
55
|
"""Add or update a record
|
|
56
56
|
|
|
57
57
|
Args:
|
|
58
58
|
state (State): Global state
|
|
59
59
|
path (str): Path to a record or records to add.
|
|
60
60
|
batch (int): Batch size per API call. If None then ingest as is
|
|
61
|
-
Returns:
|
|
62
|
-
dict: Response from service
|
|
63
61
|
"""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
connection = CliOsduClient(state.config)
|
|
62
|
+
client = CliOsduClient(state.config)
|
|
63
|
+
record_client = client.get_storage_record_client()
|
|
68
64
|
|
|
69
|
-
files =
|
|
65
|
+
files = get_files_from_path_with_suffix(path, ".json")
|
|
70
66
|
logger.debug("Files list: %s", files)
|
|
71
67
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
if batch is not None:
|
|
69
|
+
logger.info("Batching records with size %s", batch)
|
|
70
|
+
file_batches = chunk_list(files, batch)
|
|
71
|
+
for file_batch in file_batches:
|
|
72
|
+
response = add_record_batch(record_client, file_batch)
|
|
73
|
+
handle_response(client, response)
|
|
74
|
+
else:
|
|
75
|
+
response = add_record_batch(record_client, files)
|
|
76
|
+
handle_response(client, response)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def add_record_batch(record_client, files):
|
|
80
|
+
record_list = []
|
|
75
81
|
for filepath in files:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
with open(filepath, encoding="utf-8") as file:
|
|
83
|
+
storage_object = json.load(file)
|
|
84
|
+
|
|
85
|
+
logger.info("Processing file %s.", filepath)
|
|
86
|
+
record_list.append(Record.from_dict(storage_object))
|
|
87
|
+
|
|
88
|
+
return record_client.create_update_records(record_list)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def chunk_list(lst, size):
|
|
92
|
+
return [lst[i:i + size] for i in range(0, len(lst), size)]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def handle_response(client, response):
|
|
96
|
+
client.check_status_code(response, [200, 201])
|
|
97
|
+
response_json = response.json()
|
|
98
|
+
count = response_json["recordCount"]
|
|
99
|
+
added = response_json["recordIds"]
|
|
100
|
+
skipped = response_json.get("skippedRecordIds", [])
|
|
101
|
+
|
|
102
|
+
print(f"Record count: {count}")
|
|
103
|
+
print(json.dumps(added, indent=2))
|
|
104
|
+
|
|
105
|
+
if skipped:
|
|
106
|
+
print("Skipped records:")
|
|
107
|
+
print(json.dumps(skipped, indent=2))
|
|
@@ -10,13 +10,12 @@
|
|
|
10
10
|
# See the License for the specific language governing permissions and
|
|
11
11
|
# limitations under the License.
|
|
12
12
|
|
|
13
|
-
"""Storage service
|
|
13
|
+
"""Storage service delete command"""
|
|
14
14
|
|
|
15
15
|
import click
|
|
16
16
|
|
|
17
17
|
from osducli.click_cli import CustomClickCommand, State, global_params
|
|
18
18
|
from osducli.cliclient import CliOsduClient, handle_cli_exceptions
|
|
19
|
-
from osducli.config import CONFIG_STORAGE_URL
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
# click entry point
|
|
@@ -36,9 +35,11 @@ def delete(state: State, id: str): # pylint: disable=invalid-name,redefined-bui
|
|
|
36
35
|
state (State): Global state
|
|
37
36
|
id (str): id to delete
|
|
38
37
|
"""
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
client = CliOsduClient(state.config)
|
|
39
|
+
record_client = client.get_storage_record_client()
|
|
40
|
+
# TODO: Fix bug in SDK for DELETE. Workaround is to give bearer_token
|
|
41
|
+
response = record_client.delete_record(recordId=id, bearer_token=client.token_refresher.refresh_token())
|
|
42
|
+
client.check_status_code(response, [200, 204])
|
|
42
43
|
|
|
43
44
|
if state.is_user_friendly_mode():
|
|
44
45
|
print("1 record deleted")
|
osducli/util/file.py
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import errno
|
|
14
14
|
import os
|
|
15
|
+
import glob
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
def get_files_from_path(path: str) -> list:
|
|
@@ -34,6 +35,23 @@ def get_files_from_path(path: str) -> list:
|
|
|
34
35
|
return allfiles
|
|
35
36
|
|
|
36
37
|
|
|
38
|
+
def get_files_from_path_with_suffix(path: str, suffix: str) -> list:
|
|
39
|
+
"""Given a path get a list of all files with a certain suffix.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
path (str): path
|
|
43
|
+
suffix (str): file suffix to filter by
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
list: list of file paths
|
|
47
|
+
"""
|
|
48
|
+
if os.path.isfile(path):
|
|
49
|
+
return [path] if path.endswith(suffix) else []
|
|
50
|
+
|
|
51
|
+
pattern = os.path.join(path, '**', f'*{suffix}')
|
|
52
|
+
return glob.glob(pattern, recursive=True)
|
|
53
|
+
|
|
54
|
+
|
|
37
55
|
def ensure_directory_exists(directory: str):
|
|
38
56
|
"""Create a directory if it doesn't exist"""
|
|
39
57
|
if not os.path.isdir(directory):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: osducli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.44
|
|
4
4
|
Summary: OSDU command line
|
|
5
5
|
Author-email: Equinor ASA <mhew@equinor.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -17,7 +17,7 @@ Description-Content-Type: text/x-rst
|
|
|
17
17
|
License-File: LICENSE.md
|
|
18
18
|
Requires-Dist: click
|
|
19
19
|
Requires-Dist: jmespath
|
|
20
|
-
Requires-Dist: osdu-api[all]==0.28.
|
|
20
|
+
Requires-Dist: osdu-api[all]==0.28.0rc949
|
|
21
21
|
Requires-Dist: requests
|
|
22
22
|
Requires-Dist: tabulate
|
|
23
23
|
Requires-Dist: packaging
|
|
@@ -26,6 +26,10 @@ Requires-Dist: msal-extensions
|
|
|
26
26
|
Requires-Dist: azure-identity
|
|
27
27
|
Requires-Dist: azure-keyvault
|
|
28
28
|
Requires-Dist: boto3
|
|
29
|
+
Requires-Dist: google
|
|
30
|
+
Requires-Dist: google-auth
|
|
31
|
+
Requires-Dist: google-auth-oauthlib
|
|
32
|
+
Requires-Dist: google-cloud-storage
|
|
29
33
|
Provides-Extra: dev
|
|
30
34
|
Requires-Dist: black; extra == "dev"
|
|
31
35
|
Requires-Dist: isort; extra == "dev"
|
|
@@ -79,6 +83,17 @@ For more information, specify the `-h` flag:
|
|
|
79
83
|
Change Log
|
|
80
84
|
==========
|
|
81
85
|
|
|
86
|
+
0.0.44
|
|
87
|
+
------
|
|
88
|
+
|
|
89
|
+
- Fix handling of json data in put and post requests
|
|
90
|
+
|
|
91
|
+
0.0.43
|
|
92
|
+
------
|
|
93
|
+
|
|
94
|
+
- Fix storage add command
|
|
95
|
+
- Implement storage add batching
|
|
96
|
+
|
|
82
97
|
0.0.42
|
|
83
98
|
------
|
|
84
99
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
osducli/__init__.py,sha256=
|
|
1
|
+
osducli/__init__.py,sha256=ibjJ0fg460aSRsjskiE_LSNoQ5I7qcPYsI5C1Z7MFxI,615
|
|
2
2
|
osducli/__main__.py,sha256=4HonhahSaS3Un0f93qnbs_pmJ5pbbVHU-qdhsssVkB0,3661
|
|
3
3
|
osducli/click_cli.py,sha256=7lpYqufxRSMrNZM9M-VANOYKwP0wo-1oxt2eSVHSW_M,10845
|
|
4
|
-
osducli/cliclient.py,sha256=
|
|
4
|
+
osducli/cliclient.py,sha256=sUQyIiomrf-WIcFn9C6UjISvHANLjijI-SVLxQ3T2MY,13242
|
|
5
5
|
osducli/config.py,sha256=lSDxp15JiJQ_J_YjdvI1q243uexzxZpXSYMsSgQIgdQ,7802
|
|
6
6
|
osducli/log.py,sha256=a5pzV2QIOqFEWCGFj01FaZk9PEzMkAr6duHei_dCme8,1549
|
|
7
7
|
osducli/state.py,sha256=b0GHH2oZ-4ogtmHenNkYwNRSE3OpSTL0XklbKVjUAKQ,3335
|
|
@@ -73,8 +73,8 @@ osducli/commands/status/__init__.py,sha256=5g1PB_tU0sqP7aplnihjfhMzVVQdlB3Y01QIe
|
|
|
73
73
|
osducli/commands/status/status.py,sha256=yh6KVUpNYbrLJIH-7GjMyo2MpR8Wvycr4KdkxUI1V5A,4543
|
|
74
74
|
osducli/commands/storage/__init__.py,sha256=Ilc97Kje3VVLZIBJucd_2jsW1GF5En00xF-A6kiLAFM,585
|
|
75
75
|
osducli/commands/storage/_const.py,sha256=a7oIWewDVdgbE1bHcg8QTQDppVT48pgP1Yl-l8tCRhs,847
|
|
76
|
-
osducli/commands/storage/add.py,sha256=
|
|
77
|
-
osducli/commands/storage/delete.py,sha256=
|
|
76
|
+
osducli/commands/storage/add.py,sha256=nDKP0490dU18Dtpaun3rluaCguJqtAFAxkS1P7WtG2Q,3386
|
|
77
|
+
osducli/commands/storage/delete.py,sha256=ElhE5fdC1yybG7BsVY9Li0x8TG1WeQpkraWWLCB_wR0,1612
|
|
78
78
|
osducli/commands/storage/get.py,sha256=FgjoN_1cY90cbU1osh53XviGvTZaPtRjthUmtP2Y2-k,2136
|
|
79
79
|
osducli/commands/storage/info.py,sha256=CGbA92GJYkWcLXHx1Z4i9g7Auk-ws2Cg6n6X7_m27iw,1345
|
|
80
80
|
osducli/commands/storage/list.py,sha256=bIN76XW70Xml0CCldNvjN-qCumqICjZkQPXs7LTY69M,1413
|
|
@@ -102,13 +102,13 @@ osducli/commands/workflow/status.py,sha256=GNSaJrAHrCBjLkYDP0rYtsGicHsvZYLX5otLb
|
|
|
102
102
|
osducli/commands/workflow/unregister.py,sha256=lTh7yoRE8Sb3W-03L2v16cs0G-0QtfNqFf8fg2t97o4,1415
|
|
103
103
|
osducli/util/__init__.py,sha256=p2bZquIGOPfofHV6GIzWRUv_b9O_pIH5BTyv_gfQT6c,553
|
|
104
104
|
osducli/util/exceptions.py,sha256=VVvJqxLLyYSsitwe9SVfsR7iPXIRaOJzOm7uCxfELjg,790
|
|
105
|
-
osducli/util/file.py,sha256=
|
|
105
|
+
osducli/util/file.py,sha256=866XSn7AWFXWgQ9B6OvPZVhb5p8VELbv_wOsUzc55-o,1821
|
|
106
106
|
osducli/util/prompt.py,sha256=0i3eNnxOHRQstvsvfiKnN0lIxXu6sEXIcU8txeYRhNs,7492
|
|
107
107
|
osducli/util/pypi.py,sha256=-DW5CThkKKiOwLp2tg85BmrLKZzkMI9pu8DyWNPZH6E,1192
|
|
108
108
|
osducli/util/service_info.py,sha256=YsVvoRoeG1osFjql2AgVkGoj1TePuhBZf3CQXl2a9As,2577
|
|
109
|
-
osducli-0.0.
|
|
110
|
-
osducli-0.0.
|
|
111
|
-
osducli-0.0.
|
|
112
|
-
osducli-0.0.
|
|
113
|
-
osducli-0.0.
|
|
114
|
-
osducli-0.0.
|
|
109
|
+
osducli-0.0.44.dist-info/LICENSE.md,sha256=9xnGPjJkOAgd0kH4QLlvOIYKqY1M49gWUQpoUxAU-9Y,12788
|
|
110
|
+
osducli-0.0.44.dist-info/METADATA,sha256=_9Md40hzE-qk91awyx96oZ-Op-MnlE-FK98chhGP6lQ,6190
|
|
111
|
+
osducli-0.0.44.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
112
|
+
osducli-0.0.44.dist-info/entry_points.txt,sha256=gASIcihV0BSJDZOUK-zTzb8RiccZCvKfVZMna9RsEIg,47
|
|
113
|
+
osducli-0.0.44.dist-info/top_level.txt,sha256=lqiP5fuyH8lx7c2emYoIVZNxZAPX-bSwnMH789wxUAY,8
|
|
114
|
+
osducli-0.0.44.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|