From e7e8172a5824b3a44f2e793f6f374e5efc5eb563 Mon Sep 17 00:00:00 2001 From: Giorgio Salluzzo Date: Sat, 19 Oct 2024 11:20:18 +0200 Subject: [PATCH] Switching to using `puremagic` for identifying MIME types. (#255) --- mocket/__init__.py | 2 +- mocket/compat.py | 17 ++++++++--------- mocket/mockhttp.py | 15 +++------------ pyproject.toml | 2 +- tests/test_compat.py | 5 +++++ tests/test_http.py | 15 --------------- 6 files changed, 18 insertions(+), 38 deletions(-) create mode 100644 tests/test_compat.py diff --git a/mocket/__init__.py b/mocket/__init__.py index 00284855..31cd56fc 100644 --- a/mocket/__init__.py +++ b/mocket/__init__.py @@ -3,4 +3,4 @@ __all__ = ("async_mocketize", "mocketize", "Mocket", "MocketEntry", "Mocketizer") -__version__ = "3.13.0" +__version__ = "3.13.1" diff --git a/mocket/compat.py b/mocket/compat.py index 8457c274..276ae0f0 100644 --- a/mocket/compat.py +++ b/mocket/compat.py @@ -5,6 +5,8 @@ import shlex from typing import Final +import puremagic + ENCODING: Final[str] = os.getenv("MOCKET_ENCODING", "utf-8") text_type = str @@ -29,12 +31,9 @@ def shsplit(s: str | bytes) -> list[str]: return shlex.split(s) -def do_the_magic(lib_magic, body): # pragma: no cover - if hasattr(lib_magic, "from_buffer"): - # PyPI python-magic - return lib_magic.from_buffer(body, mime=True) - # file's builtin python wrapper - # used by https://www.archlinux.org/packages/community/any/python-mocket/ - _magic = lib_magic.open(lib_magic.MAGIC_MIME_TYPE) - _magic.load() - return _magic.buffer(body) +def do_the_magic(body): + try: + magic = puremagic.magic_string(body) + except puremagic.PureError: + magic = [] + return magic[0].mime_type if len(magic) else "application/octet-stream" diff --git a/mocket/mockhttp.py b/mocket/mockhttp.py index fceb831f..5058328d 100644 --- a/mocket/mockhttp.py +++ b/mocket/mockhttp.py @@ -10,12 +10,6 @@ from .compat import ENCODING, decode_from_bytes, do_the_magic, encode_to_bytes from .mocket import Mocket, MocketEntry -try: - import magic -except ImportError: - magic = None - - STATUS = {k: v[0] for k, v in BaseHTTPRequestHandler.responses.items()} CRLF = "\r\n" ASCII = "ascii" @@ -76,10 +70,7 @@ class Response: headers = None is_file_object = False - def __init__(self, body="", status=200, headers=None, lib_magic=magic): - # needed for testing libmagic import failure - self.magic = lib_magic - + def __init__(self, body="", status=200, headers=None): headers = headers or {} try: # File Objects @@ -116,8 +107,8 @@ def set_base_headers(self): } if not self.is_file_object: self.headers["Content-Type"] = f"text/plain; charset={ENCODING}" - elif self.magic: - self.headers["Content-Type"] = do_the_magic(self.magic, self.body) + else: + self.headers["Content-Type"] = do_the_magic(self.body) def set_extra_headers(self, headers): r""" diff --git a/pyproject.toml b/pyproject.toml index fbd191b9..e3b7d866 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ "License :: OSI Approved :: BSD License", ] dependencies = [ - "python-magic>=0.4.5", + "puremagic", "decorator>=4.0.0", "urllib3>=1.25.3", "h11", diff --git a/tests/test_compat.py b/tests/test_compat.py new file mode 100644 index 00000000..49b62ec7 --- /dev/null +++ b/tests/test_compat.py @@ -0,0 +1,5 @@ +from mocket.compat import do_the_magic + + +def test_unknown_binary(): + assert do_the_magic(b"foobar-binary") == "application/octet-stream" diff --git a/tests/test_http.py b/tests/test_http.py index 27324106..d516068b 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -258,21 +258,6 @@ def test_file_object(self): self.assertEqual(int(r.headers["Content-Length"]), len(local_content)) self.assertEqual(r.headers["Content-Type"], "image/png") - @mocketize - def test_file_object_with_no_lib_magic(self): - url = "http://github.com/fluidicon.png" - filename = "tests/fluidicon.png" - with open(filename, "rb") as file_obj: - Entry.register(Entry.GET, url, Response(body=file_obj, lib_magic=None)) - r = requests.get(url) - remote_content = r.content - with open(filename, "rb") as local_file_obj: - local_content = local_file_obj.read() - self.assertEqual(remote_content, local_content) - self.assertEqual(len(remote_content), len(local_content)) - self.assertEqual(int(r.headers["Content-Length"]), len(local_content)) - self.assertNotIn("Content-Type", r.headers) - @mocketize def test_same_url_different_methods(self): url = "http://bit.ly/fakeurl"