Skip to content

Commit fe8a489

Browse files
author
Steve Canny
committed
img: add Image.load()
1 parent 5a4f534 commit fe8a489

File tree

4 files changed

+70
-5
lines changed

4 files changed

+70
-5
lines changed

docx/parts/image.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,54 @@
66

77
from __future__ import absolute_import, print_function, unicode_literals
88

9+
import hashlib
10+
import os
11+
912
from docx.opc.package import Part
13+
from docx.shared import lazyproperty
1014

1115

1216
class Image(object):
1317
"""
1418
A helper object that knows how to analyze an image file.
1519
"""
20+
def __init__(self, blob, filename):
21+
super(Image, self).__init__()
22+
self._blob = blob
23+
self._filename = filename
24+
25+
@property
26+
def filename(self):
27+
"""
28+
Original image file name, if loaded from disk, or a generic filename
29+
if loaded from an anonymous stream.
30+
"""
31+
return self._filename
32+
1633
@classmethod
17-
def load(self, image_descriptor):
34+
def load(cls, image_descriptor):
1835
"""
1936
Return a new |Image| instance loaded from the image file identified
2037
by *image_descriptor*, a path or file-like object.
2138
"""
39+
if isinstance(image_descriptor, basestring):
40+
path = image_descriptor
41+
with open(path, 'rb') as f:
42+
blob = f.read()
43+
filename = os.path.basename(path)
44+
else:
45+
stream = image_descriptor
46+
stream.seek(0)
47+
blob = stream.read()
48+
filename = None
49+
return cls(blob, filename)
2250

23-
@property
51+
@lazyproperty
2452
def sha1(self):
2553
"""
2654
SHA1 hash digest of the image blob
2755
"""
28-
raise NotImplementedError
56+
return hashlib.sha1(self._blob).hexdigest()
2957

3058

3159
class ImagePart(Part):

tests/parts/test_image.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Test suite for docx.parts.image module
5+
"""
6+
7+
from __future__ import absolute_import, print_function, unicode_literals
8+
9+
from docx.parts.image import Image
10+
11+
from ..unitutil import test_file
12+
13+
14+
class DescribeImage(object):
15+
16+
def it_can_construct_from_an_image_path(self):
17+
image_file_path = test_file('monty-truth.png')
18+
image = Image.load(image_file_path)
19+
assert isinstance(image, Image)
20+
assert image.sha1 == '79769f1e202add2e963158b532e36c2c0f76a70c'
21+
assert image.filename == 'monty-truth.png'
22+
23+
def it_can_construct_from_an_image_stream(self):
24+
image_file_path = test_file('monty-truth.png')
25+
with open(image_file_path, 'rb') as image_file_stream:
26+
image = Image.load(image_file_stream)
27+
assert isinstance(image, Image)
28+
assert image.sha1 == '79769f1e202add2e963158b532e36c2c0f76a70c'
29+
assert image.filename is None

tests/unitutil.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ def docx_path(name):
3535
return absjoin(_thisdir, 'test_files', '%s.docx' % name)
3636

3737

38+
def test_file(name):
39+
"""
40+
Return the absolute path to test file having *name*.
41+
"""
42+
return absjoin(_thisdir, 'test_files', name)
43+
44+
3845
# ===========================================================================
3946
# pytest mocking helpers
4047
# ===========================================================================

tox.ini

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
# Configuration for tox and pytest
1010

1111
[pytest]
12-
norecursedirs = doc docx *.egg-info features .git .tox
12+
norecursedirs = doc docx *.egg-info features .git ref _scratch .tox
13+
python_files = test_*.py
1314
python_classes = Test Describe
14-
python_functions = test_ it_ they_
15+
python_functions = it_ they_
1516

1617
[tox]
1718
envlist = py26, py27, py33

0 commit comments

Comments
 (0)