Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ await session.commit()
doc = await session.get(Document, doc.id)
assert isinstance(doc.file, StorageFile)

url = await doc.file.get_url()
url = await doc.file.get_path()
await doc.file.delete()
```

Expand All @@ -68,7 +68,7 @@ await doc.file.delete()

```py
doc = await session.get(Document, some_id)
doc_url = await doc.file.get_url()
doc_url = await doc.file.get_path()
doc_size = await doc.file.get_size()

await doc.file.upload(another_file) # re-upload
Expand All @@ -87,7 +87,7 @@ storage = S3Storage(...)
@app.post("/upload")
async def upload_file(file: UploadFile):
name = await storage.upload(file.file, file.filename)
return {"url": await storage.get_url(name)}
return {"url": await storage.get_path(name)}
```

## License
Expand Down
2 changes: 1 addition & 1 deletion docs/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ If your app runs entirely synchronously, stick with `fastapi-storages <https://g
Can I extend it with other storage backends?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Yes. The library’s base :class:`~async_storages.base.BaseStorage` class is extensible.
You can implement new async backends (like local filesystem, Google Cloud Storage, or Azure Blob) by subclassing it and implementing the async methods ``upload``, ``get_url``, and ``delete``.
You can implement new async backends (like local filesystem, Google Cloud Storage, or Azure Blob) by subclassing it and implementing the async methods ``upload``, ``get_path``, and ``delete``.

`fastapi-async-storages <https://github.com/stabldev/fastapi-async-storages>`_ aims to stay compatible with existing `fastapi-storages <https://github.com/aminalaee/fastapi-storages>`_ APIs, so extension patterns remain familiar.
6 changes: 3 additions & 3 deletions docs/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ Now let's see a minimal example of using :class:`~async_storages.S3Storage` in a
# upload a file
await storage.upload(file_obj, file_name)
# get file URL
url = await storage.get_url(file_name)
print(url)
path = await storage.get_path(file_name)
print(path)
# get file size
size = await storage.get_size(file_name)
# delete file
Expand Down Expand Up @@ -126,7 +126,7 @@ Let's see an example:
await session.commit()

doc = await session.get(Document, doc.id)
url = await doc.file.get_url()
url = await doc.file.get_path()
print(url)
width, height = await doc.image.get_dimensions()
print(f"Dimensions: {width}x{height}")
6 changes: 3 additions & 3 deletions src/async_storages/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async def get_size(self, name: str) -> int:
pass

@abstractmethod
async def get_url(self, name: str) -> str:
async def get_path(self, name: str) -> str:
"""
Generate a URL or path to access the stored file.

Expand Down Expand Up @@ -122,14 +122,14 @@ async def get_size(self) -> int:
"""
return await self._storage.get_size(self._name)

async def get_url(self) -> str:
async def get_path(self) -> str:
"""
Get a URL or path to access the file.

:return: A URL or file path string.
:rtype: str
"""
return await self._storage.get_url(self._name)
return await self._storage.get_path(self._name)

async def upload(self, file: BinaryIO) -> str:
"""
Expand Down
2 changes: 1 addition & 1 deletion src/async_storages/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ async def get_size(self, name: str) -> int:
raise

@override
async def get_url(self, name: str) -> str:
async def get_path(self, name: str) -> str:
"""
Generate a URL for accessing an S3 object.

Expand Down
10 changes: 5 additions & 5 deletions tests/test_integrations/test_sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ async def test_sqlalchemy_with_s3(s3_test_storage: Any):
assert doc.file.name == f"{file_name}"

# methods should work
url = await doc.file.get_url()
assert file_name in url
path = await doc.file.get_path()
assert file_name in path

size = await doc.file.get_size()
assert size == len(file_content)
Expand Down Expand Up @@ -118,15 +118,15 @@ async def test_sqlalchemy_filetype_none_and_plain_string_with_s3(s3_test_storage
assert doc_plain.file.name == "plain/path/file.txt"

# methods should work
url = await doc_plain.file.get_url()
assert "plain/path/file.txt" in url
path = await doc_plain.file.get_path()
assert "plain/path/file.txt" in path

# close all connections
await engine.dispose()


@pytest.mark.asyncio
async def test_document_with_both_filetypes(s3_test_storage: Any):
async def test_sqlalchemy_imagetype_with_s3(s3_test_storage: Any):
storage = s3_test_storage
# assign s3_storage to file column
Document.__table__.columns.image.type.storage = storage
Expand Down
18 changes: 9 additions & 9 deletions tests/test_s3_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ async def test_s3_storage_methods(s3_test_env: Any):
assert returned_name == storage.get_name(file_name)

# get url test without custom domain or querystring_auth
url = await storage.get_url(file_name)
assert file_name in url
path = await storage.get_path(file_name)
assert file_name in path

# get size test
size = await storage.get_size(file_name)
Expand Down Expand Up @@ -54,11 +54,11 @@ async def test_s3_storage_querystring_auth(s3_test_env: Any):
)

name = "test/file.txt"
url = await storage.get_url(name)
path = await storage.get_path(name)

assert url.count("AWSAccessKeyId=") == 1
assert url.count("Signature=") == 1
assert url.count("Expires=") == 1
assert path.count("AWSAccessKeyId=") == 1
assert path.count("Signature=") == 1
assert path.count("Expires=") == 1


@pytest.mark.asyncio
Expand All @@ -75,10 +75,10 @@ async def test_s3_storage_custom_domain(s3_test_env: Any):
)

name = "test/file.txt"
url = await storage.get_url(name)
path = await storage.get_path(name)

assert url.startswith("http://cdn.example.com/")
assert name in await storage.get_url(name)
assert path.startswith("http://cdn.example.com/")
assert name in await storage.get_path(name)


@pytest.mark.asyncio
Expand Down