Issue #16612: Add "Argument Clinic", a compile-time preprocessor
for C files to generate argument parsing code. (See PEP 436.)
This commit is contained in:
parent
5ceae41083
commit
3182680210
|
@ -10,6 +10,9 @@ Projected release date: 2013-10-20
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #16612: Add "Argument Clinic", a compile-time preprocessor for
|
||||||
|
C files to generate argument parsing code. (See PEP 436.)
|
||||||
|
|
||||||
- Issue #18810: Shift stat calls in importlib.machinery.FileFinder such that
|
- Issue #18810: Shift stat calls in importlib.machinery.FileFinder such that
|
||||||
the code is optimistic that if something exists in a directory named exactly
|
the code is optimistic that if something exists in a directory named exactly
|
||||||
like the possible package being searched for that it's in actuality a
|
like the possible package being searched for that it's in actuality a
|
||||||
|
|
|
@ -549,68 +549,141 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo)
|
||||||
|
|
||||||
/* Addch, Addstr, Addnstr */
|
/* Addch, Addstr, Addnstr */
|
||||||
|
|
||||||
|
/*[clinic]
|
||||||
|
module curses
|
||||||
|
|
||||||
|
class curses.window
|
||||||
|
|
||||||
|
curses.window.addch
|
||||||
|
|
||||||
|
[
|
||||||
|
x: int
|
||||||
|
X-coordinate.
|
||||||
|
y: int
|
||||||
|
Y-coordinate.
|
||||||
|
]
|
||||||
|
|
||||||
|
ch: object
|
||||||
|
Character to add.
|
||||||
|
|
||||||
|
[
|
||||||
|
attr: long
|
||||||
|
Attributes for the character.
|
||||||
|
]
|
||||||
|
/
|
||||||
|
|
||||||
|
Paint character ch at (y, x) with attributes attr.
|
||||||
|
|
||||||
|
Paint character ch at (y, x) with attributes attr,
|
||||||
|
overwriting any character previously painted at that location.
|
||||||
|
By default, the character position and attributes are the
|
||||||
|
current settings for the window object.
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(curses_window_addch__doc__,
|
||||||
|
"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"
|
||||||
|
" Y-coordinate.\n"
|
||||||
|
" ch\n"
|
||||||
|
" Character to add.\n"
|
||||||
|
" attr\n"
|
||||||
|
" Attributes for the character.\n"
|
||||||
|
"\n"
|
||||||
|
"Paint character ch at (y, x) with attributes attr,\n"
|
||||||
|
"overwriting any character previously painted at that location.\n"
|
||||||
|
"By default, the character position and attributes are the\n"
|
||||||
|
"current settings for the window object.");
|
||||||
|
|
||||||
|
#define CURSES_WINDOW_ADDCH_METHODDEF \
|
||||||
|
{"addch", (PyCFunction)curses_window_addch, METH_VARARGS, curses_window_addch__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PyCursesWindow_AddCh(PyCursesWindowObject *self, PyObject *args)
|
curses_window_addch_impl(PyObject *self, int group_left_1, int x, int y, PyObject *ch, int group_right_1, long attr);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
curses_window_addch(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int rtn, x, y, use_xy = FALSE;
|
PyObject *return_value = NULL;
|
||||||
PyObject *chobj;
|
int group_left_1 = 0;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
PyObject *ch;
|
||||||
|
int group_right_1 = 0;
|
||||||
|
long attr;
|
||||||
|
|
||||||
|
switch (PyTuple_Size(args)) {
|
||||||
|
case 1:
|
||||||
|
if (!PyArg_ParseTuple(args, "O:addch", &ch))
|
||||||
|
return NULL;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!PyArg_ParseTuple(args, "Ol:addch", &ch, &attr))
|
||||||
|
return NULL;
|
||||||
|
group_right_1 = 1;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (!PyArg_ParseTuple(args, "iiO:addch", &x, &y, &ch))
|
||||||
|
return NULL;
|
||||||
|
group_left_1 = 1;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (!PyArg_ParseTuple(args, "iiOl:addch", &x, &y, &ch, &attr))
|
||||||
|
return NULL;
|
||||||
|
group_right_1 = 1;
|
||||||
|
group_left_1 = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PyErr_SetString(PyExc_TypeError, "curses.window.addch requires 1 to 4 arguments");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return_value = curses_window_addch_impl(self, group_left_1, x, y, ch, group_right_1, attr);
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
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: 98ade780397a48d0be48439763424b3b00c92089]*/
|
||||||
|
{
|
||||||
|
PyCursesWindowObject *cwself = (PyCursesWindowObject *)self;
|
||||||
|
int coordinates_group = group_left_1;
|
||||||
|
int attr_group = group_right_1;
|
||||||
|
int rtn;
|
||||||
int type;
|
int type;
|
||||||
chtype ch;
|
chtype cch;
|
||||||
#ifdef HAVE_NCURSESW
|
#ifdef HAVE_NCURSESW
|
||||||
cchar_t wch;
|
cchar_t wch;
|
||||||
#endif
|
#endif
|
||||||
attr_t attr = A_NORMAL;
|
|
||||||
long lattr;
|
|
||||||
const char *funcname;
|
const char *funcname;
|
||||||
|
|
||||||
switch (PyTuple_Size(args)) {
|
if (!attr_group)
|
||||||
case 1:
|
attr = A_NORMAL;
|
||||||
if (!PyArg_ParseTuple(args, "O;ch or int", &chobj))
|
|
||||||
return NULL;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &chobj, &lattr))
|
|
||||||
return NULL;
|
|
||||||
attr = lattr;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &chobj))
|
|
||||||
return NULL;
|
|
||||||
use_xy = TRUE;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr",
|
|
||||||
&y, &x, &chobj, &lattr))
|
|
||||||
return NULL;
|
|
||||||
attr = lattr;
|
|
||||||
use_xy = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PyErr_SetString(PyExc_TypeError, "addch requires 1 to 4 arguments");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_NCURSESW
|
#ifdef HAVE_NCURSESW
|
||||||
type = PyCurses_ConvertToCchar_t(self, chobj, &ch, &wch);
|
type = PyCurses_ConvertToCchar_t(cwself, ch, &cch, &wch);
|
||||||
if (type == 2) {
|
if (type == 2) {
|
||||||
funcname = "add_wch";
|
funcname = "add_wch";
|
||||||
wch.attr = attr;
|
wch.attr = attr;
|
||||||
if (use_xy == TRUE)
|
if (coordinates_group)
|
||||||
rtn = mvwadd_wch(self->win,y,x, &wch);
|
rtn = mvwadd_wch(cwself->win,y,x, &wch);
|
||||||
else {
|
else {
|
||||||
rtn = wadd_wch(self->win, &wch);
|
rtn = wadd_wch(cwself->win, &wch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#else
|
#else
|
||||||
type = PyCurses_ConvertToCchar_t(self, chobj, &ch);
|
type = PyCurses_ConvertToCchar_t(cwself, chobj, &cch);
|
||||||
#endif
|
#endif
|
||||||
if (type == 1) {
|
if (type == 1) {
|
||||||
funcname = "addch";
|
funcname = "addch";
|
||||||
if (use_xy == TRUE)
|
if (coordinates_group)
|
||||||
rtn = mvwaddch(self->win,y,x, ch | attr);
|
rtn = mvwaddch(cwself->win,y,x, cch | attr);
|
||||||
else {
|
else {
|
||||||
rtn = waddch(self->win, ch | attr);
|
rtn = waddch(cwself->win, cch | attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1954,7 +2027,7 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value)
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef PyCursesWindow_Methods[] = {
|
static PyMethodDef PyCursesWindow_Methods[] = {
|
||||||
{"addch", (PyCFunction)PyCursesWindow_AddCh, METH_VARARGS},
|
CURSES_WINDOW_ADDCH_METHODDEF
|
||||||
{"addnstr", (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS},
|
{"addnstr", (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS},
|
||||||
{"addstr", (PyCFunction)PyCursesWindow_AddStr, METH_VARARGS},
|
{"addstr", (PyCFunction)PyCursesWindow_AddStr, METH_VARARGS},
|
||||||
{"attroff", (PyCFunction)PyCursesWindow_AttrOff, METH_VARARGS},
|
{"attroff", (PyCFunction)PyCursesWindow_AttrOff, METH_VARARGS},
|
||||||
|
|
|
@ -4143,31 +4143,73 @@ datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
|
||||||
tzinfo);
|
tzinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return best possible local time -- this isn't constrained by the
|
/*[clinic]
|
||||||
* precision of a timestamp.
|
module datetime
|
||||||
*/
|
|
||||||
|
@classmethod
|
||||||
|
datetime.now
|
||||||
|
|
||||||
|
tz: object = None
|
||||||
|
Timezone object.
|
||||||
|
|
||||||
|
Returns new datetime object representing current time local to tz.
|
||||||
|
|
||||||
|
If no tz is specified, uses local timezone.
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(datetime_now__doc__,
|
||||||
|
"Returns new datetime object representing current time local to tz.\n"
|
||||||
|
"\n"
|
||||||
|
"datetime.now(tz=None)\n"
|
||||||
|
" tz\n"
|
||||||
|
" Timezone object.\n"
|
||||||
|
"\n"
|
||||||
|
"If no tz is specified, uses local timezone.");
|
||||||
|
|
||||||
|
#define DATETIME_NOW_METHODDEF \
|
||||||
|
{"now", (PyCFunction)datetime_now, METH_VARARGS|METH_KEYWORDS|METH_CLASS, datetime_now__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetime_now(PyObject *cls, PyObject *args, PyObject *kw)
|
datetime_now_impl(PyObject *cls, PyObject *tz);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
datetime_now(PyObject *cls, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
static char *_keywords[] = {"tz", NULL};
|
||||||
|
PyObject *tz = Py_None;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||||
|
"|O:now", _keywords,
|
||||||
|
&tz))
|
||||||
|
goto exit;
|
||||||
|
return_value = datetime_now_impl(cls, tz);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
datetime_now_impl(PyObject *cls, PyObject *tz)
|
||||||
|
/*[clinic checksum: 328b54387f4c2f8cb534997e1bd55f8cb38c4992]*/
|
||||||
{
|
{
|
||||||
PyObject *self;
|
PyObject *self;
|
||||||
PyObject *tzinfo = Py_None;
|
|
||||||
static char *keywords[] = {"tz", NULL};
|
|
||||||
|
|
||||||
if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
|
/* Return best possible local time -- this isn't constrained by the
|
||||||
&tzinfo))
|
* precision of a timestamp.
|
||||||
return NULL;
|
*/
|
||||||
if (check_tzinfo_subclass(tzinfo) < 0)
|
if (check_tzinfo_subclass(tz) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
self = datetime_best_possible(cls,
|
self = datetime_best_possible(cls,
|
||||||
tzinfo == Py_None ? localtime : gmtime,
|
tz == Py_None ? localtime : gmtime,
|
||||||
tzinfo);
|
tz);
|
||||||
if (self != NULL && tzinfo != Py_None) {
|
if (self != NULL && tz != Py_None) {
|
||||||
/* Convert UTC to tzinfo's zone. */
|
/* Convert UTC to tzinfo's zone. */
|
||||||
PyObject *temp = self;
|
PyObject *temp = self;
|
||||||
_Py_IDENTIFIER(fromutc);
|
_Py_IDENTIFIER(fromutc);
|
||||||
|
|
||||||
self = _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "O", self);
|
self = _PyObject_CallMethodId(tz, &PyId_fromutc, "O", self);
|
||||||
Py_DECREF(temp);
|
Py_DECREF(temp);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
@ -5001,9 +5043,7 @@ static PyMethodDef datetime_methods[] = {
|
||||||
|
|
||||||
/* Class methods: */
|
/* Class methods: */
|
||||||
|
|
||||||
{"now", (PyCFunction)datetime_now,
|
DATETIME_NOW_METHODDEF
|
||||||
METH_VARARGS | METH_KEYWORDS | METH_CLASS,
|
|
||||||
PyDoc_STR("[tz] -> new datetime with tz's local day and time.")},
|
|
||||||
|
|
||||||
{"utcnow", (PyCFunction)datetime_utcnow,
|
{"utcnow", (PyCFunction)datetime_utcnow,
|
||||||
METH_NOARGS | METH_CLASS,
|
METH_NOARGS | METH_CLASS,
|
||||||
|
|
|
@ -44,7 +44,7 @@ static PyTypeObject Dbmtype;
|
||||||
static PyObject *DbmError;
|
static PyObject *DbmError;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
newdbmobject(char *file, int flags, int mode)
|
newdbmobject(const char *file, int flags, int mode)
|
||||||
{
|
{
|
||||||
dbmobject *dp;
|
dbmobject *dp;
|
||||||
|
|
||||||
|
@ -361,16 +361,69 @@ static PyTypeObject Dbmtype = {
|
||||||
|
|
||||||
/* ----------------------------------------------------------------- */
|
/* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*[clinic]
|
||||||
|
module dbm
|
||||||
|
|
||||||
|
dbm.open as dbmopen
|
||||||
|
|
||||||
|
filename: str
|
||||||
|
The filename to open.
|
||||||
|
|
||||||
|
flags: str="r"
|
||||||
|
How to open the file. "r" for reading, "w" for writing, etc.
|
||||||
|
|
||||||
|
mode: int(doc_default="0o666") = 0o666
|
||||||
|
If creating a new file, the mode bits for the new file
|
||||||
|
(e.g. os.O_RDWR).
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a database object.
|
||||||
|
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(dbmopen__doc__,
|
||||||
|
"Return a database object.\n"
|
||||||
|
"\n"
|
||||||
|
"dbm.open(filename, flags=\'r\', mode=0o666)\n"
|
||||||
|
" filename\n"
|
||||||
|
" The filename to open.\n"
|
||||||
|
" flags\n"
|
||||||
|
" How to open the file. \"r\" for reading, \"w\" for writing, etc.\n"
|
||||||
|
" mode\n"
|
||||||
|
" If creating a new file, the mode bits for the new file\n"
|
||||||
|
" (e.g. os.O_RDWR).");
|
||||||
|
|
||||||
|
#define DBMOPEN_METHODDEF \
|
||||||
|
{"open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
dbmopen_impl(PyObject *self, const char *filename, const char *flags, int mode);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
dbmopen(PyObject *self, PyObject *args)
|
dbmopen(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *name;
|
PyObject *return_value = NULL;
|
||||||
char *flags = "r";
|
const char *filename;
|
||||||
int iflags;
|
const char *flags = "r";
|
||||||
int mode = 0666;
|
int mode = 438;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args,
|
||||||
|
"s|si:open",
|
||||||
|
&filename, &flags, &mode))
|
||||||
|
goto exit;
|
||||||
|
return_value = dbmopen_impl(self, filename, flags, mode);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
dbmopen_impl(PyObject *self, const char *filename, const char *flags, int mode)
|
||||||
|
/*[clinic checksum: 61007c796d38af85c8035afa769fb4bb453429ee]*/
|
||||||
|
{
|
||||||
|
int iflags;
|
||||||
|
|
||||||
if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
|
|
||||||
return NULL;
|
|
||||||
if ( strcmp(flags, "r") == 0 )
|
if ( strcmp(flags, "r") == 0 )
|
||||||
iflags = O_RDONLY;
|
iflags = O_RDONLY;
|
||||||
else if ( strcmp(flags, "w") == 0 )
|
else if ( strcmp(flags, "w") == 0 )
|
||||||
|
@ -386,13 +439,11 @@ dbmopen(PyObject *self, PyObject *args)
|
||||||
"arg 2 to open should be 'r', 'w', 'c', or 'n'");
|
"arg 2 to open should be 'r', 'w', 'c', or 'n'");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return newdbmobject(name, iflags, mode);
|
return newdbmobject(filename, iflags, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef dbmmodule_methods[] = {
|
static PyMethodDef dbmmodule_methods[] = {
|
||||||
{ "open", (PyCFunction)dbmopen, METH_VARARGS,
|
DBMOPEN_METHODDEF
|
||||||
"open(path[, flag[, mode]]) -> mapping\n"
|
|
||||||
"Return a database object."},
|
|
||||||
{ 0, 0 },
|
{ 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,25 +4,54 @@
|
||||||
#define GET_WEAKREFS_LISTPTR(o) \
|
#define GET_WEAKREFS_LISTPTR(o) \
|
||||||
((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
|
((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
|
||||||
|
|
||||||
|
/*[clinic]
|
||||||
|
|
||||||
PyDoc_STRVAR(weakref_getweakrefcount__doc__,
|
module _weakref
|
||||||
"getweakrefcount(object) -- return the number of weak references\n"
|
|
||||||
"to 'object'.");
|
_weakref.getweakrefcount -> Py_ssize_t
|
||||||
|
|
||||||
|
object: object
|
||||||
|
/
|
||||||
|
|
||||||
|
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)");
|
||||||
|
|
||||||
|
#define _WEAKREF_GETWEAKREFCOUNT_METHODDEF \
|
||||||
|
{"getweakrefcount", (PyCFunction)_weakref_getweakrefcount, METH_O, _weakref_getweakrefcount__doc__},
|
||||||
|
|
||||||
|
static Py_ssize_t
|
||||||
|
_weakref_getweakrefcount_impl(PyObject *self, PyObject *object);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
weakref_getweakrefcount(PyObject *self, PyObject *object)
|
_weakref_getweakrefcount(PyObject *self, PyObject *object)
|
||||||
{
|
{
|
||||||
PyObject *result = NULL;
|
PyObject *return_value = NULL;
|
||||||
|
Py_ssize_t _return_value;
|
||||||
|
_return_value = _weakref_getweakrefcount_impl(self, object);
|
||||||
|
if ((_return_value == -1) && PyErr_Occurred())
|
||||||
|
goto exit;
|
||||||
|
return_value = PyLong_FromSsize_t(_return_value);
|
||||||
|
|
||||||
if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
|
exit:
|
||||||
PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
result = PyLong_FromSsize_t(_PyWeakref_GetWeakrefCount(*list));
|
static Py_ssize_t
|
||||||
}
|
_weakref_getweakrefcount_impl(PyObject *self, PyObject *object)
|
||||||
else
|
/*[clinic checksum: 0b7e7ddd87d483719ebac0fba364fff0ed0182d9]*/
|
||||||
result = PyLong_FromLong(0);
|
{
|
||||||
|
PyWeakReference **list;
|
||||||
|
|
||||||
return result;
|
if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
list = GET_WEAKREFS_LISTPTR(object);
|
||||||
|
return _PyWeakref_GetWeakrefCount(*list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,8 +107,7 @@ weakref_proxy(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
static PyMethodDef
|
static PyMethodDef
|
||||||
weakref_functions[] = {
|
weakref_functions[] = {
|
||||||
{"getweakrefcount", weakref_getweakrefcount, METH_O,
|
_WEAKREF_GETWEAKREFCOUNT_METHODDEF
|
||||||
weakref_getweakrefcount__doc__},
|
|
||||||
{"getweakrefs", weakref_getweakrefs, METH_O,
|
{"getweakrefs", weakref_getweakrefs, METH_O,
|
||||||
weakref_getweakrefs__doc__},
|
weakref_getweakrefs__doc__},
|
||||||
{"proxy", weakref_proxy, METH_VARARGS,
|
{"proxy", weakref_proxy, METH_VARARGS,
|
||||||
|
@ -106,7 +134,7 @@ PyInit__weakref(void)
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
|
|
||||||
m = PyModule_Create(&weakrefmodule);
|
m = PyModule_Create(&weakrefmodule);
|
||||||
|
|
||||||
if (m != NULL) {
|
if (m != NULL) {
|
||||||
Py_INCREF(&_PyWeakref_RefType);
|
Py_INCREF(&_PyWeakref_RefType);
|
||||||
PyModule_AddObject(m, "ref",
|
PyModule_AddObject(m, "ref",
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
of the compiler used. Different compilers define their own feature
|
of the compiler used. Different compilers define their own feature
|
||||||
test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */
|
test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
/*
|
/*
|
||||||
* Step 1 of support for weak-linking a number of symbols existing on
|
* Step 1 of support for weak-linking a number of symbols existing on
|
||||||
|
@ -712,7 +714,7 @@ dir_fd_converter(PyObject *o, void *p)
|
||||||
* path.function_name
|
* path.function_name
|
||||||
* If non-NULL, path_converter will use that as the name
|
* If non-NULL, path_converter will use that as the name
|
||||||
* of the function in error messages.
|
* of the function in error messages.
|
||||||
* (If path.argument_name is NULL it omits the function name.)
|
* (If path.function_name is NULL it omits the function name.)
|
||||||
* path.argument_name
|
* path.argument_name
|
||||||
* If non-NULL, path_converter will use that as the name
|
* If non-NULL, path_converter will use that as the name
|
||||||
* of the parameter in error messages.
|
* of the parameter in error messages.
|
||||||
|
@ -776,6 +778,9 @@ typedef struct {
|
||||||
PyObject *cleanup;
|
PyObject *cleanup;
|
||||||
} path_t;
|
} path_t;
|
||||||
|
|
||||||
|
#define PATH_T_INITIALIZE(function_name, nullable, allow_fd) \
|
||||||
|
{function_name, NULL, nullable, allow_fd, NULL, NULL, 0, 0, NULL, NULL}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
path_cleanup(path_t *path) {
|
path_cleanup(path_t *path) {
|
||||||
if (path->cleanup) {
|
if (path->cleanup) {
|
||||||
|
@ -1313,6 +1318,7 @@ path_error(path_t *path)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* POSIX generic methods */
|
/* POSIX generic methods */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -2347,48 +2353,145 @@ posix_do_stat(char *function_name, path_t *path,
|
||||||
return _pystat_fromstructstat(&st);
|
return _pystat_fromstructstat(&st);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_stat__doc__,
|
#ifdef HAVE_FSTATAT
|
||||||
"stat(path, *, dir_fd=None, follow_symlinks=True) -> stat result\n\n\
|
#define OS_STAT_DIR_FD_CONVERTER dir_fd_converter
|
||||||
Perform a stat system call on the given path.\n\
|
#else
|
||||||
\n\
|
#define OS_STAT_DIR_FD_CONVERTER dir_fd_unavailable
|
||||||
path may be specified as either a string or as an open file descriptor.\n\
|
#endif
|
||||||
\n\
|
|
||||||
If dir_fd is not None, it should be a file descriptor open to a directory,\n\
|
|
||||||
and path should be relative; path will then be relative to that directory.\n\
|
/*[python]
|
||||||
dir_fd may not be supported on your platform; if it is unavailable, using\n\
|
|
||||||
it will raise a NotImplementedError.\n\
|
class path_t_converter(CConverter):
|
||||||
If follow_symlinks is False, and the last element of the path is a symbolic\n\
|
|
||||||
link, stat will examine the symbolic link itself instead of the file the\n\
|
type = "path_t"
|
||||||
link points to.\n\
|
impl_by_reference = True
|
||||||
It is an error to use dir_fd or follow_symlinks when specifying path as\n\
|
parse_by_reference = True
|
||||||
an open file descriptor.");
|
|
||||||
|
converter = 'path_converter'
|
||||||
|
|
||||||
|
def converter_init(self, *, allow_fd=False, nullable=False):
|
||||||
|
def strify(value):
|
||||||
|
return str(int(bool(value)))
|
||||||
|
|
||||||
|
# right now path_t doesn't support default values.
|
||||||
|
# to support a default value, you'll need to override initialize().
|
||||||
|
|
||||||
|
assert self.default is unspecified
|
||||||
|
|
||||||
|
self.nullable = nullable
|
||||||
|
self.allow_fd = allow_fd
|
||||||
|
|
||||||
|
self.c_default = 'PATH_T_INITIALIZE("{}", {}, {})'.format(
|
||||||
|
self.function.name,
|
||||||
|
strify(nullable),
|
||||||
|
strify(allow_fd),
|
||||||
|
)
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
return "path_cleanup(&" + self.name + ");\n"
|
||||||
|
|
||||||
|
|
||||||
|
class dir_fd_converter(CConverter):
|
||||||
|
type = 'int'
|
||||||
|
converter = 'OS_STAT_DIR_FD_CONVERTER'
|
||||||
|
|
||||||
|
def converter_init(self):
|
||||||
|
if self.default in (unspecified, None):
|
||||||
|
self.c_default = 'DEFAULT_DIR_FD'
|
||||||
|
|
||||||
|
|
||||||
|
[python]*/
|
||||||
|
/*[python checksum: da39a3ee5e6b4b0d3255bfef95601890afd80709]*/
|
||||||
|
|
||||||
|
/*[clinic]
|
||||||
|
module os
|
||||||
|
|
||||||
|
os.stat -> object(doc_default='stat_result')
|
||||||
|
|
||||||
|
path : path_t(allow_fd=True)
|
||||||
|
Path to be examined; can be string, bytes, or open-file-descriptor int.
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
dir_fd : dir_fd = None
|
||||||
|
If not None, it should be a file descriptor open to a directory,
|
||||||
|
and path should be a relative string; path will then be relative to
|
||||||
|
that directory.
|
||||||
|
|
||||||
|
follow_symlinks: bool = True
|
||||||
|
If False, and the last element of the path is a symbolic link,
|
||||||
|
stat will examine the symbolic link itself instead of the file
|
||||||
|
the link points to.
|
||||||
|
|
||||||
|
Perform a stat system call on the given path.
|
||||||
|
|
||||||
|
dir_fd and follow_symlinks may not be implemented
|
||||||
|
on your platform. If they are unavailable, using them will raise a
|
||||||
|
NotImplementedError.
|
||||||
|
|
||||||
|
It's an error to use dir_fd or follow_symlinks when specifying path as
|
||||||
|
an open file descriptor.
|
||||||
|
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(os_stat__doc__,
|
||||||
|
"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"
|
||||||
|
" If not None, it should be a file descriptor open to a directory,\n"
|
||||||
|
" and path should be a relative string; path will then be relative to\n"
|
||||||
|
" that directory.\n"
|
||||||
|
" follow_symlinks\n"
|
||||||
|
" If False, and the last element of the path is a symbolic link,\n"
|
||||||
|
" stat will examine the symbolic link itself instead of the file\n"
|
||||||
|
" the link points to.\n"
|
||||||
|
"\n"
|
||||||
|
"dir_fd and follow_symlinks may not be implemented\n"
|
||||||
|
" on your platform. If they are unavailable, using them will raise a\n"
|
||||||
|
" NotImplementedError.\n"
|
||||||
|
"\n"
|
||||||
|
"It\'s an error to use dir_fd or follow_symlinks when specifying path as\n"
|
||||||
|
" an open file descriptor.");
|
||||||
|
|
||||||
|
#define OS_STAT_METHODDEF \
|
||||||
|
{"stat", (PyCFunction)os_stat, METH_VARARGS|METH_KEYWORDS, os_stat__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_stat(PyObject *self, PyObject *args, PyObject *kwargs)
|
os_stat_impl(PyObject *self, path_t *path, int dir_fd, int follow_symlinks);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_stat(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
static char *keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
|
PyObject *return_value = NULL;
|
||||||
path_t path;
|
static char *_keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
|
||||||
|
path_t path = PATH_T_INITIALIZE("stat", 0, 1);
|
||||||
int dir_fd = DEFAULT_DIR_FD;
|
int dir_fd = DEFAULT_DIR_FD;
|
||||||
int follow_symlinks = 1;
|
int follow_symlinks = 1;
|
||||||
PyObject *return_value;
|
|
||||||
|
|
||||||
memset(&path, 0, sizeof(path));
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||||
path.function_name = "stat";
|
"O&|$O&p:stat", _keywords,
|
||||||
path.allow_fd = 1;
|
path_converter, &path, OS_STAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks))
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&p:stat", keywords,
|
goto exit;
|
||||||
path_converter, &path,
|
return_value = os_stat_impl(self, &path, dir_fd, follow_symlinks);
|
||||||
#ifdef HAVE_FSTATAT
|
|
||||||
dir_fd_converter, &dir_fd,
|
exit:
|
||||||
#else
|
/* Cleanup for path */
|
||||||
dir_fd_unavailable, &dir_fd,
|
|
||||||
#endif
|
|
||||||
&follow_symlinks))
|
|
||||||
return NULL;
|
|
||||||
return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
|
|
||||||
path_cleanup(&path);
|
path_cleanup(&path);
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_stat_impl(PyObject *self, path_t *path, int dir_fd, int follow_symlinks)
|
||||||
|
/*[clinic checksum: 9d9af08e8cfafd12f94e73ea3065eb3056f99515]*/
|
||||||
|
{
|
||||||
|
return posix_do_stat("stat", path, dir_fd, follow_symlinks);
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_lstat__doc__,
|
PyDoc_STRVAR(posix_lstat__doc__,
|
||||||
"lstat(path, *, dir_fd=None) -> stat result\n\n\
|
"lstat(path, *, dir_fd=None) -> stat result\n\n\
|
||||||
Like stat(), but do not follow symbolic links.\n\
|
Like stat(), but do not follow symbolic links.\n\
|
||||||
|
@ -2414,44 +2517,120 @@ posix_lstat(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
#endif
|
#endif
|
||||||
))
|
))
|
||||||
return NULL;
|
return NULL;
|
||||||
return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
|
return_value = posix_do_stat("lstat", &path, dir_fd, follow_symlinks);
|
||||||
path_cleanup(&path);
|
path_cleanup(&path);
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_access__doc__,
|
|
||||||
"access(path, mode, *, dir_fd=None, effective_ids=False,\
|
#ifdef HAVE_FACCESSAT
|
||||||
follow_symlinks=True)\n\n\
|
#define OS_ACCESS_DIR_FD_CONVERTER dir_fd_converter
|
||||||
Use the real uid/gid to test for access to a path. Returns True if granted,\n\
|
#else
|
||||||
False otherwise.\n\
|
#define OS_ACCESS_DIR_FD_CONVERTER dir_fd_unavailable
|
||||||
\n\
|
#endif
|
||||||
If dir_fd is not None, it should be a file descriptor open to a directory,\n\
|
/*[clinic]
|
||||||
and path should be relative; path will then be relative to that directory.\n\
|
os.access -> object(doc_default='True if granted, False otherwise')
|
||||||
If effective_ids is True, access will use the effective uid/gid instead of\n\
|
|
||||||
the real uid/gid.\n\
|
path: path_t(allow_fd=True)
|
||||||
If follow_symlinks is False, and the last element of the path is a symbolic\n\
|
Path to be tested; can be string, bytes, or open-file-descriptor int.
|
||||||
link, access will examine the symbolic link itself instead of the file the\n\
|
|
||||||
link points to.\n\
|
mode: int
|
||||||
dir_fd, effective_ids, and follow_symlinks may not be implemented\n\
|
Operating-system mode bitfield. Can be F_OK to test existence,
|
||||||
on your platform. If they are unavailable, using them will raise a\n\
|
or the inclusive-OR of R_OK, W_OK, and X_OK.
|
||||||
NotImplementedError.\n\
|
|
||||||
\n\
|
*
|
||||||
Note that most operations will use the effective uid/gid, therefore this\n\
|
|
||||||
routine can be used in a suid/sgid environment to test if the invoking user\n\
|
dir_fd : dir_fd = None
|
||||||
has the specified access to the path.\n\
|
If not None, it should be a file descriptor open to a directory,
|
||||||
The mode argument can be F_OK to test existence, or the inclusive-OR\n\
|
and path should be relative; path will then be relative to that
|
||||||
of R_OK, W_OK, and X_OK.");
|
directory.
|
||||||
|
|
||||||
|
effective_ids: bool = False
|
||||||
|
If True, access will use the effective uid/gid instead of
|
||||||
|
the real uid/gid.
|
||||||
|
|
||||||
|
follow_symlinks: bool = True
|
||||||
|
If False, and the last element of the path is a symbolic link,
|
||||||
|
access will examine the symbolic link itself instead of the file
|
||||||
|
the link points to.
|
||||||
|
|
||||||
|
Use the real uid/gid to test for access to a path.
|
||||||
|
|
||||||
|
{parameters}
|
||||||
|
dir_fd, effective_ids, and follow_symlinks may not be implemented
|
||||||
|
on your platform. If they are unavailable, using them will raise a
|
||||||
|
NotImplementedError.
|
||||||
|
|
||||||
|
Note that most operations will use the effective uid/gid, therefore this
|
||||||
|
routine can be used in a suid/sgid environment to test if the invoking user
|
||||||
|
has the specified access to the path.
|
||||||
|
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(os_access__doc__,
|
||||||
|
"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"
|
||||||
|
" Operating-system mode bitfield. Can be F_OK to test existence,\n"
|
||||||
|
" or the inclusive-OR of R_OK, W_OK, and X_OK.\n"
|
||||||
|
" dir_fd\n"
|
||||||
|
" If not None, it should be a file descriptor open to a directory,\n"
|
||||||
|
" and path should be relative; path will then be relative to that\n"
|
||||||
|
" directory.\n"
|
||||||
|
" effective_ids\n"
|
||||||
|
" If True, access will use the effective uid/gid instead of\n"
|
||||||
|
" the real uid/gid.\n"
|
||||||
|
" follow_symlinks\n"
|
||||||
|
" If False, and the last element of the path is a symbolic link,\n"
|
||||||
|
" 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"
|
||||||
|
"\n"
|
||||||
|
"Note that most operations will use the effective uid/gid, therefore this\n"
|
||||||
|
" routine can be used in a suid/sgid environment to test if the invoking user\n"
|
||||||
|
" has the specified access to the path.");
|
||||||
|
|
||||||
|
#define OS_ACCESS_METHODDEF \
|
||||||
|
{"access", (PyCFunction)os_access, METH_VARARGS|METH_KEYWORDS, os_access__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
|
os_access_impl(PyObject *self, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_access(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
static char *keywords[] = {"path", "mode", "dir_fd", "effective_ids",
|
PyObject *return_value = NULL;
|
||||||
"follow_symlinks", NULL};
|
static char *_keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL};
|
||||||
path_t path;
|
path_t path = PATH_T_INITIALIZE("access", 0, 1);
|
||||||
int mode;
|
int mode;
|
||||||
int dir_fd = DEFAULT_DIR_FD;
|
int dir_fd = DEFAULT_DIR_FD;
|
||||||
int effective_ids = 0;
|
int effective_ids = 0;
|
||||||
int follow_symlinks = 1;
|
int follow_symlinks = 1;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||||
|
"O&i|$O&pp:access", _keywords,
|
||||||
|
path_converter, &path, &mode, OS_STAT_DIR_FD_CONVERTER, &dir_fd, &effective_ids, &follow_symlinks))
|
||||||
|
goto exit;
|
||||||
|
return_value = os_access_impl(self, &path, mode, dir_fd, effective_ids, follow_symlinks);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for path */
|
||||||
|
path_cleanup(&path);
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
os_access_impl(PyObject *self, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks)
|
||||||
|
/*[clinic checksum: 0147557eb43243df57ba616cc7c35f232c69bc6a]*/
|
||||||
|
{
|
||||||
PyObject *return_value = NULL;
|
PyObject *return_value = NULL;
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -2460,17 +2639,6 @@ posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
int result;
|
int result;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(&path, 0, sizeof(path));
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&pp:access", keywords,
|
|
||||||
path_converter, &path, &mode,
|
|
||||||
#ifdef HAVE_FACCESSAT
|
|
||||||
dir_fd_converter, &dir_fd,
|
|
||||||
#else
|
|
||||||
dir_fd_unavailable, &dir_fd,
|
|
||||||
#endif
|
|
||||||
&effective_ids, &follow_symlinks))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#ifndef HAVE_FACCESSAT
|
#ifndef HAVE_FACCESSAT
|
||||||
if (follow_symlinks_specified("access", follow_symlinks))
|
if (follow_symlinks_specified("access", follow_symlinks))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -2514,11 +2682,11 @@ posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
flags |= AT_SYMLINK_NOFOLLOW;
|
flags |= AT_SYMLINK_NOFOLLOW;
|
||||||
if (effective_ids)
|
if (effective_ids)
|
||||||
flags |= AT_EACCESS;
|
flags |= AT_EACCESS;
|
||||||
result = faccessat(dir_fd, path.narrow, mode, flags);
|
result = faccessat(dir_fd, path->narrow, mode, flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
result = access(path.narrow, mode);
|
result = access(path->narrow, mode);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
return_value = PyBool_FromLong(!result);
|
return_value = PyBool_FromLong(!result);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2526,7 +2694,6 @@ posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
#ifndef HAVE_FACCESSAT
|
#ifndef HAVE_FACCESSAT
|
||||||
exit:
|
exit:
|
||||||
#endif
|
#endif
|
||||||
path_cleanup(&path);
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2543,35 +2710,76 @@ exit:
|
||||||
#define X_OK 1
|
#define X_OK 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_TTYNAME
|
#ifdef HAVE_TTYNAME
|
||||||
PyDoc_STRVAR(posix_ttyname__doc__,
|
|
||||||
"ttyname(fd) -> string\n\n\
|
/*[clinic]
|
||||||
Return the name of the terminal device connected to 'fd'.");
|
os.ttyname -> DecodeFSDefault
|
||||||
|
|
||||||
|
fd: int
|
||||||
|
Integer file descriptor handle.
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
Return the name of the terminal device connected to 'fd'.
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(os_ttyname__doc__,
|
||||||
|
"Return the name of the terminal device connected to \'fd\'.\n"
|
||||||
|
"\n"
|
||||||
|
"os.ttyname(fd)\n"
|
||||||
|
" fd\n"
|
||||||
|
" Integer file descriptor handle.");
|
||||||
|
|
||||||
|
#define OS_TTYNAME_METHODDEF \
|
||||||
|
{"ttyname", (PyCFunction)os_ttyname, METH_VARARGS, os_ttyname__doc__},
|
||||||
|
|
||||||
|
static char *
|
||||||
|
os_ttyname_impl(PyObject *self, int fd);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_ttyname(PyObject *self, PyObject *args)
|
os_ttyname(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int id;
|
PyObject *return_value = NULL;
|
||||||
char *ret;
|
int fd;
|
||||||
|
char *_return_value;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "i:ttyname", &id))
|
if (!PyArg_ParseTuple(args,
|
||||||
return NULL;
|
"i:ttyname",
|
||||||
|
&fd))
|
||||||
|
goto exit;
|
||||||
|
_return_value = os_ttyname_impl(self, fd);
|
||||||
|
if (_return_value == NULL)
|
||||||
|
goto exit;
|
||||||
|
return_value = PyUnicode_DecodeFSDefault(_return_value);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
os_ttyname_impl(PyObject *self, int fd)
|
||||||
|
/*[clinic checksum: ea680155d87bb733f542d67653eca732dd0981a8]*/
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
|
||||||
#if defined(__VMS)
|
#if defined(__VMS)
|
||||||
/* file descriptor 0 only, the default input device (stdin) */
|
/* file descriptor 0 only, the default input device (stdin) */
|
||||||
if (id == 0) {
|
if (fd == 0) {
|
||||||
ret = ttyname();
|
ret = ttyname();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ret = ttyname(id);
|
ret = ttyname(fd);
|
||||||
#endif
|
#endif
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
return posix_error();
|
posix_error();
|
||||||
return PyUnicode_DecodeFSDefault(ret);
|
return ret;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define OS_TTYNAME_METHODDEF
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CTERMID
|
#ifdef HAVE_CTERMID
|
||||||
|
@ -10912,13 +11120,13 @@ posix_set_handle_inheritable(PyObject *self, PyObject *args)
|
||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef posix_methods[] = {
|
static PyMethodDef posix_methods[] = {
|
||||||
{"access", (PyCFunction)posix_access,
|
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
OS_STAT_METHODDEF
|
||||||
posix_access__doc__},
|
OS_ACCESS_METHODDEF
|
||||||
#ifdef HAVE_TTYNAME
|
OS_TTYNAME_METHODDEF
|
||||||
{"ttyname", posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
|
|
||||||
#endif
|
|
||||||
{"chdir", (PyCFunction)posix_chdir,
|
{"chdir", (PyCFunction)posix_chdir,
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
METH_VARARGS | METH_KEYWORDS,
|
||||||
posix_chdir__doc__},
|
posix_chdir__doc__},
|
||||||
|
@ -11002,9 +11210,6 @@ static PyMethodDef posix_methods[] = {
|
||||||
{"rmdir", (PyCFunction)posix_rmdir,
|
{"rmdir", (PyCFunction)posix_rmdir,
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
METH_VARARGS | METH_KEYWORDS,
|
||||||
posix_rmdir__doc__},
|
posix_rmdir__doc__},
|
||||||
{"stat", (PyCFunction)posix_stat,
|
|
||||||
METH_VARARGS | METH_KEYWORDS,
|
|
||||||
posix_stat__doc__},
|
|
||||||
{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
|
{"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
|
||||||
#if defined(HAVE_SYMLINK)
|
#if defined(HAVE_SYMLINK)
|
||||||
{"symlink", (PyCFunction)posix_symlink,
|
{"symlink", (PyCFunction)posix_symlink,
|
||||||
|
|
|
@ -107,24 +107,62 @@ static Py_UCS4 getuchar(PyUnicodeObject *obj)
|
||||||
|
|
||||||
/* --- Module API --------------------------------------------------------- */
|
/* --- Module API --------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*[clinic]
|
||||||
|
module unicodedata
|
||||||
|
unicodedata.decimal
|
||||||
|
|
||||||
|
unichr: object(type='str')
|
||||||
|
default: object=NULL
|
||||||
|
/
|
||||||
|
|
||||||
|
Converts a Unicode character into its equivalent decimal value.
|
||||||
|
|
||||||
|
Returns the decimal value assigned to the Unicode character unichr
|
||||||
|
as integer. If no such value is defined, default is returned, or, if
|
||||||
|
not given, ValueError is raised.
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
PyDoc_STRVAR(unicodedata_decimal__doc__,
|
PyDoc_STRVAR(unicodedata_decimal__doc__,
|
||||||
"decimal(unichr[, default])\n\
|
"Converts a Unicode character into its equivalent decimal value.\n"
|
||||||
\n\
|
"\n"
|
||||||
Returns the decimal value assigned to the Unicode character unichr\n\
|
"unicodedata.decimal(unichr, default=None)\n"
|
||||||
as integer. If no such value is defined, default is returned, or, if\n\
|
"\n"
|
||||||
not given, ValueError is raised.");
|
"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.");
|
||||||
|
|
||||||
|
#define UNICODEDATA_DECIMAL_METHODDEF \
|
||||||
|
{"decimal", (PyCFunction)unicodedata_decimal, METH_VARARGS, unicodedata_decimal__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicodedata_decimal_impl(PyObject *self, PyObject *unichr, PyObject *default_value);
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
unicodedata_decimal(PyObject *self, PyObject *args)
|
unicodedata_decimal(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyUnicodeObject *v;
|
PyObject *return_value = NULL;
|
||||||
PyObject *defobj = NULL;
|
PyObject *unichr;
|
||||||
|
PyObject *default_value = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args,
|
||||||
|
"O!|O:decimal",
|
||||||
|
&PyUnicode_Type, &unichr, &default_value))
|
||||||
|
goto exit;
|
||||||
|
return_value = unicodedata_decimal_impl(self, unichr, default_value);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicodedata_decimal_impl(PyObject *self, PyObject *unichr, PyObject *default_value)
|
||||||
|
/*[clinic checksum: 76c8d1c3dbee495d4cfd86ca6829543a3129344a]*/
|
||||||
|
{
|
||||||
|
PyUnicodeObject *v = (PyUnicodeObject *)unichr;
|
||||||
int have_old = 0;
|
int have_old = 0;
|
||||||
long rc;
|
long rc;
|
||||||
Py_UCS4 c;
|
Py_UCS4 c;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O!|O:decimal", &PyUnicode_Type, &v, &defobj))
|
|
||||||
return NULL;
|
|
||||||
c = getuchar(v);
|
c = getuchar(v);
|
||||||
if (c == (Py_UCS4)-1)
|
if (c == (Py_UCS4)-1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -145,14 +183,14 @@ unicodedata_decimal(PyObject *self, PyObject *args)
|
||||||
if (!have_old)
|
if (!have_old)
|
||||||
rc = Py_UNICODE_TODECIMAL(c);
|
rc = Py_UNICODE_TODECIMAL(c);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if (defobj == NULL) {
|
if (default_value == NULL) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"not a decimal");
|
"not a decimal");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Py_INCREF(defobj);
|
Py_INCREF(default_value);
|
||||||
return defobj;
|
return default_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PyLong_FromLong(rc);
|
return PyLong_FromLong(rc);
|
||||||
|
@ -1250,7 +1288,7 @@ unicodedata_lookup(PyObject* self, PyObject* args)
|
||||||
/* XXX Add doc strings. */
|
/* XXX Add doc strings. */
|
||||||
|
|
||||||
static PyMethodDef unicodedata_functions[] = {
|
static PyMethodDef unicodedata_functions[] = {
|
||||||
{"decimal", unicodedata_decimal, METH_VARARGS, unicodedata_decimal__doc__},
|
UNICODEDATA_DECIMAL_METHODDEF
|
||||||
{"digit", unicodedata_digit, METH_VARARGS, unicodedata_digit__doc__},
|
{"digit", unicodedata_digit, METH_VARARGS, unicodedata_digit__doc__},
|
||||||
{"numeric", unicodedata_numeric, METH_VARARGS, unicodedata_numeric__doc__},
|
{"numeric", unicodedata_numeric, METH_VARARGS, unicodedata_numeric__doc__},
|
||||||
{"category", unicodedata_category, METH_VARARGS,
|
{"category", unicodedata_category, METH_VARARGS,
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
#include "pythread.h"
|
#include "pythread.h"
|
||||||
#define ENTER_ZLIB(obj) \
|
#define ENTER_ZLIB(obj) \
|
||||||
|
@ -626,87 +627,136 @@ save_unconsumed_input(compobject *self, int err)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(decomp_decompress__doc__,
|
/*[clinic]
|
||||||
"decompress(data, max_length) -- Return a string containing the decompressed\n"
|
|
||||||
"version of the data.\n"
|
module zlib
|
||||||
|
|
||||||
|
zlib.decompress
|
||||||
|
|
||||||
|
data: Py_buffer
|
||||||
|
The binary data to decompress.
|
||||||
|
max_length: int = 0
|
||||||
|
The maximum allowable length of the decompressed data.
|
||||||
|
Unconsumed input data will be stored in
|
||||||
|
the unconsumed_tail attribute.
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a string containing the decompressed version of the data.
|
||||||
|
|
||||||
|
After calling this function, some of the input data may still be stored in
|
||||||
|
internal buffers for later processing.
|
||||||
|
Call the flush() method to clear these buffers.
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(zlib_decompress__doc__,
|
||||||
|
"Return a string containing the decompressed version of the data.\n"
|
||||||
|
"\n"
|
||||||
|
"zlib.decompress(data, max_length=0)\n"
|
||||||
|
" data\n"
|
||||||
|
" The binary data to decompress.\n"
|
||||||
|
" max_length\n"
|
||||||
|
" The maximum allowable length of the decompressed data.\n"
|
||||||
|
" Unconsumed input data will be stored in\n"
|
||||||
|
" the unconsumed_tail attribute.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"After calling this function, some of the input data may still be stored in\n"
|
"After calling this function, some of the input data may still be stored in\n"
|
||||||
"internal buffers for later processing.\n"
|
"internal buffers for later processing.\n"
|
||||||
"Call the flush() method to clear these buffers.\n"
|
"Call the flush() method to clear these buffers.");
|
||||||
"If the max_length parameter is specified then the return value will be\n"
|
|
||||||
"no longer than max_length. Unconsumed input data will be stored in\n"
|
#define ZLIB_DECOMPRESS_METHODDEF \
|
||||||
"the unconsumed_tail attribute.");
|
{"decompress", (PyCFunction)zlib_decompress, METH_VARARGS, zlib_decompress__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PyZlib_objdecompress(compobject *self, PyObject *args)
|
zlib_decompress_impl(PyObject *self, Py_buffer *data, int max_length);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
zlib_decompress(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int err, max_length = 0;
|
PyObject *return_value = NULL;
|
||||||
|
Py_buffer data;
|
||||||
|
int max_length = 0;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args,
|
||||||
|
"y*|i:decompress",
|
||||||
|
&data, &max_length))
|
||||||
|
goto exit;
|
||||||
|
return_value = zlib_decompress_impl(self, &data, max_length);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
/* Cleanup for data */
|
||||||
|
PyBuffer_Release(&data);
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
zlib_decompress_impl(PyObject *self, Py_buffer *data, int max_length)
|
||||||
|
/*[clinic checksum: 168d093d400739dde947cca1f4fb0f9d51cdc2c9]*/
|
||||||
|
{
|
||||||
|
compobject *zself = (compobject *)self;
|
||||||
|
int err;
|
||||||
unsigned int inplen;
|
unsigned int inplen;
|
||||||
Py_ssize_t old_length, length = DEFAULTALLOC;
|
Py_ssize_t old_length, length = DEFAULTALLOC;
|
||||||
PyObject *RetVal = NULL;
|
PyObject *RetVal = NULL;
|
||||||
Py_buffer pinput;
|
|
||||||
Byte *input;
|
Byte *input;
|
||||||
unsigned long start_total_out;
|
unsigned long start_total_out;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "y*|i:decompress", &pinput,
|
if (data->len > UINT_MAX) {
|
||||||
&max_length))
|
|
||||||
return NULL;
|
|
||||||
if (pinput.len > UINT_MAX) {
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"Size does not fit in an unsigned int");
|
"Size does not fit in an unsigned int");
|
||||||
goto error_outer;
|
return NULL;
|
||||||
}
|
}
|
||||||
input = pinput.buf;
|
input = data->buf;
|
||||||
inplen = pinput.len;
|
inplen = data->len;
|
||||||
if (max_length < 0) {
|
if (max_length < 0) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"max_length must be greater than zero");
|
"max_length must be greater than zero");
|
||||||
goto error_outer;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* limit amount of data allocated to max_length */
|
/* limit amount of data allocated to max_length */
|
||||||
if (max_length && length > max_length)
|
if (max_length && length > max_length)
|
||||||
length = max_length;
|
length = max_length;
|
||||||
if (!(RetVal = PyBytes_FromStringAndSize(NULL, length)))
|
if (!(RetVal = PyBytes_FromStringAndSize(NULL, length)))
|
||||||
goto error_outer;
|
return NULL;
|
||||||
|
|
||||||
ENTER_ZLIB(self);
|
ENTER_ZLIB(zself);
|
||||||
|
|
||||||
start_total_out = self->zst.total_out;
|
start_total_out = zself->zst.total_out;
|
||||||
self->zst.avail_in = inplen;
|
zself->zst.avail_in = inplen;
|
||||||
self->zst.next_in = input;
|
zself->zst.next_in = input;
|
||||||
self->zst.avail_out = length;
|
zself->zst.avail_out = length;
|
||||||
self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
|
zself->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
err = inflate(&(self->zst), Z_SYNC_FLUSH);
|
err = inflate(&(zself->zst), Z_SYNC_FLUSH);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
if (err == Z_NEED_DICT && self->zdict != NULL) {
|
if (err == Z_NEED_DICT && zself->zdict != NULL) {
|
||||||
Py_buffer zdict_buf;
|
Py_buffer zdict_buf;
|
||||||
if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
|
if (PyObject_GetBuffer(zself->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
|
||||||
Py_DECREF(RetVal);
|
Py_DECREF(RetVal);
|
||||||
RetVal = NULL;
|
RetVal = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
err = inflateSetDictionary(&(self->zst), zdict_buf.buf, zdict_buf.len);
|
err = inflateSetDictionary(&(zself->zst), zdict_buf.buf, zdict_buf.len);
|
||||||
PyBuffer_Release(&zdict_buf);
|
PyBuffer_Release(&zdict_buf);
|
||||||
if (err != Z_OK) {
|
if (err != Z_OK) {
|
||||||
zlib_error(self->zst, err, "while decompressing data");
|
zlib_error(zself->zst, err, "while decompressing data");
|
||||||
Py_DECREF(RetVal);
|
Py_DECREF(RetVal);
|
||||||
RetVal = NULL;
|
RetVal = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
/* Repeat the call to inflate. */
|
/* Repeat the call to inflate. */
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
err = inflate(&(self->zst), Z_SYNC_FLUSH);
|
err = inflate(&(zself->zst), Z_SYNC_FLUSH);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
}
|
}
|
||||||
|
|
||||||
/* While Z_OK and the output buffer is full, there might be more output.
|
/* While Z_OK and the output buffer is full, there might be more output.
|
||||||
So extend the output buffer and try again.
|
So extend the output buffer and try again.
|
||||||
*/
|
*/
|
||||||
while (err == Z_OK && self->zst.avail_out == 0) {
|
while (err == Z_OK && zself->zst.avail_out == 0) {
|
||||||
/* If max_length set, don't continue decompressing if we've already
|
/* If max_length set, don't continue decompressing if we've already
|
||||||
reached the limit.
|
reached the limit.
|
||||||
*/
|
*/
|
||||||
|
@ -723,16 +773,16 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
|
||||||
Py_CLEAR(RetVal);
|
Py_CLEAR(RetVal);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
self->zst.next_out =
|
zself->zst.next_out =
|
||||||
(unsigned char *)PyBytes_AS_STRING(RetVal) + old_length;
|
(unsigned char *)PyBytes_AS_STRING(RetVal) + old_length;
|
||||||
self->zst.avail_out = length - old_length;
|
zself->zst.avail_out = length - old_length;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
err = inflate(&(self->zst), Z_SYNC_FLUSH);
|
err = inflate(&(zself->zst), Z_SYNC_FLUSH);
|
||||||
Py_END_ALLOW_THREADS
|
Py_END_ALLOW_THREADS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (save_unconsumed_input(self, err) < 0) {
|
if (save_unconsumed_input(zself, err) < 0) {
|
||||||
Py_DECREF(RetVal);
|
Py_DECREF(RetVal);
|
||||||
RetVal = NULL;
|
RetVal = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -741,26 +791,24 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
|
||||||
if (err == Z_STREAM_END) {
|
if (err == Z_STREAM_END) {
|
||||||
/* This is the logical place to call inflateEnd, but the old behaviour
|
/* This is the logical place to call inflateEnd, but the old behaviour
|
||||||
of only calling it on flush() is preserved. */
|
of only calling it on flush() is preserved. */
|
||||||
self->eof = 1;
|
zself->eof = 1;
|
||||||
} else if (err != Z_OK && err != Z_BUF_ERROR) {
|
} else if (err != Z_OK && err != Z_BUF_ERROR) {
|
||||||
/* We will only get Z_BUF_ERROR if the output buffer was full
|
/* We will only get Z_BUF_ERROR if the output buffer was full
|
||||||
but there wasn't more output when we tried again, so it is
|
but there wasn't more output when we tried again, so it is
|
||||||
not an error condition.
|
not an error condition.
|
||||||
*/
|
*/
|
||||||
zlib_error(self->zst, err, "while decompressing data");
|
zlib_error(zself->zst, err, "while decompressing data");
|
||||||
Py_DECREF(RetVal);
|
Py_DECREF(RetVal);
|
||||||
RetVal = NULL;
|
RetVal = NULL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) {
|
if (_PyBytes_Resize(&RetVal, zself->zst.total_out - start_total_out) < 0) {
|
||||||
Py_CLEAR(RetVal);
|
Py_CLEAR(RetVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
LEAVE_ZLIB(self);
|
LEAVE_ZLIB(zself);
|
||||||
error_outer:
|
|
||||||
PyBuffer_Release(&pinput);
|
|
||||||
return RetVal;
|
return RetVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,12 +904,27 @@ PyZlib_flush(compobject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_COPY
|
#ifdef HAVE_ZLIB_COPY
|
||||||
PyDoc_STRVAR(comp_copy__doc__,
|
|
||||||
"copy() -- Return a copy of the compression object.");
|
/*[clinic]
|
||||||
|
|
||||||
|
zlib.copy
|
||||||
|
|
||||||
|
Return a copy of the compression object.
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(zlib_copy__doc__,
|
||||||
|
"Return a copy of the compression object.\n"
|
||||||
|
"\n"
|
||||||
|
"zlib.copy()");
|
||||||
|
|
||||||
|
#define ZLIB_COPY_METHODDEF \
|
||||||
|
{"copy", (PyCFunction)zlib_copy, METH_NOARGS, zlib_copy__doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
PyZlib_copy(compobject *self)
|
zlib_copy(PyObject *self)
|
||||||
|
/*[clinic checksum: 7b648de2c1f933ba2b9fa17331ff1a44d9a4a740]*/
|
||||||
{
|
{
|
||||||
|
compobject *zself = (compobject *)self;
|
||||||
compobject *retval = NULL;
|
compobject *retval = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -871,8 +934,8 @@ PyZlib_copy(compobject *self)
|
||||||
/* Copy the zstream state
|
/* Copy the zstream state
|
||||||
* We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
|
* We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
|
||||||
*/
|
*/
|
||||||
ENTER_ZLIB(self);
|
ENTER_ZLIB(zself);
|
||||||
err = deflateCopy(&retval->zst, &self->zst);
|
err = deflateCopy(&retval->zst, &zself->zst);
|
||||||
switch(err) {
|
switch(err) {
|
||||||
case(Z_OK):
|
case(Z_OK):
|
||||||
break;
|
break;
|
||||||
|
@ -884,28 +947,28 @@ PyZlib_copy(compobject *self)
|
||||||
"Can't allocate memory for compression object");
|
"Can't allocate memory for compression object");
|
||||||
goto error;
|
goto error;
|
||||||
default:
|
default:
|
||||||
zlib_error(self->zst, err, "while copying compression object");
|
zlib_error(zself->zst, err, "while copying compression object");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
Py_INCREF(self->unused_data);
|
Py_INCREF(zself->unused_data);
|
||||||
Py_INCREF(self->unconsumed_tail);
|
Py_INCREF(zself->unconsumed_tail);
|
||||||
Py_XINCREF(self->zdict);
|
Py_XINCREF(zself->zdict);
|
||||||
Py_XDECREF(retval->unused_data);
|
Py_XDECREF(retval->unused_data);
|
||||||
Py_XDECREF(retval->unconsumed_tail);
|
Py_XDECREF(retval->unconsumed_tail);
|
||||||
Py_XDECREF(retval->zdict);
|
Py_XDECREF(retval->zdict);
|
||||||
retval->unused_data = self->unused_data;
|
retval->unused_data = zself->unused_data;
|
||||||
retval->unconsumed_tail = self->unconsumed_tail;
|
retval->unconsumed_tail = zself->unconsumed_tail;
|
||||||
retval->zdict = self->zdict;
|
retval->zdict = zself->zdict;
|
||||||
retval->eof = self->eof;
|
retval->eof = zself->eof;
|
||||||
|
|
||||||
/* Mark it as being initialized */
|
/* Mark it as being initialized */
|
||||||
retval->is_initialised = 1;
|
retval->is_initialised = 1;
|
||||||
|
|
||||||
LEAVE_ZLIB(self);
|
LEAVE_ZLIB(zself);
|
||||||
return (PyObject *)retval;
|
return (PyObject *)retval;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
LEAVE_ZLIB(self);
|
LEAVE_ZLIB(zself);
|
||||||
Py_XDECREF(retval);
|
Py_XDECREF(retval);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1055,16 +1118,14 @@ static PyMethodDef comp_methods[] =
|
||||||
{"flush", (binaryfunc)PyZlib_flush, METH_VARARGS,
|
{"flush", (binaryfunc)PyZlib_flush, METH_VARARGS,
|
||||||
comp_flush__doc__},
|
comp_flush__doc__},
|
||||||
#ifdef HAVE_ZLIB_COPY
|
#ifdef HAVE_ZLIB_COPY
|
||||||
{"copy", (PyCFunction)PyZlib_copy, METH_NOARGS,
|
ZLIB_COPY_METHODDEF
|
||||||
comp_copy__doc__},
|
|
||||||
#endif
|
#endif
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMethodDef Decomp_methods[] =
|
static PyMethodDef Decomp_methods[] =
|
||||||
{
|
{
|
||||||
{"decompress", (binaryfunc)PyZlib_objdecompress, METH_VARARGS,
|
ZLIB_DECOMPRESS_METHODDEF
|
||||||
decomp_decompress__doc__},
|
|
||||||
{"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS,
|
{"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS,
|
||||||
decomp_flush__doc__},
|
decomp_flush__doc__},
|
||||||
#ifdef HAVE_ZLIB_COPY
|
#ifdef HAVE_ZLIB_COPY
|
||||||
|
|
|
@ -2160,9 +2160,31 @@ dict_richcompare(PyObject *v, PyObject *w, int op)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic]
|
||||||
|
module dict
|
||||||
|
|
||||||
|
@coexist
|
||||||
|
dict.__contains__
|
||||||
|
|
||||||
|
key: object
|
||||||
|
/
|
||||||
|
|
||||||
|
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)");
|
||||||
|
|
||||||
|
#define DICT___CONTAINS___METHODDEF \
|
||||||
|
{"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__},
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
dict_contains(PyDictObject *mp, PyObject *key)
|
dict___contains__(PyObject *self, PyObject *key)
|
||||||
|
/*[clinic checksum: 61c5c802ea1d35699a1a754f1f3538ea9b259cf4]*/
|
||||||
{
|
{
|
||||||
|
register PyDictObject *mp = (PyDictObject *)self;
|
||||||
Py_hash_t hash;
|
Py_hash_t hash;
|
||||||
PyDictKeyEntry *ep;
|
PyDictKeyEntry *ep;
|
||||||
PyObject **value_addr;
|
PyObject **value_addr;
|
||||||
|
@ -2447,9 +2469,6 @@ _PyDict_KeysSize(PyDictKeysObject *keys)
|
||||||
return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
|
return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(contains__doc__,
|
|
||||||
"D.__contains__(k) -> True if D has a key k, else False");
|
|
||||||
|
|
||||||
PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
|
PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
|
||||||
|
|
||||||
PyDoc_STRVAR(sizeof__doc__,
|
PyDoc_STRVAR(sizeof__doc__,
|
||||||
|
@ -2498,8 +2517,7 @@ PyDoc_STRVAR(values__doc__,
|
||||||
"D.values() -> an object providing a view on D's values");
|
"D.values() -> an object providing a view on D's values");
|
||||||
|
|
||||||
static PyMethodDef mapp_methods[] = {
|
static PyMethodDef mapp_methods[] = {
|
||||||
{"__contains__",(PyCFunction)dict_contains, METH_O | METH_COEXIST,
|
DICT___CONTAINS___METHODDEF
|
||||||
contains__doc__},
|
|
||||||
{"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
|
{"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
|
||||||
getitem__doc__},
|
getitem__doc__},
|
||||||
{"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,
|
{"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,
|
||||||
|
|
|
@ -12656,28 +12656,76 @@ unicode_swapcase(PyObject *self)
|
||||||
return case_operation(self, do_swapcase);
|
return case_operation(self, do_swapcase);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(maketrans__doc__,
|
/*[clinic]
|
||||||
"str.maketrans(x[, y[, z]]) -> dict (static method)\n\
|
module str
|
||||||
\n\
|
|
||||||
Return a translation table usable for str.translate().\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\
|
|
||||||
If there are two arguments, they must be strings of equal length, and\n\
|
|
||||||
in the resulting dictionary, each character in x will be mapped to the\n\
|
|
||||||
character at the same position in y. If there is a third argument, it\n\
|
|
||||||
must be a string, whose characters will be mapped to None in the result.");
|
|
||||||
|
|
||||||
static PyObject*
|
@staticmethod
|
||||||
|
str.maketrans as unicode_maketrans
|
||||||
|
|
||||||
|
x: object
|
||||||
|
|
||||||
|
y: unicode=NULL
|
||||||
|
|
||||||
|
z: unicode=NULL
|
||||||
|
|
||||||
|
/
|
||||||
|
|
||||||
|
Return a translation table usable for str.translate().
|
||||||
|
|
||||||
|
If there is only one argument, it must be a dictionary mapping Unicode
|
||||||
|
ordinals (integers) or characters to Unicode ordinals, strings or None.
|
||||||
|
Character keys will be then converted to ordinals.
|
||||||
|
If there are two arguments, they must be strings of equal length, and
|
||||||
|
in the resulting dictionary, each character in x will be mapped to the
|
||||||
|
character at the same position in y. If there is a third argument, it
|
||||||
|
must be a string, whose characters will be mapped to None in the result.
|
||||||
|
[clinic]*/
|
||||||
|
|
||||||
|
PyDoc_STRVAR(unicode_maketrans__doc__,
|
||||||
|
"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"
|
||||||
|
"If there are two arguments, they must be strings of equal length, and\n"
|
||||||
|
"in the resulting dictionary, each character in x will be mapped to the\n"
|
||||||
|
"character at the same position in y. If there is a third argument, it\n"
|
||||||
|
"must be a string, whose characters will be mapped to None in the result.");
|
||||||
|
|
||||||
|
#define UNICODE_MAKETRANS_METHODDEF \
|
||||||
|
{"maketrans", (PyCFunction)unicode_maketrans, METH_VARARGS|METH_STATIC, unicode_maketrans__doc__},
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
unicode_maketrans(PyObject *null, PyObject *args)
|
unicode_maketrans(PyObject *null, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *x, *y = NULL, *z = NULL;
|
PyObject *return_value = NULL;
|
||||||
|
PyObject *x;
|
||||||
|
PyObject *y = NULL;
|
||||||
|
PyObject *z = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args,
|
||||||
|
"O|UU:maketrans",
|
||||||
|
&x, &y, &z))
|
||||||
|
goto exit;
|
||||||
|
return_value = unicode_maketrans_impl(x, y, z);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z)
|
||||||
|
/*[clinic checksum: 137db9c3199e7906b7967009f511c24fa3235b5f]*/
|
||||||
|
{
|
||||||
PyObject *new = NULL, *key, *value;
|
PyObject *new = NULL, *key, *value;
|
||||||
Py_ssize_t i = 0;
|
Py_ssize_t i = 0;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O|UU:maketrans", &x, &y, &z))
|
|
||||||
return NULL;
|
|
||||||
new = PyDict_New();
|
new = PyDict_New();
|
||||||
if (!new)
|
if (!new)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -13317,8 +13365,7 @@ static PyMethodDef unicode_methods[] = {
|
||||||
{"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},
|
{"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__},
|
||||||
{"format_map", (PyCFunction) do_string_format_map, METH_O, format_map__doc__},
|
{"format_map", (PyCFunction) do_string_format_map, METH_O, format_map__doc__},
|
||||||
{"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__},
|
{"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__},
|
||||||
{"maketrans", (PyCFunction) unicode_maketrans,
|
UNICODE_MAKETRANS_METHODDEF
|
||||||
METH_VARARGS | METH_STATIC, maketrans__doc__},
|
|
||||||
{"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__},
|
{"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__},
|
||||||
#if 0
|
#if 0
|
||||||
/* These methods are just used for debugging the implementation. */
|
/* These methods are just used for debugging the implementation. */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,699 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Argument Clinic
|
||||||
|
# Copyright 2012-2013 by Larry Hastings.
|
||||||
|
# Licensed to the PSF under a contributor agreement.
|
||||||
|
#
|
||||||
|
|
||||||
|
import builtins
|
||||||
|
import clinic
|
||||||
|
from clinic import DSLParser
|
||||||
|
import collections
|
||||||
|
import inspect
|
||||||
|
from test import support
|
||||||
|
import unittest
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
class FakeConverter:
|
||||||
|
def __init__(self, name, args):
|
||||||
|
self.name = name
|
||||||
|
self.args = args
|
||||||
|
|
||||||
|
|
||||||
|
class FakeConverterFactory:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __call__(self, name, default, **kwargs):
|
||||||
|
return FakeConverter(self.name, kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeConvertersDict:
|
||||||
|
def __init__(self):
|
||||||
|
self.used_converters = {}
|
||||||
|
|
||||||
|
def get(self, name, default):
|
||||||
|
return self.used_converters.setdefault(name, FakeConverterFactory(name))
|
||||||
|
|
||||||
|
class FakeClinic:
|
||||||
|
def __init__(self):
|
||||||
|
self.converters = FakeConvertersDict()
|
||||||
|
self.legacy_converters = FakeConvertersDict()
|
||||||
|
self.language = clinic.CLanguage()
|
||||||
|
self.filename = None
|
||||||
|
self.block_parser = clinic.BlockParser('', self.language)
|
||||||
|
self.modules = collections.OrderedDict()
|
||||||
|
clinic.clinic = self
|
||||||
|
self.name = "FakeClinic"
|
||||||
|
|
||||||
|
def is_directive(self, name):
|
||||||
|
return name == "module"
|
||||||
|
|
||||||
|
def directive(self, name, args):
|
||||||
|
self.called_directives[name] = args
|
||||||
|
|
||||||
|
_module_and_class = clinic.Clinic._module_and_class
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ClinicGroupPermuterTest(TestCase):
|
||||||
|
def _test(self, l, m, r, output):
|
||||||
|
computed = clinic.permute_optional_groups(l, m, r)
|
||||||
|
self.assertEqual(output, computed)
|
||||||
|
|
||||||
|
def test_range(self):
|
||||||
|
self._test([['start']], ['stop'], [['step']],
|
||||||
|
(
|
||||||
|
('stop',),
|
||||||
|
('start', 'stop',),
|
||||||
|
('start', 'stop', 'step',),
|
||||||
|
))
|
||||||
|
|
||||||
|
def test_add_window(self):
|
||||||
|
self._test([['x', 'y']], ['ch'], [['attr']],
|
||||||
|
(
|
||||||
|
('ch',),
|
||||||
|
('ch', 'attr'),
|
||||||
|
('x', 'y', 'ch',),
|
||||||
|
('x', 'y', 'ch', 'attr'),
|
||||||
|
))
|
||||||
|
|
||||||
|
def test_ludicrous(self):
|
||||||
|
self._test([['a1', 'a2', 'a3'], ['b1', 'b2']], ['c1'], [['d1', 'd2'], ['e1', 'e2', 'e3']],
|
||||||
|
(
|
||||||
|
('c1',),
|
||||||
|
('b1', 'b2', 'c1'),
|
||||||
|
('b1', 'b2', 'c1', 'd1', 'd2'),
|
||||||
|
('a1', 'a2', 'a3', 'b1', 'b2', 'c1'),
|
||||||
|
('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2'),
|
||||||
|
('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2', 'e1', 'e2', 'e3'),
|
||||||
|
))
|
||||||
|
|
||||||
|
def test_right_only(self):
|
||||||
|
self._test([], [], [['a'],['b'],['c']],
|
||||||
|
(
|
||||||
|
(),
|
||||||
|
('a',),
|
||||||
|
('a', 'b'),
|
||||||
|
('a', 'b', 'c')
|
||||||
|
))
|
||||||
|
|
||||||
|
def test_have_left_options_but_required_is_empty(self):
|
||||||
|
def fn():
|
||||||
|
clinic.permute_optional_groups(['a'], [], [])
|
||||||
|
self.assertRaises(AssertionError, fn)
|
||||||
|
|
||||||
|
|
||||||
|
class ClinicLinearFormatTest(TestCase):
|
||||||
|
def _test(self, input, output, **kwargs):
|
||||||
|
computed = clinic.linear_format(input, **kwargs)
|
||||||
|
self.assertEqual(output, computed)
|
||||||
|
|
||||||
|
def test_empty_strings(self):
|
||||||
|
self._test('', '')
|
||||||
|
|
||||||
|
def test_solo_newline(self):
|
||||||
|
self._test('\n', '\n')
|
||||||
|
|
||||||
|
def test_no_substitution(self):
|
||||||
|
self._test("""
|
||||||
|
abc
|
||||||
|
""", """
|
||||||
|
abc
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_empty_substitution(self):
|
||||||
|
self._test("""
|
||||||
|
abc
|
||||||
|
{name}
|
||||||
|
def
|
||||||
|
""", """
|
||||||
|
abc
|
||||||
|
def
|
||||||
|
""", name='')
|
||||||
|
|
||||||
|
def test_single_line_substitution(self):
|
||||||
|
self._test("""
|
||||||
|
abc
|
||||||
|
{name}
|
||||||
|
def
|
||||||
|
""", """
|
||||||
|
abc
|
||||||
|
GARGLE
|
||||||
|
def
|
||||||
|
""", name='GARGLE')
|
||||||
|
|
||||||
|
def test_multiline_substitution(self):
|
||||||
|
self._test("""
|
||||||
|
abc
|
||||||
|
{name}
|
||||||
|
def
|
||||||
|
""", """
|
||||||
|
abc
|
||||||
|
bingle
|
||||||
|
bungle
|
||||||
|
|
||||||
|
def
|
||||||
|
""", name='bingle\nbungle\n')
|
||||||
|
|
||||||
|
class InertParser:
|
||||||
|
def __init__(self, clinic):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def parse(self, block):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class CopyParser:
|
||||||
|
def __init__(self, clinic):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def parse(self, block):
|
||||||
|
block.output = block.input
|
||||||
|
|
||||||
|
|
||||||
|
class ClinicBlockParserTest(TestCase):
|
||||||
|
def _test(self, input, output):
|
||||||
|
language = clinic.CLanguage()
|
||||||
|
|
||||||
|
blocks = list(clinic.BlockParser(input, language))
|
||||||
|
writer = clinic.BlockPrinter(language)
|
||||||
|
for block in blocks:
|
||||||
|
writer.print_block(block)
|
||||||
|
output = writer.f.getvalue()
|
||||||
|
assert output == input, "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input)
|
||||||
|
|
||||||
|
def round_trip(self, input):
|
||||||
|
return self._test(input, input)
|
||||||
|
|
||||||
|
def test_round_trip_1(self):
|
||||||
|
self.round_trip("""
|
||||||
|
verbatim text here
|
||||||
|
lah dee dah
|
||||||
|
""")
|
||||||
|
def test_round_trip_2(self):
|
||||||
|
self.round_trip("""
|
||||||
|
verbatim text here
|
||||||
|
lah dee dah
|
||||||
|
/*[inert]
|
||||||
|
abc
|
||||||
|
[inert]*/
|
||||||
|
def
|
||||||
|
/*[inert checksum: 7b18d017f89f61cf17d47f92749ea6930a3f1deb]*/
|
||||||
|
xyz
|
||||||
|
""")
|
||||||
|
|
||||||
|
def _test_clinic(self, input, output):
|
||||||
|
language = clinic.CLanguage()
|
||||||
|
c = clinic.Clinic(language)
|
||||||
|
c.parsers['inert'] = InertParser(c)
|
||||||
|
c.parsers['copy'] = CopyParser(c)
|
||||||
|
computed = c.parse(input)
|
||||||
|
self.assertEqual(output, computed)
|
||||||
|
|
||||||
|
def test_clinic_1(self):
|
||||||
|
self._test_clinic("""
|
||||||
|
verbatim text here
|
||||||
|
lah dee dah
|
||||||
|
/*[copy]
|
||||||
|
def
|
||||||
|
[copy]*/
|
||||||
|
abc
|
||||||
|
/*[copy checksum: 03cfd743661f07975fa2f1220c5194cbaff48451]*/
|
||||||
|
xyz
|
||||||
|
""", """
|
||||||
|
verbatim text here
|
||||||
|
lah dee dah
|
||||||
|
/*[copy]
|
||||||
|
def
|
||||||
|
[copy]*/
|
||||||
|
def
|
||||||
|
/*[copy checksum: 7b18d017f89f61cf17d47f92749ea6930a3f1deb]*/
|
||||||
|
xyz
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class ClinicParserTest(TestCase):
|
||||||
|
def test_trivial(self):
|
||||||
|
parser = DSLParser(FakeClinic())
|
||||||
|
block = clinic.Block("module os\nos.access")
|
||||||
|
parser.parse(block)
|
||||||
|
module, function = block.signatures
|
||||||
|
self.assertEqual("access", function.name)
|
||||||
|
self.assertEqual("os", module.name)
|
||||||
|
|
||||||
|
def test_ignore_line(self):
|
||||||
|
block = self.parse("#\nmodule os\nos.access")
|
||||||
|
module, function = block.signatures
|
||||||
|
self.assertEqual("access", function.name)
|
||||||
|
self.assertEqual("os", module.name)
|
||||||
|
|
||||||
|
def test_param(self):
|
||||||
|
function = self.parse_function("module os\nos.access\n path: int")
|
||||||
|
self.assertEqual("access", function.name)
|
||||||
|
self.assertEqual(1, len(function.parameters))
|
||||||
|
p = function.parameters['path']
|
||||||
|
self.assertEqual('path', p.name)
|
||||||
|
self.assertIsInstance(p.converter, clinic.int_converter)
|
||||||
|
|
||||||
|
def test_param_default(self):
|
||||||
|
function = self.parse_function("module os\nos.access\n follow_symlinks: bool = True")
|
||||||
|
p = function.parameters['follow_symlinks']
|
||||||
|
self.assertEqual(True, p.default)
|
||||||
|
|
||||||
|
def test_param_no_docstring(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module os
|
||||||
|
os.access
|
||||||
|
follow_symlinks: bool = True
|
||||||
|
something_else: str""")
|
||||||
|
p = function.parameters['follow_symlinks']
|
||||||
|
self.assertEqual(2, len(function.parameters))
|
||||||
|
self.assertIsInstance(function.parameters['something_else'].converter, clinic.str_converter)
|
||||||
|
|
||||||
|
def disabled_test_converter_arguments(self):
|
||||||
|
function = self.parse_function("module os\nos.access\n path: path_t(allow_fd=1)")
|
||||||
|
p = function.parameters['path']
|
||||||
|
self.assertEqual(1, p.converter.args['allow_fd'])
|
||||||
|
|
||||||
|
def test_param_docstring(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module os
|
||||||
|
os.stat as os_stat_fn -> object(doc_default='stat_result')
|
||||||
|
|
||||||
|
path: str
|
||||||
|
Path to be examined""")
|
||||||
|
p = function.parameters['path']
|
||||||
|
self.assertEqual("Path to be examined", p.docstring)
|
||||||
|
self.assertEqual(function.return_converter.doc_default, 'stat_result')
|
||||||
|
|
||||||
|
def test_function_docstring(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module os
|
||||||
|
os.stat as os_stat_fn
|
||||||
|
|
||||||
|
path: str
|
||||||
|
Path to be examined
|
||||||
|
|
||||||
|
Perform a stat system call on the given path.""")
|
||||||
|
self.assertEqual("""
|
||||||
|
Perform a stat system call on the given path.
|
||||||
|
|
||||||
|
os.stat(path)
|
||||||
|
path
|
||||||
|
Path to be examined
|
||||||
|
""".strip(), function.docstring)
|
||||||
|
|
||||||
|
def test_explicit_parameters_in_docstring(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
x: int
|
||||||
|
Documentation for x.
|
||||||
|
y: int
|
||||||
|
|
||||||
|
This is the documentation for foo.
|
||||||
|
|
||||||
|
Okay, we're done here.
|
||||||
|
""")
|
||||||
|
self.assertEqual("""
|
||||||
|
This is the documentation for foo.
|
||||||
|
|
||||||
|
foo.bar(x, y)
|
||||||
|
x
|
||||||
|
Documentation for x.
|
||||||
|
|
||||||
|
Okay, we're done here.
|
||||||
|
""".strip(), function.docstring)
|
||||||
|
|
||||||
|
def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module os
|
||||||
|
os.stat
|
||||||
|
path: str
|
||||||
|
This/used to break Clinic!
|
||||||
|
""")
|
||||||
|
self.assertEqual("os.stat(path)\n\nThis/used to break Clinic!", function.docstring)
|
||||||
|
|
||||||
|
def test_c_name(self):
|
||||||
|
function = self.parse_function("module os\nos.stat as os_stat_fn")
|
||||||
|
self.assertEqual("os_stat_fn", function.c_basename)
|
||||||
|
|
||||||
|
def test_return_converter(self):
|
||||||
|
function = self.parse_function("module os\nos.stat -> int")
|
||||||
|
self.assertIsInstance(function.return_converter, clinic.int_return_converter)
|
||||||
|
|
||||||
|
def test_star(self):
|
||||||
|
function = self.parse_function("module os\nos.access\n *\n follow_symlinks: bool = True")
|
||||||
|
p = function.parameters['follow_symlinks']
|
||||||
|
self.assertEqual(inspect.Parameter.KEYWORD_ONLY, p.kind)
|
||||||
|
self.assertEqual(0, p.group)
|
||||||
|
|
||||||
|
def test_group(self):
|
||||||
|
function = self.parse_function("module window\nwindow.border\n [\n ls : int\n ]\n /\n")
|
||||||
|
p = function.parameters['ls']
|
||||||
|
self.assertEqual(1, p.group)
|
||||||
|
|
||||||
|
def test_left_group(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module curses
|
||||||
|
curses.window.addch
|
||||||
|
[
|
||||||
|
y: int
|
||||||
|
Y-coordinate.
|
||||||
|
x: int
|
||||||
|
X-coordinate.
|
||||||
|
]
|
||||||
|
ch: char
|
||||||
|
Character to add.
|
||||||
|
[
|
||||||
|
attr: long
|
||||||
|
Attributes for the character.
|
||||||
|
]
|
||||||
|
/
|
||||||
|
""")
|
||||||
|
for name, group in (
|
||||||
|
('y', -1), ('x', -1),
|
||||||
|
('ch', 0),
|
||||||
|
('attr', 1),
|
||||||
|
):
|
||||||
|
p = function.parameters[name]
|
||||||
|
self.assertEqual(p.group, group)
|
||||||
|
self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
|
||||||
|
self.assertEqual(function.docstring.strip(), """
|
||||||
|
curses.window.addch([y, x,] ch, [attr])
|
||||||
|
y
|
||||||
|
Y-coordinate.
|
||||||
|
x
|
||||||
|
X-coordinate.
|
||||||
|
ch
|
||||||
|
Character to add.
|
||||||
|
attr
|
||||||
|
Attributes for the character.
|
||||||
|
""".strip())
|
||||||
|
|
||||||
|
def test_nested_groups(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module curses
|
||||||
|
curses.window.imaginary
|
||||||
|
[
|
||||||
|
[
|
||||||
|
y1: int
|
||||||
|
Y-coordinate.
|
||||||
|
y2: int
|
||||||
|
Y-coordinate.
|
||||||
|
]
|
||||||
|
x1: int
|
||||||
|
X-coordinate.
|
||||||
|
x2: int
|
||||||
|
X-coordinate.
|
||||||
|
]
|
||||||
|
ch: char
|
||||||
|
Character to add.
|
||||||
|
[
|
||||||
|
attr1: long
|
||||||
|
Attributes for the character.
|
||||||
|
attr2: long
|
||||||
|
Attributes for the character.
|
||||||
|
attr3: long
|
||||||
|
Attributes for the character.
|
||||||
|
[
|
||||||
|
attr4: long
|
||||||
|
Attributes for the character.
|
||||||
|
attr5: long
|
||||||
|
Attributes for the character.
|
||||||
|
attr6: long
|
||||||
|
Attributes for the character.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/
|
||||||
|
""")
|
||||||
|
for name, group in (
|
||||||
|
('y1', -2), ('y2', -2),
|
||||||
|
('x1', -1), ('x2', -1),
|
||||||
|
('ch', 0),
|
||||||
|
('attr1', 1), ('attr2', 1), ('attr3', 1),
|
||||||
|
('attr4', 2), ('attr5', 2), ('attr6', 2),
|
||||||
|
):
|
||||||
|
p = function.parameters[name]
|
||||||
|
self.assertEqual(p.group, group)
|
||||||
|
self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
|
||||||
|
|
||||||
|
self.assertEqual(function.docstring.strip(), """
|
||||||
|
curses.window.imaginary([[y1, y2,] x1, x2,] ch, [attr1, attr2, attr3, [attr4, attr5, attr6]])
|
||||||
|
y1
|
||||||
|
Y-coordinate.
|
||||||
|
y2
|
||||||
|
Y-coordinate.
|
||||||
|
x1
|
||||||
|
X-coordinate.
|
||||||
|
x2
|
||||||
|
X-coordinate.
|
||||||
|
ch
|
||||||
|
Character to add.
|
||||||
|
attr1
|
||||||
|
Attributes for the character.
|
||||||
|
attr2
|
||||||
|
Attributes for the character.
|
||||||
|
attr3
|
||||||
|
Attributes for the character.
|
||||||
|
attr4
|
||||||
|
Attributes for the character.
|
||||||
|
attr5
|
||||||
|
Attributes for the character.
|
||||||
|
attr6
|
||||||
|
Attributes for the character.
|
||||||
|
""".strip())
|
||||||
|
|
||||||
|
def parse_function_should_fail(self, s):
|
||||||
|
with support.captured_stdout() as stdout:
|
||||||
|
with self.assertRaises(SystemExit):
|
||||||
|
self.parse_function(s)
|
||||||
|
return stdout.getvalue()
|
||||||
|
|
||||||
|
def test_disallowed_grouping__two_top_groups_on_left(self):
|
||||||
|
s = self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.two_top_groups_on_left
|
||||||
|
[
|
||||||
|
group1 : int
|
||||||
|
]
|
||||||
|
[
|
||||||
|
group2 : int
|
||||||
|
]
|
||||||
|
param: int
|
||||||
|
""")
|
||||||
|
self.assertEqual(s,
|
||||||
|
('Error on line 0:\n'
|
||||||
|
'Function two_top_groups_on_left has an unsupported group configuration. (Unexpected state 2)\n'))
|
||||||
|
|
||||||
|
def test_disallowed_grouping__two_top_groups_on_right(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.two_top_groups_on_right
|
||||||
|
param: int
|
||||||
|
[
|
||||||
|
group1 : int
|
||||||
|
]
|
||||||
|
[
|
||||||
|
group2 : int
|
||||||
|
]
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_disallowed_grouping__parameter_after_group_on_right(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.parameter_after_group_on_right
|
||||||
|
param: int
|
||||||
|
[
|
||||||
|
[
|
||||||
|
group1 : int
|
||||||
|
]
|
||||||
|
group2 : int
|
||||||
|
]
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_disallowed_grouping__group_after_parameter_on_left(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.group_after_parameter_on_left
|
||||||
|
[
|
||||||
|
group2 : int
|
||||||
|
[
|
||||||
|
group1 : int
|
||||||
|
]
|
||||||
|
]
|
||||||
|
param: int
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_disallowed_grouping__empty_group_on_left(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.empty_group
|
||||||
|
[
|
||||||
|
[
|
||||||
|
]
|
||||||
|
group2 : int
|
||||||
|
]
|
||||||
|
param: int
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_disallowed_grouping__empty_group_on_right(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.empty_group
|
||||||
|
param: int
|
||||||
|
[
|
||||||
|
[
|
||||||
|
]
|
||||||
|
group2 : int
|
||||||
|
]
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_no_parameters(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
|
||||||
|
Docstring
|
||||||
|
|
||||||
|
""")
|
||||||
|
self.assertEqual("Docstring\n\nfoo.bar()", function.docstring)
|
||||||
|
self.assertEqual(0, len(function.parameters))
|
||||||
|
|
||||||
|
def test_single_star(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
*
|
||||||
|
*
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_parameters_required_after_star_without_initial_parameters_or_docstring(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
*
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_parameters_required_after_star_without_initial_parameters_with_docstring(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
*
|
||||||
|
Docstring here.
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_parameters_required_after_star_with_initial_parameters_without_docstring(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
this: int
|
||||||
|
*
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_parameters_required_after_star_with_initial_parameters_and_docstring(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
this: int
|
||||||
|
*
|
||||||
|
Docstring.
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_single_slash(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
/
|
||||||
|
/
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_mix_star_and_slash(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
*
|
||||||
|
z: int
|
||||||
|
/
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_parameters_not_permitted_after_slash_for_now(self):
|
||||||
|
self.parse_function_should_fail("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
/
|
||||||
|
x: int
|
||||||
|
""")
|
||||||
|
|
||||||
|
def test_function_not_at_column_0(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module foo
|
||||||
|
foo.bar
|
||||||
|
x: int
|
||||||
|
Nested docstring here, goeth.
|
||||||
|
*
|
||||||
|
y: str
|
||||||
|
Not at column 0!
|
||||||
|
""")
|
||||||
|
self.assertEqual("""
|
||||||
|
Not at column 0!
|
||||||
|
|
||||||
|
foo.bar(x, *, y)
|
||||||
|
x
|
||||||
|
Nested docstring here, goeth.
|
||||||
|
""".strip(), function.docstring)
|
||||||
|
|
||||||
|
def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line(self):
|
||||||
|
function = self.parse_function("""
|
||||||
|
module os
|
||||||
|
os.stat
|
||||||
|
path: str
|
||||||
|
This/used to break Clinic!
|
||||||
|
""")
|
||||||
|
self.assertEqual("This/used to break Clinic!\n\nos.stat(path)", function.docstring)
|
||||||
|
|
||||||
|
def test_directive(self):
|
||||||
|
c = FakeClinic()
|
||||||
|
parser = DSLParser(c)
|
||||||
|
parser.flag = False
|
||||||
|
parser.directives['setflag'] = lambda : setattr(parser, 'flag', True)
|
||||||
|
block = clinic.Block("setflag")
|
||||||
|
parser.parse(block)
|
||||||
|
self.assertTrue(parser.flag)
|
||||||
|
|
||||||
|
def test_legacy_converters(self):
|
||||||
|
block = self.parse('module os\nos.access\n path: "s"')
|
||||||
|
module, function = block.signatures
|
||||||
|
self.assertIsInstance((function.parameters['path']).converter, clinic.str_converter)
|
||||||
|
|
||||||
|
def parse(self, text):
|
||||||
|
c = FakeClinic()
|
||||||
|
parser = DSLParser(c)
|
||||||
|
block = clinic.Block(text)
|
||||||
|
parser.parse(block)
|
||||||
|
return block
|
||||||
|
|
||||||
|
def parse_function(self, text):
|
||||||
|
block = self.parse(text)
|
||||||
|
s = block.signatures
|
||||||
|
assert len(s) == 2
|
||||||
|
assert isinstance(s[0], clinic.Module)
|
||||||
|
assert isinstance(s[1], clinic.Function)
|
||||||
|
return s[1]
|
||||||
|
|
||||||
|
def test_scaffolding(self):
|
||||||
|
# test repr on special values
|
||||||
|
self.assertEqual(repr(clinic.unspecified), '<Unspecified>')
|
||||||
|
self.assertEqual(repr(clinic.NULL), '<Null>')
|
||||||
|
|
||||||
|
# test that fail fails
|
||||||
|
with support.captured_stdout() as stdout:
|
||||||
|
with self.assertRaises(SystemExit):
|
||||||
|
clinic.fail('The igloos are melting!', filename='clown.txt', line_number=69)
|
||||||
|
self.assertEqual(stdout.getvalue(), 'Error in file "clown.txt" on line 69:\nThe igloos are melting!\n')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue