Skip to content

Commit a1dd358

Browse files
committed
Unbreak various things
* A merge to reduce error spam during loading broke .so loading in at least some (maybe all?) cases, where find_library doesn't return an absolute path. * Prematurely pushed some in-progress test changes that were super broken, all fixed now.
1 parent 36ecbf9 commit a1dd358

File tree

2 files changed

+140
-114
lines changed

2 files changed

+140
-114
lines changed

magic/loader.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
logger = logging.getLogger(__name__)
99

10+
1011
def _lib_candidates_linux():
1112
"""Yield possible libmagic library names on Linux.
1213
@@ -51,7 +52,7 @@ def _lib_candidates():
5152
"darwin": _lib_candidates_macos,
5253
"linux": _lib_candidates_linux,
5354
"win32": _lib_candidates_windows,
54-
"sunos5": _lib_candidates_linux,
55+
"sunos5": _lib_candidates_linux,
5556
}.get(sys.platform)
5657
if func is None:
5758
raise ImportError("python-magic: Unsupported platform: " + sys.platform)
@@ -61,17 +62,20 @@ def _lib_candidates():
6162

6263

6364
def load_lib():
65+
exc = []
6466
for lib in _lib_candidates():
6567
# find_library returns None when lib not found
6668
if lib is None:
6769
continue
68-
if not os.path.exists(lib):
69-
continue
7070

7171
try:
7272
return ctypes.CDLL(lib)
73-
except OSError:
74-
logger.warning("Failed to load: " + lib, exc_info=True)
73+
except OSError as e:
74+
exc.append(e)
75+
76+
msg = "\n".join([str(e) for e in exc])
7577

7678
# It is better to raise an ImportError since we are importing magic module
77-
raise ImportError("python-magic: failed to find libmagic. Check your installation")
79+
raise ImportError(
80+
"python-magic: failed to find libmagic. Check your installation: \n" + msg
81+
)

test/python_magic_test.py

Lines changed: 130 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import shutil
66
import sys
77
import tempfile
8+
from typing import List
89
import unittest
910

1011
import pytest
@@ -19,140 +20,162 @@
1920

2021
import magic
2122

23+
2224
@dataclass
2325
class TestFile:
2426
file_name: str
25-
mime_results: list[str]
26-
text_results: list[str]
27-
no_check_elf_results: list[str] | None
27+
mime_results: List[str]
28+
text_results: List[str]
29+
no_check_elf_results: List[str] | None
2830
buf_equals_file: bool = True
2931

32+
3033
# magic_descriptor is broken (?) in centos 7, so don't run those tests
3134
SKIP_FROM_DESCRIPTOR = bool(os.environ.get("SKIP_FROM_DESCRIPTOR"))
3235

3336

34-
COMMON_PLAIN = [
35-
{},
36-
{"check_soft": True},
37-
{"check_soft": False},
38-
{"check_json": True},
39-
{"check_json": False},
40-
]
41-
42-
NO_SOFT = {"check_soft": False}
43-
44-
COMMON_MIME = [{"mime": True, **k} for k in COMMON_PLAIN]
37+
COMMON_PLAIN = [{}]
38+
NO_SOFT = [{"check_soft": False}]
39+
COMMON_MIME = [{"mime": True}]
4540

4641
CASES = {
47-
"magic._pyc_": [
48-
(COMMON_MIME, [
49-
"application/octet-stream",
50-
"text/x-bytecode.python",
51-
"application/x-bytecode.python",
52-
]),
42+
b"magic._pyc_": [
43+
(
44+
COMMON_MIME,
45+
[
46+
"application/octet-stream",
47+
"text/x-bytecode.python",
48+
"application/x-bytecode.python",
49+
],
50+
),
5351
(COMMON_PLAIN, ["python 2.4 byte-compiled"]),
5452
(NO_SOFT, ["data"]),
5553
],
56-
"test.pdf": [
54+
b"test.pdf": [
5755
(COMMON_MIME, ["application/pdf"]),
58-
(COMMON_PLAIN, [
59-
"PDF document, version 1.2",
60-
"PDF document, version 1.2, 2 pages",
61-
"PDF document, version 1.2, 2 page(s)",
62-
]),
56+
(
57+
COMMON_PLAIN,
58+
[
59+
"PDF document, version 1.2",
60+
"PDF document, version 1.2, 2 pages",
61+
"PDF document, version 1.2, 2 page(s)",
62+
],
63+
),
6364
(NO_SOFT, ["ASCII text"]),
6465
],
65-
"test.gz": [
66+
b"test.gz": [
6667
(COMMON_MIME, ["application/gzip", "application/x-gzip"]),
67-
(COMMON_PLAIN, [
68-
'gzip compressed data, was "test", from Unix, last modified: Sun Jun 29 01:32:52 2008',
69-
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix',
70-
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, original size 15',
71-
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, original size modulo 2^32 15',
72-
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, truncated',
73-
]),
74-
({"extension": True}, [
75-
# some versions return '' for the extensions of a gz file,
76-
# including w/ the command line. Who knows...
77-
"gz/tgz/tpz/zabw/svgz/adz/kmy/xcfgz",
78-
"gz/tgz/tpz/zabw/svgz",
79-
"",
80-
"???",
81-
]),
68+
(
69+
COMMON_PLAIN,
70+
[
71+
'gzip compressed data, was "test", from Unix, last modified: Sun Jun 29 01:32:52 2008',
72+
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix',
73+
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, original size 15',
74+
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, original size modulo 2^32 15',
75+
'gzip compressed data, was "test", last modified: Sun Jun 29 01:32:52 2008, from Unix, truncated',
76+
],
77+
),
78+
(
79+
[{"extension": True}],
80+
[
81+
# some versions return '' for the extensions of a gz file,
82+
# including w/ the command line. Who knows...
83+
"gz/tgz/tpz/zabw/svgz/adz/kmy/xcfgz",
84+
"gz/tgz/tpz/zabw/svgz",
85+
"",
86+
"???",
87+
],
88+
),
8289
(NO_SOFT, ["data"]),
8390
],
84-
"test.snappy.parquet": [
91+
b"test.snappy.parquet": [
8592
(COMMON_MIME, ["application/octet-stream"]),
8693
(COMMON_PLAIN, ["Apache Parquet", "Par archive data"]),
8794
(NO_SOFT, ["data"]),
8895
],
89-
"test.json": [
90-
# TODO: soft, no_json
96+
b"test.json": [
9197
(COMMON_MIME, ["application/json"]),
9298
(COMMON_PLAIN, ["JSON text data"]),
93-
({"mime": True, "check_json": False}, [
94-
"data",
95-
]),
96-
(NO_SOFT, ["JSON text data"])
99+
(
100+
[{"mime": True, "check_json": False}],
101+
[
102+
"text/plain",
103+
],
104+
),
105+
(NO_SOFT, ["JSON text data"]),
97106
],
98-
"elf-NetBSD-x86_64-echo": [
107+
b"elf-NetBSD-x86_64-echo": [
99108
# TODO: soft, no elf
100-
(COMMON_PLAIN, [
101-
"ELF 64-bit LSB shared object, x86-64, version 1 (SYSV)",
102-
"ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libexec/ld.elf_so, for NetBSD 8.0, not stripped",
103-
]),
104-
(COMMON_MIME, [
105-
"application/x-pie-executable",
106-
"application/x-sharedlib",
107-
]),
108-
({"check_elf": False}, [
109-
"ELF 64-bit LSB shared object, x86-64, version 1 (SYSV)",
110-
]),
109+
(
110+
COMMON_PLAIN,
111+
[
112+
"ELF 64-bit LSB shared object, x86-64, version 1 (SYSV)",
113+
"ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libexec/ld.elf_so, for NetBSD 8.0, not stripped",
114+
],
115+
),
116+
(
117+
COMMON_MIME,
118+
[
119+
"application/x-pie-executable",
120+
"application/x-sharedlib",
121+
],
122+
),
123+
(
124+
[{"check_elf": False}],
125+
[
126+
"ELF 64-bit LSB shared object, x86-64, version 1 (SYSV)",
127+
],
128+
),
111129
# TODO: sometimes
112130
# "ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /libexec/ld.elf_so, for NetBSD 8.0, not stripped",
113-
114131
(NO_SOFT, ["data"]),
115132
],
116-
"test.txt": [
133+
b"text.txt": [
117134
(COMMON_MIME, ["text/plain"]),
118135
(COMMON_PLAIN, ["ASCII text"]),
119-
({"mime_encoding": True}, [
120-
"us-ascii",
121-
]),
136+
(
137+
[{"mime_encoding": True}],
138+
[
139+
"us-ascii",
140+
],
141+
),
122142
(NO_SOFT, ["ASCII text"]),
123143
],
124-
"text-iso8859-1.txt": [
125-
({"mime_encoding": True}, [
126-
"iso-8859-1",
127-
]),
144+
b"text-iso8859-1.txt": [
145+
(
146+
[{"mime_encoding": True}],
147+
[
148+
"iso-8859-1",
149+
],
150+
),
128151
],
129152
b"\xce\xbb": [
130153
(COMMON_MIME, ["text/plain"]),
131154
],
132-
"b\xce\xbb".decode("utf-8"): [
133-
(COMMON_MIME, ["text/plain"]),
155+
b"name_use.jpg": [
156+
([{"extension": True}], ["jpeg/jpg/jpe/jfif"]),
134157
],
135-
"name_use.jpg": [
136-
({"extension": True}, [
137-
"jpeg/jpg/jpe/jfif"
138-
]),
158+
b"keep-going.jpg": [
159+
(COMMON_MIME, ["image/jpeg"]),
160+
(
161+
[{"mime": True, "keep_going": True}],
162+
[
163+
"image/jpeg\\012- application/octet-stream",
164+
],
165+
),
139166
],
140-
"keep-going.jpg": [
141-
(COMMON_MIME, [
142-
"image/jpeg"
143-
]),
144-
({"mime": True, "keep_going": True}, [
145-
"image/jpeg\\012- application/octet-stream",
146-
])
167+
b"../../magic/loader.py": [
168+
(
169+
COMMON_MIME,
170+
[
171+
"text/x-python",
172+
"text/x-script.python",
173+
],
174+
)
147175
],
148-
"test.py": [
149-
(COMMON_MIME, [
150-
"text/x-python",
151-
"text/x-script.python",
152-
])
153-
]
154176
}
155177

178+
156179
class MagicTest(unittest.TestCase):
157180
TESTDATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "testdata"))
158181

@@ -165,7 +188,6 @@ def test_version(self):
165188
def test_fs_encoding(self):
166189
self.assertEqual("utf-8", sys.getfilesystemencoding().lower())
167190

168-
169191
def test_from_file_str_and_bytes(self):
170192
filename = os.path.join(self.TESTDATA_DIR, "test.pdf")
171193

@@ -174,7 +196,6 @@ def test_from_file_str_and_bytes(self):
174196
"application/pdf", magic.from_file(filename.encode("utf-8"), mime=True)
175197
)
176198

177-
178199
def test_all_cases(self):
179200
# TODO:
180201
# * MAGIC_EXTENSION not supported
@@ -184,21 +205,24 @@ def test_all_cases(self):
184205
shutil.copyfile(os.path.join(MagicTest.TESTDATA_DIR, "lambda"), dest)
185206
os.environ["TZ"] = "UTC"
186207
try:
187-
for file_name, cases in CASES:
188-
filename = os.path.join(self.TESTDATA_DIR, file_name)
189-
for flags, outputs in cases:
190-
m = magic.Magic(**flags)
191-
with open(filename) as f:
192-
self.assertIn(m.from_descriptor(f.fileno()), outputs)
193-
194-
self.assertIn(m.from_file(filename), outputs)
195-
196-
fname_bytes = filename.encode("utf-8")
197-
self.assertIn(m.from_file(fname_bytes), outputs)
198-
199-
with open(file_name, "rb") as f:
200-
buf_result = m.from_buffer(f.read(1024))
201-
self.assertIn(buf_result, outputs)
208+
for filename, cases in CASES.items():
209+
filename = os.path.join(self.TESTDATA_DIR.encode("utf-8"), filename)
210+
print("test case ", filename, file=sys.stderr)
211+
for flag_variants, outputs in cases:
212+
for flags in flag_variants:
213+
print("flags", flags, file=sys.stderr)
214+
m = magic.Magic(**flags)
215+
with open(filename) as f:
216+
self.assertIn(m.from_descriptor(f.fileno()), outputs)
217+
218+
self.assertIn(m.from_file(filename), outputs)
219+
220+
fname_str = filename.decode("utf-8")
221+
self.assertIn(m.from_file(fname_str), outputs)
222+
223+
with open(filename, "rb") as f:
224+
buf_result = m.from_buffer(f.read(1024))
225+
self.assertIn(buf_result, outputs)
202226
finally:
203227
del os.environ["TZ"]
204228
os.unlink(dest)
@@ -222,7 +246,6 @@ def test_unicode_result_raw(self):
222246
else:
223247
raise unittest.SkipTest("Magic file doesn't return expected type.")
224248

225-
226249
def test_errors(self):
227250
m = magic.Magic()
228251
self.assertRaises(IOError, m.from_file, "nonexistent")
@@ -233,7 +256,6 @@ def test_errors(self):
233256
finally:
234257
del os.environ["MAGIC"]
235258

236-
237259
def test_rethrow(self):
238260
old = magic.magic_buffer
239261
try:

0 commit comments

Comments
 (0)