[Python-checkins] cpython (merge default -> default): merge heads
benjamin.peterson
python-checkins at python.org
Tue Sep 6 18:57:59 EDT 2016
https://hg.python.org/cpython/rev/a882c1981029
changeset: 103162:a882c1981029
parent: 103160:42673b6fc6c5
parent: 103158:1d29d3a1e0c6
user: Benjamin Peterson <benjamin at python.org>
date: Tue Sep 06 15:57:48 2016 -0700
summary:
merge heads
files:
Doc/c-api/unicode.rst | 5 +-
Lib/test/test_os.py | 64 +++++++++------------
Misc/NEWS | 5 +
Modules/clinic/posixmodule.c.h | 14 ++--
Modules/posixmodule.c | 8 +-
Objects/unicodeobject.c | 27 ++++----
6 files changed, 62 insertions(+), 61 deletions(-)
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -810,13 +810,16 @@
.. c:function:: int PyUnicode_FSConverter(PyObject* obj, void* result)
- ParseTuple converter: encode :class:`str` objects to :class:`bytes` using
+ ParseTuple converter: encode :class:`str` objects -- obtained directly or
+ through the :class:`os.PathLike` interface -- to :class:`bytes` using
:c:func:`PyUnicode_EncodeFSDefault`; :class:`bytes` objects are output as-is.
*result* must be a :c:type:`PyBytesObject*` which must be released when it is
no longer used.
.. versionadded:: 3.1
+ .. versionchanged:: 3.6
+ Accepts a :term:`path-like object`.
To decode file names during argument parsing, the ``"O&"`` converter should be
used, passing :c:func:`PyUnicode_FSDecoder` as the conversion function:
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -100,6 +100,21 @@
yield
+class _PathLike(os.PathLike):
+
+ def __init__(self, path=""):
+ self.path = path
+
+ def __str__(self):
+ return str(self.path)
+
+ def __fspath__(self):
+ if isinstance(self.path, BaseException):
+ raise self.path
+ else:
+ return self.path
+
+
def create_file(filename, content=b'content'):
with open(filename, "xb", 0) as fp:
fp.write(content)
@@ -894,15 +909,7 @@
self.assertEqual(all[1], self.sub2_tree)
def test_file_like_path(self):
- class FileLike:
- def __init__(self, path):
- self._path = path
- def __str__(self):
- return str(self._path)
- def __fspath__(self):
- return self._path
-
- self.test_walk_prune(FileLike(self.walk_path))
+ self.test_walk_prune(_PathLike(self.walk_path))
def test_walk_bottom_up(self):
# Walk bottom-up.
@@ -2124,7 +2131,8 @@
def test_waitpid(self):
args = [sys.executable, '-c', 'pass']
- pid = os.spawnv(os.P_NOWAIT, args[0], args)
+ # Add an implicit test for PyUnicode_FSConverter().
+ pid = os.spawnv(os.P_NOWAIT, _PathLike(args[0]), args)
status = os.waitpid(pid, 0)
self.assertEqual(status, (pid, 0))
@@ -2833,25 +2841,18 @@
]
def test_path_t_converter(self):
- class PathLike:
- def __init__(self, path):
- self.path = path
-
- def __fspath__(self):
- return self.path
-
str_filename = support.TESTFN
if os.name == 'nt':
bytes_fspath = bytes_filename = None
else:
bytes_filename = support.TESTFN.encode('ascii')
- bytes_fspath = PathLike(bytes_filename)
- fd = os.open(PathLike(str_filename), os.O_WRONLY|os.O_CREAT)
+ bytes_fspath = _PathLike(bytes_filename)
+ fd = os.open(_PathLike(str_filename), os.O_WRONLY|os.O_CREAT)
self.addCleanup(support.unlink, support.TESTFN)
self.addCleanup(os.close, fd)
- int_fspath = PathLike(fd)
- str_fspath = PathLike(str_filename)
+ int_fspath = _PathLike(fd)
+ str_fspath = _PathLike(str_filename)
for name, allow_fd, extra_args, cleanup_fn in self.functions:
with self.subTest(name=name):
@@ -3205,15 +3206,6 @@
# if a C version is provided.
fspath = staticmethod(os.fspath)
- class PathLike:
- def __init__(self, path=''):
- self.path = path
- def __fspath__(self):
- if isinstance(self.path, BaseException):
- raise self.path
- else:
- return self.path
-
def test_return_bytes(self):
for b in b'hello', b'goodbye', b'some/path/and/file':
self.assertEqual(b, self.fspath(b))
@@ -3224,16 +3216,16 @@
def test_fsencode_fsdecode(self):
for p in "path/like/object", b"path/like/object":
- pathlike = self.PathLike(p)
+ pathlike = _PathLike(p)
self.assertEqual(p, self.fspath(pathlike))
self.assertEqual(b"path/like/object", os.fsencode(pathlike))
self.assertEqual("path/like/object", os.fsdecode(pathlike))
def test_pathlike(self):
- self.assertEqual('#feelthegil', self.fspath(self.PathLike('#feelthegil')))
- self.assertTrue(issubclass(self.PathLike, os.PathLike))
- self.assertTrue(isinstance(self.PathLike(), os.PathLike))
+ self.assertEqual('#feelthegil', self.fspath(_PathLike('#feelthegil')))
+ self.assertTrue(issubclass(_PathLike, os.PathLike))
+ self.assertTrue(isinstance(_PathLike(), os.PathLike))
def test_garbage_in_exception_out(self):
vapor = type('blah', (), {})
@@ -3245,14 +3237,14 @@
def test_bad_pathlike(self):
# __fspath__ returns a value other than str or bytes.
- self.assertRaises(TypeError, self.fspath, self.PathLike(42))
+ self.assertRaises(TypeError, self.fspath, _PathLike(42))
# __fspath__ attribute that is not callable.
c = type('foo', (), {})
c.__fspath__ = 1
self.assertRaises(TypeError, self.fspath, c())
# __fspath__ raises an exception.
self.assertRaises(ZeroDivisionError, self.fspath,
- self.PathLike(ZeroDivisionError()))
+ _PathLike(ZeroDivisionError()))
# Only test if the C version is provided, otherwise TestPEP519 already tested
# the pure Python implementation.
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -188,6 +188,11 @@
- Issue #27573: exit message for code.interact is now configurable.
+C API
+-----
+
+- Issue #26027: Add support for path-like objects in PyUnicode_FSConverter().
+
Tests
-----
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -3011,13 +3011,13 @@
{"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__},
static PyObject *
-os_waitpid_impl(PyObject *module, Py_intptr_t pid, int options);
+os_waitpid_impl(PyObject *module, intptr_t pid, int options);
static PyObject *
os_waitpid(PyObject *module, PyObject *args)
{
PyObject *return_value = NULL;
- Py_intptr_t pid;
+ intptr_t pid;
int options;
if (!PyArg_ParseTuple(args, "" _Py_PARSE_INTPTR "i:waitpid",
@@ -5479,13 +5479,13 @@
{"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_O, os_get_handle_inheritable__doc__},
static int
-os_get_handle_inheritable_impl(PyObject *module, Py_intptr_t handle);
+os_get_handle_inheritable_impl(PyObject *module, intptr_t handle);
static PyObject *
os_get_handle_inheritable(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
- Py_intptr_t handle;
+ intptr_t handle;
int _return_value;
if (!PyArg_Parse(arg, "" _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) {
@@ -5515,14 +5515,14 @@
{"set_handle_inheritable", (PyCFunction)os_set_handle_inheritable, METH_VARARGS, os_set_handle_inheritable__doc__},
static PyObject *
-os_set_handle_inheritable_impl(PyObject *module, Py_intptr_t handle,
+os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
int inheritable);
static PyObject *
os_set_handle_inheritable(PyObject *module, PyObject *args)
{
PyObject *return_value = NULL;
- Py_intptr_t handle;
+ intptr_t handle;
int inheritable;
if (!PyArg_ParseTuple(args, "" _Py_PARSE_INTPTR "p:set_handle_inheritable",
@@ -6042,4 +6042,4 @@
#ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF
#define OS_SET_HANDLE_INHERITABLE_METHODDEF
#endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */
-/*[clinic end generated code: output=2b85bb3703a6488a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=677ce794fb126161 input=a9049054013a1b77]*/
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -2520,7 +2520,7 @@
impl_by_reference = True;
[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=affe68316f160401]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=418fce0e01144461]*/
/*[clinic input]
@@ -7092,7 +7092,7 @@
static PyObject *
os_waitpid_impl(PyObject *module, intptr_t pid, int options)
-/*[clinic end generated code: output=15f1ce005a346b09 input=444c8f51cca5b862]*/
+/*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
{
int status;
intptr_t res;
@@ -11383,7 +11383,7 @@
static int
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
-/*[clinic end generated code: output=9e5389b0aa0916ce input=5f7759443aae3dc5]*/
+/*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
{
DWORD flags;
@@ -11408,7 +11408,7 @@
static PyObject *
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
int inheritable)
-/*[clinic end generated code: output=b1e67bfa3213d745 input=e64b2b2730469def]*/
+/*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
{
DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3842,6 +3842,7 @@
int
PyUnicode_FSConverter(PyObject* arg, void* addr)
{
+ PyObject *path = NULL;
PyObject *output = NULL;
Py_ssize_t size;
void *data;
@@ -3850,22 +3851,22 @@
*(PyObject**)addr = NULL;
return 1;
}
- if (PyBytes_Check(arg)) {
- output = arg;
- Py_INCREF(output);
- }
- else if (PyUnicode_Check(arg)) {
- output = PyUnicode_EncodeFSDefault(arg);
- if (!output)
+ path = PyOS_FSPath(arg);
+ if (path == NULL) {
+ return 0;
+ }
+ if (PyBytes_Check(path)) {
+ output = path;
+ }
+ else { // PyOS_FSPath() guarantees its returned value is bytes or str.
+ output = PyUnicode_EncodeFSDefault(path);
+ Py_DECREF(path);
+ if (!output) {
return 0;
+ }
assert(PyBytes_Check(output));
}
- else {
- PyErr_Format(PyExc_TypeError,
- "must be str or bytes, not %.100s",
- Py_TYPE(arg)->tp_name);
- return 0;
- }
+
size = PyBytes_GET_SIZE(output);
data = PyBytes_AS_STRING(output);
if ((size_t)size != strlen(data)) {
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list