[Python-checkins] cpython: Issue #26671: Enhanced path_converter.

serhiy.storchaka python-checkins at python.org
Wed Apr 6 15:19:12 EDT 2016


https://hg.python.org/cpython/rev/a866f5727b7f
changeset:   100860:a866f5727b7f
parent:      100858:719c11b6b6ff
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Wed Apr 06 22:17:52 2016 +0300
summary:
  Issue #26671: Enhanced path_converter.

Exceptions raised during converting argument of correct type are no longer
overridded with TypeError. Some error messages are now more detailed.

files:
  Modules/posixmodule.c |  116 ++++++++++++++---------------
  1 files changed, 55 insertions(+), 61 deletions(-)


diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -669,21 +669,20 @@
 #endif
 
 static int
-_fd_converter(PyObject *o, int *p, const char *allowed)
+_fd_converter(PyObject *o, int *p)
 {
     int overflow;
     long long_value;
 
     PyObject *index = PyNumber_Index(o);
     if (index == NULL) {
-        PyErr_Format(PyExc_TypeError,
-                     "argument should be %s, not %.200s",
-                     allowed, Py_TYPE(o)->tp_name);
         return 0;
     }
 
+    assert(PyLong_Check(index));
     long_value = PyLong_AsLongAndOverflow(index, &overflow);
     Py_DECREF(index);
+    assert(!PyErr_Occurred());
     if (overflow > 0 || long_value > INT_MAX) {
         PyErr_SetString(PyExc_OverflowError,
                         "fd is greater than maximum");
@@ -706,7 +705,15 @@
         *(int *)p = DEFAULT_DIR_FD;
         return 1;
     }
-    return _fd_converter(o, (int *)p, "integer");
+    else if (PyIndex_Check(o)) {
+        return _fd_converter(o, (int *)p);
+    }
+    else {
+        PyErr_Format(PyExc_TypeError,
+                     "argument should be integer or None, not %.200s",
+                     Py_TYPE(o)->tp_name);
+        return 0;
+    }
 }
 
 
@@ -816,9 +823,10 @@
 }
 
 static int
-path_converter(PyObject *o, void *p) {
+path_converter(PyObject *o, void *p)
+{
     path_t *path = (path_t *)p;
-    PyObject *unicode, *bytes;
+    PyObject *bytes;
     Py_ssize_t length;
     char *narrow;
 
@@ -837,12 +845,7 @@
     /* ensure it's always safe to call path_cleanup() */
     path->cleanup = NULL;
 
-    if (o == Py_None) {
-        if (!path->nullable) {
-            FORMAT_EXCEPTION(PyExc_TypeError,
-                             "can't specify None for %s argument");
-            return 0;
-        }
+    if ((o == Py_None) && path->nullable) {
         path->wide = NULL;
         path->narrow = NULL;
         path->length = 0;
@@ -851,24 +854,20 @@
         return 1;
     }
 
-    unicode = PyUnicode_FromObject(o);
-    if (unicode) {
+    if (PyUnicode_Check(o)) {
 #ifdef MS_WINDOWS
         wchar_t *wide;
 
-        wide = PyUnicode_AsUnicodeAndSize(unicode, &length);
+        wide = PyUnicode_AsUnicodeAndSize(o, &length);
         if (!wide) {
-            Py_DECREF(unicode);
             return 0;
         }
         if (length > 32767) {
             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
-            Py_DECREF(unicode);
             return 0;
         }
         if (wcslen(wide) != length) {
-            FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character");
-            Py_DECREF(unicode);
+            FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
             return 0;
         }
 
@@ -877,52 +876,47 @@
         path->length = length;
         path->object = o;
         path->fd = -1;
-        path->cleanup = unicode;
-        return Py_CLEANUP_SUPPORTED;
-#else
-        int converted = PyUnicode_FSConverter(unicode, &bytes);
-        Py_DECREF(unicode);
-        if (!converted)
-            bytes = NULL;
-#endif
+        return 1;
+#else
+        if (!PyUnicode_FSConverter(o, &bytes)) {
+            return 0;
+        }
+#endif
+    }
+    else if (PyObject_CheckBuffer(o)) {
+#  ifdef MS_WINDOWS
+        if (win32_warn_bytes_api()) {
+            return 0;
+        }
+#  endif
+        bytes = PyBytes_FromObject(o);
+        if (!bytes) {
+            return 0;
+        }
+    }
+    else if (path->allow_fd && PyIndex_Check(o)) {
+        if (!_fd_converter(o, &path->fd)) {
+            return 0;
+        }
+        path->wide = NULL;
+        path->narrow = NULL;
+        path->length = 0;
+        path->object = o;
+        return 1;
     }
     else {
-        PyErr_Clear();
-        if (PyObject_CheckBuffer(o))
-            bytes = PyBytes_FromObject(o);
-        else
-            bytes = NULL;
-        if (!bytes) {
-            PyErr_Clear();
-            if (path->allow_fd) {
-                int fd;
-                int result = _fd_converter(o, &fd,
-                        "string, bytes or integer");
-                if (result) {
-                    path->wide = NULL;
-                    path->narrow = NULL;
-                    path->length = 0;
-                    path->object = o;
-                    path->fd = fd;
-                    return result;
-                }
-            }
-        }
-    }
-
-    if (!bytes) {
-        if (!PyErr_Occurred())
-            FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter");
+        PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
+            path->function_name ? path->function_name : "",
+            path->function_name ? ": "                : "",
+            path->argument_name ? path->argument_name : "path",
+            path->allow_fd && path->nullable ? "string, bytes, integer or None" :
+            path->allow_fd ? "string, bytes or integer" :
+            path->nullable ? "string, bytes or None" :
+                             "string or bytes",
+            Py_TYPE(o)->tp_name);
         return 0;
     }
 
-#ifdef MS_WINDOWS
-    if (win32_warn_bytes_api()) {
-        Py_DECREF(bytes);
-        return 0;
-    }
-#endif
-
     length = PyBytes_GET_SIZE(bytes);
 #ifdef MS_WINDOWS
     if (length > MAX_PATH-1) {

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list