| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -197,6 +197,24 @@ def splitdoc(doc): | |||
| 197 | 197 | return lines[0], '\n'.join(lines[2:]) | |
| 198 | 198 | return '', '\n'.join(lines) | |
| 199 | 199 | ||
| 200 | + def _getargspec(object): | ||
| 201 | + try: | ||
| 202 | + signature = inspect.signature(object) | ||
| 203 | + if signature: | ||
| 204 | + return str(signature) | ||
| 205 | + except (ValueError, TypeError): | ||
| 206 | + argspec = getattr(object, '__text_signature__', None) | ||
| 207 | + if argspec: | ||
| 208 | + if argspec[:2] == '($': | ||
| 209 | + argspec = '(' + argspec[2:] | ||
| 210 | + if getattr(object, '__self__', None) is not None: | ||
| 211 | + # Strip the bound argument. | ||
| 212 | + m = re.match(r'\(\w+(?:(?=\))|,\s*(?:/(?:(?=\))|,\s*))?)', argspec) | ||
| 213 | + if m: | ||
| 214 | + argspec = '(' + argspec[m.end():] | ||
| 215 | + return argspec | ||
| 216 | + return None | ||
| 217 | + | ||
| 200 | 218 | def classname(object, modname): | |
| 201 | 219 | """Get a class name and qualify it with a module name if necessary.""" | |
| 202 | 220 | name = object.__name__ | |
@@ -1003,14 +1021,9 @@ def spilldata(msg, attrs, predicate): | |||
| 1003 | 1021 | title = title + '(%s)' % ', '.join(parents) | |
| 1004 | 1022 | ||
| 1005 | 1023 | decl = '' | |
| 1006 | - try: | ||
| 1007 | - signature = inspect.signature(object) | ||
| 1008 | - except (ValueError, TypeError): | ||
| 1009 | - signature = None | ||
| 1010 | - if signature: | ||
| 1011 | - argspec = str(signature) | ||
| 1012 | - if argspec and argspec != '()': | ||
| 1013 | - decl = name + self.escape(argspec) + '\n\n' | ||
| 1024 | + argspec = _getargspec(object) | ||
| 1025 | + if argspec and argspec != '()': | ||
| 1026 | + decl = name + self.escape(argspec) + '\n\n' | ||
| 1014 | 1027 | ||
| 1015 | 1028 | doc = getdoc(object) | |
| 1016 | 1029 | if decl: | |
@@ -1063,18 +1076,13 @@ def docroutine(self, object, name=None, mod=None, | |||
| 1063 | 1076 | anchor, name, reallink) | |
| 1064 | 1077 | argspec = None | |
| 1065 | 1078 | if inspect.isroutine(object): | |
| 1066 | - try: | ||
| 1067 | - signature = inspect.signature(object) | ||
| 1068 | - except (ValueError, TypeError): | ||
| 1069 | - signature = None | ||
| 1070 | - if signature: | ||
| 1071 | - argspec = str(signature) | ||
| 1072 | - if realname == '<lambda>': | ||
| 1073 | - title = '<strong>%s</strong> <em>lambda</em> ' % name | ||
| 1074 | - # XXX lambda's won't usually have func_annotations['return'] | ||
| 1075 | - # since the syntax doesn't support but it is possible. | ||
| 1076 | - # So removing parentheses isn't truly safe. | ||
| 1077 | - argspec = argspec[1:-1] # remove parentheses | ||
| 1079 | + argspec = _getargspec(object) | ||
| 1080 | + if argspec and realname == '<lambda>': | ||
| 1081 | + title = '<strong>%s</strong> <em>lambda</em> ' % name | ||
| 1082 | + # XXX lambda's won't usually have func_annotations['return'] | ||
| 1083 | + # since the syntax doesn't support but it is possible. | ||
| 1084 | + # So removing parentheses isn't truly safe. | ||
| 1085 | + argspec = argspec[1:-1] # remove parentheses | ||
| 1078 | 1086 | if not argspec: | |
| 1079 | 1087 | argspec = '(...)' | |
| 1080 | 1088 | ||
@@ -1321,14 +1329,9 @@ def makename(c, m=object.__module__): | |||
| 1321 | 1329 | contents = [] | |
| 1322 | 1330 | push = contents.append | |
| 1323 | 1331 | ||
| 1324 | - try: | ||
| 1325 | - signature = inspect.signature(object) | ||
| 1326 | - except (ValueError, TypeError): | ||
| 1327 | - signature = None | ||
| 1328 | - if signature: | ||
| 1329 | - argspec = str(signature) | ||
| 1330 | - if argspec and argspec != '()': | ||
| 1331 | - push(name + argspec + '\n') | ||
| 1332 | + argspec = _getargspec(object) | ||
| 1333 | + if argspec and argspec != '()': | ||
| 1334 | + push(name + argspec + '\n') | ||
| 1332 | 1335 | ||
| 1333 | 1336 | doc = getdoc(object) | |
| 1334 | 1337 | if doc: | |
@@ -1492,18 +1495,13 @@ def docroutine(self, object, name=None, mod=None, cl=None): | |||
| 1492 | 1495 | argspec = None | |
| 1493 | 1496 | ||
| 1494 | 1497 | if inspect.isroutine(object): | |
| 1495 | - try: | ||
| 1496 | - signature = inspect.signature(object) | ||
| 1497 | - except (ValueError, TypeError): | ||
| 1498 | - signature = None | ||
| 1499 | - if signature: | ||
| 1500 | - argspec = str(signature) | ||
| 1501 | - if realname == '<lambda>': | ||
| 1502 | - title = self.bold(name) + ' lambda ' | ||
| 1503 | - # XXX lambda's won't usually have func_annotations['return'] | ||
| 1504 | - # since the syntax doesn't support but it is possible. | ||
| 1505 | - # So removing parentheses isn't truly safe. | ||
| 1506 | - argspec = argspec[1:-1] # remove parentheses | ||
| 1498 | + argspec = _getargspec(object) | ||
| 1499 | + if argspec and realname == '<lambda>': | ||
| 1500 | + title = self.bold(name) + ' lambda ' | ||
| 1501 | + # XXX lambda's won't usually have func_annotations['return'] | ||
| 1502 | + # since the syntax doesn't support but it is possible. | ||
| 1503 | + # So removing parentheses isn't truly safe. | ||
| 1504 | + argspec = argspec[1:-1] # remove parentheses | ||
| 1507 | 1505 | if not argspec: | |
| 1508 | 1506 | argspec = '(...)' | |
| 1509 | 1507 | decl = asyncqualifier + title + argspec + note | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1230,6 +1230,60 @@ def test_bound_builtin_classmethod_o(self): | |||
| 1230 | 1230 | self.assertEqual(self._get_summary_line(dict.__class_getitem__), | |
| 1231 | 1231 | "__class_getitem__(object, /) method of builtins.type instance") | |
| 1232 | 1232 | ||
| 1233 | + def test_module_level_callable_unrepresentable_default(self): | ||
| 1234 | + self.assertEqual(self._get_summary_line(getattr), | ||
| 1235 | + "getattr(object, name, default=<unrepresentable>, /)") | ||
| 1236 | + | ||
| 1237 | + def test_builtin_staticmethod_unrepresentable_default(self): | ||
| 1238 | + self.assertEqual(self._get_summary_line(str.maketrans), | ||
| 1239 | + "maketrans(x, y=<unrepresentable>, z=<unrepresentable>, /)") | ||
| 1240 | + | ||
| 1241 | + def test_unbound_builtin_method_unrepresentable_default(self): | ||
| 1242 | + self.assertEqual(self._get_summary_line(dict.pop), | ||
| 1243 | + "pop(self, key, default=<unrepresentable>, /)") | ||
| 1244 | + | ||
| 1245 | + def test_bound_builtin_method_unrepresentable_default(self): | ||
| 1246 | + self.assertEqual(self._get_summary_line({}.pop), | ||
| 1247 | + "pop(key, default=<unrepresentable>, /) " | ||
| 1248 | + "method of builtins.dict instance") | ||
| 1249 | + | ||
| 1250 | + def test_overridden_text_signature(self): | ||
| 1251 | + class C: | ||
| 1252 | + def meth(*args, **kwargs): | ||
| 1253 | + pass | ||
| 1254 | + @classmethod | ||
| 1255 | + def cmeth(*args, **kwargs): | ||
| 1256 | + pass | ||
| 1257 | + @staticmethod | ||
| 1258 | + def smeth(*args, **kwargs): | ||
| 1259 | + pass | ||
| 1260 | + for text_signature, unbound, bound in [ | ||
| 1261 | + ("($slf)", "(slf, /)", "()"), | ||
| 1262 | + ("($slf, /)", "(slf, /)", "()"), | ||
| 1263 | + ("($slf, /, arg)", "(slf, /, arg)", "(arg)"), | ||
| 1264 | + ("($slf, /, arg=<x>)", "(slf, /, arg=<x>)", "(arg=<x>)"), | ||
| 1265 | + ("($slf, arg, /)", "(slf, arg, /)", "(arg, /)"), | ||
| 1266 | + ("($slf, arg=<x>, /)", "(slf, arg=<x>, /)", "(arg=<x>, /)"), | ||
| 1267 | + ("(/, slf, arg)", "(/, slf, arg)", "(/, slf, arg)"), | ||
| 1268 | + ("(/, slf, arg=<x>)", "(/, slf, arg=<x>)", "(/, slf, arg=<x>)"), | ||
| 1269 | + ("(slf, /, arg)", "(slf, /, arg)", "(arg)"), | ||
| 1270 | + ("(slf, /, arg=<x>)", "(slf, /, arg=<x>)", "(arg=<x>)"), | ||
| 1271 | + ("(slf, arg, /)", "(slf, arg, /)", "(arg, /)"), | ||
| 1272 | + ("(slf, arg=<x>, /)", "(slf, arg=<x>, /)", "(arg=<x>, /)"), | ||
| 1273 | + ]: | ||
| 1274 | + with self.subTest(text_signature): | ||
| 1275 | + C.meth.__text_signature__ = text_signature | ||
| 1276 | + self.assertEqual(self._get_summary_line(C.meth), | ||
| 1277 | + "meth" + unbound) | ||
| 1278 | + self.assertEqual(self._get_summary_line(C().meth), | ||
| 1279 | + "meth" + bound + " method of test.test_pydoc.C instance") | ||
| 1280 | + C.cmeth.__func__.__text_signature__ = text_signature | ||
| 1281 | + self.assertEqual(self._get_summary_line(C.cmeth), | ||
| 1282 | + "cmeth" + bound + " method of builtins.type instance") | ||
| 1283 | + C.smeth.__text_signature__ = text_signature | ||
| 1284 | + self.assertEqual(self._get_summary_line(C.smeth), | ||
| 1285 | + "smeth" + unbound) | ||
| 1286 | + | ||
| 1233 | 1287 | @requires_docstrings | |
| 1234 | 1288 | def test_staticmethod(self): | |
| 1235 | 1289 | class X: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + :mod:`pydoc` is now able to show signatures which are not representable in | ||
| 2 | + Python, e.g. for ``getattr`` and ``dict.pop``. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments