Show More
@@ -1165,6 +1165,10 b' class InteractiveShell(Configurable, Magic):' | |||
|
1165 | 1165 | |
|
1166 | 1166 | def object_inspect(self, oname): |
|
1167 | 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 | 1174 | # Things related to history management |
@@ -25,6 +25,8 b' import os' | |||
|
25 | 25 | import string |
|
26 | 26 | import sys |
|
27 | 27 | import types |
|
28 | from collections import namedtuple | |
|
29 | from itertools import izip_longest | |
|
28 | 30 | |
|
29 | 31 | # IPython's own |
|
30 | 32 | from IPython.core import page |
@@ -36,45 +38,6 b' from IPython.utils.wildcard import list_namespace' | |||
|
36 | 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 | 41 | # Builtin color schemes |
|
79 | 42 | |
|
80 | 43 | Colors = TermColors # just a shorthand |
@@ -103,7 +66,30 b' InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],' | |||
|
103 | 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 | 93 | def getdoc(obj): |
|
108 | 94 | """Stable wrapper around inspect.getdoc. |
|
109 | 95 | |
@@ -553,6 +539,215 b' class Inspector:' | |||
|
553 | 539 | page.page(output) |
|
554 | 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 | 751 | def psearch(self,pattern,ns_table,ns_search=[], |
|
557 | 752 | ignore_case=False,show_all=False): |
|
558 | 753 | """Search namespaces with wildcards for objects. |
@@ -210,10 +210,11 b' class Kernel(Configurable):' | |||
|
210 | 210 | io.raw_print(completion_msg) |
|
211 | 211 | |
|
212 | 212 | def object_info_request(self, ident, parent): |
|
213 | context = parent['content']['oname'].split('.') | |
|
214 | object_info = self._object_info(context) | |
|
213 | ##context = parent['content']['oname'].split('.') | |
|
214 | ##object_info = self._object_info(context) | |
|
215 | object_info = self.shell.object_inspect(parent['content']['oname']) | |
|
215 | 216 | msg = self.session.send(self.reply_socket, 'object_info_reply', |
|
216 | object_info, parent, ident) | |
|
217 | object_info._asdict(), parent, ident) | |
|
217 | 218 | io.raw_print(msg) |
|
218 | 219 | |
|
219 | 220 | def history_request(self, ident, parent): |
@@ -450,13 +450,18 b' Message type: ``object_info_reply``::' | |||
|
450 | 450 | # For instances, provide the constructor and class docstrings |
|
451 | 451 | 'init_docstring' : str, |
|
452 | 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 | 459 | # If detail_level was 1, we also try to find the source code that |
|
455 | 460 | # defines the object, if possible. The string 'None' will indicate |
|
456 | 461 | # that no source was found. |
|
457 | 462 | 'source' : str, |
|
458 | 463 | } |
|
459 | ||
|
464 | ' | |
|
460 | 465 | |
|
461 | 466 | Complete |
|
462 | 467 | -------- |
General Comments 0
You need to be logged in to leave comments.
Login now