Skip to content

Commit 3954b5b

Browse files
author
Steve Canny
committed
img: add Image.from_file()
1 parent 3d1ddee commit 3954b5b

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

docx/image/image.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Provides objects that can characterize image streams as to content type and
5+
size, as a required step in including them in a document.
6+
"""
7+
8+
from __future__ import (
9+
absolute_import, division, print_function, unicode_literals
10+
)
11+
12+
import os
13+
14+
from docx.compat import BytesIO, is_string
15+
16+
17+
class Image(object):
18+
"""
19+
Graphical image stream such as JPEG, PNG, or GIF with properties and
20+
methods required by ImagePart.
21+
"""
22+
@classmethod
23+
def from_file(cls, image_descriptor):
24+
"""
25+
Return a new |Image| subclass instance loaded from the image file
26+
identified by *image_descriptor*, a path or file-like object.
27+
"""
28+
if is_string(image_descriptor):
29+
path = image_descriptor
30+
with open(path, 'rb') as f:
31+
blob = f.read()
32+
stream = BytesIO(blob)
33+
filename = os.path.basename(path)
34+
else:
35+
stream = image_descriptor
36+
stream.seek(0)
37+
blob = stream.read()
38+
filename = None
39+
return cls._from_stream(stream, blob, filename)
40+
41+
@classmethod
42+
def _from_stream(cls, stream, blob, filename=None):
43+
"""
44+
Return an instance of the |Image| subclass corresponding to the
45+
format of the image in *stream*.
46+
"""

tests/image/test_image.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,67 @@
88

99
import pytest
1010

11+
from docx.compat import BytesIO
1112
from docx.image import Image_OLD
13+
from docx.image.image import Image
1214
from docx.opc.constants import CONTENT_TYPE as CT
1315

14-
from ..unitutil import test_file
16+
from ..unitutil import class_mock, instance_mock, method_mock, test_file
17+
18+
19+
class DescribeImage(object):
20+
21+
def it_can_construct_from_an_image_path(self, from_path_fixture):
22+
image_path, _from_stream_, stream_, blob, filename, image_ = (
23+
from_path_fixture
24+
)
25+
image = Image.from_file(image_path)
26+
_from_stream_.assert_called_once_with(stream_, blob, filename)
27+
assert image is image_
28+
29+
def it_can_construct_from_an_image_stream(self, from_stream_fixture):
30+
image_stream, _from_stream_, blob, image_ = from_stream_fixture
31+
image = Image.from_file(image_stream)
32+
_from_stream_.assert_called_once_with(image_stream, blob, None)
33+
assert image is image_
34+
35+
# fixtures -------------------------------------------------------
36+
37+
@pytest.fixture
38+
def BytesIO_(self, request, stream_):
39+
return class_mock(
40+
request, 'docx.image.image.BytesIO', return_value=stream_
41+
)
42+
43+
@pytest.fixture
44+
def from_path_fixture(self, _from_stream_, BytesIO_, stream_, image_):
45+
filename = 'python-icon.png'
46+
image_path = test_file(filename)
47+
with open(image_path, 'rb') as f:
48+
blob = f.read()
49+
return image_path, _from_stream_, stream_, blob, filename, image_
50+
51+
@pytest.fixture
52+
def from_stream_fixture(self, _from_stream_, image_):
53+
image_path = test_file('python-icon.png')
54+
with open(image_path, 'rb') as f:
55+
blob = f.read()
56+
image_stream = BytesIO(blob)
57+
return image_stream, _from_stream_, blob, image_
58+
59+
@pytest.fixture
60+
def _from_stream_(self, request, image_):
61+
return method_mock(
62+
request, Image, '_from_stream', return_value=image_
63+
)
64+
65+
@pytest.fixture
66+
def image_(self, request):
67+
return instance_mock(request, Image)
68+
69+
@pytest.fixture
70+
def stream_(self, request):
71+
return instance_mock(request, BytesIO)
1572

1673

1774
class DescribeImage_OLD(object):

tests/test_files/python-icon.png

1.99 KB
Loading

0 commit comments

Comments
 (0)