4343
4444import ctypes
4545import os
46+ import warnings
4647
4748from commoncode import command
4849from plugincode .location_provider import get_location
7980TYPECODE_LIBMAGIC_DATABASE = 'typecode.libmagic.db'
8081
8182
83+ def load_lib_failover ():
84+ # loader from python-magic
85+ libmagic = None
86+ # Let's try to find magic or magic1
87+ dll = (ctypes .util .find_library ('magic' )
88+ or ctypes .util .find_library ('magic1' )
89+ or ctypes .util .find_library ('cygmagic-1' )
90+ or ctypes .util .find_library ('libmagic-1' )
91+ or ctypes .util .find_library ('msys-magic-1' ) # for MSYS2
92+ )
93+ # necessary because find_library returns None if it doesn't find the library
94+ if dll :
95+ libmagic = ctypes .CDLL (dll )
96+
97+ if not libmagic or not libmagic ._name :
98+ windows_dlls = ['magic1.dll' , 'cygmagic-1.dll' , 'libmagic-1.dll' , 'msys-magic-1.dll' ]
99+ platform_to_lib = {'darwin' : ['/opt/local/lib/libmagic.dylib' ,
100+ '/usr/local/lib/libmagic.dylib' ] +
101+ # Assumes there will only be one version installed
102+ glob .glob ('/usr/local/Cellar/libmagic/*/lib/libmagic.dylib' ), # flake8:noqa
103+ 'win32' : windows_dlls ,
104+ 'cygwin' : windows_dlls ,
105+ 'linux' : ['libmagic.so.1' ],
106+ # fallback for some Linuxes (e.g. Alpine) where library search does not work # flake8:noqa
107+ }
108+ platform = 'linux' if sys .platform .startswith ('linux' ) else sys .platform
109+ for dll in platform_to_lib .get (platform , []):
110+ try :
111+ libmagic = ctypes .CDLL (dll )
112+ break
113+ except OSError :
114+ pass
115+
116+ if not libmagic or not libmagic ._name :
117+ return None
118+ return libmagic
119+
82120def load_lib ():
83121 """
84122 Return the loaded libmagic shared library object from plugin-provided path.
85123 """
86124 dll = get_location (TYPECODE_LIBMAGIC_DLL )
87125 libdir = get_location (TYPECODE_LIBMAGIC_LIBDIR )
88126 if not (dll and libdir ) or not os .path .isfile (dll ) or not os .path .isdir (libdir ):
89- raise Exception (
90- 'CRITICAL: libmagic DLL and is magic database are not installed. '
91- 'Unable to continue: you need to install a valid typecode-libmagic '
92- 'plugin with a valid and proper libmagic and magic DB available.'
93- )
127+ ret = load_lib_failover ()
128+ if ret is None :
129+ raise ImportError (
130+ 'CRITICAL: libmagic DLL and is magic database are not installed. '
131+ 'Unable to continue: you need to install a valid typecode-libmagic '
132+ 'plugin with a valid and proper libmagic and magic DB available.'
133+ )
134+ warnings .warn ("System libmagic is used. Install typecode-libmagic for best consitency" )
135+ return ret
94136 return command .load_shared_library (dll , libdir )
95137
96138
@@ -164,6 +206,7 @@ def __init__(self, flags, magic_db_location=None):
164206 self .flags = flags
165207 self .cookie = _magic_open (self .flags )
166208 if not magic_db_location :
209+ # if no plugin, None is returned, and libmagic will load the default db
167210 magic_db_location = get_location (TYPECODE_LIBMAGIC_DATABASE )
168211
169212 # Note: this location must always be bytes on Python2 and 3, all OSes
@@ -257,3 +300,9 @@ def check_error(result, func, args): # NOQA
257300_magic_load .restype = ctypes .c_int
258301_magic_load .argtypes = [ctypes .c_void_p , ctypes .c_char_p ]
259302_magic_load .errcheck = check_error
303+
304+ _magic_version = libmagic .magic_version
305+ _magic_version .restype = ctypes .c_int
306+ _magic_version .argtypes = []
307+
308+ libmagic_version = _magic_version ()
0 commit comments