[Python-checkins] cpython: Issue #27182: Add support for path-like objects to PyUnicode_FSDecoder().

brett.cannon python-checkins at python.org
Tue Sep 6 22:36:28 EDT 2016


https://hg.python.org/cpython/rev/3417d324cbf9
changeset: 103197:3417d324cbf9
user: Brett Cannon <brett at python.org>
date: Tue Sep 06 19:36:01 2016 -0700
summary:
 Issue #27182: Add support for path-like objects to PyUnicode_FSDecoder().
files:
 Doc/c-api/unicode.rst | 12 ++++--
 Doc/whatsnew/3.6.rst | 18 +++++---
 Lib/test/test_compile.py | 10 +++++
 Misc/NEWS | 3 +-
 Objects/unicodeobject.c | 53 ++++++++++++++++++++-------
 5 files changed, 69 insertions(+), 27 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
@@ -826,13 +826,17 @@
 
 .. c:function:: int PyUnicode_FSDecoder(PyObject* obj, void* result)
 
- ParseTuple converter: decode :class:`bytes` objects to :class:`str` using
- :c:func:`PyUnicode_DecodeFSDefaultAndSize`; :class:`str` objects are output
- as-is. *result* must be a :c:type:`PyUnicodeObject*` which must be released
- when it is no longer used.
+ ParseTuple converter: decode :class:`bytes` objects -- obtained either
+ directly or indirectly through the :class:`os.PathLike` interface -- to
+ :class:`str` using :c:func:`PyUnicode_DecodeFSDefaultAndSize`; :class:`str`
+ objects are output as-is. *result* must be a :c:type:`PyUnicodeObject*` which
+ must be released when it is no longer used.
 
 .. versionadded:: 3.2
 
+ .. versionchanged:: 3.6
+ Accepts a :term:`path-like object`.
+
 
 .. c:function:: PyObject* PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
 
diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst
--- a/Doc/whatsnew/3.6.rst
+++ b/Doc/whatsnew/3.6.rst
@@ -160,14 +160,18 @@
 
 The built-in :func:`open` function has been updated to accept
 :class:`os.PathLike` objects as have all relevant functions in the
-:mod:`os` and :mod:`os.path` modules. The :class:`os.DirEntry` class
+:mod:`os` and :mod:`os.path` modules. :c:func:`PyUnicode_FSConverter`
+and :c:func:`PyUnicode_FSConverter` have been changed to accept
+path-like objects. The :class:`os.DirEntry` class
 and relevant classes in :mod:`pathlib` have also been updated to
-implement :class:`os.PathLike`. The hope is that updating the
-fundamental functions for operating on file system paths will lead
-to third-party code to implicitly support all
-:term:`path-like objects <path-like object>` without any code changes
-or at least very minimal ones (e.g. calling :func:`os.fspath` at the
-beginning of code before operating on a path-like object).
+implement :class:`os.PathLike`.
+
+The hope in is that updating the fundamental functions for operating
+on file system paths will lead to third-party code to implicitly
+support all :term:`path-like objects <path-like object>` without any
+code changes or at least very minimal ones (e.g. calling
+:func:`os.fspath` at the beginning of code before operating on a
+path-like object).
 
 Here are some examples of how the new interface allows for
 :class:`pathlib.Path` to be used more easily and transparently with
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -664,6 +664,16 @@
 self.assertTrue(f1(0))
 self.assertTrue(f2(0.0))
 
+ def test_path_like_objects(self):
+ # An implicit test for PyUnicode_FSDecoder().
+ class PathLike:
+ def __init__(self, path):
+ self._path = path
+ def __fspath__(self):
+ return self._path
+
+ compile("42", PathLike("test_compile_pathlike"), "single")
+
 
 class TestStackSize(unittest.TestCase):
 # These tests check that the computed stack size for a code object
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -202,7 +202,8 @@
 C API
 -----
 
-- Issue #26027: Add support for path-like objects in PyUnicode_FSConverter().
+- Issue #26027: Add support for path-like objects in PyUnicode_FSConverter() &
+ PyUnicode_FSDecoder().
 
 Tests
 -----
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -3882,37 +3882,60 @@
 int
 PyUnicode_FSDecoder(PyObject* arg, void* addr)
 {
+ int is_buffer = 0;
+ PyObject *path = NULL;
 PyObject *output = NULL;
 if (arg == NULL) {
 Py_DECREF(*(PyObject**)addr);
 return 1;
 }
- if (PyUnicode_Check(arg)) {
- if (PyUnicode_READY(arg) == -1)
+
+ is_buffer = PyObject_CheckBuffer(arg);
+ if (!is_buffer) {
+ path = PyOS_FSPath(arg);
+ if (path == NULL) {
 return 0;
- output = arg;
- Py_INCREF(output);
- }
- else if (PyBytes_Check(arg) || PyObject_CheckBuffer(arg)) {
- if (!PyBytes_Check(arg) &&
+ }
+ }
+ else {
+ path = arg;
+ Py_INCREF(arg);
+ }
+
+ if (PyUnicode_Check(path)) {
+ if (PyUnicode_READY(path) == -1) {
+ Py_DECREF(path);
+ return 0;
+ }
+ output = path;
+ }
+ else if (PyBytes_Check(path) || is_buffer) {
+ PyObject *path_bytes = NULL;
+
+ if (!PyBytes_Check(path) &&
 PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
- "path should be string or bytes, not %.200s",
+ "path should be string, bytes, or os.PathLike, not %.200s",
 Py_TYPE(arg)->tp_name)) {
+ Py_DECREF(path);
 return 0;
 }
- arg = PyBytes_FromObject(arg);
- if (!arg)
+ path_bytes = PyBytes_FromObject(path);
+ Py_DECREF(path);
+ if (!path_bytes) {
 return 0;
- output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(arg),
- PyBytes_GET_SIZE(arg));
- Py_DECREF(arg);
- if (!output)
+ }
+ output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(path_bytes),
+ PyBytes_GET_SIZE(path_bytes));
+ Py_DECREF(path_bytes);
+ if (!output) {
 return 0;
+ }
 }
 else {
 PyErr_Format(PyExc_TypeError,
- "path should be string or bytes, not %.200s",
+ "path should be string, bytes, or os.PathLike, not %.200s",
 Py_TYPE(arg)->tp_name);
+ Py_DECREF(path);
 return 0;
 }
 if (PyUnicode_READY(output) == -1) {
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /