1# Copyright (c) Jupyter Development Team.
2# Distributed under the terms of the Modified BSD License.
3
4"""Test Image widget"""
5
6import io
7import os
8
9from ipywidgets import Image
10
11import hashlib
12
13import pkgutil
14
15import tempfile
16from contextlib import contextmanager
17
18# Data
19@contextmanager
20def get_logo_png():
21    # Once the tests are not in the package, this context manager can be
22    # replaced with the location of the actual file
23    LOGO_DATA = pkgutil.get_data('ipywidgets.widgets.tests',
24                                 'data/jupyter-logo-transparent.png')
25    handle, fname = tempfile.mkstemp()
26    os.close(handle)
27    with open(fname, 'wb') as f:
28        f.write(LOGO_DATA)
29
30    yield fname
31
32    os.remove(fname)
33
34LOGO_PNG_DIGEST = '3ff9eafd7197083153e83339a72e7a335539bae189c33554c680e4382c98af02'
35
36
37def test_empty_image():
38    # Empty images shouldn't raise any errors
39    Image()
40
41
42def test_image_value():
43    random_bytes = b'\x0ee\xca\x80\xcd\x9ak#\x7f\x07\x03\xa7'
44
45    Image(value=random_bytes)
46
47
48def test_image_format():
49    # Test that these format names don't throw an error
50    Image(format='png')
51
52    Image(format='jpeg')
53
54    Image(format='url')
55
56
57def test_from_filename():
58    with get_logo_png() as LOGO_PNG:
59        img = Image.from_file(LOGO_PNG)
60
61        assert_equal_hash(img.value, LOGO_PNG_DIGEST)
62
63
64def test_set_from_filename():
65    img = Image()
66    with get_logo_png() as LOGO_PNG:
67        img.set_value_from_file(LOGO_PNG)
68
69        assert_equal_hash(img.value, LOGO_PNG_DIGEST)
70
71
72def test_from_file():
73    with get_logo_png() as LOGO_PNG:
74        with open(LOGO_PNG, 'rb') as f:
75            img = Image.from_file(f)
76            assert_equal_hash(img.value, LOGO_PNG_DIGEST)
77
78
79def test_set_value_from_file():
80    img = Image()
81    with get_logo_png() as LOGO_PNG:
82        with open(LOGO_PNG, 'rb') as f:
83            img.set_value_from_file(f)
84            assert_equal_hash(img.value, LOGO_PNG_DIGEST)
85
86
87def test_from_url_unicode():
88    img = Image.from_url(u'https://jupyter.org/assets/main-logo.svg')
89    assert img.value == b'https://jupyter.org/assets/main-logo.svg'
90
91
92def test_from_url_bytes():
93    img = Image.from_url(b'https://jupyter.org/assets/main-logo.svg')
94
95    assert img.value == b'https://jupyter.org/assets/main-logo.svg'
96
97
98def test_format_inference_filename():
99    with tempfile.NamedTemporaryFile(suffix='.svg', delete=False) as f:
100        name = f.name
101        f.close()           # Allow tests to run on Windows
102        img = Image.from_file(name)
103
104    assert img.format == 'svg+xml'
105
106
107def test_format_inference_file():
108    with tempfile.NamedTemporaryFile(suffix='.gif', delete=False) as f:
109        img = Image.from_file(f)
110
111        assert img.format == 'gif'
112
113
114def test_format_inference_stream():
115    # There's no way to infer the format, so it should default to png
116    fstream = io.BytesIO(b'')
117    img = Image.from_file(fstream)
118
119    assert img.format == 'png'
120
121
122def test_serialize():
123    fstream = io.BytesIO(b'123')
124    img = Image.from_file(fstream)
125
126    img_state = img.get_state()
127
128    # for python27 it is a memoryview
129    assert isinstance(img_state['value'], (bytes, memoryview))
130    # make sure it is (for python 3), since that is what it will be once it comes off the wire
131    img_state['value'] = memoryview(img_state['value'])
132
133    # check that we can deserialize it and get back the original value
134    img_copy = Image()
135    img_copy.set_state(img_state)
136    assert img.value == img_copy.value
137
138
139def test_format_inference_overridable():
140    with tempfile.NamedTemporaryFile(suffix='.svg', delete=False) as f:
141        name = f.name
142        f.close()           # Allow tests to run on Windows
143        img = Image.from_file(name, format='gif')
144
145    assert img.format == 'gif'
146
147
148def test_value_repr_length():
149    with get_logo_png() as LOGO_PNG:
150        with open(LOGO_PNG, 'rb') as f:
151            img = Image.from_file(f)
152            assert len(img.__repr__()) < 120
153            assert img.__repr__().endswith("...')")
154
155
156def test_value_repr_url():
157    img = Image.from_url(b'https://jupyter.org/assets/main-logo.svg')
158
159    assert 'https://jupyter.org/assets/main-logo.svg' in img.__repr__()
160
161
162# Helper functions
163def get_hash_hex(byte_str):
164    m = hashlib.new('sha256')
165
166    m.update(byte_str)
167
168    return m.hexdigest()
169
170
171def assert_equal_hash(byte_str, digest):
172    assert get_hash_hex(byte_str) == digest
173