Return a line number of the given object's docstring. Returns `None` if the given object does not have a docstring.
(self, obj, source_lines)
| 1114 | filename, lineno) |
| 1115 | |
| 1116 | def _find_lineno(self, obj, source_lines): |
| 1117 | """ |
| 1118 | Return a line number of the given object's docstring. |
| 1119 | |
| 1120 | Returns `None` if the given object does not have a docstring. |
| 1121 | """ |
| 1122 | lineno = None |
| 1123 | docstring = getattr(obj, '__doc__', None) |
| 1124 | |
| 1125 | # Find the line number for modules. |
| 1126 | if inspect.ismodule(obj) and docstring is not None: |
| 1127 | lineno = 0 |
| 1128 | |
| 1129 | # Find the line number for classes. |
| 1130 | # Note: this could be fooled if a class is defined multiple |
| 1131 | # times in a single file. |
| 1132 | if inspect.isclass(obj) and docstring is not None: |
| 1133 | if source_lines is None: |
| 1134 | return None |
| 1135 | pat = re.compile(r'^\s*class\s*%s\b' % |
| 1136 | re.escape(getattr(obj, '__name__', '-'))) |
| 1137 | for i, line in enumerate(source_lines): |
| 1138 | if pat.match(line): |
| 1139 | lineno = i |
| 1140 | break |
| 1141 | |
| 1142 | # Find the line number for functions & methods. |
| 1143 | if inspect.ismethod(obj): obj = obj.__func__ |
| 1144 | if isinstance(obj, property): |
| 1145 | obj = obj.fget |
| 1146 | if isinstance(obj, functools.cached_property): |
| 1147 | obj = obj.func |
| 1148 | if inspect.isroutine(obj) and getattr(obj, '__doc__', None): |
| 1149 | # We don't use `docstring` var here, because `obj` can be changed. |
| 1150 | obj = inspect.unwrap(obj) |
| 1151 | try: |
| 1152 | obj = obj.__code__ |
| 1153 | except AttributeError: |
| 1154 | # Functions implemented in C don't necessarily |
| 1155 | # have a __code__ attribute. |
| 1156 | # If there's no code, there's no lineno |
| 1157 | return None |
| 1158 | if inspect.istraceback(obj): obj = obj.tb_frame |
| 1159 | if inspect.isframe(obj): obj = obj.f_code |
| 1160 | if inspect.iscode(obj): |
| 1161 | lineno = obj.co_firstlineno - 1 |
| 1162 | |
| 1163 | # Find the line number where the docstring starts. Assume |
| 1164 | # that it's the first line that begins with a quote mark. |
| 1165 | # Note: this could be fooled by a multiline function |
| 1166 | # signature, where a continuation line begins with a quote |
| 1167 | # mark. |
| 1168 | if lineno is not None: |
| 1169 | if source_lines is None: |
| 1170 | return lineno+1 |
| 1171 | pat = re.compile(r'(^|.*:)\s*\w*("|\')') |
| 1172 | for lineno in range(lineno, len(source_lines)): |
| 1173 | if pat.match(source_lines[lineno]): |