Skip to content
Closed
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,9 @@ Usage: lean cloud object-store set [OPTIONS] KEY PATH

Sets the data to the given key in the organization's cloud object store.

:param key: The key to set the data to. :param path: Path to the file containing the object data.
:param key: The key to set the data to. The cloud stores a key that does not follow the object store key format under
a sanitized name, with a warning naming the key to use from then on. :param path: Path to the file containing the
object data.

Options:
--verbose Enable debug logging
Expand Down
8 changes: 6 additions & 2 deletions lean/commands/cloud/object_store/set.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from html import unescape
from click import command, argument
from pathlib import Path
from lean.click import LeanCommand, PathParameter
Expand All @@ -23,12 +24,15 @@
def set(key: str, path: Path) -> None:
"""Sets the data to the given key in the organization's cloud object store.

:param key: The key to set the data to.
:param key: The key to set the data to. The cloud stores a key that does not follow the object store key format under a sanitized name, with a warning naming the key to use from then on.
:param path: Path to the file containing the object data.
"""
organization_id = container.organization_manager.try_get_working_organization_id()
container.logger.info(f"Setting object {key} in organization {organization_id}")
api_client = container.api_client
with open(path, "rb") as file:
bytes_data: bytes = file.read()
api_client.object_store.set(key, bytes_data, organization_id)
response = api_client.object_store.set(key, bytes_data, organization_id)
# the cloud encodes the key in its messages for web pages
for warning in response.get("warnings", []) if isinstance(response, dict) else []:
container.logger.warn(unescape(warning))
5 changes: 3 additions & 2 deletions lean/components/api/object_store_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,12 @@ def get(self, keys: [str], organization_id: str, logger: Logger) -> str:

return data["url"]

def set(self, key: str, object_data: bytes, organization_id: str) -> None:
def set(self, key: str, object_data: bytes, organization_id: str) -> dict:
"""Sets the given key in the Object Store.
:param key: key of the object to set
:param object_data: the data to set
:param organization_id: the id of the organization who's object store to set data in
:return: the api response, with the key the object was stored under and any warnings about it
"""
payload = {
"organizationId": organization_id,
Expand All @@ -93,7 +94,7 @@ def set(self, key: str, object_data: bytes, organization_id: str) -> None:
extra_options = {
"files": {"objectData": object_data}
}
self._api.post("object/set", payload, False, extra_options)
return self._api.post("object/set", payload, False, extra_options)

def list(self, path: str, organization_id: str) -> str:
"""List all values for the given root key in the Object Store.
Expand Down
38 changes: 38 additions & 0 deletions tests/commands/cloud/object_store/test_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,41 @@ def test_set_sets_value_when_path_is_given() -> None:
with open(file_path, "rb") as file:
bytes_data: bytes = file.read()
container.api_client.object_store.set.assert_called_once_with('test-key', bytes_data, 'abc')


def test_set_prints_the_warnings_the_api_returns() -> None:
create_fake_lean_cli_project("test", "python")
api_client = mock.Mock()
api_client.is_authenticated.return_value = True
api_client.object_store.set.return_value = {
"success": True,
"key": "trade log_ AI _ Cloud.csv",
"warnings": ["Key 'trade log: AI & Cloud.csv' is not supported: unsupported characters ':', '&'. "
"Using 'trade log_ AI _ Cloud.csv' instead"]
}
initialize_container(api_client_to_use=api_client)
file_path = str(Path.joinpath(Path.cwd(), "lean.json"))

result = CliRunner().invoke(lean, ["cloud", "object-store", "set", "trade log: AI & Cloud.csv", file_path])

assert result.exit_code == 0
output = " ".join(result.output.split())
assert "Key 'trade log: AI & Cloud.csv' is not supported: unsupported characters ':', '&'. " \
"Using 'trade log_ AI _ Cloud.csv' instead" in output
with open(file_path, "rb") as file:
container.api_client.object_store.set.assert_called_once_with('trade log: AI & Cloud.csv', file.read(), 'abc')


def test_set_prints_no_warning_when_the_api_returns_none() -> None:
create_fake_lean_cli_project("test", "python")
api_client = mock.Mock()
api_client.is_authenticated.return_value = True
api_client.object_store.set.return_value = {"success": True, "key": "folder/trade_log-2024.csv", "warnings": []}
initialize_container(api_client_to_use=api_client)
file_path = str(Path.joinpath(Path.cwd(), "lean.json"))

result = CliRunner().invoke(lean, ["cloud", "object-store", "set", "folder/trade_log-2024.csv", file_path])

assert result.exit_code == 0
assert "is not supported" not in result.output
container.api_client.object_store.set.assert_called_once_with('folder/trade_log-2024.csv', mock.ANY, 'abc')
Loading