Issue #16612: Add "Argument Clinic", a compile-time preprocessor
for C files to generate argument parsing code.  (See PEP 436.)
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index b5af867..c61f67f 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -549,68 +549,141 @@
 
 /* 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 *
-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 *chobj;
+    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 *
+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;
-    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 @@
 
 
 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 fb78e6d..8848432 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -4143,31 +4143,73 @@
                                       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(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 *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 @@
 
     /* 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 d899480..8babd0e 100644
--- a/Modules/_dbmmodule.c
+++ b/Modules/_dbmmodule.c
@@ -44,7 +44,7 @@
 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 @@
 
 /* ----------------------------------------------------------------- */
 
+/*[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";
-    int iflags;
-    int mode = 0666;
+    PyObject *return_value = NULL;
+    const char *filename;
+    const char *flags = "r";
+    int mode = 438;
 
-    if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
-        return NULL;
+    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 ( strcmp(flags, "r") == 0 )
         iflags = O_RDONLY;
     else if ( strcmp(flags, "w") == 0 )
@@ -386,13 +439,11 @@
                         "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 88995b8..1e8debc 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;
+    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))) {
-        PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
+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 @@
 
 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 @@
     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 2779852..1d02e73 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 @@
  *   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 @@
     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 @@
 #endif
 }
 
+
 /* POSIX generic methods */
 
 static PyObject *
@@ -2347,48 +2353,145 @@
     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 @@
 #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.");
+
+#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 *
-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",
-                                "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 @@
     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 @@
             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 @@
 #ifndef HAVE_FACCESSAT
 exit:
 #endif
-    path_cleanup(&path);
     return return_value;
 }
 
@@ -2543,35 +2710,76 @@
 #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 @@
 #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 @@
     {"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 eba403a..5097d44 100644
--- a/Modules/unicodedata.c
+++ b/Modules/unicodedata.c
@@ -107,24 +107,62 @@
 
 /* --- 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 @@
     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 @@
 /* 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 169903e..1b65eb0 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 @@
     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 *
-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;
     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 @@
             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 @@
     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 @@
 }
 
 #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 @@
     /* 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 @@
                         "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 @@
     {"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