Skip to content

Commit 36ecbf9

Browse files
committed
update magic/compat.py
This pulls changes from https://github.com/file/file, commit 512840337ead1076519332d24fefcaa8fac36e06
1 parent 42980e5 commit 36ecbf9

File tree

2 files changed

+90
-23
lines changed

2 files changed

+90
-23
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pyvenv.cfg
1111
*.pyc
1212
*~
1313
dist/
14+
.vscode/

magic/compat.py

Lines changed: 89 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,12 @@
44
Python bindings for libmagic
55
'''
66

7-
import ctypes
8-
7+
import threading
98
from collections import namedtuple
109

1110
from ctypes import *
1211
from ctypes.util import find_library
1312

14-
1513
from . import loader
1614

1715
_libraries = {}
@@ -45,13 +43,19 @@
4543

4644
MAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824
4745

46+
MAGIC_PARAM_INDIR_MAX = PARAM_INDIR_MAX = 0
47+
MAGIC_PARAM_NAME_MAX = PARAM_NAME_MAX = 1
48+
MAGIC_PARAM_ELF_PHNUM_MAX = PARAM_ELF_PHNUM_MAX = 2
49+
MAGIC_PARAM_ELF_SHNUM_MAX = PARAM_ELF_SHNUM_MAX = 3
50+
MAGIC_PARAM_ELF_NOTES_MAX = PARAM_ELF_NOTES_MAX = 4
51+
MAGIC_PARAM_REGEX_MAX = PARAM_REGEX_MAX = 5
52+
MAGIC_PARAM_BYTES_MAX = PARAM_BYTES_MAX = 6
53+
4854
FileMagic = namedtuple('FileMagic', ('mime_type', 'encoding', 'name'))
4955

5056

5157
class magic_set(Structure):
5258
pass
53-
54-
5559
magic_set._fields_ = []
5660
magic_t = POINTER(magic_set)
5761

@@ -103,6 +107,14 @@ class magic_set(Structure):
103107
_errno.restype = c_int
104108
_errno.argtypes = [magic_t]
105109

110+
_getparam = _libraries['magic'].magic_getparam
111+
_getparam.restype = c_int
112+
_getparam.argtypes = [magic_t, c_int, c_void_p]
113+
114+
_setparam = _libraries['magic'].magic_setparam
115+
_setparam.restype = c_int
116+
_setparam.argtypes = [magic_t, c_int, c_void_p]
117+
106118

107119
class Magic(object):
108120
def __init__(self, ms):
@@ -228,29 +240,81 @@ def errno(self):
228240
"""
229241
return _errno(self._magic_t)
230242

243+
def getparam(self, param):
244+
"""
245+
Returns the param value if successful and -1 if the parameter
246+
was unknown.
247+
"""
248+
v = c_int()
249+
i = _getparam(self._magic_t, param, byref(v))
250+
if i == -1:
251+
return -1
252+
return v.value
253+
254+
def setparam(self, param, value):
255+
"""
256+
Returns 0 if successful and -1 if the parameter was unknown.
257+
"""
258+
v = c_int(value)
259+
return _setparam(self._magic_t, param, byref(v))
260+
231261

232262
def open(flags):
233263
"""
234264
Returns a magic object on success and None on failure.
235265
Flags argument as for setflags.
236266
"""
237-
return Magic(_open(flags))
267+
magic_t = _open(flags)
268+
if magic_t is None:
269+
return None
270+
return Magic(magic_t)
238271

239272

240273
# Objects used by `detect_from_` functions
241-
mime_magic = Magic(_open(MAGIC_MIME))
242-
mime_magic.load()
243-
none_magic = Magic(_open(MAGIC_NONE))
244-
none_magic.load()
274+
class error(Exception):
275+
pass
245276

277+
class MagicDetect(object):
278+
def __init__(self):
279+
self.mime_magic = open(MAGIC_MIME)
280+
if self.mime_magic is None:
281+
raise error
282+
if self.mime_magic.load() == -1:
283+
self.mime_magic.close()
284+
self.mime_magic = None
285+
raise error
286+
self.none_magic = open(MAGIC_NONE)
287+
if self.none_magic is None:
288+
self.mime_magic.close()
289+
self.mime_magic = None
290+
raise error
291+
if self.none_magic.load() == -1:
292+
self.none_magic.close()
293+
self.none_magic = None
294+
self.mime_magic.close()
295+
self.mime_magic = None
296+
raise error
297+
298+
def __del__(self):
299+
if self.mime_magic is not None:
300+
self.mime_magic.close()
301+
if self.none_magic is not None:
302+
self.none_magic.close()
303+
304+
threadlocal = threading.local()
305+
306+
def _detect_make():
307+
v = getattr(threadlocal, "magic_instance", None)
308+
if v is None:
309+
v = MagicDetect()
310+
setattr(threadlocal, "magic_instance", v)
311+
return v
246312

247313
def _create_filemagic(mime_detected, type_detected):
248-
splat = mime_detected.split('; ')
249-
mime_type = splat[0]
250-
if len(splat) == 2:
251-
mime_encoding = splat[1]
252-
else:
253-
mime_encoding = ''
314+
try:
315+
mime_type, mime_encoding = mime_detected.split('; ')
316+
except ValueError:
317+
raise ValueError(mime_detected)
254318

255319
return FileMagic(name=type_detected, mime_type=mime_type,
256320
encoding=mime_encoding.replace('charset=', ''))
@@ -261,9 +325,9 @@ def detect_from_filename(filename):
261325
262326
Returns a `FileMagic` namedtuple.
263327
'''
264-
265-
return _create_filemagic(mime_magic.file(filename),
266-
none_magic.file(filename))
328+
x = _detect_make()
329+
return _create_filemagic(x.mime_magic.file(filename),
330+
x.none_magic.file(filename))
267331

268332

269333
def detect_from_fobj(fobj):
@@ -273,8 +337,9 @@ def detect_from_fobj(fobj):
273337
'''
274338

275339
file_descriptor = fobj.fileno()
276-
return _create_filemagic(mime_magic.descriptor(file_descriptor),
277-
none_magic.descriptor(file_descriptor))
340+
x = _detect_make()
341+
return _create_filemagic(x.mime_magic.descriptor(file_descriptor),
342+
x.none_magic.descriptor(file_descriptor))
278343

279344

280345
def detect_from_content(byte_content):
@@ -283,5 +348,6 @@ def detect_from_content(byte_content):
283348
Returns a `FileMagic` namedtuple.
284349
'''
285350

286-
return _create_filemagic(mime_magic.buffer(byte_content),
287-
none_magic.buffer(byte_content))
351+
x = _detect_make()
352+
return _create_filemagic(x.mime_magic.buffer(byte_content),
353+
x.none_magic.buffer(byte_content))

0 commit comments

Comments
 (0)