Show More
@@ -447,12 +447,12 b' class Inspector:' | |||||
447 | if inspect.isclass(obj) and hasattr(obj, '__init__'): |
|
447 | if inspect.isclass(obj) and hasattr(obj, '__init__'): | |
448 | init_ds = getdoc(obj.__init__) |
|
448 | init_ds = getdoc(obj.__init__) | |
449 | if init_ds is not None: |
|
449 | if init_ds is not None: | |
450 |
lines.append(head(" |
|
450 | lines.append(head("Init Docstring:")) | |
451 | lines.append(indent(init_ds)) |
|
451 | lines.append(indent(init_ds)) | |
452 | elif hasattr(obj,'__call__'): |
|
452 | elif hasattr(obj,'__call__'): | |
453 | call_ds = getdoc(obj.__call__) |
|
453 | call_ds = getdoc(obj.__call__) | |
454 | if call_ds: |
|
454 | if call_ds: | |
455 |
lines.append(head("Call |
|
455 | lines.append(head("Call Docstring:")) | |
456 | lines.append(indent(call_ds)) |
|
456 | lines.append(indent(call_ds)) | |
457 |
|
457 | |||
458 | if not lines: |
|
458 | if not lines: | |
@@ -494,7 +494,7 b' class Inspector:' | |||||
494 | # 0-offset, so we must adjust. |
|
494 | # 0-offset, so we must adjust. | |
495 | page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1) |
|
495 | page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1) | |
496 |
|
496 | |||
497 |
def _format_fields(self, fields, title_width= |
|
497 | def _format_fields(self, fields, title_width=0): | |
498 | """Formats a list of fields for display. |
|
498 | """Formats a list of fields for display. | |
499 |
|
499 | |||
500 | Parameters |
|
500 | Parameters | |
@@ -502,10 +502,13 b' class Inspector:' | |||||
502 | fields : list |
|
502 | fields : list | |
503 | A list of 2-tuples: (field_title, field_content) |
|
503 | A list of 2-tuples: (field_title, field_content) | |
504 | title_width : int |
|
504 | title_width : int | |
505 |
How many characters to pad titles to. Default |
|
505 | How many characters to pad titles to. Default to longest title. | |
506 | """ |
|
506 | """ | |
507 | out = [] |
|
507 | out = [] | |
508 | header = self.__head |
|
508 | header = self.__head | |
|
509 | if title_width == 0: | |||
|
510 | for title, _ in fields: | |||
|
511 | title_width = max(len(title) + 2, title_width) | |||
509 | for title, content in fields: |
|
512 | for title, content in fields: | |
510 | if len(content.splitlines()) > 1: |
|
513 | if len(content.splitlines()) > 1: | |
511 | title = header(title + ":") + "\n" |
|
514 | title = header(title + ":") + "\n" | |
@@ -527,7 +530,7 b' class Inspector:' | |||||
527 | ] |
|
530 | ] | |
528 |
|
531 | |||
529 | pinfo_fields_obj = [("Class Docstring", "class_docstring"), |
|
532 | pinfo_fields_obj = [("Class Docstring", "class_docstring"), | |
530 |
(" |
|
533 | ("Init Docstring", "init_docstring"), | |
531 | ("Call def", "call_def"), |
|
534 | ("Call def", "call_def"), | |
532 | ("Call docstring", "call_docstring")] |
|
535 | ("Call docstring", "call_docstring")] | |
533 |
|
536 | |||
@@ -567,6 +570,9 b' class Inspector:' | |||||
567 | displayfields.append(("Namespace", info['namespace'].rstrip())) |
|
570 | displayfields.append(("Namespace", info['namespace'].rstrip())) | |
568 |
|
571 | |||
569 | add_fields(self.pinfo_fields3) |
|
572 | add_fields(self.pinfo_fields3) | |
|
573 | if info['isclass'] and info['init_definition']: | |||
|
574 | displayfields.append(("Init Definition", | |||
|
575 | info['init_definition'].rstrip())) | |||
570 |
|
576 | |||
571 | # Source or docstring, depending on detail level and whether |
|
577 | # Source or docstring, depending on detail level and whether | |
572 | # source found. |
|
578 | # source found. | |
@@ -578,14 +584,9 b' class Inspector:' | |||||
578 |
|
584 | |||
579 | # Constructor info for classes |
|
585 | # Constructor info for classes | |
580 | if info['isclass']: |
|
586 | if info['isclass']: | |
581 | if info['init_definition'] or info['init_docstring']: |
|
|||
582 | displayfields.append(("Constructor information", "")) |
|
|||
583 | if info['init_definition'] is not None: |
|
|||
584 | displayfields.append((" Definition", |
|
|||
585 | info['init_definition'].rstrip())) |
|
|||
586 |
|
|
587 | if info['init_docstring'] is not None: | |
587 |
|
|
588 | displayfields.append(("Init Docstring", | |
588 |
|
|
589 | info['init_docstring'])) | |
589 |
|
590 | |||
590 | # Info for objects: |
|
591 | # Info for objects: | |
591 | else: |
|
592 | else: | |
@@ -693,11 +694,6 b' class Inspector:' | |||||
693 | fname = 'Dynamically generated function. No source code available.' |
|
694 | fname = 'Dynamically generated function. No source code available.' | |
694 | out['file'] = fname |
|
695 | out['file'] = fname | |
695 |
|
696 | |||
696 | # reconstruct the function definition and print it: |
|
|||
697 | defln = self._getdef(obj, oname) |
|
|||
698 | if defln: |
|
|||
699 | out['definition'] = self.format(defln) |
|
|||
700 |
|
||||
701 | # Docstrings only in detail 0 mode, since source contains them (we |
|
697 | # Docstrings only in detail 0 mode, since source contains them (we | |
702 | # avoid repetitions). If source fails, we add them back, see below. |
|
698 | # avoid repetitions). If source fails, we add them back, see below. | |
703 | if ds and detail_level == 0: |
|
699 | if ds and detail_level == 0: | |
@@ -747,6 +743,11 b' class Inspector:' | |||||
747 |
|
743 | |||
748 | # and class docstring for instances: |
|
744 | # and class docstring for instances: | |
749 | else: |
|
745 | else: | |
|
746 | # reconstruct the function definition and print it: | |||
|
747 | defln = self._getdef(obj, oname) | |||
|
748 | if defln: | |||
|
749 | out['definition'] = self.format(defln) | |||
|
750 | ||||
750 | # First, check whether the instance docstring is identical to the |
|
751 | # First, check whether the instance docstring is identical to the | |
751 | # class one, and print it separately if they don't coincide. In |
|
752 | # class one, and print it separately if they don't coincide. In | |
752 | # most cases they will, but it's nice to print all the info for |
|
753 | # most cases they will, but it's nice to print all the info for | |
@@ -778,8 +779,12 b' class Inspector:' | |||||
778 | # Call form docstring for callable instances |
|
779 | # Call form docstring for callable instances | |
779 | if safe_hasattr(obj, '__call__') and not is_simple_callable(obj): |
|
780 | if safe_hasattr(obj, '__call__') and not is_simple_callable(obj): | |
780 | call_def = self._getdef(obj.__call__, oname) |
|
781 | call_def = self._getdef(obj.__call__, oname) | |
781 |
if call_def |
|
782 | if call_def: | |
782 |
|
|
783 | call_def = self.format(call_def) | |
|
784 | # it may never be the case that call def and definition differ, | |||
|
785 | # but don't include the same signature twice | |||
|
786 | if call_def != out.get('definition'): | |||
|
787 | out['call_def'] = call_def | |||
783 | call_ds = getdoc(obj.__call__) |
|
788 | call_ds = getdoc(obj.__call__) | |
784 | # Skip Python's auto-generated docstrings |
|
789 | # Skip Python's auto-generated docstrings | |
785 | if call_ds == _func_call_docstring: |
|
790 | if call_ds == _func_call_docstring: |
@@ -116,14 +116,14 b' def test_ipdb_magics():' | |||||
116 | ipdb> pdoc ExampleClass |
|
116 | ipdb> pdoc ExampleClass | |
117 | Class Docstring: |
|
117 | Class Docstring: | |
118 | Docstring for ExampleClass. |
|
118 | Docstring for ExampleClass. | |
119 |
|
|
119 | Init Docstring: | |
120 | Docstring for ExampleClass.__init__ |
|
120 | Docstring for ExampleClass.__init__ | |
121 | ipdb> pinfo a |
|
121 | ipdb> pinfo a | |
122 | Type: ExampleClass |
|
122 | Type: ExampleClass | |
123 | String Form:ExampleClass() |
|
123 | String Form: ExampleClass() | |
124 | Namespace: Local... |
|
124 | Namespace: Local... | |
125 | Docstring: Docstring for ExampleClass. |
|
125 | Docstring: Docstring for ExampleClass. | |
126 |
|
|
126 | Init Docstring: Docstring for ExampleClass.__init__ | |
127 | ipdb> continue |
|
127 | ipdb> continue | |
128 |
|
128 | |||
129 | Restore previous trace function, e.g. for coverage.py |
|
129 | Restore previous trace function, e.g. for coverage.py |
@@ -242,7 +242,7 b' def test_info():' | |||||
242 | # case-insensitive comparison needed on some filesystems |
|
242 | # case-insensitive comparison needed on some filesystems | |
243 | # e.g. Windows: |
|
243 | # e.g. Windows: | |
244 | nt.assert_equal(i['file'].lower(), fname.lower()) |
|
244 | nt.assert_equal(i['file'].lower(), fname.lower()) | |
245 |
nt.assert_equal(i['definition'], |
|
245 | nt.assert_equal(i['definition'], None) | |
246 | nt.assert_equal(i['docstring'], Call.__doc__) |
|
246 | nt.assert_equal(i['docstring'], Call.__doc__) | |
247 | nt.assert_equal(i['source'], None) |
|
247 | nt.assert_equal(i['source'], None) | |
248 | nt.assert_true(i['isclass']) |
|
248 | nt.assert_true(i['isclass']) | |
@@ -260,7 +260,7 b' def test_info():' | |||||
260 | nt.assert_equal(i['docstring'], "Modified instance docstring") |
|
260 | nt.assert_equal(i['docstring'], "Modified instance docstring") | |
261 | nt.assert_equal(i['class_docstring'], Call.__doc__) |
|
261 | nt.assert_equal(i['class_docstring'], Call.__doc__) | |
262 | nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) |
|
262 | nt.assert_equal(i['init_docstring'], Call.__init__.__doc__) | |
263 |
nt.assert_equal(i['call_docstring'], |
|
263 | nt.assert_equal(i['call_docstring'], Call.__call__.__doc__) | |
264 |
|
264 | |||
265 | # Test old-style classes, which for example may not have an __init__ method. |
|
265 | # Test old-style classes, which for example may not have an __init__ method. | |
266 | if not py3compat.PY3: |
|
266 | if not py3compat.PY3: |
General Comments 0
You need to be logged in to leave comments.
Login now