Show More
@@ -271,6 +271,24 b' def display_javascript(*objs, **kwargs):' | |||||
271 | """ |
|
271 | """ | |
272 | _display_mimetype('application/javascript', objs, **kwargs) |
|
272 | _display_mimetype('application/javascript', objs, **kwargs) | |
273 |
|
273 | |||
|
274 | ||||
|
275 | def display_pdf(*objs, **kwargs): | |||
|
276 | """Display the PDF representation of an object. | |||
|
277 | ||||
|
278 | Parameters | |||
|
279 | ---------- | |||
|
280 | objs : tuple of objects | |||
|
281 | The Python objects to display, or if raw=True raw javascript data to | |||
|
282 | display. | |||
|
283 | raw : bool | |||
|
284 | Are the data objects raw data or Python objects that need to be | |||
|
285 | formatted before display? [default: False] | |||
|
286 | metadata : dict (optional) | |||
|
287 | Metadata to be associated with the specific mimetype output. | |||
|
288 | """ | |||
|
289 | _display_mimetype('application/pdf', objs, **kwargs) | |||
|
290 | ||||
|
291 | ||||
274 | #----------------------------------------------------------------------------- |
|
292 | #----------------------------------------------------------------------------- | |
275 | # Smart classes |
|
293 | # Smart classes | |
276 | #----------------------------------------------------------------------------- |
|
294 | #----------------------------------------------------------------------------- |
@@ -93,6 +93,7 b' class DisplayFormatter(Configurable):' | |||||
93 | HTMLFormatter, |
|
93 | HTMLFormatter, | |
94 | SVGFormatter, |
|
94 | SVGFormatter, | |
95 | PNGFormatter, |
|
95 | PNGFormatter, | |
|
96 | PDFFormatter, | |||
96 | JPEGFormatter, |
|
97 | JPEGFormatter, | |
97 | LatexFormatter, |
|
98 | LatexFormatter, | |
98 | JSONFormatter, |
|
99 | JSONFormatter, | |
@@ -116,6 +117,7 b' class DisplayFormatter(Configurable):' | |||||
116 | * text/latex |
|
117 | * text/latex | |
117 | * application/json |
|
118 | * application/json | |
118 | * application/javascript |
|
119 | * application/javascript | |
|
120 | * application/pdf | |||
119 | * image/png |
|
121 | * image/png | |
120 | * image/jpeg |
|
122 | * image/jpeg | |
121 | * image/svg+xml |
|
123 | * image/svg+xml | |
@@ -766,11 +768,29 b' class JavascriptFormatter(BaseFormatter):' | |||||
766 |
|
768 | |||
767 | print_method = ObjectName('_repr_javascript_') |
|
769 | print_method = ObjectName('_repr_javascript_') | |
768 |
|
770 | |||
|
771 | ||||
|
772 | class PDFFormatter(BaseFormatter): | |||
|
773 | """A PDF formatter. | |||
|
774 | ||||
|
775 | To defined the callables that compute to PDF representation of your | |||
|
776 | objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type` | |||
|
777 | or :meth:`for_type_by_name` methods to register functions that handle | |||
|
778 | this. | |||
|
779 | ||||
|
780 | The return value of this formatter should be raw PDF data, *not* | |||
|
781 | base64 encoded. | |||
|
782 | """ | |||
|
783 | format_type = Unicode('application/pdf') | |||
|
784 | ||||
|
785 | print_method = ObjectName('_repr_pdf_') | |||
|
786 | ||||
|
787 | ||||
769 | FormatterABC.register(BaseFormatter) |
|
788 | FormatterABC.register(BaseFormatter) | |
770 | FormatterABC.register(PlainTextFormatter) |
|
789 | FormatterABC.register(PlainTextFormatter) | |
771 | FormatterABC.register(HTMLFormatter) |
|
790 | FormatterABC.register(HTMLFormatter) | |
772 | FormatterABC.register(SVGFormatter) |
|
791 | FormatterABC.register(SVGFormatter) | |
773 | FormatterABC.register(PNGFormatter) |
|
792 | FormatterABC.register(PNGFormatter) | |
|
793 | FormatterABC.register(PDFFormatter) | |||
774 | FormatterABC.register(JPEGFormatter) |
|
794 | FormatterABC.register(JPEGFormatter) | |
775 | FormatterABC.register(LatexFormatter) |
|
795 | FormatterABC.register(LatexFormatter) | |
776 | FormatterABC.register(JSONFormatter) |
|
796 | FormatterABC.register(JSONFormatter) | |
@@ -789,6 +809,7 b' def format_display_data(obj, include=None, exclude=None):' | |||||
789 | * text/latex |
|
809 | * text/latex | |
790 | * application/json |
|
810 | * application/json | |
791 | * application/javascript |
|
811 | * application/javascript | |
|
812 | * application/pdf | |||
792 | * image/png |
|
813 | * image/png | |
793 | * image/jpeg |
|
814 | * image/jpeg | |
794 | * image/svg+xml |
|
815 | * image/svg+xml |
@@ -8,7 +8,9 b' except:' | |||||
8 | numpy = None |
|
8 | numpy = None | |
9 | import nose.tools as nt |
|
9 | import nose.tools as nt | |
10 |
|
10 | |||
11 | from IPython.core.formatters import PlainTextFormatter, HTMLFormatter, _mod_name_key |
|
11 | from IPython.core.formatters import ( | |
|
12 | PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key | |||
|
13 | ) | |||
12 | from IPython.utils.io import capture_output |
|
14 | from IPython.utils.io import capture_output | |
13 |
|
15 | |||
14 | class A(object): |
|
16 | class A(object): | |
@@ -279,4 +281,11 b' def test_warn_error_pretty_method():' | |||||
279 | nt.assert_in("text/plain", captured.stderr) |
|
281 | nt.assert_in("text/plain", captured.stderr) | |
280 | nt.assert_in("argument", captured.stderr) |
|
282 | nt.assert_in("argument", captured.stderr) | |
281 |
|
283 | |||
|
284 | class MakePDF(object): | |||
|
285 | def _repr_pdf_(self): | |||
|
286 | return 'PDF' | |||
282 |
|
287 | |||
|
288 | def test_pdf_formatter(): | |||
|
289 | pdf = MakePDF() | |||
|
290 | f = PDFFormatter() | |||
|
291 | nt.assert_equal(f(pdf), 'PDF') |
@@ -119,6 +119,8 b" PNG64 = b'iVBORw0KG'" | |||||
119 | JPEG = b'\xff\xd8' |
|
119 | JPEG = b'\xff\xd8' | |
120 | # front of JPEG base64-encoded |
|
120 | # front of JPEG base64-encoded | |
121 | JPEG64 = b'/9' |
|
121 | JPEG64 = b'/9' | |
|
122 | # front of PDF base64-encoded | |||
|
123 | PDF64 = b'JVBER' | |||
122 |
|
124 | |||
123 | def encode_images(format_dict): |
|
125 | def encode_images(format_dict): | |
124 | """b64-encodes images in a displaypub format dict |
|
126 | """b64-encodes images in a displaypub format dict | |
@@ -136,7 +138,7 b' def encode_images(format_dict):' | |||||
136 |
|
138 | |||
137 | format_dict : dict |
|
139 | format_dict : dict | |
138 | A copy of the same dictionary, |
|
140 | A copy of the same dictionary, | |
139 |
but binary image data ('image/png' |
|
141 | but binary image data ('image/png', 'image/jpeg' or 'application/pdf') | |
140 | is base64-encoded. |
|
142 | is base64-encoded. | |
141 |
|
143 | |||
142 | """ |
|
144 | """ | |
@@ -156,6 +158,13 b' def encode_images(format_dict):' | |||||
156 | jpegdata = encodebytes(jpegdata) |
|
158 | jpegdata = encodebytes(jpegdata) | |
157 | encoded['image/jpeg'] = jpegdata.decode('ascii') |
|
159 | encoded['image/jpeg'] = jpegdata.decode('ascii') | |
158 |
|
160 | |||
|
161 | pdfdata = format_dict.get('application/pdf') | |||
|
162 | if isinstance(pdfdata, bytes): | |||
|
163 | # make sure we don't double-encode | |||
|
164 | if not pdfdata.startswith(PDF64): | |||
|
165 | pdfdata = encodebytes(pdfdata) | |||
|
166 | encoded['application/pdf'] = pdfdata.decode('ascii') | |||
|
167 | ||||
159 | return encoded |
|
168 | return encoded | |
160 |
|
169 | |||
161 |
|
170 |
@@ -69,10 +69,12 b' def test_encode_images():' | |||||
69 | # invalid data, but the header and footer are from real files |
|
69 | # invalid data, but the header and footer are from real files | |
70 | pngdata = b'\x89PNG\r\n\x1a\nblahblahnotactuallyvalidIEND\xaeB`\x82' |
|
70 | pngdata = b'\x89PNG\r\n\x1a\nblahblahnotactuallyvalidIEND\xaeB`\x82' | |
71 | jpegdata = b'\xff\xd8\xff\xe0\x00\x10JFIFblahblahjpeg(\xa0\x0f\xff\xd9' |
|
71 | jpegdata = b'\xff\xd8\xff\xe0\x00\x10JFIFblahblahjpeg(\xa0\x0f\xff\xd9' | |
|
72 | pdfdata = b'%PDF-1.\ntrailer<</Root<</Pages<</Kids[<</MediaBox[0 0 3 3]>>]>>>>>>' | |||
72 |
|
73 | |||
73 | fmt = { |
|
74 | fmt = { | |
74 | 'image/png' : pngdata, |
|
75 | 'image/png' : pngdata, | |
75 | 'image/jpeg' : jpegdata, |
|
76 | 'image/jpeg' : jpegdata, | |
|
77 | 'application/pdf' : pdfdata | |||
76 | } |
|
78 | } | |
77 | encoded = encode_images(fmt) |
|
79 | encoded = encode_images(fmt) | |
78 | for key, value in iteritems(fmt): |
|
80 | for key, value in iteritems(fmt): |
General Comments 0
You need to be logged in to leave comments.
Login now