From 2ea25752217a2cce66d046da035805dd14eeb500 Mon Sep 17 00:00:00 2001 From: patarapolw Date: Tue, 16 Oct 2018 20:09:49 +0700 Subject: [PATCH 1/4] add building data-uri (`build()`) --- datauri/datauri.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/datauri/datauri.py b/datauri/datauri.py index 673a4df..15c509c 100644 --- a/datauri/datauri.py +++ b/datauri/datauri.py @@ -1,6 +1,8 @@ import base64 import re import urllib.parse +import mimetypes +from tempfile import NamedTemporaryFile # RFC 3986: reserved characters, unreserved characters, and percent. @@ -89,3 +91,22 @@ def discover(s): yield parse(match.group()) except DataURIError: continue + + +def build(fp): + """based on https://gist.github.com/jsocol/1089733""" + if hasattr(fp, 'read'): + b = fp.read() + else: + b = fp + + with NamedTemporaryFile() as f: + f.write(b) + mime, _ = mimetypes.guess_type(f.name) + + if mime is None: + raise DataURIError + + data64 = u''.join(base64.b64encode(b).splitlines()) + + return 'data:{};base64,{}'.format(mime, data64) From 8aaea8a2791bb3dc2ffdb735c0b7e5358b17ea93 Mon Sep 17 00:00:00 2001 From: patarapolw Date: Tue, 16 Oct 2018 20:13:32 +0700 Subject: [PATCH 2/4] Add build to __init__ --- datauri/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/datauri/__init__.py b/datauri/__init__.py index 1a2f5ba..b74c3ad 100644 --- a/datauri/__init__.py +++ b/datauri/__init__.py @@ -5,4 +5,5 @@ from .datauri import ( # noqa: F401 DataURIError, discover, - parse) + parse, + build) From 31eb75869285f88a578044d60fa11587466417a7 Mon Sep 17 00:00:00 2001 From: patarapolw Date: Tue, 16 Oct 2018 20:58:16 +0700 Subject: [PATCH 3/4] Use libmagic instead of mimetypes --- .gitignore | 3 +++ datauri/datauri.py | 30 ++++++++++++++++++------------ requirements.txt | 1 + setup.py | 3 ++- tox.ini | 2 +- 5 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 2c362ab..745bf36 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ /dist /htmlcov __pycache__ +venv/ +.idea/ +.vscode/ diff --git a/datauri/datauri.py b/datauri/datauri.py index 15c509c..a6b9273 100644 --- a/datauri/datauri.py +++ b/datauri/datauri.py @@ -1,8 +1,9 @@ import base64 import re import urllib.parse -import mimetypes -from tempfile import NamedTemporaryFile +import magic +from io import BytesIO +from pathlib import Path # RFC 3986: reserved characters, unreserved characters, and percent. @@ -94,19 +95,24 @@ def discover(s): def build(fp): - """based on https://gist.github.com/jsocol/1089733""" - if hasattr(fp, 'read'): + """ + Build data URI according to RFC 2397 + (data:[][;base64],) + + :param str|Path|bytes|BytesIO fp: + :return: + """ + if isinstance(fp, (str, Path)) and Path(fp).is_file(): + b = Path(fp).read_bytes() + mime = magic.from_file(fp, mime=True) + elif hasattr(fp, 'read'): b = fp.read() + fp.seek(0) + mime = magic.from_buffer(fp, mime=True) else: b = fp + mime = magic.from_buffer(BytesIO(fp), mime=True) - with NamedTemporaryFile() as f: - f.write(b) - mime, _ = mimetypes.guess_type(f.name) - - if mime is None: - raise DataURIError - - data64 = u''.join(base64.b64encode(b).splitlines()) + data64 = base64.b64encode(b).decode() return 'data:{};base64,{}'.format(mime, data64) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6863aff --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +python-magic==0.4.15 diff --git a/setup.py b/setup.py index c84f471..710cd66 100644 --- a/setup.py +++ b/setup.py @@ -8,10 +8,11 @@ name='datauri', description="implementation of the data uri scheme defined in rfc2397", long_description=long_description, - version='1.0.0', + version='1.0.1', author="EclecticIQ", author_email="info@eclecticiq.com", packages=['datauri'], + install_requires=['python-magic'], url='https://github.com/eclecticiq/python-data-uri', license="BSD", classifiers=[ diff --git a/tox.ini b/tox.ini index de50511..be132f4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py33,py34,py35,py36 +envlist = py34,py35,py36 [testenv] deps=-rrequirements-test.txt From efc5dd46733fe87ec066f2a9294d57fad8e2f50d Mon Sep 17 00:00:00 2001 From: patarapolw Date: Tue, 16 Oct 2018 21:15:42 +0700 Subject: [PATCH 4/4] tested `build()` externally --- datauri/datauri.py | 21 ++++++++++++--------- setup.py | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/datauri/datauri.py b/datauri/datauri.py index a6b9273..764af13 100644 --- a/datauri/datauri.py +++ b/datauri/datauri.py @@ -1,9 +1,8 @@ import base64 import re import urllib.parse -import magic -from io import BytesIO from pathlib import Path +import mimetypes # RFC 3986: reserved characters, unreserved characters, and percent. @@ -99,19 +98,23 @@ def build(fp): Build data URI according to RFC 2397 (data:[][;base64],) - :param str|Path|bytes|BytesIO fp: + :param str|Path|bytes fp: :return: """ if isinstance(fp, (str, Path)) and Path(fp).is_file(): b = Path(fp).read_bytes() - mime = magic.from_file(fp, mime=True) - elif hasattr(fp, 'read'): - b = fp.read() - fp.seek(0) - mime = magic.from_buffer(fp, mime=True) + try: + import magic + mime = magic.from_file(fp, mime=True) + except ImportError: + mime, _ = mimetypes.guess_type(str(fp)) + + if mime is None: + raise DataURIError('Invalid MIME type') else: + import magic b = fp - mime = magic.from_buffer(BytesIO(fp), mime=True) + mime = magic.from_buffer(fp, mime=True) data64 = base64.b64encode(b).decode() diff --git a/setup.py b/setup.py index 710cd66..3eb7646 100644 --- a/setup.py +++ b/setup.py @@ -13,6 +13,7 @@ author_email="info@eclecticiq.com", packages=['datauri'], install_requires=['python-magic'], + tests_require=['pytest'], url='https://github.com/eclecticiq/python-data-uri', license="BSD", classifiers=[