Show More
@@ -1165,6 +1165,10 b' class InteractiveShell(Configurable, Magic):' | |||||
1165 |
|
1165 | |||
1166 | def object_inspect(self, oname): |
|
1166 | def object_inspect(self, oname): | |
1167 | info = self._object_find(oname) |
|
1167 | info = self._object_find(oname) | |
|
1168 | if info.found: | |||
|
1169 | return self.inspector.info(info.obj, info=info) | |||
|
1170 | else: | |||
|
1171 | return {} | |||
1168 |
|
1172 | |||
1169 | #------------------------------------------------------------------------- |
|
1173 | #------------------------------------------------------------------------- | |
1170 | # Things related to history management |
|
1174 | # Things related to history management |
@@ -25,6 +25,8 b' import os' | |||||
25 | import string |
|
25 | import string | |
26 | import sys |
|
26 | import sys | |
27 | import types |
|
27 | import types | |
|
28 | from collections import namedtuple | |||
|
29 | from itertools import izip_longest | |||
28 |
|
30 | |||
29 | # IPython's own |
|
31 | # IPython's own | |
30 | from IPython.core import page |
|
32 | from IPython.core import page | |
@@ -36,45 +38,6 b' from IPython.utils.wildcard import list_namespace' | |||||
36 | from IPython.utils.coloransi import * |
|
38 | from IPython.utils.coloransi import * | |
37 |
|
39 | |||
38 | #**************************************************************************** |
|
40 | #**************************************************************************** | |
39 | # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We |
|
|||
40 | # simply monkeypatch inspect with code copied from python 2.4. |
|
|||
41 | if sys.version_info[:2] == (2,3): |
|
|||
42 | from inspect import ismodule, getabsfile, modulesbyfile |
|
|||
43 | def getmodule(object): |
|
|||
44 | """Return the module an object was defined in, or None if not found.""" |
|
|||
45 | if ismodule(object): |
|
|||
46 | return object |
|
|||
47 | if hasattr(object, '__module__'): |
|
|||
48 | return sys.modules.get(object.__module__) |
|
|||
49 | try: |
|
|||
50 | file = getabsfile(object) |
|
|||
51 | except TypeError: |
|
|||
52 | return None |
|
|||
53 | if file in modulesbyfile: |
|
|||
54 | return sys.modules.get(modulesbyfile[file]) |
|
|||
55 | for module in sys.modules.values(): |
|
|||
56 | if hasattr(module, '__file__'): |
|
|||
57 | modulesbyfile[ |
|
|||
58 | os.path.realpath( |
|
|||
59 | getabsfile(module))] = module.__name__ |
|
|||
60 | if file in modulesbyfile: |
|
|||
61 | return sys.modules.get(modulesbyfile[file]) |
|
|||
62 | main = sys.modules['__main__'] |
|
|||
63 | if not hasattr(object, '__name__'): |
|
|||
64 | return None |
|
|||
65 | if hasattr(main, object.__name__): |
|
|||
66 | mainobject = getattr(main, object.__name__) |
|
|||
67 | if mainobject is object: |
|
|||
68 | return main |
|
|||
69 | builtin = sys.modules['__builtin__'] |
|
|||
70 | if hasattr(builtin, object.__name__): |
|
|||
71 | builtinobject = getattr(builtin, object.__name__) |
|
|||
72 | if builtinobject is object: |
|
|||
73 | return builtin |
|
|||
74 |
|
||||
75 | inspect.getmodule = getmodule |
|
|||
76 |
|
||||
77 | #**************************************************************************** |
|
|||
78 | # Builtin color schemes |
|
41 | # Builtin color schemes | |
79 |
|
42 | |||
80 | Colors = TermColors # just a shorthand |
|
43 | Colors = TermColors # just a shorthand | |
@@ -103,7 +66,30 b' InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],' | |||||
103 | 'Linux') |
|
66 | 'Linux') | |
104 |
|
67 | |||
105 | #**************************************************************************** |
|
68 | #**************************************************************************** | |
106 | # Auxiliary functions |
|
69 | # Auxiliary functions and objects | |
|
70 | ||||
|
71 | # See the messaging spec for the definition of all these fields. This list | |||
|
72 | # effectively defines the order of display | |||
|
73 | info_fields = ['type_name', 'base_class', 'string_form', 'namespace', | |||
|
74 | 'length', 'file', 'definition', 'docstring', 'source', | |||
|
75 | 'init_definition', 'class_docstring', 'init_docstring', | |||
|
76 | 'call_def', 'call_docstring', | |||
|
77 | # These won't be printed but will be used to determine how to | |||
|
78 | # format the object | |||
|
79 | 'ismagic', 'isalias', | |||
|
80 | ] | |||
|
81 | ||||
|
82 | ||||
|
83 | ObjectInfo = namedtuple('ObjectInfo', info_fields) | |||
|
84 | ||||
|
85 | ||||
|
86 | def mk_object_info(kw): | |||
|
87 | """Make a f""" | |||
|
88 | infodict = dict(izip_longest(info_fields, [None])) | |||
|
89 | infodict.update(kw) | |||
|
90 | return ObjectInfo(**infodict) | |||
|
91 | ||||
|
92 | ||||
107 | def getdoc(obj): |
|
93 | def getdoc(obj): | |
108 | """Stable wrapper around inspect.getdoc. |
|
94 | """Stable wrapper around inspect.getdoc. | |
109 |
|
95 | |||
@@ -553,6 +539,215 b' class Inspector:' | |||||
553 | page.page(output) |
|
539 | page.page(output) | |
554 | # end pinfo |
|
540 | # end pinfo | |
555 |
|
541 | |||
|
542 | def info(self, obj, oname='', formatter=None, info=None, detail_level=0): | |||
|
543 | """Compute a dict with detailed information about an object. | |||
|
544 | ||||
|
545 | Optional arguments: | |||
|
546 | ||||
|
547 | - oname: name of the variable pointing to the object. | |||
|
548 | ||||
|
549 | - formatter: special formatter for docstrings (see pdoc) | |||
|
550 | ||||
|
551 | - info: a structure with some information fields which may have been | |||
|
552 | precomputed already. | |||
|
553 | ||||
|
554 | - detail_level: if set to 1, more information is given. | |||
|
555 | """ | |||
|
556 | ||||
|
557 | obj_type = type(obj) | |||
|
558 | ||||
|
559 | header = self.__head | |||
|
560 | if info is None: | |||
|
561 | ismagic = 0 | |||
|
562 | isalias = 0 | |||
|
563 | ospace = '' | |||
|
564 | else: | |||
|
565 | ismagic = info.ismagic | |||
|
566 | isalias = info.isalias | |||
|
567 | ospace = info.namespace | |||
|
568 | # Get docstring, special-casing aliases: | |||
|
569 | if isalias: | |||
|
570 | if not callable(obj): | |||
|
571 | try: | |||
|
572 | ds = "Alias to the system command:\n %s" % obj[1] | |||
|
573 | except: | |||
|
574 | ds = "Alias: " + str(obj) | |||
|
575 | else: | |||
|
576 | ds = "Alias to " + str(obj) | |||
|
577 | if obj.__doc__: | |||
|
578 | ds += "\nDocstring:\n" + obj.__doc__ | |||
|
579 | else: | |||
|
580 | ds = getdoc(obj) | |||
|
581 | if ds is None: | |||
|
582 | ds = '<no docstring>' | |||
|
583 | if formatter is not None: | |||
|
584 | ds = formatter(ds) | |||
|
585 | ||||
|
586 | # store output in a dict, we'll later convert it to an ObjectInfo | |||
|
587 | out = {} | |||
|
588 | ||||
|
589 | string_max = 200 # max size of strings to show (snipped if longer) | |||
|
590 | shalf = int((string_max -5)/2) | |||
|
591 | ||||
|
592 | if ismagic: | |||
|
593 | obj_type_name = 'Magic function' | |||
|
594 | elif isalias: | |||
|
595 | obj_type_name = 'System alias' | |||
|
596 | else: | |||
|
597 | obj_type_name = obj_type.__name__ | |||
|
598 | out['type_name'] = obj_type_name | |||
|
599 | ||||
|
600 | try: | |||
|
601 | bclass = obj.__class__ | |||
|
602 | out['base_class'] = str(bclass) | |||
|
603 | except: pass | |||
|
604 | ||||
|
605 | # String form, but snip if too long in ? form (full in ??) | |||
|
606 | if detail_level >= self.str_detail_level: | |||
|
607 | try: | |||
|
608 | ostr = str(obj) | |||
|
609 | str_head = 'string_form' | |||
|
610 | if not detail_level and len(ostr)>string_max: | |||
|
611 | ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:] | |||
|
612 | ostr = ("\n" + " " * len(str_head.expandtabs())).\ | |||
|
613 | join(map(string.strip,ostr.split("\n"))) | |||
|
614 | if ostr.find('\n') > -1: | |||
|
615 | # Print multi-line strings starting at the next line. | |||
|
616 | str_sep = '\n' | |||
|
617 | else: | |||
|
618 | str_sep = '\t' | |||
|
619 | out[str_head] = ostr | |||
|
620 | except: | |||
|
621 | pass | |||
|
622 | ||||
|
623 | if ospace: | |||
|
624 | out['namespace'] = ospace | |||
|
625 | ||||
|
626 | # Length (for strings and lists) | |||
|
627 | try: | |||
|
628 | out['length'] = str(len(obj)) | |||
|
629 | except: pass | |||
|
630 | ||||
|
631 | # Filename where object was defined | |||
|
632 | binary_file = False | |||
|
633 | try: | |||
|
634 | try: | |||
|
635 | fname = inspect.getabsfile(obj) | |||
|
636 | except TypeError: | |||
|
637 | # For an instance, the file that matters is where its class was | |||
|
638 | # declared. | |||
|
639 | if hasattr(obj,'__class__'): | |||
|
640 | fname = inspect.getabsfile(obj.__class__) | |||
|
641 | if fname.endswith('<string>'): | |||
|
642 | fname = 'Dynamically generated function. No source code available.' | |||
|
643 | if (fname.endswith('.so') or fname.endswith('.dll')): | |||
|
644 | binary_file = True | |||
|
645 | out['file'] = fname | |||
|
646 | except: | |||
|
647 | # if anything goes wrong, we don't want to show source, so it's as | |||
|
648 | # if the file was binary | |||
|
649 | binary_file = True | |||
|
650 | ||||
|
651 | # reconstruct the function definition and print it: | |||
|
652 | defln = self._getdef(obj,oname) | |||
|
653 | if defln: | |||
|
654 | out['definition'] = self.format(defln) | |||
|
655 | ||||
|
656 | # Docstrings only in detail 0 mode, since source contains them (we | |||
|
657 | # avoid repetitions). If source fails, we add them back, see below. | |||
|
658 | if ds and detail_level == 0: | |||
|
659 | out['docstring'] = indent(ds) | |||
|
660 | ||||
|
661 | # Original source code for any callable | |||
|
662 | if detail_level: | |||
|
663 | # Flush the source cache because inspect can return out-of-date | |||
|
664 | # source | |||
|
665 | linecache.checkcache() | |||
|
666 | source_success = False | |||
|
667 | try: | |||
|
668 | try: | |||
|
669 | src = getsource(obj,binary_file) | |||
|
670 | except TypeError: | |||
|
671 | if hasattr(obj,'__class__'): | |||
|
672 | src = getsource(obj.__class__,binary_file) | |||
|
673 | if src is not None: | |||
|
674 | source = self.format(src) | |||
|
675 | out['source'] = source.rstrip() | |||
|
676 | source_success = True | |||
|
677 | except Exception, msg: | |||
|
678 | pass | |||
|
679 | ||||
|
680 | # Constructor docstring for classes | |||
|
681 | if inspect.isclass(obj): | |||
|
682 | # reconstruct the function definition and print it: | |||
|
683 | try: | |||
|
684 | obj_init = obj.__init__ | |||
|
685 | except AttributeError: | |||
|
686 | init_def = init_ds = None | |||
|
687 | else: | |||
|
688 | init_def = self._getdef(obj_init,oname) | |||
|
689 | init_ds = getdoc(obj_init) | |||
|
690 | # Skip Python's auto-generated docstrings | |||
|
691 | if init_ds and \ | |||
|
692 | init_ds.startswith('x.__init__(...) initializes'): | |||
|
693 | init_ds = None | |||
|
694 | ||||
|
695 | if init_def or init_ds: | |||
|
696 | if init_def: | |||
|
697 | out['init_definition'] = self.format(init_def) | |||
|
698 | if init_ds: | |||
|
699 | out['init_docstring'] = indent(init_ds) | |||
|
700 | # and class docstring for instances: | |||
|
701 | elif obj_type is types.InstanceType or \ | |||
|
702 | isinstance(obj,object): | |||
|
703 | ||||
|
704 | # First, check whether the instance docstring is identical to the | |||
|
705 | # class one, and print it separately if they don't coincide. In | |||
|
706 | # most cases they will, but it's nice to print all the info for | |||
|
707 | # objects which use instance-customized docstrings. | |||
|
708 | if ds: | |||
|
709 | try: | |||
|
710 | cls = getattr(obj,'__class__') | |||
|
711 | except: | |||
|
712 | class_ds = None | |||
|
713 | else: | |||
|
714 | class_ds = getdoc(cls) | |||
|
715 | # Skip Python's auto-generated docstrings | |||
|
716 | if class_ds and \ | |||
|
717 | (class_ds.startswith('function(code, globals[,') or \ | |||
|
718 | class_ds.startswith('instancemethod(function, instance,') or \ | |||
|
719 | class_ds.startswith('module(name[,') ): | |||
|
720 | class_ds = None | |||
|
721 | if class_ds and ds != class_ds: | |||
|
722 | out['class_docstring'] = indent(class_ds) | |||
|
723 | ||||
|
724 | # Next, try to show constructor docstrings | |||
|
725 | try: | |||
|
726 | init_ds = getdoc(obj.__init__) | |||
|
727 | # Skip Python's auto-generated docstrings | |||
|
728 | if init_ds and \ | |||
|
729 | init_ds.startswith('x.__init__(...) initializes'): | |||
|
730 | init_ds = None | |||
|
731 | except AttributeError: | |||
|
732 | init_ds = None | |||
|
733 | if init_ds: | |||
|
734 | out['init_docstring'] = indent(init_ds) | |||
|
735 | ||||
|
736 | # Call form docstring for callable instances | |||
|
737 | if hasattr(obj,'__call__'): | |||
|
738 | call_def = self._getdef(obj.__call__,oname) | |||
|
739 | if call_def is not None: | |||
|
740 | out['call_def'] = self.format(call_def) | |||
|
741 | call_ds = getdoc(obj.__call__) | |||
|
742 | # Skip Python's auto-generated docstrings | |||
|
743 | if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'): | |||
|
744 | call_ds = None | |||
|
745 | if call_ds: | |||
|
746 | out['call_docstring'] = indent(call_ds) | |||
|
747 | ||||
|
748 | return mk_object_info(out) | |||
|
749 | ||||
|
750 | ||||
556 | def psearch(self,pattern,ns_table,ns_search=[], |
|
751 | def psearch(self,pattern,ns_table,ns_search=[], | |
557 | ignore_case=False,show_all=False): |
|
752 | ignore_case=False,show_all=False): | |
558 | """Search namespaces with wildcards for objects. |
|
753 | """Search namespaces with wildcards for objects. |
@@ -210,10 +210,11 b' class Kernel(Configurable):' | |||||
210 | io.raw_print(completion_msg) |
|
210 | io.raw_print(completion_msg) | |
211 |
|
211 | |||
212 | def object_info_request(self, ident, parent): |
|
212 | def object_info_request(self, ident, parent): | |
213 | context = parent['content']['oname'].split('.') |
|
213 | ##context = parent['content']['oname'].split('.') | |
214 | object_info = self._object_info(context) |
|
214 | ##object_info = self._object_info(context) | |
|
215 | object_info = self.shell.object_inspect(parent['content']['oname']) | |||
215 | msg = self.session.send(self.reply_socket, 'object_info_reply', |
|
216 | msg = self.session.send(self.reply_socket, 'object_info_reply', | |
216 | object_info, parent, ident) |
|
217 | object_info._asdict(), parent, ident) | |
217 | io.raw_print(msg) |
|
218 | io.raw_print(msg) | |
218 |
|
219 | |||
219 | def history_request(self, ident, parent): |
|
220 | def history_request(self, ident, parent): |
@@ -450,13 +450,18 b' Message type: ``object_info_reply``::' | |||||
450 | # For instances, provide the constructor and class docstrings |
|
450 | # For instances, provide the constructor and class docstrings | |
451 | 'init_docstring' : str, |
|
451 | 'init_docstring' : str, | |
452 | 'class_docstring' : str, |
|
452 | 'class_docstring' : str, | |
453 |
|
453 | |||
|
454 | # If it's a callable object whose call method has a separate docstring and | |||
|
455 | # definition line: | |||
|
456 | 'call_def' : str, | |||
|
457 | 'call_docstring' : str, | |||
|
458 | ||||
454 | # If detail_level was 1, we also try to find the source code that |
|
459 | # If detail_level was 1, we also try to find the source code that | |
455 | # defines the object, if possible. The string 'None' will indicate |
|
460 | # defines the object, if possible. The string 'None' will indicate | |
456 | # that no source was found. |
|
461 | # that no source was found. | |
457 | 'source' : str, |
|
462 | 'source' : str, | |
458 | } |
|
463 | } | |
459 |
|
464 | ' | ||
460 |
|
465 | |||
461 | Complete |
|
466 | Complete | |
462 | -------- |
|
467 | -------- |
General Comments 0
You need to be logged in to leave comments.
Login now