Skip to content

Commit

Permalink
feat: add support for complex storage names (#154)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
NickNaskida and pre-commit-ci[bot] authored Jul 4, 2024
1 parent 321fc84 commit d8b59ad
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
22 changes: 16 additions & 6 deletions sqlalchemy_file/storage.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import contextlib
import warnings
from typing import Any, ClassVar, Dict, Iterator, Optional
from typing import Any, ClassVar, Dict, Iterator, Optional, Tuple

from libcloud.storage.base import Container
from libcloud.storage.types import ObjectDoesNotExistError
Expand Down Expand Up @@ -122,10 +122,11 @@ def save_file(

@classmethod
def get_file(cls, path: str) -> StoredFile:
"""Retrieve the file with `provided` path,
path is expected to be `storage_name/file_id`.
"""Retrieve the file with `provided` path.
The path is expected to be `storage_name/file_id`.
"""
upload_storage, file_id = path.split("/")
upload_storage, file_id = cls._get_storage_and_file_id(path)
return StoredFile(StorageManager.get(upload_storage).get_object(file_id))

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

@classmethod
def _clear(cls) -> None:
"""This is only for testing pourposes, resets the StorageManager."""
"""This is only for testing purposes, resets the StorageManager."""
cls._default_storage_name = None
cls._storages = {}

@classmethod
def _get_storage_and_file_id(cls, path: str) -> Tuple[str, str]:
"""Extract the storage name and file_id from the path.
The path is expected to be `storage_name/file_id`.
"""
path_parts = path.split("/")
return "/".join(path_parts[:-1]), path_parts[-1]
19 changes: 19 additions & 0 deletions tests/test_storage_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ class TestStorageManager:
def setup_method(self, method) -> None:
StorageManager._clear()

def test_get_storage_and_file_id(self) -> None:
assert StorageManager._get_storage_and_file_id("storage/file") == (
"storage",
"file",
)
assert StorageManager._get_storage_and_file_id("storage/folder/file") == (
"storage/folder",
"file",
)

def test_first_configured_is_default(self) -> None:
StorageManager.add_storage("first", get_dummy_container("first"))
StorageManager.add_storage("second", get_dummy_container("second"))
Expand All @@ -19,6 +29,15 @@ def test_changing_default_storage_works(self) -> None:
StorageManager.set_default("second")
assert StorageManager.get_default() == "second"

def test_complex_storage_name(self) -> None:
StorageManager.add_storage(
"storage/folder", get_dummy_container("storage/folder")
)
StorageManager.add_storage(
"storage/folder/subfolder", get_dummy_container("storage/folder/subfolder")
)
assert StorageManager.get_default() == "storage/folder"

def test_no_storage_is_detected(self) -> None:
with pytest.raises(RuntimeError):
StorageManager.get_default()
Expand Down

0 comments on commit d8b59ad

Please sign in to comment.