Show More
@@ -6,6 +6,7 b'' | |||||
6 |
|
6 | |||
7 |
|
7 | |||
8 | from binascii import b2a_base64, hexlify |
|
8 | from binascii import b2a_base64, hexlify | |
|
9 | import html | |||
9 | import json |
|
10 | import json | |
10 | import mimetypes |
|
11 | import mimetypes | |
11 | import os |
|
12 | import os | |
@@ -371,7 +372,7 b' class DisplayObject(object):' | |||||
371 | with gzip.open(BytesIO(data), 'rt', encoding=encoding) as fp: |
|
372 | with gzip.open(BytesIO(data), 'rt', encoding=encoding) as fp: | |
372 | encoding = None |
|
373 | encoding = None | |
373 | data = fp.read() |
|
374 | data = fp.read() | |
374 |
|
375 | |||
375 | # decode data, if an encoding was specified |
|
376 | # decode data, if an encoding was specified | |
376 | # We only touch self.data once since |
|
377 | # We only touch self.data once since | |
377 | # subclasses such as SVG have @data.setter methods |
|
378 | # subclasses such as SVG have @data.setter methods | |
@@ -802,7 +803,7 b' class Image(DisplayObject):' | |||||
802 |
|
803 | |||
803 | def __init__(self, data=None, url=None, filename=None, format=None, |
|
804 | def __init__(self, data=None, url=None, filename=None, format=None, | |
804 | embed=None, width=None, height=None, retina=False, |
|
805 | embed=None, width=None, height=None, retina=False, | |
805 | unconfined=False, metadata=None): |
|
806 | unconfined=False, metadata=None, alt=None): | |
806 | """Create a PNG/JPEG/GIF image object given raw data. |
|
807 | """Create a PNG/JPEG/GIF image object given raw data. | |
807 |
|
808 | |||
808 | When this object is returned by an input cell or passed to the |
|
809 | When this object is returned by an input cell or passed to the | |
@@ -847,6 +848,8 b' class Image(DisplayObject):' | |||||
847 | Set unconfined=True to disable max-width confinement of the image. |
|
848 | Set unconfined=True to disable max-width confinement of the image. | |
848 | metadata : dict |
|
849 | metadata : dict | |
849 | Specify extra metadata to attach to the image. |
|
850 | Specify extra metadata to attach to the image. | |
|
851 | alt : unicode | |||
|
852 | Alternative text for the image, for use by screen readers. | |||
850 |
|
853 | |||
851 | Examples |
|
854 | Examples | |
852 | -------- |
|
855 | -------- | |
@@ -924,6 +927,7 b' class Image(DisplayObject):' | |||||
924 | self.height = height |
|
927 | self.height = height | |
925 | self.retina = retina |
|
928 | self.retina = retina | |
926 | self.unconfined = unconfined |
|
929 | self.unconfined = unconfined | |
|
930 | self.alt = alt | |||
927 | super(Image, self).__init__(data=data, url=url, filename=filename, |
|
931 | super(Image, self).__init__(data=data, url=url, filename=filename, | |
928 | metadata=metadata) |
|
932 | metadata=metadata) | |
929 |
|
933 | |||
@@ -933,6 +937,9 b' class Image(DisplayObject):' | |||||
933 | if self.height is None and self.metadata.get('height', {}): |
|
937 | if self.height is None and self.metadata.get('height', {}): | |
934 | self.height = metadata['height'] |
|
938 | self.height = metadata['height'] | |
935 |
|
939 | |||
|
940 | if self.alt is None and self.metadata.get('alt', {}): | |||
|
941 | self.alt = metadata['alt'] | |||
|
942 | ||||
936 | if retina: |
|
943 | if retina: | |
937 | self._retina_shape() |
|
944 | self._retina_shape() | |
938 |
|
945 | |||
@@ -962,18 +969,21 b' class Image(DisplayObject):' | |||||
962 |
|
969 | |||
963 | def _repr_html_(self): |
|
970 | def _repr_html_(self): | |
964 | if not self.embed: |
|
971 | if not self.embed: | |
965 | width = height = klass = '' |
|
972 | width = height = klass = alt = '' | |
966 | if self.width: |
|
973 | if self.width: | |
967 | width = ' width="%d"' % self.width |
|
974 | width = ' width="%d"' % self.width | |
968 | if self.height: |
|
975 | if self.height: | |
969 | height = ' height="%d"' % self.height |
|
976 | height = ' height="%d"' % self.height | |
970 | if self.unconfined: |
|
977 | if self.unconfined: | |
971 | klass = ' class="unconfined"' |
|
978 | klass = ' class="unconfined"' | |
972 | return u'<img src="{url}"{width}{height}{klass}/>'.format( |
|
979 | if self.alt: | |
|
980 | alt = ' alt="%s"' % html.escape(self.alt) | |||
|
981 | return u'<img src="{url}"{width}{height}{klass}{alt}/>'.format( | |||
973 | url=self.url, |
|
982 | url=self.url, | |
974 | width=width, |
|
983 | width=width, | |
975 | height=height, |
|
984 | height=height, | |
976 | klass=klass, |
|
985 | klass=klass, | |
|
986 | alt=alt, | |||
977 | ) |
|
987 | ) | |
978 |
|
988 | |||
979 | def _repr_mimebundle_(self, include=None, exclude=None): |
|
989 | def _repr_mimebundle_(self, include=None, exclude=None): | |
@@ -1006,6 +1016,8 b' class Image(DisplayObject):' | |||||
1006 | md['height'] = self.height |
|
1016 | md['height'] = self.height | |
1007 | if self.unconfined: |
|
1017 | if self.unconfined: | |
1008 | md['unconfined'] = self.unconfined |
|
1018 | md['unconfined'] = self.unconfined | |
|
1019 | if self.alt: | |||
|
1020 | md['alt'] = self.alt | |||
1009 | if md or always_both: |
|
1021 | if md or always_both: | |
1010 | return b64_data, md |
|
1022 | return b64_data, md | |
1011 | else: |
|
1023 | else: |
@@ -77,12 +77,12 b' def test_embed_svg_url():' | |||||
77 | from io import BytesIO |
|
77 | from io import BytesIO | |
78 | svg_data = b'<svg><circle x="0" y="0" r="1"/></svg>' |
|
78 | svg_data = b'<svg><circle x="0" y="0" r="1"/></svg>' | |
79 | url = 'http://test.com/circle.svg' |
|
79 | url = 'http://test.com/circle.svg' | |
80 |
|
80 | |||
81 | gzip_svg = BytesIO() |
|
81 | gzip_svg = BytesIO() | |
82 | with gzip.open(gzip_svg, 'wb') as fp: |
|
82 | with gzip.open(gzip_svg, 'wb') as fp: | |
83 | fp.write(svg_data) |
|
83 | fp.write(svg_data) | |
84 | gzip_svg = gzip_svg.getvalue() |
|
84 | gzip_svg = gzip_svg.getvalue() | |
85 |
|
85 | |||
86 | def mocked_urlopen(*args, **kwargs): |
|
86 | def mocked_urlopen(*args, **kwargs): | |
87 | class MockResponse: |
|
87 | class MockResponse: | |
88 | def __init__(self, svg): |
|
88 | def __init__(self, svg): | |
@@ -94,7 +94,7 b' def test_embed_svg_url():' | |||||
94 |
|
94 | |||
95 | if args[0] == url: |
|
95 | if args[0] == url: | |
96 | return MockResponse(svg_data) |
|
96 | return MockResponse(svg_data) | |
97 |
elif args[0] == url + 'z': |
|
97 | elif args[0] == url + 'z': | |
98 | ret= MockResponse(gzip_svg) |
|
98 | ret= MockResponse(gzip_svg) | |
99 | ret.headers['content-encoding']= 'gzip' |
|
99 | ret.headers['content-encoding']= 'gzip' | |
100 | return ret |
|
100 | return ret | |
@@ -105,7 +105,7 b' def test_embed_svg_url():' | |||||
105 | nt.assert_true(svg._repr_svg_().startswith('<svg')) |
|
105 | nt.assert_true(svg._repr_svg_().startswith('<svg')) | |
106 | svg = display.SVG(url=url + 'z') |
|
106 | svg = display.SVG(url=url + 'z') | |
107 | nt.assert_true(svg._repr_svg_().startswith('<svg')) |
|
107 | nt.assert_true(svg._repr_svg_().startswith('<svg')) | |
108 |
|
108 | |||
109 | def test_retina_jpeg(): |
|
109 | def test_retina_jpeg(): | |
110 | here = os.path.dirname(__file__) |
|
110 | here = os.path.dirname(__file__) | |
111 | img = display.Image(os.path.join(here, "2x2.jpg"), retina=True) |
|
111 | img = display.Image(os.path.join(here, "2x2.jpg"), retina=True) | |
@@ -457,3 +457,21 b' def test_display_handle():' | |||||
457 | 'update': True, |
|
457 | 'update': True, | |
458 | }) |
|
458 | }) | |
459 |
|
459 | |||
|
460 | def test_image_alt_tag(): | |||
|
461 | """Simple test for display.Image(args, alt=x,)""" | |||
|
462 | thisurl = 'http://example.com/image.png' | |||
|
463 | img = display.Image(url=thisurl, alt='an image') | |||
|
464 | nt.assert_equal(u'<img src="%s" alt="an image"/>' % (thisurl), img._repr_html_()) | |||
|
465 | img = display.Image(url=thisurl, unconfined=True, alt='an image') | |||
|
466 | nt.assert_equal(u'<img src="%s" class="unconfined" alt="an image"/>' % (thisurl), img._repr_html_()) | |||
|
467 | img = display.Image(url=thisurl, alt='>"& <') | |||
|
468 | nt.assert_equal(u'<img src="%s" alt=">"& <"/>' % (thisurl), img._repr_html_()) | |||
|
469 | ||||
|
470 | img = display.Image(url=thisurl, metadata={'alt':'an image'}) | |||
|
471 | nt.assert_equal(img.alt, 'an image') | |||
|
472 | ||||
|
473 | here = os.path.dirname(__file__) | |||
|
474 | img = display.Image(os.path.join(here, "2x2.png"), alt='an image') | |||
|
475 | nt.assert_equal(img.alt, 'an image') | |||
|
476 | _, md = img._repr_png_() | |||
|
477 | nt.assert_equal(md['alt'], 'an image') |
General Comments 0
You need to be logged in to leave comments.
Login now