Issue #19674: inspect.signature() now produces a correct signature
for some builtins.
This commit is contained in:
parent
7fa6e1aeea
commit
44e2eaab54
|
@ -31,6 +31,7 @@ Here are some of the useful functions provided by this module:
|
|||
__author__ = ('Ka-Ping Yee <ping@lfw.org>',
|
||||
'Yury Selivanov <yselivanov@sprymix.com>')
|
||||
|
||||
import ast
|
||||
import importlib.machinery
|
||||
import itertools
|
||||
import linecache
|
||||
|
@ -1461,6 +1462,9 @@ def signature(obj):
|
|||
if isinstance(obj, types.FunctionType):
|
||||
return Signature.from_function(obj)
|
||||
|
||||
if isinstance(obj, types.BuiltinFunctionType):
|
||||
return Signature.from_builtin(obj)
|
||||
|
||||
if isinstance(obj, functools.partial):
|
||||
sig = signature(obj.func)
|
||||
|
||||
|
@ -1942,6 +1946,64 @@ class Signature:
|
|||
return_annotation=annotations.get('return', _empty),
|
||||
__validate_parameters__=False)
|
||||
|
||||
@classmethod
|
||||
def from_builtin(cls, func):
|
||||
s = getattr(func, "__text_signature__", None)
|
||||
if not s:
|
||||
return None
|
||||
|
||||
if s.endswith("/)"):
|
||||
kind = Parameter.POSITIONAL_ONLY
|
||||
s = s[:-2] + ')'
|
||||
else:
|
||||
kind = Parameter.POSITIONAL_OR_KEYWORD
|
||||
|
||||
s = "def foo" + s + ": pass"
|
||||
|
||||
try:
|
||||
module = ast.parse(s)
|
||||
except SyntaxError:
|
||||
return None
|
||||
if not isinstance(module, ast.Module):
|
||||
return None
|
||||
|
||||
# ast.FunctionDef
|
||||
f = module.body[0]
|
||||
|
||||
parameters = []
|
||||
empty = Parameter.empty
|
||||
|
||||
def p(name_node, default_node, default=empty):
|
||||
name = name_node.arg
|
||||
|
||||
if isinstance(default_node, ast.Num):
|
||||
default = default.n
|
||||
elif isinstance(default_node, ast.NameConstant):
|
||||
default = default_node.value
|
||||
parameters.append(Parameter(name, kind, default=default, annotation=empty))
|
||||
|
||||
# non-keyword-only parameters
|
||||
for name, default in reversed(list(itertools.zip_longest(reversed(f.args.args), reversed(f.args.defaults), fillvalue=None))):
|
||||
p(name, default)
|
||||
|
||||
# *args
|
||||
if f.args.vararg:
|
||||
kind = Parameter.VAR_POSITIONAL
|
||||
p(f.args.vararg, empty)
|
||||
|
||||
# keyword-only arguments
|
||||
kind = Parameter.KEYWORD_ONLY
|
||||
for name, default in zip(f.args.kwonlyargs, f.args.kw_defaults):
|
||||
p(name, default)
|
||||
|
||||
# **kwargs
|
||||
if f.args.kwarg:
|
||||
kind = Parameter.VAR_KEYWORD
|
||||
p(f.args.kwarg, empty)
|
||||
|
||||
return cls(parameters, return_annotation=cls.empty)
|
||||
|
||||
|
||||
@property
|
||||
def parameters(self):
|
||||
return self._parameters
|
||||
|
|
52
Lib/pydoc.py
52
Lib/pydoc.py
|
@ -916,20 +916,18 @@ class HTMLDoc(Doc):
|
|||
reallink = realname
|
||||
title = '<a name="%s"><strong>%s</strong></a> = %s' % (
|
||||
anchor, name, reallink)
|
||||
if inspect.isfunction(object):
|
||||
args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann = \
|
||||
inspect.getfullargspec(object)
|
||||
argspec = inspect.formatargspec(
|
||||
args, varargs, kwonlyargs, kwdefaults, varkw, defaults, ann,
|
||||
formatvalue=self.formatvalue,
|
||||
formatannotation=inspect.formatannotationrelativeto(object))
|
||||
if realname == '<lambda>':
|
||||
title = '<strong>%s</strong> <em>lambda</em> ' % name
|
||||
# XXX lambda's won't usually have func_annotations['return']
|
||||
# since the syntax doesn't support but it is possible.
|
||||
# So removing parentheses isn't truly safe.
|
||||
argspec = argspec[1:-1] # remove parentheses
|
||||
else:
|
||||
argspec = None
|
||||
if inspect.isfunction(object) or inspect.isbuiltin(object):
|
||||
signature = inspect.signature(object)
|
||||
if signature:
|
||||
argspec = str(signature)
|
||||
if realname == '<lambda>':
|
||||
title = '<strong>%s</strong> <em>lambda</em> ' % name
|
||||
# XXX lambda's won't usually have func_annotations['return']
|
||||
# since the syntax doesn't support but it is possible.
|
||||
# So removing parentheses isn't truly safe.
|
||||
argspec = argspec[1:-1] # remove parentheses
|
||||
if not argspec:
|
||||
argspec = '(...)'
|
||||
|
||||
decl = title + argspec + (note and self.grey(
|
||||
|
@ -1313,20 +1311,18 @@ location listed above.
|
|||
cl.__dict__[realname] is object):
|
||||
skipdocs = 1
|
||||
title = self.bold(name) + ' = ' + realname
|
||||
if inspect.isfunction(object):
|
||||
args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann = \
|
||||
inspect.getfullargspec(object)
|
||||
argspec = inspect.formatargspec(
|
||||
args, varargs, varkw, defaults, kwonlyargs, kwdefaults, ann,
|
||||
formatvalue=self.formatvalue,
|
||||
formatannotation=inspect.formatannotationrelativeto(object))
|
||||
if realname == '<lambda>':
|
||||
title = self.bold(name) + ' lambda '
|
||||
# XXX lambda's won't usually have func_annotations['return']
|
||||
# since the syntax doesn't support but it is possible.
|
||||
# So removing parentheses isn't truly safe.
|
||||
argspec = argspec[1:-1] # remove parentheses
|
||||
else:
|
||||
argspec = None
|
||||
if inspect.isfunction(object) or inspect.isbuiltin(object):
|
||||
signature = inspect.signature(object)
|
||||
if signature:
|
||||
argspec = str(signature)
|
||||
if realname == '<lambda>':
|
||||
title = self.bold(name) + ' lambda '
|
||||
# XXX lambda's won't usually have func_annotations['return']
|
||||
# since the syntax doesn't support but it is possible.
|
||||
# So removing parentheses isn't truly safe.
|
||||
argspec = argspec[1:-1] # remove parentheses
|
||||
if not argspec:
|
||||
argspec = '(...)'
|
||||
decl = title + argspec + note
|
||||
|
||||
|
|
|
@ -109,6 +109,35 @@ class CAPITest(unittest.TestCase):
|
|||
self.assertRaises(TypeError, _posixsubprocess.fork_exec,
|
||||
Z(),[b'1'],3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
|
||||
|
||||
def test_docstring_signature_parsing(self):
|
||||
|
||||
self.assertEqual(_testcapi.no_docstring.__doc__, None)
|
||||
self.assertEqual(_testcapi.no_docstring.__text_signature__, None)
|
||||
|
||||
self.assertEqual(_testcapi.docstring_empty.__doc__, "")
|
||||
self.assertEqual(_testcapi.docstring_empty.__text_signature__, None)
|
||||
|
||||
self.assertEqual(_testcapi.docstring_no_signature.__doc__,
|
||||
"This docstring has no signature.")
|
||||
self.assertEqual(_testcapi.docstring_no_signature.__text_signature__, None)
|
||||
|
||||
self.assertEqual(_testcapi.docstring_with_invalid_signature.__doc__,
|
||||
"docstring_with_invalid_signature (boo)\n"
|
||||
"\n"
|
||||
"This docstring has an invalid signature."
|
||||
)
|
||||
self.assertEqual(_testcapi.docstring_with_invalid_signature.__text_signature__, None)
|
||||
|
||||
self.assertEqual(_testcapi.docstring_with_signature.__doc__,
|
||||
"This docstring has a valid signature.")
|
||||
self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "(sig)")
|
||||
|
||||
self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__doc__,
|
||||
"This docstring has a valid signature and some extra newlines.")
|
||||
self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__text_signature__,
|
||||
"(parameter)")
|
||||
|
||||
|
||||
@unittest.skipUnless(threading, 'Threading required for this test.')
|
||||
class TestPendingCalls(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -1588,10 +1588,9 @@ class TestSignatureObject(unittest.TestCase):
|
|||
with self.assertRaisesRegex(ValueError, 'not supported by signature'):
|
||||
# support for 'method-wrapper'
|
||||
inspect.signature(min.__call__)
|
||||
with self.assertRaisesRegex(ValueError,
|
||||
'no signature found for builtin function'):
|
||||
# support for 'method-wrapper'
|
||||
inspect.signature(min)
|
||||
self.assertEqual(inspect.signature(min), None)
|
||||
signature = inspect.signature(os.stat)
|
||||
self.assertTrue(isinstance(signature, inspect.Signature))
|
||||
|
||||
def test_signature_on_non_function(self):
|
||||
with self.assertRaisesRegex(TypeError, 'is not a callable object'):
|
||||
|
|
|
@ -68,6 +68,9 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #19674: inspect.signature() now produces a correct signature
|
||||
for some builtins.
|
||||
|
||||
- Issue #19722: Added opcode.stack_effect(), which
|
||||
computes the stack effect of bytecode instructions.
|
||||
|
||||
|
|
|
@ -134,6 +134,12 @@ typedef chtype attr_t; /* No attr_t type is available */
|
|||
#define STRICT_SYSV_CURSES
|
||||
#endif
|
||||
|
||||
/*[clinic]
|
||||
module curses
|
||||
class curses.window
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/* Definition of exception curses.error */
|
||||
|
||||
static PyObject *PyCursesError;
|
||||
|
@ -550,8 +556,6 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo)
|
|||
/* Addch, Addstr, Addnstr */
|
||||
|
||||
/*[clinic]
|
||||
module curses
|
||||
class curses.window
|
||||
|
||||
curses.window.addch
|
||||
|
||||
|
@ -580,9 +584,9 @@ current settings for the window object.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(curses_window_addch__doc__,
|
||||
"addch([x, y,] ch, [attr])\n"
|
||||
"Paint character ch at (y, x) with attributes attr.\n"
|
||||
"\n"
|
||||
"curses.window.addch([x, y,] ch, [attr])\n"
|
||||
" x\n"
|
||||
" X-coordinate.\n"
|
||||
" y\n"
|
||||
|
@ -646,7 +650,7 @@ curses_window_addch(PyObject *self, PyObject *args)
|
|||
|
||||
static PyObject *
|
||||
curses_window_addch_impl(PyObject *self, int group_left_1, int x, int y, PyObject *ch, int group_right_1, long attr)
|
||||
/*[clinic checksum: 094d012af1019387c0219a9c0bc76e90729c833f]*/
|
||||
/*[clinic checksum: 44ed958b891cde91205e584c766e048f3999714f]*/
|
||||
{
|
||||
PyCursesWindowObject *cwself = (PyCursesWindowObject *)self;
|
||||
int coordinates_group = group_left_1;
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
#include "datetime.h"
|
||||
#undef Py_BUILD_CORE
|
||||
|
||||
/*[clinic]
|
||||
module datetime
|
||||
class datetime.datetime
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/* We require that C int be at least 32 bits, and use int virtually
|
||||
* everywhere. In just a few cases we use a temp long, where a Python
|
||||
* API returns a C long. In such cases, we have to ensure that the
|
||||
|
@ -4140,8 +4146,6 @@ datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
|
|||
}
|
||||
|
||||
/*[clinic]
|
||||
module datetime
|
||||
class datetime.datetime
|
||||
|
||||
@classmethod
|
||||
datetime.datetime.now
|
||||
|
@ -4155,9 +4159,9 @@ If no tz is specified, uses local timezone.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(datetime_datetime_now__doc__,
|
||||
"now(tz=None)\n"
|
||||
"Returns new datetime object representing current time local to tz.\n"
|
||||
"\n"
|
||||
"datetime.datetime.now(tz=None)\n"
|
||||
" tz\n"
|
||||
" Timezone object.\n"
|
||||
"\n"
|
||||
|
@ -4188,7 +4192,7 @@ exit:
|
|||
|
||||
static PyObject *
|
||||
datetime_datetime_now_impl(PyTypeObject *cls, PyObject *tz)
|
||||
/*[clinic checksum: 5e61647d5d1feaf1ab096c5406ccea17bb7b061c]*/
|
||||
/*[clinic checksum: ca3d26a423b3f633b260c7622e303f0915a96f7c]*/
|
||||
{
|
||||
PyObject *self;
|
||||
|
||||
|
|
|
@ -28,6 +28,12 @@ static char *which_dbm = "Berkeley DB";
|
|||
#error "No ndbm.h available!"
|
||||
#endif
|
||||
|
||||
/*[clinic]
|
||||
module dbm
|
||||
class dbm.dbm
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
int di_size; /* -1 means recompute */
|
||||
|
@ -43,12 +49,6 @@ static PyTypeObject Dbmtype;
|
|||
|
||||
static PyObject *DbmError;
|
||||
|
||||
/*[clinic]
|
||||
module dbm
|
||||
class dbm.dbm
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/*[python]
|
||||
class dbmobject_converter(self_converter):
|
||||
type = "dbmobject *"
|
||||
|
@ -278,9 +278,8 @@ Return the value for key if present, otherwise default.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(dbm_dbm_get__doc__,
|
||||
"Return the value for key if present, otherwise default.\n"
|
||||
"\n"
|
||||
"dbm.dbm.get(key, [default])");
|
||||
"get(key, [default])\n"
|
||||
"Return the value for key if present, otherwise default.");
|
||||
|
||||
#define DBM_DBM_GET_METHODDEF \
|
||||
{"get", (PyCFunction)dbm_dbm_get, METH_VARARGS, dbm_dbm_get__doc__},
|
||||
|
@ -318,7 +317,7 @@ dbm_dbm_get(PyObject *self, PyObject *args)
|
|||
|
||||
static PyObject *
|
||||
dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, int group_right_1, PyObject *default_value)
|
||||
/*[clinic checksum: 5b4265e66568f163ef0fc7efec09410eaf793508]*/
|
||||
/*[clinic checksum: 28cf8928811bde51e535d67ae98ea039d79df717]*/
|
||||
{
|
||||
datum dbm_key, val;
|
||||
|
||||
|
@ -461,9 +460,9 @@ Return a database object.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(dbmopen__doc__,
|
||||
"open(filename, flags=\'r\', mode=0o666)\n"
|
||||
"Return a database object.\n"
|
||||
"\n"
|
||||
"dbm.open(filename, flags=\'r\', mode=0o666)\n"
|
||||
" filename\n"
|
||||
" The filename to open.\n"
|
||||
" flags\n"
|
||||
|
@ -498,7 +497,7 @@ exit:
|
|||
|
||||
static PyObject *
|
||||
dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode)
|
||||
/*[clinic checksum: c1f2036017ec36a43ac6f59893732751e67c19d5]*/
|
||||
/*[clinic checksum: fb265f75641553ccd963f84c143b35c11f9121fc]*/
|
||||
{
|
||||
int iflags;
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#include "Python.h"
|
||||
#include "opcode.h"
|
||||
|
||||
/*[clinic]
|
||||
module _opcode
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/*[clinic]
|
||||
|
||||
module _opcode
|
||||
|
||||
_opcode.stack_effect -> int
|
||||
|
||||
opcode: int
|
||||
|
@ -19,18 +21,17 @@ Compute the stack effect of the opcode.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(_opcode_stack_effect__doc__,
|
||||
"Compute the stack effect of the opcode.\n"
|
||||
"\n"
|
||||
"_opcode.stack_effect(opcode, [oparg])");
|
||||
"stack_effect(opcode, [oparg])\n"
|
||||
"Compute the stack effect of the opcode.");
|
||||
|
||||
#define _OPCODE_STACK_EFFECT_METHODDEF \
|
||||
{"stack_effect", (PyCFunction)_opcode_stack_effect, METH_VARARGS, _opcode_stack_effect__doc__},
|
||||
|
||||
static int
|
||||
_opcode_stack_effect_impl(PyObject *module, int opcode, int group_right_1, int oparg);
|
||||
_opcode_stack_effect_impl(PyModuleDef *module, int opcode, int group_right_1, int oparg);
|
||||
|
||||
static PyObject *
|
||||
_opcode_stack_effect(PyObject *module, PyObject *args)
|
||||
_opcode_stack_effect(PyModuleDef *module, PyObject *args)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int opcode;
|
||||
|
@ -62,8 +63,8 @@ exit:
|
|||
}
|
||||
|
||||
static int
|
||||
_opcode_stack_effect_impl(PyObject *module, int opcode, int group_right_1, int oparg)
|
||||
/*[clinic checksum: 2312ded40abc9bcbce718942de21f53e61a2dfd3]*/
|
||||
_opcode_stack_effect_impl(PyModuleDef *module, int opcode, int group_right_1, int oparg)
|
||||
/*[clinic checksum: e880e62dc7b0de73403026eaf4f8074aa106358b]*/
|
||||
{
|
||||
int effect;
|
||||
if (HAS_ARG(opcode)) {
|
||||
|
|
|
@ -2842,6 +2842,33 @@ test_pyobject_setallocators(PyObject *self)
|
|||
return test_setallocators(PYMEM_DOMAIN_OBJ);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(docstring_empty,
|
||||
""
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(docstring_no_signature,
|
||||
"This docstring has no signature."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(docstring_with_invalid_signature,
|
||||
"docstring_with_invalid_signature (boo)\n"
|
||||
"\n"
|
||||
"This docstring has an invalid signature."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(docstring_with_signature,
|
||||
"docstring_with_signature(sig)\n"
|
||||
"This docstring has a valid signature."
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(docstring_with_signature_and_extra_newlines,
|
||||
"docstring_with_signature_and_extra_newlines(parameter)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"This docstring has a valid signature and some extra newlines."
|
||||
);
|
||||
|
||||
static PyMethodDef TestMethods[] = {
|
||||
{"raise_exception", raise_exception, METH_VARARGS},
|
||||
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
|
||||
|
@ -2953,6 +2980,23 @@ static PyMethodDef TestMethods[] = {
|
|||
(PyCFunction)test_pymem_setallocators, METH_NOARGS},
|
||||
{"test_pyobject_setallocators",
|
||||
(PyCFunction)test_pyobject_setallocators, METH_NOARGS},
|
||||
{"no_docstring",
|
||||
(PyCFunction)test_with_docstring, METH_NOARGS},
|
||||
{"docstring_empty",
|
||||
(PyCFunction)test_with_docstring, METH_NOARGS,
|
||||
docstring_empty},
|
||||
{"docstring_no_signature",
|
||||
(PyCFunction)test_with_docstring, METH_NOARGS,
|
||||
docstring_no_signature},
|
||||
{"docstring_with_invalid_signature",
|
||||
(PyCFunction)test_with_docstring, METH_NOARGS,
|
||||
docstring_with_invalid_signature},
|
||||
{"docstring_with_signature",
|
||||
(PyCFunction)test_with_docstring, METH_NOARGS,
|
||||
docstring_with_signature},
|
||||
{"docstring_with_signature_and_extra_newlines",
|
||||
(PyCFunction)test_with_docstring, METH_NOARGS,
|
||||
docstring_with_signature_and_extra_newlines},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
|
||||
|
||||
/*[clinic]
|
||||
|
||||
module _weakref
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/*[clinic]
|
||||
|
||||
_weakref.getweakrefcount -> Py_ssize_t
|
||||
|
||||
|
@ -17,9 +20,8 @@ Return the number of weak references to 'object'.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(_weakref_getweakrefcount__doc__,
|
||||
"Return the number of weak references to \'object\'.\n"
|
||||
"\n"
|
||||
"_weakref.getweakrefcount(object)");
|
||||
"getweakrefcount(object)\n"
|
||||
"Return the number of weak references to \'object\'.");
|
||||
|
||||
#define _WEAKREF_GETWEAKREFCOUNT_METHODDEF \
|
||||
{"getweakrefcount", (PyCFunction)_weakref_getweakrefcount, METH_O, _weakref_getweakrefcount__doc__},
|
||||
|
@ -43,7 +45,7 @@ exit:
|
|||
|
||||
static Py_ssize_t
|
||||
_weakref_getweakrefcount_impl(PyModuleDef *module, PyObject *object)
|
||||
/*[clinic checksum: 015113be0c9a0a8672d35df10c63e3642cc23da4]*/
|
||||
/*[clinic checksum: 436e8fbe0297434375f039d8c2d9fc3a9bbe773c]*/
|
||||
{
|
||||
PyWeakReference **list;
|
||||
|
||||
|
|
|
@ -190,7 +190,10 @@ corresponding Unix manual entries for more information on calls.");
|
|||
#endif /* ! __WATCOMC__ || __QNX__ */
|
||||
|
||||
|
||||
|
||||
/*[clinic]
|
||||
module os
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
|
@ -2404,7 +2407,6 @@ class dir_fd_converter(CConverter):
|
|||
/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/*[clinic]
|
||||
module os
|
||||
|
||||
os.stat -> object(doc_default='stat_result')
|
||||
|
||||
|
@ -2435,9 +2437,9 @@ It's an error to use dir_fd or follow_symlinks when specifying path as
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(os_stat__doc__,
|
||||
"stat(path, *, dir_fd=None, follow_symlinks=True)\n"
|
||||
"Perform a stat system call on the given path.\n"
|
||||
"\n"
|
||||
"os.stat(path, *, dir_fd=None, follow_symlinks=True) -> stat_result\n"
|
||||
" path\n"
|
||||
" Path to be examined; can be string, bytes, or open-file-descriptor int.\n"
|
||||
" dir_fd\n"
|
||||
|
@ -2486,7 +2488,7 @@ exit:
|
|||
|
||||
static PyObject *
|
||||
os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks)
|
||||
/*[clinic checksum: b08112eff0ceab3ec2c72352da95ce73f245d104]*/
|
||||
/*[clinic checksum: 85a71ad602e89f8e280118da976f70cd2f9abdf1]*/
|
||||
{
|
||||
return posix_do_stat("stat", path, dir_fd, follow_symlinks);
|
||||
}
|
||||
|
@ -2567,9 +2569,9 @@ Note that most operations will use the effective uid/gid, therefore this
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(os_access__doc__,
|
||||
"access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True)\n"
|
||||
"Use the real uid/gid to test for access to a path.\n"
|
||||
"\n"
|
||||
"os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True) -> True if granted, False otherwise\n"
|
||||
" path\n"
|
||||
" Path to be tested; can be string, bytes, or open-file-descriptor int.\n"
|
||||
" mode\n"
|
||||
|
@ -2587,7 +2589,6 @@ PyDoc_STRVAR(os_access__doc__,
|
|||
" access will examine the symbolic link itself instead of the file\n"
|
||||
" the link points to.\n"
|
||||
"\n"
|
||||
"{parameters}\n"
|
||||
"dir_fd, effective_ids, and follow_symlinks may not be implemented\n"
|
||||
" on your platform. If they are unavailable, using them will raise a\n"
|
||||
" NotImplementedError.\n"
|
||||
|
@ -2628,7 +2629,7 @@ exit:
|
|||
|
||||
static PyObject *
|
||||
os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks)
|
||||
/*[clinic checksum: b9f8ececb061d31b64220c29526bfee642d1b602]*/
|
||||
/*[clinic checksum: 636e835c36562a2fc11acab75314634127fdf769]*/
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
|
||||
|
@ -2724,9 +2725,9 @@ Return the name of the terminal device connected to 'fd'.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(os_ttyname__doc__,
|
||||
"ttyname(fd)\n"
|
||||
"Return the name of the terminal device connected to \'fd\'.\n"
|
||||
"\n"
|
||||
"os.ttyname(fd)\n"
|
||||
" fd\n"
|
||||
" Integer file descriptor handle.");
|
||||
|
||||
|
@ -2758,7 +2759,7 @@ exit:
|
|||
|
||||
static char *
|
||||
os_ttyname_impl(PyModuleDef *module, int fd)
|
||||
/*[clinic checksum: 61e4e525984cb293f949ccae6ae393c0011dfe8e]*/
|
||||
/*[clinic checksum: 0f368134dc0a7f21f25185e2e6bacf7675fb473a]*/
|
||||
{
|
||||
char *ret;
|
||||
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
#include "ucnhash.h"
|
||||
#include "structmember.h"
|
||||
|
||||
/*[clinic]
|
||||
module unicodedata
|
||||
class unicodedata.UCD
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/* character properties */
|
||||
|
||||
typedef struct {
|
||||
|
@ -108,8 +114,7 @@ static Py_UCS4 getuchar(PyUnicodeObject *obj)
|
|||
/* --- Module API --------------------------------------------------------- */
|
||||
|
||||
/*[clinic]
|
||||
module unicodedata
|
||||
class unicodedata.UCD
|
||||
|
||||
unicodedata.UCD.decimal
|
||||
|
||||
unichr: object(type='str')
|
||||
|
@ -124,10 +129,9 @@ not given, ValueError is raised.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(unicodedata_UCD_decimal__doc__,
|
||||
"decimal(unichr, default=None)\n"
|
||||
"Converts a Unicode character into its equivalent decimal value.\n"
|
||||
"\n"
|
||||
"unicodedata.UCD.decimal(unichr, default=None)\n"
|
||||
"\n"
|
||||
"Returns the decimal value assigned to the Unicode character unichr\n"
|
||||
"as integer. If no such value is defined, default is returned, or, if\n"
|
||||
"not given, ValueError is raised.");
|
||||
|
@ -157,7 +161,7 @@ exit:
|
|||
|
||||
static PyObject *
|
||||
unicodedata_UCD_decimal_impl(PyObject *self, PyObject *unichr, PyObject *default_value)
|
||||
/*[clinic checksum: a0980c387387287e2ac230c37d95b26f6903e0d2]*/
|
||||
/*[clinic checksum: 9576fa55f4ea0be82968af39dc9d0283e634beeb]*/
|
||||
{
|
||||
PyUnicodeObject *v = (PyUnicodeObject *)unichr;
|
||||
int have_old = 0;
|
||||
|
|
|
@ -165,6 +165,7 @@ PyZlib_Free(voidpf ctx, void *ptr)
|
|||
}
|
||||
|
||||
/*[clinic]
|
||||
|
||||
zlib.compress
|
||||
bytes: Py_buffer
|
||||
Binary data to be compressed.
|
||||
|
@ -179,9 +180,9 @@ Returns compressed string.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(zlib_compress__doc__,
|
||||
"compress(bytes, [level])\n"
|
||||
"Returns compressed string.\n"
|
||||
"\n"
|
||||
"zlib.compress(bytes, [level])\n"
|
||||
" bytes\n"
|
||||
" Binary data to be compressed.\n"
|
||||
" level\n"
|
||||
|
@ -226,7 +227,7 @@ zlib_compress(PyModuleDef *module, PyObject *args)
|
|||
|
||||
static PyObject *
|
||||
zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int group_right_1, int level)
|
||||
/*[clinic checksum: 03e857836db25448d4d572da537eb7faf7695d71]*/
|
||||
/*[clinic checksum: f490708eff84be652b5ebe7fe622ab73ac12c888]*/
|
||||
{
|
||||
PyObject *ReturnVal = NULL;
|
||||
Byte *input, *output = NULL;
|
||||
|
@ -742,6 +743,7 @@ save_unconsumed_input(compobject *self, int err)
|
|||
}
|
||||
|
||||
/*[clinic]
|
||||
|
||||
zlib.Decompress.decompress
|
||||
|
||||
data: Py_buffer
|
||||
|
@ -760,9 +762,9 @@ Call the flush() method to clear these buffers.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(zlib_Decompress_decompress__doc__,
|
||||
"decompress(data, max_length=0)\n"
|
||||
"Return a string containing the decompressed version of the data.\n"
|
||||
"\n"
|
||||
"zlib.Decompress.decompress(data, max_length=0)\n"
|
||||
" data\n"
|
||||
" The binary data to decompress.\n"
|
||||
" max_length\n"
|
||||
|
@ -803,7 +805,7 @@ exit:
|
|||
|
||||
static PyObject *
|
||||
zlib_Decompress_decompress_impl(PyObject *self, Py_buffer *data, unsigned int max_length)
|
||||
/*[clinic checksum: f83e91728d327462d7ccbee95299514f26b92253]*/
|
||||
/*[clinic checksum: 4683928665a1fa6987f5c57cada4a22807a78fbb]*/
|
||||
{
|
||||
compobject *zself = (compobject *)self;
|
||||
int err;
|
||||
|
@ -1029,16 +1031,15 @@ Return a copy of the compression object.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(zlib_Compress_copy__doc__,
|
||||
"Return a copy of the compression object.\n"
|
||||
"\n"
|
||||
"zlib.Compress.copy()");
|
||||
"copy()\n"
|
||||
"Return a copy of the compression object.");
|
||||
|
||||
#define ZLIB_COMPRESS_COPY_METHODDEF \
|
||||
{"copy", (PyCFunction)zlib_Compress_copy, METH_NOARGS, zlib_Compress_copy__doc__},
|
||||
|
||||
static PyObject *
|
||||
zlib_Compress_copy(PyObject *self)
|
||||
/*[clinic checksum: 2551952e72329f0f2beb48a1dde3780e485a220b]*/
|
||||
/*[clinic checksum: 8d30351f05defbc2b335c2a78d18f07aa367bb1d]*/
|
||||
{
|
||||
compobject *zself = (compobject *)self;
|
||||
compobject *retval = NULL;
|
||||
|
|
|
@ -69,6 +69,11 @@ to the combined-table form.
|
|||
#include "Python.h"
|
||||
#include "stringlib/eq.h"
|
||||
|
||||
/*[clinic]
|
||||
class dict
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
typedef struct {
|
||||
/* Cached hash code of me_key. */
|
||||
Py_hash_t me_hash;
|
||||
|
@ -2160,7 +2165,6 @@ dict_richcompare(PyObject *v, PyObject *w, int op)
|
|||
}
|
||||
|
||||
/*[clinic]
|
||||
class dict
|
||||
|
||||
@coexist
|
||||
dict.__contains__
|
||||
|
@ -2172,16 +2176,15 @@ True if D has a key k, else False"
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(dict___contains____doc__,
|
||||
"True if D has a key k, else False\"\n"
|
||||
"\n"
|
||||
"dict.__contains__(key)");
|
||||
"__contains__(key)\n"
|
||||
"True if D has a key k, else False\"");
|
||||
|
||||
#define DICT___CONTAINS___METHODDEF \
|
||||
{"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__},
|
||||
|
||||
static PyObject *
|
||||
dict___contains__(PyObject *self, PyObject *key)
|
||||
/*[clinic checksum: 61c5c802ea1d35699a1a754f1f3538ea9b259cf4]*/
|
||||
/*[clinic checksum: 3bbac5ce898ae630d9668fa1c8b3afb645ff22e8]*/
|
||||
{
|
||||
register PyDictObject *mp = (PyDictObject *)self;
|
||||
Py_hash_t hash;
|
||||
|
|
|
@ -159,15 +159,75 @@ meth_dealloc(PyCFunctionObject *m)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* finds the docstring's introspection signature.
|
||||
* if present, returns a pointer pointing to the first '('.
|
||||
* otherwise returns NULL.
|
||||
*/
|
||||
static const char *find_signature(PyCFunctionObject *m)
|
||||
{
|
||||
const char *trace = m->m_ml->ml_doc;
|
||||
const char *name = m->m_ml->ml_name;
|
||||
size_t length;
|
||||
if (!trace || !name)
|
||||
return NULL;
|
||||
length = strlen(name);
|
||||
if (strncmp(trace, name, length))
|
||||
return NULL;
|
||||
trace += length;
|
||||
if (*trace != '(')
|
||||
return NULL;
|
||||
return trace;
|
||||
}
|
||||
|
||||
/*
|
||||
* skips to the end of the docstring's instrospection signature.
|
||||
*/
|
||||
static const char *skip_signature(const char *trace)
|
||||
{
|
||||
while (*trace && *trace != '\n')
|
||||
trace++;
|
||||
return trace;
|
||||
}
|
||||
|
||||
static const char *skip_eols(const char *trace)
|
||||
{
|
||||
while (*trace == '\n')
|
||||
trace++;
|
||||
return trace;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
meth_get__text_signature__(PyCFunctionObject *m, void *closure)
|
||||
{
|
||||
const char *start = find_signature(m);
|
||||
const char *trace;
|
||||
|
||||
if (!start) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
trace = skip_signature(start);
|
||||
return PyUnicode_FromStringAndSize(start, trace - start);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
meth_get__doc__(PyCFunctionObject *m, void *closure)
|
||||
{
|
||||
const char *doc = m->m_ml->ml_doc;
|
||||
const char *doc = find_signature(m);
|
||||
|
||||
if (doc != NULL)
|
||||
return PyUnicode_FromString(doc);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
if (doc)
|
||||
doc = skip_eols(skip_signature(doc));
|
||||
else
|
||||
doc = m->m_ml->ml_doc;
|
||||
|
||||
if (!doc) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
return PyUnicode_FromString(doc);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
@ -236,6 +296,7 @@ static PyGetSetDef meth_getsets [] = {
|
|||
{"__name__", (getter)meth_get__name__, NULL, NULL},
|
||||
{"__qualname__", (getter)meth_get__qualname__, NULL, NULL},
|
||||
{"__self__", (getter)meth_get__self__, NULL, NULL},
|
||||
{"__text_signature__", (getter)meth_get__text_signature__, NULL, NULL},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -47,6 +47,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/*[clinic]
|
||||
class str
|
||||
[clinic]*/
|
||||
/*[clinic checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||
|
||||
/* --- Globals ------------------------------------------------------------
|
||||
|
||||
NOTE: In the interpreter's initialization phase, some globals are currently
|
||||
|
@ -12883,7 +12888,6 @@ unicode_swapcase(PyObject *self)
|
|||
}
|
||||
|
||||
/*[clinic]
|
||||
class str
|
||||
|
||||
@staticmethod
|
||||
str.maketrans as unicode_maketrans
|
||||
|
@ -12908,10 +12912,9 @@ must be a string, whose characters will be mapped to None in the result.
|
|||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(unicode_maketrans__doc__,
|
||||
"maketrans(x, y=None, z=None)\n"
|
||||
"Return a translation table usable for str.translate().\n"
|
||||
"\n"
|
||||
"str.maketrans(x, y=None, z=None)\n"
|
||||
"\n"
|
||||
"If there is only one argument, it must be a dictionary mapping Unicode\n"
|
||||
"ordinals (integers) or characters to Unicode ordinals, strings or None.\n"
|
||||
"Character keys will be then converted to ordinals.\n"
|
||||
|
@ -12946,7 +12949,7 @@ exit:
|
|||
|
||||
static PyObject *
|
||||
unicode_maketrans_impl(void *null, PyObject *x, PyObject *y, PyObject *z)
|
||||
/*[clinic checksum: 6d522e3aea2f2e123da3c5d367132a99d803f9b9]*/
|
||||
/*[clinic checksum: 7f76f414a0dfd0c614e0d4717872eeb520516da7]*/
|
||||
{
|
||||
PyObject *new = NULL, *key, *value;
|
||||
Py_ssize_t i = 0;
|
||||
|
|
|
@ -24,17 +24,6 @@ import tempfile
|
|||
import textwrap
|
||||
|
||||
# TODO:
|
||||
# converters for
|
||||
#
|
||||
# es
|
||||
# es#
|
||||
# et
|
||||
# et#
|
||||
# s#
|
||||
# u#
|
||||
# y#
|
||||
# z#
|
||||
# Z#
|
||||
#
|
||||
# soon:
|
||||
#
|
||||
|
@ -44,12 +33,6 @@ import textwrap
|
|||
# * max and min use positional only with an optional group
|
||||
# and keyword-only
|
||||
#
|
||||
# * Generate forward slash for docstring first line
|
||||
# (if I get positional-only syntax pep accepted)
|
||||
#
|
||||
# * Add "version" directive, so we can complain if the file
|
||||
# is too new for us.
|
||||
#
|
||||
|
||||
version = '1'
|
||||
|
||||
|
@ -2441,7 +2424,7 @@ class DSLParser:
|
|||
## docstring first line
|
||||
##
|
||||
|
||||
add(f.full_name)
|
||||
add(f.name)
|
||||
add('(')
|
||||
|
||||
# populate "right_bracket_count" field for every parameter
|
||||
|
@ -2498,29 +2481,32 @@ class DSLParser:
|
|||
add(fix_right_bracket_count(0))
|
||||
add(')')
|
||||
|
||||
if f.return_converter.doc_default:
|
||||
add(' -> ')
|
||||
add(f.return_converter.doc_default)
|
||||
# if f.return_converter.doc_default:
|
||||
# add(' -> ')
|
||||
# add(f.return_converter.doc_default)
|
||||
|
||||
docstring_first_line = output()
|
||||
|
||||
# now fix up the places where the brackets look wrong
|
||||
docstring_first_line = docstring_first_line.replace(', ]', ',] ')
|
||||
|
||||
# okay. now we're officially building the
|
||||
# "prototype" section.
|
||||
add(docstring_first_line)
|
||||
|
||||
# okay. now we're officially building the "parameters" section.
|
||||
# create substitution text for {parameters}
|
||||
spacer_line = False
|
||||
for p in parameters:
|
||||
if not p.docstring.strip():
|
||||
continue
|
||||
add('\n')
|
||||
if spacer_line:
|
||||
add('\n')
|
||||
else:
|
||||
spacer_line = True
|
||||
add(" ")
|
||||
add(p.name)
|
||||
add('\n')
|
||||
add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
|
||||
prototype = output()
|
||||
parameters = output()
|
||||
if parameters:
|
||||
parameters += '\n'
|
||||
|
||||
##
|
||||
## docstring body
|
||||
|
@ -2549,21 +2535,26 @@ class DSLParser:
|
|||
elif len(lines) == 1:
|
||||
# the docstring is only one line right now--the summary line.
|
||||
# add an empty line after the summary line so we have space
|
||||
# between it and the {prototype} we're about to add.
|
||||
# between it and the {parameters} we're about to add.
|
||||
lines.append('')
|
||||
|
||||
prototype_marker_count = len(docstring.split('{prototype}')) - 1
|
||||
if prototype_marker_count:
|
||||
fail('You may not specify {prototype} in a docstring!')
|
||||
# insert *after* the summary line
|
||||
lines.insert(2, '{prototype}\n')
|
||||
parameters_marker_count = len(docstring.split('{parameters}')) - 1
|
||||
if parameters_marker_count > 1:
|
||||
fail('You may not specify {parameters} more than once in a docstring!')
|
||||
|
||||
if not parameters_marker_count:
|
||||
# insert after summary line
|
||||
lines.insert(2, '{parameters}')
|
||||
|
||||
# insert at front of docstring
|
||||
lines.insert(0, docstring_first_line)
|
||||
|
||||
docstring = "\n".join(lines)
|
||||
|
||||
add(docstring)
|
||||
docstring = output()
|
||||
|
||||
docstring = linear_format(docstring, prototype=prototype)
|
||||
docstring = linear_format(docstring, parameters=parameters)
|
||||
docstring = docstring.rstrip()
|
||||
|
||||
return docstring
|
||||
|
|
Loading…
Reference in New Issue