##// END OF EJS Templates
Merge pull request #13143 from meeseeksmachine/auto-backport-of-pr-13133-on-7.x...
Blazej Michalik -
r26785:ecce8d31 merge
parent child Browse files
Show More
@@ -0,0 +1,37 b''
1 Enable to add extra attributes to iframe
2 ========================================
3
4 You can add any extra attributes to the ``<iframe>`` tag
5 since the argument ``extras`` has been added to the ``IFrame`` class.
6 for example::
7
8 In [1]: from IPython.display import IFrame
9
10 In [2]: print(IFrame(src="src", width=300, height=300, extras=["hello", "world"])._repr_html_())
11
12 <iframe
13 width="300"
14 height="300"
15 src="src"
16 frameborder="0"
17 allowfullscreen
18 hello world
19 ></iframe>
20
21 Using it, you can autoplay ``YouTubeVideo`` by adding ``'allow="autoplay"'``,
22 even in browsers that disable it by default, such as Google Chrome.
23 And, you can write it more briefly by using the argument ``allow_autoplay``.
24 ::
25
26 In [1]: from IPython.display import YouTubeVideo
27
28 In [2]: print(YouTubeVideo("video-id", allow_autoplay=True)._repr_html_())
29
30 <iframe
31 width="400"
32 height="300"
33 src="https://www.youtube.com/embed/video-id?autoplay=1"
34 frameborder="0"
35 allowfullscreen
36 allow="autoplay"
37 ></iframe>
@@ -1,655 +1,667 b''
1 1 """Various display related classes.
2 2
3 3 Authors : MinRK, gregcaporaso, dannystaple
4 4 """
5 5 from html import escape as html_escape
6 6 from os.path import exists, isfile, splitext, abspath, join, isdir
7 7 from os import walk, sep, fsdecode
8 8
9 9 from IPython.core.display import DisplayObject, TextDisplayObject
10 10
11 from typing import Tuple
11 from typing import Tuple, Iterable
12 12
13 13 __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument',
14 14 'FileLink', 'FileLinks', 'Code']
15 15
16 16
17 17 class Audio(DisplayObject):
18 18 """Create an audio object.
19 19
20 20 When this object is returned by an input cell or passed to the
21 21 display function, it will result in Audio controls being displayed
22 22 in the frontend (only works in the notebook).
23 23
24 24 Parameters
25 25 ----------
26 26 data : numpy array, list, unicode, str or bytes
27 27 Can be one of
28 28
29 29 * Numpy 1d array containing the desired waveform (mono)
30 30 * Numpy 2d array containing waveforms for each channel.
31 31 Shape=(NCHAN, NSAMPLES). For the standard channel order, see
32 32 http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
33 33 * List of float or integer representing the waveform (mono)
34 34 * String containing the filename
35 35 * Bytestring containing raw PCM data or
36 36 * URL pointing to a file on the web.
37 37
38 38 If the array option is used, the waveform will be normalized.
39 39
40 40 If a filename or url is used, the format support will be browser
41 41 dependent.
42 42 url : unicode
43 43 A URL to download the data from.
44 44 filename : unicode
45 45 Path to a local file to load the data from.
46 46 embed : boolean
47 47 Should the audio data be embedded using a data URI (True) or should
48 48 the original source be referenced. Set this to True if you want the
49 49 audio to playable later with no internet connection in the notebook.
50 50
51 51 Default is `True`, unless the keyword argument `url` is set, then
52 52 default value is `False`.
53 53 rate : integer
54 54 The sampling rate of the raw data.
55 55 Only required when data parameter is being used as an array
56 56 autoplay : bool
57 57 Set to True if the audio should immediately start playing.
58 58 Default is `False`.
59 59 normalize : bool
60 60 Whether audio should be normalized (rescaled) to the maximum possible
61 61 range. Default is `True`. When set to `False`, `data` must be between
62 62 -1 and 1 (inclusive), otherwise an error is raised.
63 63 Applies only when `data` is a list or array of samples; other types of
64 64 audio are never normalized.
65 65
66 66 Examples
67 67 --------
68 68 ::
69 69
70 70 # Generate a sound
71 71 import numpy as np
72 72 framerate = 44100
73 73 t = np.linspace(0,5,framerate*5)
74 74 data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t)
75 75 Audio(data,rate=framerate)
76 76
77 77 # Can also do stereo or more channels
78 78 dataleft = np.sin(2*np.pi*220*t)
79 79 dataright = np.sin(2*np.pi*224*t)
80 80 Audio([dataleft, dataright],rate=framerate)
81 81
82 82 Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # From URL
83 83 Audio(url="http://www.w3schools.com/html/horse.ogg")
84 84
85 85 Audio('/path/to/sound.wav') # From file
86 86 Audio(filename='/path/to/sound.ogg')
87 87
88 88 Audio(b'RAW_WAV_DATA..) # From bytes
89 89 Audio(data=b'RAW_WAV_DATA..)
90 90
91 91 See Also
92 92 --------
93 93
94 94 See also the ``Audio`` widgets form the ``ipywidget`` package for more flexibility and options.
95 95
96 96 """
97 97 _read_flags = 'rb'
98 98
99 99 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False, normalize=True, *,
100 100 element_id=None):
101 101 if filename is None and url is None and data is None:
102 102 raise ValueError("No audio data found. Expecting filename, url, or data.")
103 103 if embed is False and url is None:
104 104 raise ValueError("No url found. Expecting url when embed=False")
105 105
106 106 if url is not None and embed is not True:
107 107 self.embed = False
108 108 else:
109 109 self.embed = True
110 110 self.autoplay = autoplay
111 111 self.element_id = element_id
112 112 super(Audio, self).__init__(data=data, url=url, filename=filename)
113 113
114 114 if self.data is not None and not isinstance(self.data, bytes):
115 115 if rate is None:
116 116 raise ValueError("rate must be specified when data is a numpy array or list of audio samples.")
117 117 self.data = Audio._make_wav(data, rate, normalize)
118 118
119 119 def reload(self):
120 120 """Reload the raw data from file or URL."""
121 121 import mimetypes
122 122 if self.embed:
123 123 super(Audio, self).reload()
124 124
125 125 if self.filename is not None:
126 126 self.mimetype = mimetypes.guess_type(self.filename)[0]
127 127 elif self.url is not None:
128 128 self.mimetype = mimetypes.guess_type(self.url)[0]
129 129 else:
130 130 self.mimetype = "audio/wav"
131 131
132 132 @staticmethod
133 133 def _make_wav(data, rate, normalize):
134 134 """ Transform a numpy array to a PCM bytestring """
135 135 from io import BytesIO
136 136 import wave
137 137
138 138 try:
139 139 scaled, nchan = Audio._validate_and_normalize_with_numpy(data, normalize)
140 140 except ImportError:
141 141 scaled, nchan = Audio._validate_and_normalize_without_numpy(data, normalize)
142 142
143 143 fp = BytesIO()
144 144 waveobj = wave.open(fp,mode='wb')
145 145 waveobj.setnchannels(nchan)
146 146 waveobj.setframerate(rate)
147 147 waveobj.setsampwidth(2)
148 148 waveobj.setcomptype('NONE','NONE')
149 149 waveobj.writeframes(scaled)
150 150 val = fp.getvalue()
151 151 waveobj.close()
152 152
153 153 return val
154 154
155 155 @staticmethod
156 156 def _validate_and_normalize_with_numpy(data, normalize) -> Tuple[bytes, int]:
157 157 import numpy as np
158 158
159 159 data = np.array(data, dtype=float)
160 160 if len(data.shape) == 1:
161 161 nchan = 1
162 162 elif len(data.shape) == 2:
163 163 # In wave files,channels are interleaved. E.g.,
164 164 # "L1R1L2R2..." for stereo. See
165 165 # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
166 166 # for channel ordering
167 167 nchan = data.shape[0]
168 168 data = data.T.ravel()
169 169 else:
170 170 raise ValueError('Array audio input must be a 1D or 2D array')
171 171
172 172 max_abs_value = np.max(np.abs(data))
173 173 normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
174 174 scaled = data / normalization_factor * 32767
175 175 return scaled.astype("<h").tobytes(), nchan
176 176
177 177 @staticmethod
178 178 def _validate_and_normalize_without_numpy(data, normalize):
179 179 import array
180 180 import sys
181 181
182 182 data = array.array('f', data)
183 183
184 184 try:
185 185 max_abs_value = float(max([abs(x) for x in data]))
186 186 except TypeError:
187 187 raise TypeError('Only lists of mono audio are '
188 188 'supported if numpy is not installed')
189 189
190 190 normalization_factor = Audio._get_normalization_factor(max_abs_value, normalize)
191 191 scaled = array.array('h', [int(x / normalization_factor * 32767) for x in data])
192 192 if sys.byteorder == 'big':
193 193 scaled.byteswap()
194 194 nchan = 1
195 195 return scaled.tobytes(), nchan
196 196
197 197 @staticmethod
198 198 def _get_normalization_factor(max_abs_value, normalize):
199 199 if not normalize and max_abs_value > 1:
200 200 raise ValueError('Audio data must be between -1 and 1 when normalize=False.')
201 201 return max_abs_value if normalize else 1
202 202
203 203 def _data_and_metadata(self):
204 204 """shortcut for returning metadata with url information, if defined"""
205 205 md = {}
206 206 if self.url:
207 207 md['url'] = self.url
208 208 if md:
209 209 return self.data, md
210 210 else:
211 211 return self.data
212 212
213 213 def _repr_html_(self):
214 214 src = """
215 215 <audio {element_id} controls="controls" {autoplay}>
216 216 <source src="{src}" type="{type}" />
217 217 Your browser does not support the audio element.
218 218 </audio>
219 219 """
220 220 return src.format(src=self.src_attr(), type=self.mimetype, autoplay=self.autoplay_attr(),
221 221 element_id=self.element_id_attr())
222 222
223 223 def src_attr(self):
224 224 import base64
225 225 if self.embed and (self.data is not None):
226 226 data = base64=base64.b64encode(self.data).decode('ascii')
227 227 return """data:{type};base64,{base64}""".format(type=self.mimetype,
228 228 base64=data)
229 229 elif self.url is not None:
230 230 return self.url
231 231 else:
232 232 return ""
233 233
234 234 def autoplay_attr(self):
235 235 if(self.autoplay):
236 236 return 'autoplay="autoplay"'
237 237 else:
238 238 return ''
239 239
240 240 def element_id_attr(self):
241 241 if (self.element_id):
242 242 return 'id="{element_id}"'.format(element_id=self.element_id)
243 243 else:
244 244 return ''
245 245
246 246 class IFrame(object):
247 247 """
248 248 Generic class to embed an iframe in an IPython notebook
249 249 """
250 250
251 251 iframe = """
252 252 <iframe
253 253 width="{width}"
254 254 height="{height}"
255 255 src="{src}{params}"
256 256 frameborder="0"
257 257 allowfullscreen
258 {extras}
258 259 ></iframe>
259 260 """
260 261
261 def __init__(self, src, width, height, **kwargs):
262 def __init__(self, src, width, height, extras: Iterable[str] = None, **kwargs):
263 if extras is None:
264 extras = []
265
262 266 self.src = src
263 267 self.width = width
264 268 self.height = height
269 self.extras = extras
265 270 self.params = kwargs
266 271
267 272 def _repr_html_(self):
268 273 """return the embed iframe"""
269 274 if self.params:
270 275 try:
271 276 from urllib.parse import urlencode # Py 3
272 277 except ImportError:
273 278 from urllib import urlencode
274 279 params = "?" + urlencode(self.params)
275 280 else:
276 281 params = ""
277 return self.iframe.format(src=self.src,
278 width=self.width,
279 height=self.height,
280 params=params)
282 return self.iframe.format(
283 src=self.src,
284 width=self.width,
285 height=self.height,
286 params=params,
287 extras=" ".join(self.extras),
288 )
289
281 290
282 291 class YouTubeVideo(IFrame):
283 292 """Class for embedding a YouTube Video in an IPython session, based on its video id.
284 293
285 294 e.g. to embed the video from https://www.youtube.com/watch?v=foo , you would
286 295 do::
287 296
288 297 vid = YouTubeVideo("foo")
289 298 display(vid)
290 299
291 300 To start from 30 seconds::
292 301
293 302 vid = YouTubeVideo("abc", start=30)
294 303 display(vid)
295 304
296 305 To calculate seconds from time as hours, minutes, seconds use
297 306 :class:`datetime.timedelta`::
298 307
299 308 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
300 309
301 310 Other parameters can be provided as documented at
302 311 https://developers.google.com/youtube/player_parameters#Parameters
303 312
304 313 When converting the notebook using nbconvert, a jpeg representation of the video
305 314 will be inserted in the document.
306 315 """
307 316
308 def __init__(self, id, width=400, height=300, **kwargs):
317 def __init__(self, id, width=400, height=300, allow_autoplay=False, **kwargs):
309 318 self.id=id
310 319 src = "https://www.youtube.com/embed/{0}".format(id)
320 if allow_autoplay:
321 extras = list(kwargs.get("extras", [])) + ['allow="autoplay"']
322 kwargs.update(autoplay=1, extras=extras)
311 323 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
312
324
313 325 def _repr_jpeg_(self):
314 326 # Deferred import
315 327 from urllib.request import urlopen
316 328
317 329 try:
318 330 return urlopen("https://img.youtube.com/vi/{id}/hqdefault.jpg".format(id=self.id)).read()
319 331 except IOError:
320 332 return None
321 333
322 334 class VimeoVideo(IFrame):
323 335 """
324 336 Class for embedding a Vimeo video in an IPython session, based on its video id.
325 337 """
326 338
327 339 def __init__(self, id, width=400, height=300, **kwargs):
328 340 src="https://player.vimeo.com/video/{0}".format(id)
329 341 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
330 342
331 343 class ScribdDocument(IFrame):
332 344 """
333 345 Class for embedding a Scribd document in an IPython session
334 346
335 347 Use the start_page params to specify a starting point in the document
336 348 Use the view_mode params to specify display type one off scroll | slideshow | book
337 349
338 350 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
339 351
340 352 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
341 353 """
342 354
343 355 def __init__(self, id, width=400, height=300, **kwargs):
344 356 src="https://www.scribd.com/embeds/{0}/content".format(id)
345 357 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
346 358
347 359 class FileLink(object):
348 360 """Class for embedding a local file link in an IPython session, based on path
349 361
350 362 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
351 363
352 364 you would do::
353 365
354 366 local_file = FileLink("my/data.txt")
355 367 display(local_file)
356 368
357 369 or in the HTML notebook, just::
358 370
359 371 FileLink("my/data.txt")
360 372 """
361 373
362 374 html_link_str = "<a href='%s' target='_blank'>%s</a>"
363 375
364 376 def __init__(self,
365 377 path,
366 378 url_prefix='',
367 379 result_html_prefix='',
368 380 result_html_suffix='<br>'):
369 381 """
370 382 Parameters
371 383 ----------
372 384 path : str
373 385 path to the file or directory that should be formatted
374 386 url_prefix : str
375 387 prefix to be prepended to all files to form a working link [default:
376 388 '']
377 389 result_html_prefix : str
378 390 text to append to beginning to link [default: '']
379 391 result_html_suffix : str
380 392 text to append at the end of link [default: '<br>']
381 393 """
382 394 if isdir(path):
383 395 raise ValueError("Cannot display a directory using FileLink. "
384 396 "Use FileLinks to display '%s'." % path)
385 397 self.path = fsdecode(path)
386 398 self.url_prefix = url_prefix
387 399 self.result_html_prefix = result_html_prefix
388 400 self.result_html_suffix = result_html_suffix
389 401
390 402 def _format_path(self):
391 403 fp = ''.join([self.url_prefix, html_escape(self.path)])
392 404 return ''.join([self.result_html_prefix,
393 405 self.html_link_str % \
394 406 (fp, html_escape(self.path, quote=False)),
395 407 self.result_html_suffix])
396 408
397 409 def _repr_html_(self):
398 410 """return html link to file
399 411 """
400 412 if not exists(self.path):
401 413 return ("Path (<tt>%s</tt>) doesn't exist. "
402 414 "It may still be in the process of "
403 415 "being generated, or you may have the "
404 416 "incorrect path." % self.path)
405 417
406 418 return self._format_path()
407 419
408 420 def __repr__(self):
409 421 """return absolute path to file
410 422 """
411 423 return abspath(self.path)
412 424
413 425 class FileLinks(FileLink):
414 426 """Class for embedding local file links in an IPython session, based on path
415 427
416 428 e.g. to embed links to files that were generated in the IPython notebook
417 429 under ``my/data``, you would do::
418 430
419 431 local_files = FileLinks("my/data")
420 432 display(local_files)
421 433
422 434 or in the HTML notebook, just::
423 435
424 436 FileLinks("my/data")
425 437 """
426 438 def __init__(self,
427 439 path,
428 440 url_prefix='',
429 441 included_suffixes=None,
430 442 result_html_prefix='',
431 443 result_html_suffix='<br>',
432 444 notebook_display_formatter=None,
433 445 terminal_display_formatter=None,
434 446 recursive=True):
435 447 """
436 448 See :class:`FileLink` for the ``path``, ``url_prefix``,
437 449 ``result_html_prefix`` and ``result_html_suffix`` parameters.
438 450
439 451 included_suffixes : list
440 452 Filename suffixes to include when formatting output [default: include
441 453 all files]
442 454
443 455 notebook_display_formatter : function
444 456 Used to format links for display in the notebook. See discussion of
445 457 formatter functions below.
446 458
447 459 terminal_display_formatter : function
448 460 Used to format links for display in the terminal. See discussion of
449 461 formatter functions below.
450 462
451 463 Formatter functions must be of the form::
452 464
453 465 f(dirname, fnames, included_suffixes)
454 466
455 467 dirname : str
456 468 The name of a directory
457 469 fnames : list
458 470 The files in that directory
459 471 included_suffixes : list
460 472 The file suffixes that should be included in the output (passing None
461 473 meansto include all suffixes in the output in the built-in formatters)
462 474 recursive : boolean
463 475 Whether to recurse into subdirectories. Default is True.
464 476
465 477 The function should return a list of lines that will be printed in the
466 478 notebook (if passing notebook_display_formatter) or the terminal (if
467 479 passing terminal_display_formatter). This function is iterated over for
468 480 each directory in self.path. Default formatters are in place, can be
469 481 passed here to support alternative formatting.
470 482
471 483 """
472 484 if isfile(path):
473 485 raise ValueError("Cannot display a file using FileLinks. "
474 486 "Use FileLink to display '%s'." % path)
475 487 self.included_suffixes = included_suffixes
476 488 # remove trailing slashes for more consistent output formatting
477 489 path = path.rstrip('/')
478 490
479 491 self.path = path
480 492 self.url_prefix = url_prefix
481 493 self.result_html_prefix = result_html_prefix
482 494 self.result_html_suffix = result_html_suffix
483 495
484 496 self.notebook_display_formatter = \
485 497 notebook_display_formatter or self._get_notebook_display_formatter()
486 498 self.terminal_display_formatter = \
487 499 terminal_display_formatter or self._get_terminal_display_formatter()
488 500
489 501 self.recursive = recursive
490 502
491 503 def _get_display_formatter(self,
492 504 dirname_output_format,
493 505 fname_output_format,
494 506 fp_format,
495 507 fp_cleaner=None):
496 508 """ generate built-in formatter function
497 509
498 510 this is used to define both the notebook and terminal built-in
499 511 formatters as they only differ by some wrapper text for each entry
500 512
501 513 dirname_output_format: string to use for formatting directory
502 514 names, dirname will be substituted for a single "%s" which
503 515 must appear in this string
504 516 fname_output_format: string to use for formatting file names,
505 517 if a single "%s" appears in the string, fname will be substituted
506 518 if two "%s" appear in the string, the path to fname will be
507 519 substituted for the first and fname will be substituted for the
508 520 second
509 521 fp_format: string to use for formatting filepaths, must contain
510 522 exactly two "%s" and the dirname will be substituted for the first
511 523 and fname will be substituted for the second
512 524 """
513 525 def f(dirname, fnames, included_suffixes=None):
514 526 result = []
515 527 # begin by figuring out which filenames, if any,
516 528 # are going to be displayed
517 529 display_fnames = []
518 530 for fname in fnames:
519 531 if (isfile(join(dirname,fname)) and
520 532 (included_suffixes is None or
521 533 splitext(fname)[1] in included_suffixes)):
522 534 display_fnames.append(fname)
523 535
524 536 if len(display_fnames) == 0:
525 537 # if there are no filenames to display, don't print anything
526 538 # (not even the directory name)
527 539 pass
528 540 else:
529 541 # otherwise print the formatted directory name followed by
530 542 # the formatted filenames
531 543 dirname_output_line = dirname_output_format % dirname
532 544 result.append(dirname_output_line)
533 545 for fname in display_fnames:
534 546 fp = fp_format % (dirname,fname)
535 547 if fp_cleaner is not None:
536 548 fp = fp_cleaner(fp)
537 549 try:
538 550 # output can include both a filepath and a filename...
539 551 fname_output_line = fname_output_format % (fp, fname)
540 552 except TypeError:
541 553 # ... or just a single filepath
542 554 fname_output_line = fname_output_format % fname
543 555 result.append(fname_output_line)
544 556 return result
545 557 return f
546 558
547 559 def _get_notebook_display_formatter(self,
548 560 spacer="&nbsp;&nbsp;"):
549 561 """ generate function to use for notebook formatting
550 562 """
551 563 dirname_output_format = \
552 564 self.result_html_prefix + "%s/" + self.result_html_suffix
553 565 fname_output_format = \
554 566 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
555 567 fp_format = self.url_prefix + '%s/%s'
556 568 if sep == "\\":
557 569 # Working on a platform where the path separator is "\", so
558 570 # must convert these to "/" for generating a URI
559 571 def fp_cleaner(fp):
560 572 # Replace all occurrences of backslash ("\") with a forward
561 573 # slash ("/") - this is necessary on windows when a path is
562 574 # provided as input, but we must link to a URI
563 575 return fp.replace('\\','/')
564 576 else:
565 577 fp_cleaner = None
566 578
567 579 return self._get_display_formatter(dirname_output_format,
568 580 fname_output_format,
569 581 fp_format,
570 582 fp_cleaner)
571 583
572 584 def _get_terminal_display_formatter(self,
573 585 spacer=" "):
574 586 """ generate function to use for terminal formatting
575 587 """
576 588 dirname_output_format = "%s/"
577 589 fname_output_format = spacer + "%s"
578 590 fp_format = '%s/%s'
579 591
580 592 return self._get_display_formatter(dirname_output_format,
581 593 fname_output_format,
582 594 fp_format)
583 595
584 596 def _format_path(self):
585 597 result_lines = []
586 598 if self.recursive:
587 599 walked_dir = list(walk(self.path))
588 600 else:
589 601 walked_dir = [next(walk(self.path))]
590 602 walked_dir.sort()
591 603 for dirname, subdirs, fnames in walked_dir:
592 604 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
593 605 return '\n'.join(result_lines)
594 606
595 607 def __repr__(self):
596 608 """return newline-separated absolute paths
597 609 """
598 610 result_lines = []
599 611 if self.recursive:
600 612 walked_dir = list(walk(self.path))
601 613 else:
602 614 walked_dir = [next(walk(self.path))]
603 615 walked_dir.sort()
604 616 for dirname, subdirs, fnames in walked_dir:
605 617 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
606 618 return '\n'.join(result_lines)
607 619
608 620
609 621 class Code(TextDisplayObject):
610 622 """Display syntax-highlighted source code.
611 623
612 624 This uses Pygments to highlight the code for HTML and Latex output.
613 625
614 626 Parameters
615 627 ----------
616 628 data : str
617 629 The code as a string
618 630 url : str
619 631 A URL to fetch the code from
620 632 filename : str
621 633 A local filename to load the code from
622 634 language : str
623 635 The short name of a Pygments lexer to use for highlighting.
624 636 If not specified, it will guess the lexer based on the filename
625 637 or the code. Available lexers: http://pygments.org/docs/lexers/
626 638 """
627 639 def __init__(self, data=None, url=None, filename=None, language=None):
628 640 self.language = language
629 641 super().__init__(data=data, url=url, filename=filename)
630 642
631 643 def _get_lexer(self):
632 644 if self.language:
633 645 from pygments.lexers import get_lexer_by_name
634 646 return get_lexer_by_name(self.language)
635 647 elif self.filename:
636 648 from pygments.lexers import get_lexer_for_filename
637 649 return get_lexer_for_filename(self.filename)
638 650 else:
639 651 from pygments.lexers import guess_lexer
640 652 return guess_lexer(self.data)
641 653
642 654 def __repr__(self):
643 655 return self.data
644 656
645 657 def _repr_html_(self):
646 658 from pygments import highlight
647 659 from pygments.formatters import HtmlFormatter
648 660 fmt = HtmlFormatter()
649 661 style = '<style>{}</style>'.format(fmt.get_style_defs('.output_html'))
650 662 return style + highlight(self.data, self._get_lexer(), fmt)
651 663
652 664 def _repr_latex_(self):
653 665 from pygments import highlight
654 666 from pygments.formatters import LatexFormatter
655 667 return highlight(self.data, self._get_lexer(), LatexFormatter())
General Comments 0
You need to be logged in to leave comments. Login now