From: Christos Zoulas Date: Mon, 23 Nov 2015 20:41:43 +0000 (+0000) Subject: PR/477: Make python code pypi friendly. X-Git-Tag: FILE5_26~68 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8048d19f40df4e7a2175a231fa525bc202d6b006;p=file PR/477: Make python code pypi friendly. --- diff --git a/python/CHANGELOG.md b/python/CHANGELOG.md new file mode 100644 index 00000000..2ec12660 --- /dev/null +++ b/python/CHANGELOG.md @@ -0,0 +1,8 @@ +# Python `file-magic` Log of Changes + +## `0.3.0` + +- Fix `setup.py` so we can upload to PyPI +- Add function `detect_from_filename` +- Add function `detect_from_fobj` +- Add function `detect_from_content` diff --git a/python/README b/python/README index 8b9a2a7e..e69de29b 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/README.md b/python/README.md new file mode 100644 index 00000000..68d3af24 --- /dev/null +++ b/python/README.md @@ -0,0 +1,29 @@ +# `file-magic`: Python Bindings + +This library is a Python ctypes interface to `libmagic`. + + +## Installing + +You can install `file-magic` either with: + + python setup.py install + # or + easy_install . + + +## Using + + import magic + + detected = magic.detect_from_filename('magic.py') + print 'Detected MIME type: {}'.format(detected.mime_type) + print 'Detected encoding: {}'.format(detected.encoding) + print 'Detected file type name: {}'.format(detected.name) + + +## Developing/Contributing + +To run the tests: + + python setup.py test diff --git a/python/magic.py b/python/magic.py index 2c1c012b..8cff29a9 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 @@ -222,3 +227,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 2c3b527b..24ae182f 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', + ]) diff --git a/python/tests.py b/python/tests.py new file mode 100644 index 00000000..197a8fc4 --- /dev/null +++ b/python/tests.py @@ -0,0 +1,32 @@ +# coding: utf-8 + +import unittest + +import magic + + +class MagicTestCase(unittest.TestCase): + + filename = 'magic.py' + expected_mime_type = 'text/x-python' + expected_encoding = 'us-ascii' + expected_name = 'Python script, ASCII text executable' + + def assert_result(self, result): + self.assertEqual(result.mime_type, self.expected_mime_type) + self.assertEqual(result.encoding, self.expected_encoding) + self.assertEqual(result.name, self.expected_name) + + def test_detect_from_filename(self): + result = magic.detect_from_filename(self.filename) + self.assert_result(result) + + def test_detect_from_fobj(self): + with open(self.filename) as fobj: + result = magic.detect_from_fobj(fobj) + self.assert_result(result) + + def test_detect_from_content(self): + with open(self.filename) as fobj: + result = magic.detect_from_content(fobj.read(4096)) + self.assert_result(result)