diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-09-02 08:54:31 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-09-02 08:54:31 +0000 |
commit | 10429269fbeb9442be4c5592b9111ccedbfefd0d (patch) | |
tree | ec492f5b26d71445da74668b4c967621e9ebc556 /python | |
parent | 670c2bbcffe873a2b8589ed140c12e7923ef20c0 (diff) | |
download | file-master.tar.gz |
Diffstat (limited to 'python')
-rw-r--r-- | python/Makefile.in | 22 | ||||
-rw-r--r-- | python/README | 13 | ||||
-rw-r--r-- | python/magic.py | 116 | ||||
-rw-r--r-- | python/setup.py | 32 |
4 files changed, 129 insertions, 54 deletions
diff --git a/python/Makefile.in b/python/Makefile.in index 63a34b4..70bf456 100644 --- a/python/Makefile.in +++ b/python/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -77,7 +87,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = python -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ @@ -85,6 +94,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -109,6 +119,7 @@ am__can_run_installinfo = \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) pkgdatadir = @pkgdatadir@ ACLOCAL = @ACLOCAL@ @@ -246,7 +257,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign python/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -421,6 +431,8 @@ uninstall-am: mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/python/README b/python/README index 8b9a2a7..e69de29 100644 --- a/python/README +++ b/python/README @@ -1,13 +0,0 @@ -This directory contains Python bindings to allow you to access the -libmagic api. At the moment their status is "experimental". - -You can install the modules either with: - -$ python setup.py build -$ python setup.py install - -or, if you have easy_install: - -$ easy_install . - -magic-python should work now! diff --git a/python/magic.py b/python/magic.py index a17e8da..662569e 100644 --- a/python/magic.py +++ b/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 @@ -112,26 +117,43 @@ class Magic(object): """ _close(self._magic_t) + @staticmethod + def __tostr(s): + if s is None: + return None + if isinstance(s, str): + return s + try: # keep Python 2 compatibility + return str(s, 'utf-8') + except TypeError: + return str(s) + + @staticmethod + def __tobytes(b): + if b is None: + return None + if isinstance(b, bytes): + return b + try: # keep Python 2 compatibility + return bytes(b, 'utf-8') + except TypeError: + return bytes(b) + def file(self, filename): """ Returns a textual description of the contents of the argument passed 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. + is set. A call to errno() will return the numeric error code. """ - try: # attempt python3 approach first - if isinstance(filename, bytes): - bi = filename - else: - bi = bytes(filename, 'utf-8') - return str(_file(self._magic_t, bi), 'utf-8') - except: - return _file(self._magic_t, filename.encode('utf-8')) + return Magic.__tostr(_file(self._magic_t, Magic.__tobytes(filename))) def descriptor(self, fd): """ - Like the file method, but the argument is a file descriptor. + Returns a textual description of the contents of the argument passed + as a file descriptor or None if an error occurred and the MAGIC_ERROR + flag is set. A call to errno() will return the numeric error code. """ - return _descriptor(self._magic_t, fd) + return Magic.__tostr(_descriptor(self._magic_t, fd)) def buffer(self, buf): """ @@ -139,20 +161,14 @@ 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)) + return Magic.__tostr(_buffer(self._magic_t, buf, len(buf))) 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) + return Magic.__tostr(_error(self._magic_t)) def setflags(self, flags): """ @@ -173,35 +189,38 @@ class Magic(object): Returns 0 on success and -1 on failure. """ - return _load(self._magic_t, filename) + return _load(self._magic_t, Magic.__tobytes(filename)) def compile(self, dbs): """ Compile entries in the colon separated list of database files passed as argument or the default database file if no argument. - Returns 0 on success and -1 on failure. The compiled files created are named from the basename(1) of each file argument with ".mgc" appended to it. + + Returns 0 on success and -1 on failure. """ - return _compile(self._magic_t, dbs) + return _compile(self._magic_t, Magic.__tobytes(dbs)) def check(self, dbs): """ Check the validity of entries in the colon separated list of database files passed as argument or the default database file if no argument. + Returns 0 on success and -1 on failure. """ - return _check(self._magic_t, dbs) + return _check(self._magic_t, Magic.__tobytes(dbs)) def list(self, dbs): """ Check the validity of entries in the colon separated list of database files passed as argument or the default database file if no argument. + Returns 0 on success and -1 on failure. """ - return _list(self._magic_t, dbs) + return _list(self._magic_t, Magic.__tobytes(dbs)) def errno(self): """ @@ -219,3 +238,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)) diff --git a/python/setup.py b/python/setup.py index 2c3b527..24ae182 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,10 +1,22 @@ -# Python distutils build script for magic extension -from distutils.core import setup - -setup(name = 'Magic file extensions', - version = '0.2', - author = 'Reuben Thomas', - author_email = 'rrt@sc3d.org', - license = 'BSD', - description = 'libmagic Python bindings', - py_modules = ['magic']) +# coding: utf-8 + +from __future__ import unicode_literals + +from setuptools import setup + + +setup(name='file-magic', + version='0.3.0', + author='Reuben Thomas, Álvaro Justen', + author_email='rrt@sc3d.org, alvarojusten@gmail.com', + url='https://github.com/file/file', + license='BSD', + description='(official) libmagic Python bindings', + py_modules=['magic'], + test_suite='tests', + classifiers = [ + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Natural Language :: English', + 'Topic :: Software Development :: Libraries :: Python Modules', + ]) |