diff options
author | Larry Hastings <larry@hastings.org> | 2013-10-19 00:09:25 -0700 |
---|---|---|
committer | Larry Hastings <larry@hastings.org> | 2013-10-19 00:09:25 -0700 |
commit | 3182680210fa0cf570233382bbaec8b64d57f4da (patch) | |
tree | 93932cf52fd5cbbdeab62b2fc43851e3cb637e3d /Modules | |
parent | 5ceae41083f3bec479fe8f135f442e6576c6e273 (diff) | |
download | cpython-git-3182680210fa0cf570233382bbaec8b64d57f4da.tar.gz |
Issue #16612: Add "Argument Clinic", a compile-time preprocessor
for C files to generate argument parsing code. (See PEP 436.)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_cursesmodule.c | 155 | ||||
-rw-r--r-- | Modules/_datetimemodule.c | 74 | ||||
-rw-r--r-- | Modules/_dbmmodule.c | 71 | ||||
-rw-r--r-- | Modules/_weakref.c | 60 | ||||
-rw-r--r-- | Modules/posixmodule.c | 397 | ||||
-rw-r--r-- | Modules/unicodedata.c | 64 | ||||
-rw-r--r-- | Modules/zlibmodule.c | 183 |
7 files changed, 750 insertions, 254 deletions
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index b5af867acf..c61f67f074 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -549,68 +549,141 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo) /* 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 * +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) +{ + PyObject *return_value = NULL; + 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 * -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) +/*[clinic checksum: 98ade780397a48d0be48439763424b3b00c92089]*/ { - int rtn, x, y, use_xy = FALSE; - PyObject *chobj; + PyCursesWindowObject *cwself = (PyCursesWindowObject *)self; + int coordinates_group = group_left_1; + int attr_group = group_right_1; + int rtn; int type; - chtype ch; + chtype cch; #ifdef HAVE_NCURSESW cchar_t wch; #endif - attr_t attr = A_NORMAL; - long lattr; const char *funcname; - switch (PyTuple_Size(args)) { - case 1: - 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; - } + if (!attr_group) + attr = A_NORMAL; #ifdef HAVE_NCURSESW - type = PyCurses_ConvertToCchar_t(self, chobj, &ch, &wch); + type = PyCurses_ConvertToCchar_t(cwself, ch, &cch, &wch); if (type == 2) { funcname = "add_wch"; wch.attr = attr; - if (use_xy == TRUE) - rtn = mvwadd_wch(self->win,y,x, &wch); + if (coordinates_group) + rtn = mvwadd_wch(cwself->win,y,x, &wch); else { - rtn = wadd_wch(self->win, &wch); + rtn = wadd_wch(cwself->win, &wch); } } else #else - type = PyCurses_ConvertToCchar_t(self, chobj, &ch); + type = PyCurses_ConvertToCchar_t(cwself, chobj, &cch); #endif if (type == 1) { funcname = "addch"; - if (use_xy == TRUE) - rtn = mvwaddch(self->win,y,x, ch | attr); + if (coordinates_group) + rtn = mvwaddch(cwself->win,y,x, cch | attr); else { - rtn = waddch(self->win, ch | attr); + rtn = waddch(cwself->win, cch | attr); } } else { @@ -1954,7 +2027,7 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value) static PyMethodDef PyCursesWindow_Methods[] = { - {"addch", (PyCFunction)PyCursesWindow_AddCh, METH_VARARGS}, + CURSES_WINDOW_ADDCH_METHODDEF {"addnstr", (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS}, {"addstr", (PyCFunction)PyCursesWindow_AddStr, METH_VARARGS}, {"attroff", (PyCFunction)PyCursesWindow_AttrOff, METH_VARARGS}, diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index fb78e6d0fe..88484327fe 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4143,31 +4143,73 @@ datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo) tzinfo); } -/* Return best possible local time -- this isn't constrained by the - * precision of a timestamp. - */ +/*[clinic] +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 * +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(PyObject *cls, PyObject *args, PyObject *kw) +datetime_now_impl(PyObject *cls, PyObject *tz) +/*[clinic checksum: 328b54387f4c2f8cb534997e1bd55f8cb38c4992]*/ { PyObject *self; - PyObject *tzinfo = Py_None; - static char *keywords[] = {"tz", NULL}; - if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords, - &tzinfo)) - return NULL; - if (check_tzinfo_subclass(tzinfo) < 0) + /* Return best possible local time -- this isn't constrained by the + * precision of a timestamp. + */ + if (check_tzinfo_subclass(tz) < 0) return NULL; self = datetime_best_possible(cls, - tzinfo == Py_None ? localtime : gmtime, - tzinfo); - if (self != NULL && tzinfo != Py_None) { + tz == Py_None ? localtime : gmtime, + tz); + if (self != NULL && tz != Py_None) { /* Convert UTC to tzinfo's zone. */ PyObject *temp = self; _Py_IDENTIFIER(fromutc); - self = _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "O", self); + self = _PyObject_CallMethodId(tz, &PyId_fromutc, "O", self); Py_DECREF(temp); } return self; @@ -5001,9 +5043,7 @@ static PyMethodDef datetime_methods[] = { /* Class methods: */ - {"now", (PyCFunction)datetime_now, - METH_VARARGS | METH_KEYWORDS | METH_CLASS, - PyDoc_STR("[tz] -> new datetime with tz's local day and time.")}, + DATETIME_NOW_METHODDEF {"utcnow", (PyCFunction)datetime_utcnow, METH_NOARGS | METH_CLASS, diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index d89948050f..8babd0eb15 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -44,7 +44,7 @@ static PyTypeObject Dbmtype; static PyObject *DbmError; static PyObject * -newdbmobject(char *file, int flags, int mode) +newdbmobject(const char *file, int flags, int mode) { 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 * dbmopen(PyObject *self, PyObject *args) { - char *name; - char *flags = "r"; + PyObject *return_value = NULL; + const char *filename; + const char *flags = "r"; + 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; - int mode = 0666; - if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) ) - return NULL; if ( strcmp(flags, "r") == 0 ) iflags = O_RDONLY; 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'"); return NULL; } - return newdbmobject(name, iflags, mode); + return newdbmobject(filename, iflags, mode); } static PyMethodDef dbmmodule_methods[] = { - { "open", (PyCFunction)dbmopen, METH_VARARGS, - "open(path[, flag[, mode]]) -> mapping\n" - "Return a database object."}, + DBMOPEN_METHODDEF { 0, 0 }, }; diff --git a/Modules/_weakref.c b/Modules/_weakref.c index 88995b88a8..1e8debc5a1 100644 --- a/Modules/_weakref.c +++ b/Modules/_weakref.c @@ -4,25 +4,54 @@ #define GET_WEAKREFS_LISTPTR(o) \ ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o)) +/*[clinic] -PyDoc_STRVAR(weakref_getweakrefcount__doc__, -"getweakrefcount(object) -- return the number of weak references\n" -"to 'object'."); +module _weakref + +_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 * -weakref_getweakrefcount(PyObject *self, PyObject *object) +_weakref_getweakrefcount(PyObject *self, PyObject *object) { - PyObject *result = NULL; - - if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { - PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); + 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); + +exit: + return return_value; +} - result = PyLong_FromSsize_t(_PyWeakref_GetWeakrefCount(*list)); - } - else - result = PyLong_FromLong(0); +static Py_ssize_t +_weakref_getweakrefcount_impl(PyObject *self, PyObject *object) +/*[clinic checksum: 0b7e7ddd87d483719ebac0fba364fff0ed0182d9]*/ +{ + 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 weakref_functions[] = { - {"getweakrefcount", weakref_getweakrefcount, METH_O, - weakref_getweakrefcount__doc__}, + _WEAKREF_GETWEAKREFCOUNT_METHODDEF {"getweakrefs", weakref_getweakrefs, METH_O, weakref_getweakrefs__doc__}, {"proxy", weakref_proxy, METH_VARARGS, @@ -106,7 +134,7 @@ PyInit__weakref(void) PyObject *m; m = PyModule_Create(&weakrefmodule); - + if (m != NULL) { Py_INCREF(&_PyWeakref_RefType); PyModule_AddObject(m, "ref", diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 27798528be..1d02e73dfa 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -8,6 +8,8 @@ of the compiler used. Different compilers define their own feature test macro, e.g. '__BORLANDC__' or '_MSC_VER'. */ + + #ifdef __APPLE__ /* * 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 * If non-NULL, path_converter will use that as the name * 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 * If non-NULL, path_converter will use that as the name * of the parameter in error messages. @@ -776,6 +778,9 @@ typedef struct { PyObject *cleanup; } 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 path_cleanup(path_t *path) { if (path->cleanup) { @@ -1313,6 +1318,7 @@ path_error(path_t *path) #endif } + /* POSIX generic methods */ static PyObject * @@ -2347,48 +2353,145 @@ posix_do_stat(char *function_name, path_t *path, return _pystat_fromstructstat(&st); } -PyDoc_STRVAR(posix_stat__doc__, -"stat(path, *, dir_fd=None, follow_symlinks=True) -> stat result\n\n\ -Perform a stat system call on the given path.\n\ -\n\ -path may be specified as either a string or as an open file descriptor.\n\ -\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\ - dir_fd may not be supported on your platform; if it is unavailable, using\n\ - it will raise a NotImplementedError.\n\ -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\ - link points to.\n\ -It is an error to use dir_fd or follow_symlinks when specifying path as\n\ - an open file descriptor."); +#ifdef HAVE_FSTATAT + #define OS_STAT_DIR_FD_CONVERTER dir_fd_converter +#else + #define OS_STAT_DIR_FD_CONVERTER dir_fd_unavailable +#endif + + +/*[python] + +class path_t_converter(CConverter): + + type = "path_t" + impl_by_reference = True + parse_by_reference = True + + 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 * -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}; - path_t path; + PyObject *return_value = NULL; + 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 follow_symlinks = 1; - PyObject *return_value; - memset(&path, 0, sizeof(path)); - path.function_name = "stat"; - path.allow_fd = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&p:stat", keywords, - path_converter, &path, -#ifdef HAVE_FSTATAT - dir_fd_converter, &dir_fd, -#else - dir_fd_unavailable, &dir_fd, -#endif - &follow_symlinks)) - return NULL; - return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks); + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&|$O&p:stat", _keywords, + path_converter, &path, OS_STAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) + goto exit; + return_value = os_stat_impl(self, &path, dir_fd, follow_symlinks); + +exit: + /* Cleanup for path */ path_cleanup(&path); + 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__, "lstat(path, *, dir_fd=None) -> stat result\n\n\ Like stat(), but do not follow symbolic links.\n\ @@ -2414,44 +2517,120 @@ posix_lstat(PyObject *self, PyObject *args, PyObject *kwargs) #endif )) 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); return return_value; } -PyDoc_STRVAR(posix_access__doc__, -"access(path, mode, *, dir_fd=None, effective_ids=False,\ - follow_symlinks=True)\n\n\ -Use the real uid/gid to test for access to a path. Returns True if granted,\n\ -False otherwise.\n\ -\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\ -If effective_ids is True, access will use the effective uid/gid instead of\n\ - the real uid/gid.\n\ -If follow_symlinks is False, and the last element of the path is a symbolic\n\ - link, access will examine the symbolic link itself instead of the file the\n\ - link points to.\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.\n\ -The mode argument can be F_OK to test existence, or the inclusive-OR\n\ - of R_OK, W_OK, and X_OK."); -static PyObject * -posix_access(PyObject *self, PyObject *args, PyObject *kwargs) +#ifdef HAVE_FACCESSAT + #define OS_ACCESS_DIR_FD_CONVERTER dir_fd_converter +#else + #define OS_ACCESS_DIR_FD_CONVERTER dir_fd_unavailable +#endif +/*[clinic] +os.access -> object(doc_default='True if granted, False otherwise') + + path: path_t(allow_fd=True) + Path to be tested; can be string, bytes, or open-file-descriptor int. + + mode: int + Operating-system mode bitfield. Can be F_OK to test existence, + or the inclusive-OR of R_OK, W_OK, and X_OK. + + * + + dir_fd : dir_fd = None + If not None, it should be a file descriptor open to a directory, + and path should be relative; path will then be relative to that + 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 * +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", - "follow_symlinks", NULL}; - path_t path; + PyObject *return_value = NULL; + static char *_keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; + path_t path = PATH_T_INITIALIZE("access", 0, 1); int mode; int dir_fd = DEFAULT_DIR_FD; int effective_ids = 0; 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; #ifdef MS_WINDOWS @@ -2460,17 +2639,6 @@ posix_access(PyObject *self, PyObject *args, PyObject *kwargs) int result; #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 if (follow_symlinks_specified("access", follow_symlinks)) goto exit; @@ -2514,11 +2682,11 @@ posix_access(PyObject *self, PyObject *args, PyObject *kwargs) flags |= AT_SYMLINK_NOFOLLOW; if (effective_ids) flags |= AT_EACCESS; - result = faccessat(dir_fd, path.narrow, mode, flags); + result = faccessat(dir_fd, path->narrow, mode, flags); } else #endif - result = access(path.narrow, mode); + result = access(path->narrow, mode); Py_END_ALLOW_THREADS return_value = PyBool_FromLong(!result); #endif @@ -2526,7 +2694,6 @@ posix_access(PyObject *self, PyObject *args, PyObject *kwargs) #ifndef HAVE_FACCESSAT exit: #endif - path_cleanup(&path); return return_value; } @@ -2543,35 +2710,76 @@ exit: #define X_OK 1 #endif + #ifdef HAVE_TTYNAME -PyDoc_STRVAR(posix_ttyname__doc__, -"ttyname(fd) -> string\n\n\ -Return the name of the terminal device connected to 'fd'."); + +/*[clinic] +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 * -posix_ttyname(PyObject *self, PyObject *args) +os_ttyname(PyObject *self, PyObject *args) { - int id; - char *ret; + PyObject *return_value = NULL; + int fd; + char *_return_value; - if (!PyArg_ParseTuple(args, "i:ttyname", &id)) - return NULL; + if (!PyArg_ParseTuple(args, + "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) /* file descriptor 0 only, the default input device (stdin) */ - if (id == 0) { + if (fd == 0) { ret = ttyname(); } else { ret = NULL; } #else - ret = ttyname(id); + ret = ttyname(fd); #endif if (ret == NULL) - return posix_error(); - return PyUnicode_DecodeFSDefault(ret); + posix_error(); + return ret; } +#else +#define OS_TTYNAME_METHODDEF #endif #ifdef HAVE_CTERMID @@ -10912,13 +11120,13 @@ posix_set_handle_inheritable(PyObject *self, PyObject *args) #endif /* MS_WINDOWS */ + static PyMethodDef posix_methods[] = { - {"access", (PyCFunction)posix_access, - METH_VARARGS | METH_KEYWORDS, - posix_access__doc__}, -#ifdef HAVE_TTYNAME - {"ttyname", posix_ttyname, METH_VARARGS, posix_ttyname__doc__}, -#endif + + OS_STAT_METHODDEF + OS_ACCESS_METHODDEF + OS_TTYNAME_METHODDEF + {"chdir", (PyCFunction)posix_chdir, METH_VARARGS | METH_KEYWORDS, posix_chdir__doc__}, @@ -11002,9 +11210,6 @@ static PyMethodDef posix_methods[] = { {"rmdir", (PyCFunction)posix_rmdir, METH_VARARGS | METH_KEYWORDS, 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__}, #if defined(HAVE_SYMLINK) {"symlink", (PyCFunction)posix_symlink, diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index eba403a8e5..5097d44020 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -107,24 +107,62 @@ static Py_UCS4 getuchar(PyUnicodeObject *obj) /* --- 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__, -"decimal(unichr[, default])\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."); +"Converts a Unicode character into its equivalent decimal value.\n" +"\n" +"unicodedata.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."); + +#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 * unicodedata_decimal(PyObject *self, PyObject *args) { - PyUnicodeObject *v; - PyObject *defobj = NULL; + PyObject *return_value = 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; long rc; Py_UCS4 c; - if (!PyArg_ParseTuple(args, "O!|O:decimal", &PyUnicode_Type, &v, &defobj)) - return NULL; c = getuchar(v); if (c == (Py_UCS4)-1) return NULL; @@ -145,14 +183,14 @@ unicodedata_decimal(PyObject *self, PyObject *args) if (!have_old) rc = Py_UNICODE_TODECIMAL(c); if (rc < 0) { - if (defobj == NULL) { + if (default_value == NULL) { PyErr_SetString(PyExc_ValueError, "not a decimal"); return NULL; } else { - Py_INCREF(defobj); - return defobj; + Py_INCREF(default_value); + return default_value; } } return PyLong_FromLong(rc); @@ -1250,7 +1288,7 @@ unicodedata_lookup(PyObject* self, PyObject* args) /* XXX Add doc strings. */ static PyMethodDef unicodedata_functions[] = { - {"decimal", unicodedata_decimal, METH_VARARGS, unicodedata_decimal__doc__}, + UNICODEDATA_DECIMAL_METHODDEF {"digit", unicodedata_digit, METH_VARARGS, unicodedata_digit__doc__}, {"numeric", unicodedata_numeric, METH_VARARGS, unicodedata_numeric__doc__}, {"category", unicodedata_category, METH_VARARGS, diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 169903e7ea..1b65eb0be7 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -8,6 +8,7 @@ #include "structmember.h" #include "zlib.h" + #ifdef WITH_THREAD #include "pythread.h" #define ENTER_ZLIB(obj) \ @@ -626,87 +627,136 @@ save_unconsumed_input(compobject *self, int err) return 0; } -PyDoc_STRVAR(decomp_decompress__doc__, -"decompress(data, max_length) -- Return a string containing the decompressed\n" -"version of the data.\n" +/*[clinic] + +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" "After calling this function, some of the input data may still be stored in\n" "internal buffers for later processing.\n" -"Call the flush() method to clear these buffers.\n" -"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" -"the unconsumed_tail attribute."); +"Call the flush() method to clear these buffers."); + +#define ZLIB_DECOMPRESS_METHODDEF \ + {"decompress", (PyCFunction)zlib_decompress, METH_VARARGS, zlib_decompress__doc__}, + +static PyObject * +zlib_decompress_impl(PyObject *self, Py_buffer *data, int max_length); static PyObject * -PyZlib_objdecompress(compobject *self, PyObject *args) +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; Py_ssize_t old_length, length = DEFAULTALLOC; PyObject *RetVal = NULL; - Py_buffer pinput; Byte *input; unsigned long start_total_out; - if (!PyArg_ParseTuple(args, "y*|i:decompress", &pinput, - &max_length)) - return NULL; - if (pinput.len > UINT_MAX) { + if (data->len > UINT_MAX) { PyErr_SetString(PyExc_OverflowError, "Size does not fit in an unsigned int"); - goto error_outer; + return NULL; } - input = pinput.buf; - inplen = pinput.len; + input = data->buf; + inplen = data->len; if (max_length < 0) { PyErr_SetString(PyExc_ValueError, "max_length must be greater than zero"); - goto error_outer; + return NULL; } /* limit amount of data allocated to max_length */ if (max_length && length > max_length) length = max_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; - self->zst.avail_in = inplen; - self->zst.next_in = input; - self->zst.avail_out = length; - self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal); + start_total_out = zself->zst.total_out; + zself->zst.avail_in = inplen; + zself->zst.next_in = input; + zself->zst.avail_out = length; + zself->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal); Py_BEGIN_ALLOW_THREADS - err = inflate(&(self->zst), Z_SYNC_FLUSH); + err = inflate(&(zself->zst), Z_SYNC_FLUSH); Py_END_ALLOW_THREADS - if (err == Z_NEED_DICT && self->zdict != NULL) { + if (err == Z_NEED_DICT && zself->zdict != NULL) { 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); RetVal = NULL; 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); if (err != Z_OK) { - zlib_error(self->zst, err, "while decompressing data"); + zlib_error(zself->zst, err, "while decompressing data"); Py_DECREF(RetVal); RetVal = NULL; goto error; } /* Repeat the call to inflate. */ Py_BEGIN_ALLOW_THREADS - err = inflate(&(self->zst), Z_SYNC_FLUSH); + err = inflate(&(zself->zst), Z_SYNC_FLUSH); Py_END_ALLOW_THREADS } /* While Z_OK and the output buffer is full, there might be more output. 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 reached the limit. */ @@ -723,16 +773,16 @@ PyZlib_objdecompress(compobject *self, PyObject *args) Py_CLEAR(RetVal); goto error; } - self->zst.next_out = + zself->zst.next_out = (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 - err = inflate(&(self->zst), Z_SYNC_FLUSH); + err = inflate(&(zself->zst), Z_SYNC_FLUSH); Py_END_ALLOW_THREADS } - if (save_unconsumed_input(self, err) < 0) { + if (save_unconsumed_input(zself, err) < 0) { Py_DECREF(RetVal); RetVal = NULL; goto error; @@ -741,26 +791,24 @@ PyZlib_objdecompress(compobject *self, PyObject *args) if (err == Z_STREAM_END) { /* This is the logical place to call inflateEnd, but the old behaviour of only calling it on flush() is preserved. */ - self->eof = 1; + zself->eof = 1; } else if (err != Z_OK && err != Z_BUF_ERROR) { /* 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 not an error condition. */ - zlib_error(self->zst, err, "while decompressing data"); + zlib_error(zself->zst, err, "while decompressing data"); Py_DECREF(RetVal); RetVal = NULL; 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); } error: - LEAVE_ZLIB(self); - error_outer: - PyBuffer_Release(&pinput); + LEAVE_ZLIB(zself); return RetVal; } @@ -856,12 +904,27 @@ PyZlib_flush(compobject *self, PyObject *args) } #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 * -PyZlib_copy(compobject *self) +zlib_copy(PyObject *self) +/*[clinic checksum: 7b648de2c1f933ba2b9fa17331ff1a44d9a4a740]*/ { + compobject *zself = (compobject *)self; compobject *retval = NULL; int err; @@ -871,8 +934,8 @@ PyZlib_copy(compobject *self) /* Copy the zstream state * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe */ - ENTER_ZLIB(self); - err = deflateCopy(&retval->zst, &self->zst); + ENTER_ZLIB(zself); + err = deflateCopy(&retval->zst, &zself->zst); switch(err) { case(Z_OK): break; @@ -884,28 +947,28 @@ PyZlib_copy(compobject *self) "Can't allocate memory for compression object"); goto error; default: - zlib_error(self->zst, err, "while copying compression object"); + zlib_error(zself->zst, err, "while copying compression object"); goto error; } - Py_INCREF(self->unused_data); - Py_INCREF(self->unconsumed_tail); - Py_XINCREF(self->zdict); + Py_INCREF(zself->unused_data); + Py_INCREF(zself->unconsumed_tail); + Py_XINCREF(zself->zdict); Py_XDECREF(retval->unused_data); Py_XDECREF(retval->unconsumed_tail); Py_XDECREF(retval->zdict); - retval->unused_data = self->unused_data; - retval->unconsumed_tail = self->unconsumed_tail; - retval->zdict = self->zdict; - retval->eof = self->eof; + retval->unused_data = zself->unused_data; + retval->unconsumed_tail = zself->unconsumed_tail; + retval->zdict = zself->zdict; + retval->eof = zself->eof; /* Mark it as being initialized */ retval->is_initialised = 1; - LEAVE_ZLIB(self); + LEAVE_ZLIB(zself); return (PyObject *)retval; error: - LEAVE_ZLIB(self); + LEAVE_ZLIB(zself); Py_XDECREF(retval); return NULL; } @@ -1055,16 +1118,14 @@ static PyMethodDef comp_methods[] = {"flush", (binaryfunc)PyZlib_flush, METH_VARARGS, comp_flush__doc__}, #ifdef HAVE_ZLIB_COPY - {"copy", (PyCFunction)PyZlib_copy, METH_NOARGS, - comp_copy__doc__}, + ZLIB_COPY_METHODDEF #endif {NULL, NULL} }; static PyMethodDef Decomp_methods[] = { - {"decompress", (binaryfunc)PyZlib_objdecompress, METH_VARARGS, - decomp_decompress__doc__}, + ZLIB_DECOMPRESS_METHODDEF {"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS, decomp_flush__doc__}, #ifdef HAVE_ZLIB_COPY |