##// END OF EJS Templates
Merge pull request #12864 from blois/alt_text...
Matthias Bussonnier -
r26828:59e313b1 merge
parent child Browse files
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
@@ -800,9 +801,20 b' class Image(DisplayObject):'
800 _FMT_GIF: 'image/gif',
801 _FMT_GIF: 'image/gif',
801 }
802 }
802
803
803 def __init__(self, data=None, url=None, filename=None, format=None,
804 def __init__(
804 embed=None, width=None, height=None, retina=False,
805 self,
805 unconfined=False, metadata=None):
806 data=None,
807 url=None,
808 filename=None,
809 format=None,
810 embed=None,
811 width=None,
812 height=None,
813 retina=False,
814 unconfined=False,
815 metadata=None,
816 alt=None,
817 ):
806 """Create a PNG/JPEG/GIF image object given raw data.
818 """Create a PNG/JPEG/GIF image object given raw data.
807
819
808 When this object is returned by an input cell or passed to the
820 When this object is returned by an input cell or passed to the
@@ -847,6 +859,8 b' class Image(DisplayObject):'
847 Set unconfined=True to disable max-width confinement of the image.
859 Set unconfined=True to disable max-width confinement of the image.
848 metadata : dict
860 metadata : dict
849 Specify extra metadata to attach to the image.
861 Specify extra metadata to attach to the image.
862 alt : unicode
863 Alternative text for the image, for use by screen readers.
850
864
851 Examples
865 Examples
852 --------
866 --------
@@ -924,6 +938,7 b' class Image(DisplayObject):'
924 self.height = height
938 self.height = height
925 self.retina = retina
939 self.retina = retina
926 self.unconfined = unconfined
940 self.unconfined = unconfined
941 self.alt = alt
927 super(Image, self).__init__(data=data, url=url, filename=filename,
942 super(Image, self).__init__(data=data, url=url, filename=filename,
928 metadata=metadata)
943 metadata=metadata)
929
944
@@ -933,6 +948,9 b' class Image(DisplayObject):'
933 if self.height is None and self.metadata.get('height', {}):
948 if self.height is None and self.metadata.get('height', {}):
934 self.height = metadata['height']
949 self.height = metadata['height']
935
950
951 if self.alt is None and self.metadata.get("alt", {}):
952 self.alt = metadata["alt"]
953
936 if retina:
954 if retina:
937 self._retina_shape()
955 self._retina_shape()
938
956
@@ -962,18 +980,21 b' class Image(DisplayObject):'
962
980
963 def _repr_html_(self):
981 def _repr_html_(self):
964 if not self.embed:
982 if not self.embed:
965 width = height = klass = ''
983 width = height = klass = alt = ""
966 if self.width:
984 if self.width:
967 width = ' width="%d"' % self.width
985 width = ' width="%d"' % self.width
968 if self.height:
986 if self.height:
969 height = ' height="%d"' % self.height
987 height = ' height="%d"' % self.height
970 if self.unconfined:
988 if self.unconfined:
971 klass = ' class="unconfined"'
989 klass = ' class="unconfined"'
972 return u'<img src="{url}"{width}{height}{klass}/>'.format(
990 if self.alt:
991 alt = ' alt="%s"' % html.escape(self.alt)
992 return '<img src="{url}"{width}{height}{klass}{alt}/>'.format(
973 url=self.url,
993 url=self.url,
974 width=width,
994 width=width,
975 height=height,
995 height=height,
976 klass=klass,
996 klass=klass,
997 alt=alt,
977 )
998 )
978
999
979 def _repr_mimebundle_(self, include=None, exclude=None):
1000 def _repr_mimebundle_(self, include=None, exclude=None):
@@ -1006,6 +1027,8 b' class Image(DisplayObject):'
1006 md['height'] = self.height
1027 md['height'] = self.height
1007 if self.unconfined:
1028 if self.unconfined:
1008 md['unconfined'] = self.unconfined
1029 md['unconfined'] = self.unconfined
1030 if self.alt:
1031 md["alt"] = self.alt
1009 if md or always_both:
1032 if md or always_both:
1010 return b64_data, md
1033 return b64_data, md
1011 else:
1034 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,9 +94,9 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
101 return MockResponse(None)
101 return MockResponse(None)
102
102
@@ -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)
@@ -460,6 +460,31 b' def test_display_handle():'
460 })
460 })
461
461
462
462
463 def test_image_alt_tag():
464 """Simple test for display.Image(args, alt=x,)"""
465 thisurl = "http://example.com/image.png"
466 img = display.Image(url=thisurl, alt="an image")
467 nt.assert_equal(u'<img src="%s" alt="an image"/>' % (thisurl), img._repr_html_())
468 img = display.Image(url=thisurl, unconfined=True, alt="an image")
469 nt.assert_equal(
470 u'<img src="%s" class="unconfined" alt="an image"/>' % (thisurl),
471 img._repr_html_(),
472 )
473 img = display.Image(url=thisurl, alt='>"& <')
474 nt.assert_equal(
475 u'<img src="%s" alt="&gt;&quot;&amp; &lt;"/>' % (thisurl), img._repr_html_()
476 )
477
478 img = display.Image(url=thisurl, metadata={"alt": "an image"})
479 nt.assert_equal(img.alt, "an image")
480
481 here = os.path.dirname(__file__)
482 img = display.Image(os.path.join(here, "2x2.png"), alt="an image")
483 nt.assert_equal(img.alt, "an image")
484 _, md = img._repr_png_()
485 nt.assert_equal(md["alt"], "an image")
486
487
463 @nt.raises(FileNotFoundError)
488 @nt.raises(FileNotFoundError)
464 def test_image_bad_filename_raises_proper_exception():
489 def test_image_bad_filename_raises_proper_exception():
465 display.Image("/this/file/does/not/exist/")._repr_png_()
490 display.Image("/this/file/does/not/exist/")._repr_png_()
General Comments 0
You need to be logged in to leave comments. Login now