osducli 0.0.42__tar.gz → 0.0.44__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.
Files changed (122) hide show
  1. {osducli-0.0.42/src/osducli.egg-info → osducli-0.0.44}/PKG-INFO +17 -2
  2. {osducli-0.0.42 → osducli-0.0.44}/README.rst +11 -0
  3. {osducli-0.0.42 → osducli-0.0.44}/pyproject.toml +6 -1
  4. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/__init__.py +1 -1
  5. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/cliclient.py +38 -10
  6. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/add.py +45 -29
  7. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/delete.py +6 -5
  8. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/util/file.py +18 -0
  9. {osducli-0.0.42 → osducli-0.0.44/src/osducli.egg-info}/PKG-INFO +17 -2
  10. {osducli-0.0.42 → osducli-0.0.44}/src/osducli.egg-info/requires.txt +5 -1
  11. {osducli-0.0.42 → osducli-0.0.44}/tests/test_cliclient.py +11 -2
  12. {osducli-0.0.42 → osducli-0.0.44}/LICENSE.md +0 -0
  13. {osducli-0.0.42 → osducli-0.0.44}/setup.cfg +0 -0
  14. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/__main__.py +0 -0
  15. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/auth/__init__.py +0 -0
  16. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/auth/aws_token_credential.py +0 -0
  17. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/auth/credentials.py +0 -0
  18. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/auth/msal_interactive.py +0 -0
  19. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/auth/msal_non_interactive.py +0 -0
  20. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/auth/token_credential.py +0 -0
  21. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/click_cli.py +0 -0
  22. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/__init__.py +0 -0
  23. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/config/__init__.py +0 -0
  24. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/config/consts.py +0 -0
  25. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/config/default.py +0 -0
  26. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/config/info.py +0 -0
  27. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/config/list.py +0 -0
  28. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/config/update.py +0 -0
  29. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/crs/__init__.py +0 -0
  30. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/crs/_const.py +0 -0
  31. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/crs/areas.py +0 -0
  32. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/crs/info.py +0 -0
  33. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/crs/list.py +0 -0
  34. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/crs/summary.py +0 -0
  35. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/crs/transforms.py +0 -0
  36. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/dataload/__init__.py +0 -0
  37. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/dataload/checkrefs.py +0 -0
  38. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/dataload/ingest.py +0 -0
  39. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/dataload/status.py +0 -0
  40. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/dataload/verify.py +0 -0
  41. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/__init__.py +0 -0
  42. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/_const.py +0 -0
  43. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/groups/__init__.py +0 -0
  44. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/groups/add.py +0 -0
  45. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/groups/delete.py +0 -0
  46. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/groups/members.py +0 -0
  47. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/info.py +0 -0
  48. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/members/__init__.py +0 -0
  49. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/members/add.py +0 -0
  50. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/members/groups.py +0 -0
  51. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/members/list.py +0 -0
  52. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/members/remove.py +0 -0
  53. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/entitlements/mygroups.py +0 -0
  54. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/file/__init__.py +0 -0
  55. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/file/_const.py +0 -0
  56. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/file/download.py +0 -0
  57. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/file/info.py +0 -0
  58. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/file/metadata.py +0 -0
  59. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/legal/__init__.py +0 -0
  60. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/legal/_const.py +0 -0
  61. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/legal/add.py +0 -0
  62. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/legal/delete.py +0 -0
  63. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/legal/info.py +0 -0
  64. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/legal/listtags.py +0 -0
  65. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/list/__init__.py +0 -0
  66. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/list/records.py +0 -0
  67. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/schema/__init__.py +0 -0
  68. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/schema/_const.py +0 -0
  69. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/schema/add.py +0 -0
  70. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/schema/get.py +0 -0
  71. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/schema/info.py +0 -0
  72. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/schema/list.py +0 -0
  73. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/search/__init__.py +0 -0
  74. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/search/_const.py +0 -0
  75. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/search/id.py +0 -0
  76. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/search/info.py +0 -0
  77. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/search/kind.py +0 -0
  78. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/search/query.py +0 -0
  79. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/status/__init__.py +0 -0
  80. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/status/status.py +0 -0
  81. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/__init__.py +0 -0
  82. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/_const.py +0 -0
  83. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/get.py +0 -0
  84. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/info.py +0 -0
  85. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/list.py +0 -0
  86. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/storage/versions.py +0 -0
  87. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/unit/__init__.py +0 -0
  88. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/unit/_const.py +0 -0
  89. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/unit/info.py +0 -0
  90. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/unit/list.py +0 -0
  91. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/version/__init__.py +0 -0
  92. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/version/version.py +0 -0
  93. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/wellbore_ddms/__init__.py +0 -0
  94. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/wellbore_ddms/_const.py +0 -0
  95. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/wellbore_ddms/info.py +0 -0
  96. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/wellbore_ddms/well_log/__init__.py +0 -0
  97. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/wellbore_ddms/well_log/data.py +0 -0
  98. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/wellbore_ddms/well_log/record.py +0 -0
  99. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/__init__.py +0 -0
  100. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/_const.py +0 -0
  101. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/get.py +0 -0
  102. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/info.py +0 -0
  103. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/list.py +0 -0
  104. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/register.py +0 -0
  105. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/runs.py +0 -0
  106. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/status.py +0 -0
  107. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/commands/workflow/unregister.py +0 -0
  108. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/config.py +0 -0
  109. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/log.py +0 -0
  110. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/state.py +0 -0
  111. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/util/__init__.py +0 -0
  112. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/util/exceptions.py +0 -0
  113. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/util/prompt.py +0 -0
  114. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/util/pypi.py +0 -0
  115. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/util/service_info.py +0 -0
  116. {osducli-0.0.42 → osducli-0.0.44}/src/osducli/wbddms_client.py +0 -0
  117. {osducli-0.0.42 → osducli-0.0.44}/src/osducli.egg-info/SOURCES.txt +0 -0
  118. {osducli-0.0.42 → osducli-0.0.44}/src/osducli.egg-info/dependency_links.txt +0 -0
  119. {osducli-0.0.42 → osducli-0.0.44}/src/osducli.egg-info/entry_points.txt +0 -0
  120. {osducli-0.0.42 → osducli-0.0.44}/src/osducli.egg-info/top_level.txt +0 -0
  121. {osducli-0.0.42 → osducli-0.0.44}/tests/test_click_cli_state.py +0 -0
  122. {osducli-0.0.42 → osducli-0.0.44}/tests/test_help_text.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: osducli
3
- Version: 0.0.42
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.0rc912
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
 
@@ -35,6 +35,17 @@ For more information, specify the `-h` flag:
35
35
  Change Log
36
36
  ==========
37
37
 
38
+ 0.0.44
39
+ ------
40
+
41
+ - Fix handling of json data in put and post requests
42
+
43
+ 0.0.43
44
+ ------
45
+
46
+ - Fix storage add command
47
+ - Implement storage add batching
48
+
38
49
  0.0.42
39
50
  ------
40
51
 
@@ -26,7 +26,7 @@ keywords = ["osdu"]
26
26
  dependencies = [
27
27
  "click",
28
28
  "jmespath",
29
- "osdu-api[all]==0.28.0rc912",
29
+ "osdu-api[all]==0.28.0rc949",
30
30
  "requests",
31
31
  "tabulate",
32
32
  "packaging",
@@ -37,6 +37,11 @@ dependencies = [
37
37
  "azure-keyvault",
38
38
  # AWS specific
39
39
  "boto3",
40
+ # GCP specific
41
+ "google",
42
+ "google-auth",
43
+ "google-auth-oauthlib",
44
+ "google-cloud-storage",
40
45
  ]
41
46
 
42
47
  [project.urls]
@@ -12,4 +12,4 @@
12
12
 
13
13
  """ OSDU command line environment"""
14
14
 
15
- __VERSION__ = "0.0.42"
15
+ __VERSION__ = "0.0.44"
@@ -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(self, url_extra_path: str) -> WellboreDdmsClient:
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, config_url_key: str, url_extra_path: str, ok_status_codes: list = None
220
+ self,
221
+ config_url_key: str,
222
+ url_extra_path: str,
223
+ ok_status_codes: list = None
209
224
  ) -> requests.Response:
210
- """[summary]
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, config_url_key: str, url_extra_path: str, ok_status_codes: list = None
238
+ self,
239
+ config_url_key: str,
240
+ url_extra_path: str,
241
+ ok_status_codes: list = None
224
242
  ) -> dict:
225
- """[summary]
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
- """[summary]
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
- """[summary]
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
- response = self.make_request(method=HttpMethod.DELETE, url=url)
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
- """[summary]
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 the data to the given url.
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()
@@ -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 get_files_from_path
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) -> dict:
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
- if batch is not None:
65
- raise NotImplementedError("--batch is not supported yet for storage add")
66
-
67
- connection = CliOsduClient(state.config)
62
+ client = CliOsduClient(state.config)
63
+ record_client = client.get_storage_record_client()
68
64
 
69
- files = get_files_from_path(path)
65
+ files = get_files_from_path_with_suffix(path, ".json")
70
66
  logger.debug("Files list: %s", files)
71
67
 
72
- # TODO: Check if loaded file is already an array, or a single file
73
- # TODO: Batch uploads
74
- responses = []
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
- if filepath.endswith(".json"):
77
- with open(filepath, encoding="utf-8") as file:
78
- storage_object = json.load(file)
79
-
80
- logger.info("Processing file %s.", filepath)
81
- if isinstance(storage_object, list):
82
- payload = storage_object
83
- else:
84
- payload = [storage_object]
85
-
86
- response_json = None
87
- response_json = connection.cli_put_returning_json(
88
- CONFIG_STORAGE_URL, "records", payload, [200, 201]
89
- )
90
- responses.append(response_json)
91
- return responses
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 versions command"""
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
- connection = CliOsduClient(state.config)
40
- url = "records/" + id
41
- connection.cli_delete(CONFIG_STORAGE_URL, url, [200, 204])
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")
@@ -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.42
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.0rc912
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,6 +1,6 @@
1
1
  click
2
2
  jmespath
3
- osdu-api[all]==0.28.0rc912
3
+ osdu-api[all]==0.28.0rc949
4
4
  requests
5
5
  tabulate
6
6
  packaging
@@ -9,6 +9,10 @@ msal-extensions
9
9
  azure-identity
10
10
  azure-keyvault
11
11
  boto3
12
+ google
13
+ google-auth
14
+ google-auth-oauthlib
15
+ google-cloud-storage
12
16
 
13
17
  [dev]
14
18
  black
@@ -15,6 +15,7 @@
15
15
  from unittest.mock import MagicMock, Mock
16
16
 
17
17
  import pytest
18
+ import json
18
19
  from osdu_api.clients.base_client import BaseClient
19
20
  from osdu_api.model.http_method import HttpMethod
20
21
 
@@ -159,6 +160,8 @@ def test_cli_put(mocker, cli_client, config, path, data):
159
160
  response = cli_client.cli_put(config, path, data)
160
161
 
161
162
  mock_put.assert_called_once()
163
+ if isinstance(data, dict):
164
+ data = json.dumps(data)
162
165
  mock_put.assert_called_with(method=HttpMethod.PUT, url="https://dummy.com/core_" + config + path, data=data)
163
166
  assert response_mock == response
164
167
 
@@ -205,11 +208,14 @@ def test_cli_delete(mocker, cli_client, config, path):
205
208
  response_mock = Mock()
206
209
  response_mock.status_code = 200
207
210
  mock_delete = mocker.patch.object(cli_client, "make_request", return_value=response_mock)
211
+ mock_token_refresher = mocker.Mock()
212
+ mock_token_refresher.refresh_token.return_value = "some-token"
213
+ cli_client.token_refresher = mock_token_refresher
208
214
 
209
215
  response = cli_client.cli_delete(config, path)
210
216
 
211
217
  mock_delete.assert_called_once()
212
- mock_delete.assert_called_with(method=HttpMethod.DELETE, url="https://dummy.com/core_" + config + path)
218
+ mock_delete.assert_called_with(method=HttpMethod.DELETE, url="https://dummy.com/core_" + config + path, bearer_token="some-token")
213
219
  assert response_mock == response
214
220
 
215
221
  @pytest.mark.parametrize("ok_status_codes, actual_status_code",
@@ -224,11 +230,14 @@ def test_cli_delete_status_codes(mocker, cli_client, ok_status_codes, actual_sta
224
230
  response_mock = Mock()
225
231
  response_mock.status_code = actual_status_code
226
232
  mock_delete = mocker.patch.object(cli_client, "make_request", return_value=response_mock)
233
+ mock_token_refresher = mocker.Mock()
234
+ mock_token_refresher.refresh_token.return_value = "some-token"
235
+ cli_client.token_refresher = mock_token_refresher
227
236
 
228
237
  response = cli_client.cli_delete("config", "/path", ok_status_codes)
229
238
 
230
239
  mock_delete.assert_called_once()
231
- mock_delete.assert_called_with(method=HttpMethod.DELETE, url="https://dummy.com/core_config/path")
240
+ mock_delete.assert_called_with(method=HttpMethod.DELETE, url="https://dummy.com/core_config/path", bearer_token="some-token")
232
241
  assert response_mock == response
233
242
 
234
243
  # endregion test cli_delete
File without changes
File without changes
File without changes
File without changes
File without changes