summaryrefslogtreecommitdiffstats
path: root/contrib/file/python/magic.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/file/python/magic.py')
-rw-r--r--contrib/file/python/magic.py90
1 files changed, 73 insertions, 17 deletions
diff --git a/contrib/file/python/magic.py b/contrib/file/python/magic.py
index a17e8da..c48f7d5 100644
--- a/contrib/file/python/magic.py
+++ b/contrib/file/python/magic.py
@@ -1,10 +1,13 @@
-#!/usr/bin/env python
+# coding: utf-8
+
'''
Python bindings for libmagic
'''
import ctypes
+from collections import namedtuple
+
from ctypes import *
from ctypes.util import find_library
@@ -32,7 +35,7 @@ MAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128
MAGIC_RAW = RAW = 256
MAGIC_ERROR = ERROR = 512
MAGIC_MIME_ENCODING = MIME_ENCODING = 1024
-MAGIC_MIME = MIME = 1040
+MAGIC_MIME = MIME = 1040 # MIME_TYPE + MIME_ENCODING
MAGIC_APPLE = APPLE = 2048
MAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096
@@ -47,6 +50,8 @@ MAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152
MAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824
+FileMagic = namedtuple('FileMagic', ('mime_type', 'encoding', 'name'))
+
class magic_set(Structure):
pass
@@ -118,14 +123,18 @@ class Magic(object):
as a filename or None if an error occurred and the MAGIC_ERROR flag
is set. A call to errno() will return the numeric error code.
"""
- try: # attempt python3 approach first
- if isinstance(filename, bytes):
- bi = filename
- else:
+ if isinstance(filename, bytes):
+ bi = filename
+ else:
+ try: # keep Python 2 compatibility
bi = bytes(filename, 'utf-8')
- return str(_file(self._magic_t, bi), 'utf-8')
- except:
- return _file(self._magic_t, filename.encode('utf-8'))
+ except TypeError:
+ bi = bytes(filename)
+ r = _file(self._magic_t, bi)
+ if isinstance(r, str):
+ return r
+ else:
+ return str(r).encode('utf-8')
def descriptor(self, fd):
"""
@@ -139,20 +148,22 @@ class Magic(object):
as a buffer or None if an error occurred and the MAGIC_ERROR flag
is set. A call to errno() will return the numeric error code.
"""
- try: # attempt python3 approach first
- return str(_buffer(self._magic_t, buf, len(buf)), 'utf-8')
- except:
- return _buffer(self._magic_t, buf, len(buf))
+ r = _buffer(self._magic_t, buf, len(buf))
+ if isinstance(r, str):
+ return r
+ else:
+ return str(r).encode('utf-8')
def error(self):
"""
Returns a textual explanation of the last error or None
if there was no error.
"""
- try: # attempt python3 approach first
- return str(_error(self._magic_t), 'utf-8')
- except:
- return _error(self._magic_t)
+ e = _error(self._magic_t)
+ if isinstance(e, str):
+ return e
+ else:
+ return str(e).encode('utf-8')
def setflags(self, flags):
"""
@@ -219,3 +230,48 @@ def open(flags):
Flags argument as for setflags.
"""
return Magic(_open(flags))
+
+
+# Objects used by `detect_from_` functions
+mime_magic = Magic(_open(MAGIC_MIME))
+mime_magic.load()
+none_magic = Magic(_open(MAGIC_NONE))
+none_magic.load()
+
+
+def _create_filemagic(mime_detected, type_detected):
+ mime_type, mime_encoding = mime_detected.split('; ')
+
+ return FileMagic(name=type_detected, mime_type=mime_type,
+ encoding=mime_encoding.replace('charset=', ''))
+
+
+def detect_from_filename(filename):
+ '''Detect mime type, encoding and file type from a filename
+
+ Returns a `FileMagic` namedtuple.
+ '''
+
+ return _create_filemagic(mime_magic.file(filename),
+ none_magic.file(filename))
+
+
+def detect_from_fobj(fobj):
+ '''Detect mime type, encoding and file type from file-like object
+
+ Returns a `FileMagic` namedtuple.
+ '''
+
+ file_descriptor = fobj.fileno()
+ return _create_filemagic(mime_magic.descriptor(file_descriptor),
+ none_magic.descriptor(file_descriptor))
+
+
+def detect_from_content(byte_content):
+ '''Detect mime type, encoding and file type from bytes
+
+ Returns a `FileMagic` namedtuple.
+ '''
+
+ return _create_filemagic(mime_magic.buffer(byte_content),
+ none_magic.buffer(byte_content))
OpenPOWER on IntegriCloud