Skip to content

Commit d8b59ad

Browse files
feat: add support for complex storage names (#154)
* feat: add support for complex storage names * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 321fc84 commit d8b59ad

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

sqlalchemy_file/storage.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import contextlib
22
import warnings
3-
from typing import Any, ClassVar, Dict, Iterator, Optional
3+
from typing import Any, ClassVar, Dict, Iterator, Optional, Tuple
44

55
from libcloud.storage.base import Container
66
from libcloud.storage.types import ObjectDoesNotExistError
@@ -122,10 +122,11 @@ def save_file(
122122

123123
@classmethod
124124
def get_file(cls, path: str) -> StoredFile:
125-
"""Retrieve the file with `provided` path,
126-
path is expected to be `storage_name/file_id`.
125+
"""Retrieve the file with `provided` path.
126+
127+
The path is expected to be `storage_name/file_id`.
127128
"""
128-
upload_storage, file_id = path.split("/")
129+
upload_storage, file_id = cls._get_storage_and_file_id(path)
129130
return StoredFile(StorageManager.get(upload_storage).get_object(file_id))
130131

131132
@classmethod
@@ -134,7 +135,7 @@ def delete_file(cls, path: str) -> bool:
134135
135136
The path is expected to be `storage_name/file_id`.
136137
"""
137-
upload_storage, file_id = path.split("/")
138+
upload_storage, file_id = cls._get_storage_and_file_id(path)
138139
obj = StorageManager.get(upload_storage).get_object(file_id)
139140
if obj.driver.name == LOCAL_STORAGE_DRIVER_NAME:
140141
"""Try deleting associated metadata file"""
@@ -145,6 +146,15 @@ def delete_file(cls, path: str) -> bool:
145146

146147
@classmethod
147148
def _clear(cls) -> None:
148-
"""This is only for testing pourposes, resets the StorageManager."""
149+
"""This is only for testing purposes, resets the StorageManager."""
149150
cls._default_storage_name = None
150151
cls._storages = {}
152+
153+
@classmethod
154+
def _get_storage_and_file_id(cls, path: str) -> Tuple[str, str]:
155+
"""Extract the storage name and file_id from the path.
156+
157+
The path is expected to be `storage_name/file_id`.
158+
"""
159+
path_parts = path.split("/")
160+
return "/".join(path_parts[:-1]), path_parts[-1]

tests/test_storage_manager.py

+19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ class TestStorageManager:
88
def setup_method(self, method) -> None:
99
StorageManager._clear()
1010

11+
def test_get_storage_and_file_id(self) -> None:
12+
assert StorageManager._get_storage_and_file_id("storage/file") == (
13+
"storage",
14+
"file",
15+
)
16+
assert StorageManager._get_storage_and_file_id("storage/folder/file") == (
17+
"storage/folder",
18+
"file",
19+
)
20+
1121
def test_first_configured_is_default(self) -> None:
1222
StorageManager.add_storage("first", get_dummy_container("first"))
1323
StorageManager.add_storage("second", get_dummy_container("second"))
@@ -19,6 +29,15 @@ def test_changing_default_storage_works(self) -> None:
1929
StorageManager.set_default("second")
2030
assert StorageManager.get_default() == "second"
2131

32+
def test_complex_storage_name(self) -> None:
33+
StorageManager.add_storage(
34+
"storage/folder", get_dummy_container("storage/folder")
35+
)
36+
StorageManager.add_storage(
37+
"storage/folder/subfolder", get_dummy_container("storage/folder/subfolder")
38+
)
39+
assert StorageManager.get_default() == "storage/folder"
40+
2241
def test_no_storage_is_detected(self) -> None:
2342
with pytest.raises(RuntimeError):
2443
StorageManager.get_default()

0 commit comments

Comments
 (0)