##// END OF EJS Templates
Merge pull request #9551 from SylvainCorlay/sphinxify...
Matthias Bussonnier -
r22499:3c35fa32 merge
parent child Browse files
Show More
@@ -73,8 +73,8 b' from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,'
73 with_metaclass, iteritems)
73 with_metaclass, iteritems)
74 from IPython.utils.strdispatch import StrDispatch
74 from IPython.utils.strdispatch import StrDispatch
75 from IPython.utils.syspathcontext import prepended_to_syspath
75 from IPython.utils.syspathcontext import prepended_to_syspath
76 from IPython.utils.text import (format_screen, LSString, SList,
76 from IPython.utils.text import format_screen, LSString, SList, DollarFormatter
77 DollarFormatter)
77 from IPython.utils.tempdir import TemporaryDirectory
78 from traitlets import (
78 from traitlets import (
79 Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type,
79 Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type,
80 observe, default,
80 observe, default,
@@ -83,6 +83,18 b' from warnings import warn'
83 from logging import error
83 from logging import error
84 import IPython.core.hooks
84 import IPython.core.hooks
85
85
86 try:
87 import docrepr.sphinxify as sphx
88
89 def sphinxify(doc):
90 with TemporaryDirectory() as dirname:
91 return {
92 'text/html': sphx.sphinxify(doc, dirname),
93 'text/plain': doc
94 }
95 except ImportError:
96 sphinxify = None
97
86 #-----------------------------------------------------------------------------
98 #-----------------------------------------------------------------------------
87 # Globals
99 # Globals
88 #-----------------------------------------------------------------------------
100 #-----------------------------------------------------------------------------
@@ -265,6 +277,16 b' class InteractiveShell(SingletonConfigurable):'
265 display_formatter = Instance(DisplayFormatter, allow_none=True)
277 display_formatter = Instance(DisplayFormatter, allow_none=True)
266 displayhook_class = Type(DisplayHook)
278 displayhook_class = Type(DisplayHook)
267 display_pub_class = Type(DisplayPublisher)
279 display_pub_class = Type(DisplayPublisher)
280 sphinxify_docstring = Bool(False, help=
281 """
282 Enables rich html representation of docstrings. (This requires the
283 docrepr module).
284 """).tag(config=True)
285 enable_html_pager = Bool(False, help=
286 """
287 (Provisional API) enables html representation in mime bundles sent
288 to pagers.
289 """).tag(config=True)
268 data_pub_class = None
290 data_pub_class = None
269
291
270 exit_now = Bool(False)
292 exit_now = Bool(False)
@@ -281,12 +303,12 b' class InteractiveShell(SingletonConfigurable):'
281 # is ready to be executed.
303 # is ready to be executed.
282 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
304 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
283 (), {'line_input_checker': True})
305 (), {'line_input_checker': True})
284
306
285 # This InputSplitter instance is used to transform completed cells before
307 # This InputSplitter instance is used to transform completed cells before
286 # running them. It allows cell magics to contain blank lines.
308 # running them. It allows cell magics to contain blank lines.
287 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
309 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
288 (), {'line_input_checker': False})
310 (), {'line_input_checker': False})
289
311
290 logstart = Bool(False, help=
312 logstart = Bool(False, help=
291 """
313 """
292 Start logging to the default log file in overwrite mode.
314 Start logging to the default log file in overwrite mode.
@@ -341,11 +363,11 b' class InteractiveShell(SingletonConfigurable):'
341 name=name)
363 name=name)
342 )
364 )
343 # protect against weird cases where self.config may not exist:
365 # protect against weird cases where self.config may not exist:
344
366
345 show_rewritten_input = Bool(True,
367 show_rewritten_input = Bool(True,
346 help="Show rewritten input, e.g. for autocall."
368 help="Show rewritten input, e.g. for autocall."
347 ).tag(config=True)
369 ).tag(config=True)
348
370
349 quiet = Bool(False).tag(config=True)
371 quiet = Bool(False).tag(config=True)
350
372
351 history_length = Integer(10000,
373 history_length = Integer(10000,
@@ -1358,7 +1380,7 b' class InteractiveShell(SingletonConfigurable):'
1358 user_ns_hidden.pop(name, None)
1380 user_ns_hidden.pop(name, None)
1359 else:
1381 else:
1360 user_ns_hidden.update(vdict)
1382 user_ns_hidden.update(vdict)
1361
1383
1362 def drop_by_id(self, variables):
1384 def drop_by_id(self, variables):
1363 """Remove a dict of variables from the user namespace, if they are the
1385 """Remove a dict of variables from the user namespace, if they are the
1364 same as the values in the dictionary.
1386 same as the values in the dictionary.
@@ -1524,15 +1546,20 b' class InteractiveShell(SingletonConfigurable):'
1524 def _inspect(self, meth, oname, namespaces=None, **kw):
1546 def _inspect(self, meth, oname, namespaces=None, **kw):
1525 """Generic interface to the inspector system.
1547 """Generic interface to the inspector system.
1526
1548
1527 This function is meant to be called by pdef, pdoc & friends."""
1549 This function is meant to be called by pdef, pdoc & friends.
1550 """
1528 info = self._object_find(oname, namespaces)
1551 info = self._object_find(oname, namespaces)
1552 docformat = sphinxify if self.sphinxify_docstring else None
1529 if info.found:
1553 if info.found:
1530 pmethod = getattr(self.inspector, meth)
1554 pmethod = getattr(self.inspector, meth)
1531 formatter = format_screen if info.ismagic else None
1555 # TODO: only apply format_screen to the plain/text repr of the mime
1556 # bundle.
1557 formatter = format_screen if info.ismagic else docformat
1532 if meth == 'pdoc':
1558 if meth == 'pdoc':
1533 pmethod(info.obj, oname, formatter)
1559 pmethod(info.obj, oname, formatter)
1534 elif meth == 'pinfo':
1560 elif meth == 'pinfo':
1535 pmethod(info.obj, oname, formatter, info, **kw)
1561 pmethod(info.obj, oname, formatter, info,
1562 enable_html_pager=self.enable_html_pager, **kw)
1536 else:
1563 else:
1537 pmethod(info.obj, oname)
1564 pmethod(info.obj, oname)
1538 else:
1565 else:
@@ -1555,7 +1582,7 b' class InteractiveShell(SingletonConfigurable):'
1555 with self.builtin_trap:
1582 with self.builtin_trap:
1556 info = self._object_find(oname)
1583 info = self._object_find(oname)
1557 if info.found:
1584 if info.found:
1558 return self.inspector._format_info(info.obj, oname, info=info,
1585 return self.inspector._get_info(info.obj, oname, info=info,
1559 detail_level=detail_level
1586 detail_level=detail_level
1560 )
1587 )
1561 else:
1588 else:
@@ -17,6 +17,7 b" __all__ = ['Inspector','InspectColors']"
17 # stdlib modules
17 # stdlib modules
18 import inspect
18 import inspect
19 import linecache
19 import linecache
20 import warnings
20 import os
21 import os
21 from textwrap import dedent
22 from textwrap import dedent
22 import types
23 import types
@@ -43,6 +44,13 b' from IPython.utils.py3compat import cast_unicode, string_types, PY3'
43 from IPython.utils.signatures import signature
44 from IPython.utils.signatures import signature
44 from IPython.utils.colorable import Colorable
45 from IPython.utils.colorable import Colorable
45
46
47 from pygments import highlight
48 from pygments.lexers import PythonLexer
49 from pygments.formatters import HtmlFormatter
50
51 def pylight(code):
52 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
53
46 # builtin docstrings to ignore
54 # builtin docstrings to ignore
47 _func_call_docstring = types.FunctionType.__call__.__doc__
55 _func_call_docstring = types.FunctionType.__call__.__doc__
48 _object_init_docstring = object.__init__.__doc__
56 _object_init_docstring = object.__init__.__doc__
@@ -112,7 +120,8 b' def getdoc(obj):'
112
120
113 It also attempts to call a getdoc() method on the given object. This
121 It also attempts to call a getdoc() method on the given object. This
114 allows objects which provide their docstrings via non-standard mechanisms
122 allows objects which provide their docstrings via non-standard mechanisms
115 (like Pyro proxies) to still be inspected by ipython's ? system."""
123 (like Pyro proxies) to still be inspected by ipython's ? system.
124 """
116 # Allow objects to offer customized documentation via a getdoc method:
125 # Allow objects to offer customized documentation via a getdoc method:
117 try:
126 try:
118 ds = obj.getdoc()
127 ds = obj.getdoc()
@@ -122,14 +131,13 b' def getdoc(obj):'
122 # if we get extra info, we add it to the normal docstring.
131 # if we get extra info, we add it to the normal docstring.
123 if isinstance(ds, string_types):
132 if isinstance(ds, string_types):
124 return inspect.cleandoc(ds)
133 return inspect.cleandoc(ds)
125
126 try:
134 try:
127 docstr = inspect.getdoc(obj)
135 docstr = inspect.getdoc(obj)
128 encoding = get_encoding(obj)
136 encoding = get_encoding(obj)
129 return py3compat.cast_unicode(docstr, encoding=encoding)
137 return py3compat.cast_unicode(docstr, encoding=encoding)
130 except Exception:
138 except Exception:
131 # Harden against an inspect failure, which can occur with
139 # Harden against an inspect failure, which can occur with
132 # SWIG-wrapped extensions.
140 # extensions modules.
133 raise
141 raise
134 return None
142 return None
135
143
@@ -364,12 +372,12 b' def find_source_lines(obj):'
364
372
365 return lineno
373 return lineno
366
374
367
368 class Inspector(Colorable):
375 class Inspector(Colorable):
376
369 def __init__(self, color_table=InspectColors,
377 def __init__(self, color_table=InspectColors,
370 code_color_table=PyColorize.ANSICodeColors,
378 code_color_table=PyColorize.ANSICodeColors,
371 scheme='NoColor',
379 scheme='NoColor',
372 str_detail_level=0,
380 str_detail_level=0,
373 parent=None, config=None):
381 parent=None, config=None):
374 super(Inspector, self).__init__(parent=parent, config=config)
382 super(Inspector, self).__init__(parent=parent, config=config)
375 self.color_table = color_table
383 self.color_table = color_table
@@ -430,7 +438,7 b' class Inspector(Colorable):'
430
438
431 # In Python 3, all classes are new-style, so they all have __init__.
439 # In Python 3, all classes are new-style, so they all have __init__.
432 @skip_doctest_py3
440 @skip_doctest_py3
433 def pdoc(self,obj,oname='',formatter = None):
441 def pdoc(self, obj, oname='', formatter=None):
434 """Print the docstring for any object.
442 """Print the docstring for any object.
435
443
436 Optional:
444 Optional:
@@ -468,7 +476,7 b' class Inspector(Colorable):'
468 lines = []
476 lines = []
469 ds = getdoc(obj)
477 ds = getdoc(obj)
470 if formatter:
478 if formatter:
471 ds = formatter(ds)
479 ds = formatter(ds).get('plain/text', ds)
472 if ds:
480 if ds:
473 lines.append(head("Class docstring:"))
481 lines.append(head("Class docstring:"))
474 lines.append(indent(ds))
482 lines.append(indent(ds))
@@ -505,7 +513,7 b' class Inspector(Colorable):'
505
513
506 def pfile(self, obj, oname=''):
514 def pfile(self, obj, oname=''):
507 """Show the whole file where an object was defined."""
515 """Show the whole file where an object was defined."""
508
516
509 lineno = find_source_lines(obj)
517 lineno = find_source_lines(obj)
510 if lineno is None:
518 if lineno is None:
511 self.noinfo('file', oname)
519 self.noinfo('file', oname)
@@ -541,118 +549,171 b' class Inspector(Colorable):'
541 title_width = max(len(title) + 2 for title, _ in fields)
549 title_width = max(len(title) + 2 for title, _ in fields)
542 for title, content in fields:
550 for title, content in fields:
543 if len(content.splitlines()) > 1:
551 if len(content.splitlines()) > 1:
544 title = header(title + ":") + "\n"
552 title = header(title + ':') + '\n'
545 else:
553 else:
546 title = header((title+":").ljust(title_width))
554 title = header((title + ':').ljust(title_width))
547 out.append(cast_unicode(title) + cast_unicode(content))
555 out.append(cast_unicode(title) + cast_unicode(content))
548 return "\n".join(out)
556 return "\n".join(out)
549
557
550 def _format_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
558 def _mime_format(self, text, formatter=None):
551 """Format an info dict as text"""
559 """Return a mime bundle representation of the input text.
552 info = self.info(obj, oname=oname, formatter=formatter,
560
553 info=info, detail_level=detail_level)
561 - if `formatter` is None, the returned mime bundle has
554 displayfields = []
562 a `text/plain` field, with the input text.
555 def add_fields(fields):
563 a `text/html` field with a `<pre>` tag containing the input text.
556 for title, key in fields:
564
557 field = info[key]
565 - if `formatter` is not None, it must be a callable transforming the
558 if field is not None:
566 input text into a mime bundle. Default values for `text/plain` and
559 if key == "source":
567 `text/html` representations are the ones described above.
560 displayfields.append((title, self.format(cast_unicode(field.rstrip()))))
568
561 else:
569 Note:
562 displayfields.append((title, field.rstrip()))
570
571 Formatters returning strings are supported but this behavior is deprecated.
572
573 """
574 text = cast_unicode(text)
575 defaults = {
576 'text/plain': text,
577 'text/html': '<pre>' + text + '</pre>'
578 }
579
580 if formatter is None:
581 return defaults
582 else:
583 formatted = formatter(text)
584
585 if not isinstance(formatted, dict):
586 # Handle the deprecated behavior of a formatter returning
587 # a string instead of a mime bundle.
588 return {
589 'text/plain': formatted,
590 'text/html': '<pre>' + formatted + '</pre>'
591 }
592
593 else:
594 return dict(defaults, **formatted)
595
596 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
597 """Retrieve an info dict and format it."""
598
599 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
600
601 mime = {
602 'text/plain': '',
603 'text/html': '',
604 }
605
606 def append_field(bundle, title, key, formatter=None):
607 field = info[key]
608 if field is not None:
609 formatted_field = self._mime_format(field, formatter)
610 bundle['text/plain'] += self.__head(title) + ':\n' + formatted_field['text/plain'] + '\n'
611 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
612
613 def code_formatter(text):
614 return {
615 'text/plain': self.format(text),
616 'text/html': pylight(text)
617 }
563
618
564 if info['isalias']:
619 if info['isalias']:
565 add_fields([('Repr', "string_form")])
620 append_field(mime, 'Repr', 'string_form')
566
621
567 elif info['ismagic']:
622 elif info['ismagic']:
568 if detail_level > 0 and info['source'] is not None:
623 if detail_level > 0:
569 add_fields([("Source", "source")])
624 append_field(mime, 'Source', 'source', code_formatter)
570 else:
625 else:
571 add_fields([("Docstring", "docstring")])
626 append_field(mime, 'Docstring', 'docstring', formatter)
572
627 append_field(mime, 'File', 'file')
573 add_fields([("File", "file"),
574 ])
575
628
576 elif info['isclass'] or is_simple_callable(obj):
629 elif info['isclass'] or is_simple_callable(obj):
577 # Functions, methods, classes
630 # Functions, methods, classes
578 add_fields([("Signature", "definition"),
631 append_field(mime, 'Signature', 'definition', code_formatter)
579 ("Init signature", "init_definition"),
632 append_field(mime, 'Init signature', 'init_definition', code_formatter)
580 ])
633 if detail_level > 0:
581 if detail_level > 0 and info['source'] is not None:
634 append_field(mime, 'Source', 'source', code_formatter)
582 add_fields([("Source", "source")])
583 else:
635 else:
584 add_fields([("Docstring", "docstring"),
636 append_field(mime, 'Docstring', 'docstring', formatter)
585 ("Init docstring", "init_docstring"),
637 append_field(mime, 'Init docstring', 'init_docstring', formatter)
586 ])
587
638
588 add_fields([('File', 'file'),
639 append_field(mime, 'File', 'file')
589 ('Type', 'type_name'),
640 append_field(mime, 'Type', 'type_name')
590 ])
591
641
592 else:
642 else:
593 # General Python objects
643 # General Python objects
594 add_fields([("Type", "type_name")])
644 append_field(mime, 'Type', 'type_name')
595
645
596 # Base class for old-style instances
646 # Base class for old-style instances
597 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
647 if (not py3compat.PY3) and isinstance(obj, types.InstanceType) and info['base_class']:
598 displayfields.append(("Base Class", info['base_class'].rstrip()))
648 append_field(mime, 'Base Class', 'base_class')
599
649
600 add_fields([("String form", "string_form")])
650 append_field(mime, 'String form', 'string_form')
601
651
602 # Namespace
652 # Namespace
603 if info['namespace'] != 'Interactive':
653 if info['namespace'] != 'Interactive':
604 displayfields.append(("Namespace", info['namespace'].rstrip()))
654 append_field(mime, 'Namespace', 'namespace')
605
655
606 add_fields([("Length", "length"),
656 append_field(mime, 'Length', 'length')
607 ("File", "file"),
657 append_field(mime, 'File', 'file'),
608 ("Signature", "definition"),
658 append_field(mime, 'Signature', 'definition', code_formatter)
609 ])
610
659
611 # Source or docstring, depending on detail level and whether
660 # Source or docstring, depending on detail level and whether
612 # source found.
661 # source found.
613 if detail_level > 0 and info['source'] is not None:
662 if detail_level > 0:
614 displayfields.append(("Source",
663 append_field(mime, 'Source', 'source', code_formatter)
615 self.format(cast_unicode(info['source']))))
664 else:
616 elif info['docstring'] is not None:
665 append_field(mime, 'Docstring', 'docstring', formatter)
617 displayfields.append(("Docstring", info["docstring"]))
666
618
667 append_field(mime, 'Class docstring', 'class_docstring', formatter)
619 add_fields([("Class docstring", "class_docstring"),
668 append_field(mime, 'Init docstring', 'init_docstring', formatter)
620 ("Init docstring", "init_docstring"),
669 append_field(mime, 'Call signature', 'call_def', code_formatter)
621 ("Call signature", "call_def"),
670 append_field(mime, 'Call docstring', 'call_docstring', formatter)
622 ("Call docstring", "call_docstring")])
671
623
672 return mime
624 if displayfields:
673
625 return self._format_fields(displayfields)
674 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
626 else:
627 return u''
628
629 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0):
630 """Show detailed information about an object.
675 """Show detailed information about an object.
631
676
632 Optional arguments:
677 Optional arguments:
633
678
634 - oname: name of the variable pointing to the object.
679 - oname: name of the variable pointing to the object.
635
680
636 - formatter: special formatter for docstrings (see pdoc)
681 - formatter: callable (optional)
682 A special formatter for docstrings.
683
684 The formatter is a callable that takes a string as an input
685 and returns either a formatted string or a mime type bundle
686 in the form of a dictionnary.
687
688 Although the support of custom formatter returning a string
689 instead of a mime type bundle is deprecated.
637
690
638 - info: a structure with some information fields which may have been
691 - info: a structure with some information fields which may have been
639 precomputed already.
692 precomputed already.
640
693
641 - detail_level: if set to 1, more information is given.
694 - detail_level: if set to 1, more information is given.
642 """
695 """
643 text = self._format_info(obj, oname, formatter, info, detail_level)
696 info = self._get_info(obj, oname, formatter, info, detail_level)
644 if text:
697 if not enable_html_pager:
645 page.page(text)
698 del info['text/html']
646
699 page.page(info)
700
647 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
701 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
702 """DEPRECATED. Compute a dict with detailed information about an object.
703 """
704 if formatter is not None:
705 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
706 'is deprecated as of IPython 5.0 and will have no effects.',
707 DeprecationWarning, stacklevel=2)
708 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
709
710 def _info(self, obj, oname='', info=None, detail_level=0):
648 """Compute a dict with detailed information about an object.
711 """Compute a dict with detailed information about an object.
649
712
650 Optional arguments:
713 Optional arguments:
651
714
652 - oname: name of the variable pointing to the object.
715 - oname: name of the variable pointing to the object.
653
716
654 - formatter: special formatter for docstrings (see pdoc)
655
656 - info: a structure with some information fields which may have been
717 - info: a structure with some information fields which may have been
657 precomputed already.
718 precomputed already.
658
719
@@ -685,14 +746,12 b' class Inspector(Colorable):'
685 ds = getdoc(obj)
746 ds = getdoc(obj)
686 if ds is None:
747 if ds is None:
687 ds = '<no docstring>'
748 ds = '<no docstring>'
688 if formatter is not None:
689 ds = formatter(ds)
690
749
691 # store output in a dict, we initialize it here and fill it as we go
750 # store output in a dict, we initialize it here and fill it as we go
692 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
751 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
693
752
694 string_max = 200 # max size of strings to show (snipped if longer)
753 string_max = 200 # max size of strings to show (snipped if longer)
695 shalf = int((string_max -5)/2)
754 shalf = int((string_max - 5) / 2)
696
755
697 if ismagic:
756 if ismagic:
698 obj_type_name = 'Magic function'
757 obj_type_name = 'Magic function'
@@ -793,7 +852,7 b' class Inspector(Colorable):'
793 # reconstruct the function definition and print it:
852 # reconstruct the function definition and print it:
794 defln = self._getdef(obj, oname)
853 defln = self._getdef(obj, oname)
795 if defln:
854 if defln:
796 out['definition'] = self.format(defln)
855 out['definition'] = defln
797
856
798 # First, check whether the instance docstring is identical to the
857 # First, check whether the instance docstring is identical to the
799 # class one, and print it separately if they don't coincide. In
858 # class one, and print it separately if they don't coincide. In
@@ -826,12 +885,10 b' class Inspector(Colorable):'
826 # Call form docstring for callable instances
885 # Call form docstring for callable instances
827 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
886 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
828 call_def = self._getdef(obj.__call__, oname)
887 call_def = self._getdef(obj.__call__, oname)
829 if call_def:
888 if call_def and (call_def != out.get('definition')):
830 call_def = self.format(call_def)
831 # it may never be the case that call def and definition differ,
889 # it may never be the case that call def and definition differ,
832 # but don't include the same signature twice
890 # but don't include the same signature twice
833 if call_def != out.get('definition'):
891 out['call_def'] = call_def
834 out['call_def'] = call_def
835 call_ds = getdoc(obj.__call__)
892 call_ds = getdoc(obj.__call__)
836 # Skip Python's auto-generated docstrings
893 # Skip Python's auto-generated docstrings
837 if call_ds == _func_call_docstring:
894 if call_ds == _func_call_docstring:
@@ -38,7 +38,7 b' def display_page(strng, start=0, screen_lines=25):'
38 else:
38 else:
39 if start:
39 if start:
40 strng = u'\n'.join(strng.splitlines()[start:])
40 strng = u'\n'.join(strng.splitlines()[start:])
41 data = {'text/plain': strng}
41 data = { 'text/plain': strng }
42 display(data, raw=True)
42 display(data, raw=True)
43
43
44
44
@@ -56,8 +56,10 b' def page_dumb(strng, start=0, screen_lines=25):'
56 """Very dumb 'pager' in Python, for when nothing else works.
56 """Very dumb 'pager' in Python, for when nothing else works.
57
57
58 Only moves forward, same interface as page(), except for pager_cmd and
58 Only moves forward, same interface as page(), except for pager_cmd and
59 mode."""
59 mode.
60
60 """
61 if isinstance(strng, dict):
62 strng = strng.get('text/plain', '')
61 out_ln = strng.splitlines()[start:]
63 out_ln = strng.splitlines()[start:]
62 screens = chop(out_ln,screen_lines-1)
64 screens = chop(out_ln,screen_lines-1)
63 if len(screens) == 1:
65 if len(screens) == 1:
@@ -341,13 +341,13 b' if py3compat.PY3:'
341 @skipif(not py3compat.PY3)
341 @skipif(not py3compat.PY3)
342 def test_definition_kwonlyargs():
342 def test_definition_kwonlyargs():
343 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
343 i = inspector.info(f_kwarg, oname='f_kwarg') # analysis:ignore
344 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)\n")
344 nt.assert_equal(i['definition'], "f_kwarg(pos, *, kwonly)")
345
345
346 def test_getdoc():
346 def test_getdoc():
347 class A(object):
347 class A(object):
348 """standard docstring"""
348 """standard docstring"""
349 pass
349 pass
350
350
351 class B(object):
351 class B(object):
352 """standard docstring"""
352 """standard docstring"""
353 def getdoc(self):
353 def getdoc(self):
@@ -20,7 +20,6 b' from __future__ import print_function'
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 # stdlib
22 # stdlib
23 import os
24 import sys
23 import sys
25
24
26 # our own
25 # our own
@@ -141,6 +140,8 b' def start_ipython():'
141
140
142 # Override paging, so we don't require user interaction during the tests.
141 # Override paging, so we don't require user interaction during the tests.
143 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
142 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
143 if isinstance(strng, dict):
144 strng = strng.get('text/plain', '')
144 print(strng)
145 print(strng)
145
146
146 page.orig_page = page.pager_page
147 page.orig_page = page.pager_page
@@ -41,3 +41,46 b' IPython itself.'
41 the `PromptManager` class have been removed, and the prompt machinery simplified.
41 the `PromptManager` class have been removed, and the prompt machinery simplified.
42 See `TerminalINteractiveShell.prompts` configurable for how to setup your prompts.
42 See `TerminalINteractiveShell.prompts` configurable for how to setup your prompts.
43
43
44
45
46 Provisional Changes
47 -------------------
48
49 Provisional changes are in experimental functionality that may, or may not make
50 it to future version of IPython, and which API may change without warnings.
51 Activating these feature and using these API is at your own risk, and may have
52 security implication for your system, especially if used with the Jupyter notebook,
53
54 When running via the Jupyter notebook interfaces, or other compatible client,
55 you can enable rich documentation experimental functionality:
56
57 When the ``docrepr`` package is installed setting the boolean flag
58 ``InteractiveShell.sphinxify_docstring`` to ``True``, will process the various
59 object through sphinx before displaying them (see the ``docrepr`` package
60 documentation for more information.
61
62 You need to also enable the IPython pager display rich HTML representation
63 using the ``InteractiveShell.enable_html_pager`` boolean configuration option.
64 As usual you can set these configuration options globally in your configuration
65 files, alternatively you can turn them on dynamically using the following
66 snippet:
67
68 .. code-block:: python
69
70 ip = get_ipython()
71 ip.sphinxify_docstring = True
72 ip.enable_html_pager = True
73
74 You can test the effect of various combinations of the above configuration in
75 the Jupyter notebook, with things example like :
76
77 .. code-block:: python
78
79 import numpy as np
80 np.histogram?
81
82 This is part of an effort to make Documentation in Python richer and provide in
83 the long term if possible dynamic examples that can contain math, images,
84 widgets... As stated above this is nightly experimental feature with a lot of
85 (fun) problem to solve. We would be happy to get your feedback and expertise on
86 it.
General Comments 0
You need to be logged in to leave comments. Login now