Skip to content

Commit b5d40b2

Browse files
authored
feat(py-client): Add a util to guess MIME type (#197)
1 parent 50249ed commit b5d40b2

File tree

4 files changed

+44
-0
lines changed

4 files changed

+44
-0
lines changed

clients/python/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ dependencies = [
1414
"sentry-sdk>=2.42.1",
1515
"urllib3>=2.2.2",
1616
"zstandard>=0.18.0",
17+
"filetype>=1.2.0",
1718
]
1819

1920
[build-system]

clients/python/src/objectstore_client/client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ def put(
234234
This can be overridden by explicitly giving a `compression` argument.
235235
Providing `"none"` as the argument will instruct the client to not apply
236236
any compression to this upload, which is useful for uncompressible formats.
237+
238+
You can use the utility function `objectstore_client.utils.guess_mime_type`
239+
to attempt to guess a `content_type` based on magic bytes.
237240
"""
238241
headers = self._make_headers()
239242
body = BytesIO(contents) if isinstance(contents, bytes) else contents
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from __future__ import annotations
2+
3+
from typing import IO
4+
5+
import filetype # type: ignore
6+
7+
8+
def guess_mime_type(contents: bytes | IO[bytes]) -> str | None:
9+
"""
10+
Guesses the MIME type from the given contents.
11+
12+
Reads up to 261 bytes from the beginning of the content to determine
13+
the MIME type using file header signatures.
14+
15+
To guess the MIME type from a filename, use `mimetypes.guess_type`,
16+
which is part of the standard library.
17+
"""
18+
19+
if isinstance(contents, bytes):
20+
header = contents[:261]
21+
else:
22+
if not contents.seekable():
23+
return None
24+
pos = contents.tell()
25+
header = contents.read(261)
26+
contents.seek(pos)
27+
28+
kind = filetype.guess(header)
29+
return kind.mime if kind else None

uv.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)