1- #!/usr/bin/env python
2-
31"""
4- Adam Hupp <adam@hupp.org>
2+ magic is a wrapper around the libmagic file identification library.
3+
4+ See README for more information.
5+
6+ Usage:
7+
8+ >>> import magic
9+ >>> magic.from_file("testdata/test.pdf")
10+ 'PDF document, version 1.2'
11+ >>> magic.from_file("testdata/test.pdf", mime=True)
12+ 'application/pdf'
13+ >>> magic.from_buffer(open("testdata/test.pdf").read(1024))
14+ 'PDF document, version 1.2'
15+ >>>
516
6- Reference: http://hupp.org/adam/hg/python-magic
717
8- License: PSF (http://www.python.org/psf/license/)
918"""
1019
20+ import sys
1121import os .path
1222import ctypes
1323import ctypes .util
@@ -18,26 +28,30 @@ class MagicException(Exception): pass
1828
1929class Magic :
2030 """
21- Magic is a wrapper around the libmagic C library.
31+ Magic is a wrapper around the libmagic C library.
2232
2333 """
2434
25- def __init__ (self , mime = False , magic_file = None ):
35+ def __init__ (self , mime = False , magic_file = None , mime_encoding = False ):
2636 """
2737 Create a new libmagic wrapper.
2838
2939 mime - if True, mimetypes are returned instead of textual descriptions
40+ mime_encoding - if True, codec is returned
3041 magic_file - use a mime database other than the system default
3142
3243 """
3344 flags = MAGIC_NONE
3445 if mime :
3546 flags |= MAGIC_MIME
47+ elif mime_encoding :
48+ flags |= MAGIC_MIME_ENCODING
3649
3750 self .cookie = magic_open (flags )
3851
3952 magic_load (self .cookie , magic_file )
4053
54+
4155 def from_buffer (self , buf ):
4256 """
4357 Identify the contents of `buf`
@@ -56,10 +70,10 @@ def from_file(self, filename):
5670 return magic_file (self .cookie , filename )
5771
5872 def __del__ (self ):
59- try :
73+ # during shutdown magic_close may have been cleared already
74+ if self .cookie and magic_close :
6075 magic_close (self .cookie )
61- except Exception , _ :
62- pass
76+ self .cookie = None
6377
6478_magic_mime = None
6579_magic = None
@@ -90,66 +104,102 @@ def from_buffer(buffer, mime=False):
90104 m = _get_magic_type (mime )
91105 return m .from_buffer (buffer )
92106
93- try :
94- libmagic = ctypes .CDLL (ctypes .util .find_library ('magic' ))
95107
96- magic_t = ctypes .c_void_p
97108
98- def errorcheck (result , func , args ):
99- err = magic_error (args [0 ])
100- if err is not None :
101- raise MagicException (err )
102- else :
103- return result
104109
105- magic_open = libmagic .magic_open
106- magic_open .restype = magic_t
107- magic_open .argtypes = [c_int ]
110+ libmagic = None
111+ # Let's try to find magic or magic1
112+ dll = ctypes .util .find_library ('magic' ) or ctypes .util .find_library ('magic1' )
113+
114+ # This is necessary because find_library returns None if it doesn't find the library
115+ if dll :
116+ libmagic = ctypes .CDLL (dll )
117+
118+ if not libmagic or not libmagic ._name :
119+ import sys
120+ platform_to_lib = {'darwin' : ['/opt/local/lib/libmagic.dylib' ,
121+ '/usr/local/lib/libmagic.dylib' ,
122+ '/usr/local/Cellar/libmagic/5.10/lib/libmagic.dylib' ],
123+ 'win32' : ['magic1.dll' ]}
124+ for dll in platform_to_lib .get (sys .platform , []):
125+ try :
126+ libmagic = ctypes .CDLL (dll )
127+ except OSError :
128+ pass
129+
130+ if not libmagic or not libmagic ._name :
131+ # It is better to raise an ImportError since we are importing magic module
132+ raise ImportError ('failed to find libmagic. Check your installation' )
133+
134+ magic_t = ctypes .c_void_p
135+
136+ def errorcheck (result , func , args ):
137+ err = magic_error (args [0 ])
138+ if err is not None :
139+ raise MagicException (err )
140+ else :
141+ return result
142+
143+ def coerce_filename (filename ):
144+ if filename is None :
145+ return None
146+ return filename .encode (sys .getfilesystemencoding ())
147+
148+ magic_open = libmagic .magic_open
149+ magic_open .restype = magic_t
150+ magic_open .argtypes = [c_int ]
151+
152+ magic_close = libmagic .magic_close
153+ magic_close .restype = None
154+ magic_close .argtypes = [magic_t ]
108155
109- magic_close = libmagic .magic_close
110- magic_close .restype = None
111- magic_close .argtypes = [magic_t ]
112- magic_close .errcheck = errorcheck
156+ magic_error = libmagic .magic_error
157+ magic_error .restype = c_char_p
158+ magic_error .argtypes = [magic_t ]
113159
114- magic_error = libmagic .magic_error
115- magic_error .restype = c_char_p
116- magic_error .argtypes = [magic_t ]
160+ magic_errno = libmagic .magic_errno
161+ magic_errno .restype = c_int
162+ magic_errno .argtypes = [magic_t ]
117163
118- magic_errno = libmagic .magic_errno
119- magic_errno .restype = c_int
120- magic_errno .argtypes = [magic_t ]
164+ _magic_file = libmagic .magic_file
165+ _magic_file .restype = c_char_p
166+ _magic_file .argtypes = [magic_t , c_char_p ]
167+ _magic_file .errcheck = errorcheck
121168
122- magic_file = libmagic .magic_file
123- magic_file .restype = c_char_p
124- magic_file .argtypes = [magic_t , c_char_p ]
125- magic_file .errcheck = errorcheck
169+ def magic_file (cookie , filename ):
170+ return _magic_file (cookie , coerce_filename (filename ))
126171
127- _magic_buffer = libmagic .magic_buffer
128- _magic_buffer .restype = c_char_p
129- _magic_buffer .argtypes = [magic_t , c_void_p , c_size_t ]
130- _magic_buffer .errcheck = errorcheck
172+ _magic_buffer = libmagic .magic_buffer
173+ _magic_buffer .restype = c_char_p
174+ _magic_buffer .argtypes = [magic_t , c_void_p , c_size_t ]
175+ _magic_buffer .errcheck = errorcheck
131176
132- def magic_buffer (cookie , buf ):
133- return _magic_buffer (cookie , buf , len (buf ))
134177
135- magic_load = libmagic .magic_load
136- magic_load .restype = c_int
137- magic_load .argtypes = [magic_t , c_char_p ]
138- magic_load .errcheck = errorcheck
178+ def magic_buffer (cookie , buf ):
179+ return _magic_buffer (cookie , buf , len (buf ))
139180
140- magic_setflags = libmagic .magic_setflags
141- magic_setflags .restype = c_int
142- magic_setflags .argtypes = [magic_t , c_int ]
143181
144- magic_check = libmagic .magic_check
145- magic_check .restype = c_int
146- magic_check .argtypes = [magic_t , c_char_p ]
182+ _magic_load = libmagic .magic_load
183+ _magic_load .restype = c_int
184+ _magic_load .argtypes = [magic_t , c_char_p ]
185+ _magic_load .errcheck = errorcheck
186+
187+ def magic_load (cookie , filename ):
188+ return _magic_load (cookie , coerce_filename (filename ))
189+
190+ magic_setflags = libmagic .magic_setflags
191+ magic_setflags .restype = c_int
192+ magic_setflags .argtypes = [magic_t , c_int ]
193+
194+ magic_check = libmagic .magic_check
195+ magic_check .restype = c_int
196+ magic_check .argtypes = [magic_t , c_char_p ]
197+
198+ magic_compile = libmagic .magic_compile
199+ magic_compile .restype = c_int
200+ magic_compile .argtypes = [magic_t , c_char_p ]
201+
147202
148- magic_compile = libmagic .magic_compile
149- magic_compile .restype = c_int
150- magic_compile .argtypes = [magic_t , c_char_p ]
151- except :
152- pass
153203
154204MAGIC_NONE = 0x000000 # No flags
155205
@@ -163,6 +213,8 @@ def magic_buffer(cookie, buf):
163213
164214MAGIC_MIME = 0x000010 # Return a mime string
165215
216+ MAGIC_MIME_ENCODING = 0x000400 # Return the MIME encoding
217+
166218MAGIC_CONTINUE = 0x000020 # Return all matches
167219
168220MAGIC_CHECK = 0x000040 # Print warnings to stderr
0 commit comments