mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Issue #27182: Add support for path-like objects to PyUnicode_FSDecoder().
This commit is contained in:
parent
a439191efa
commit
a571120410
5 changed files with 72 additions and 30 deletions
|
@ -826,13 +826,17 @@ used, passing :c:func:`PyUnicode_FSDecoder` as the conversion function:
|
||||||
|
|
||||||
.. c:function:: int PyUnicode_FSDecoder(PyObject* obj, void* result)
|
.. c:function:: int PyUnicode_FSDecoder(PyObject* obj, void* result)
|
||||||
|
|
||||||
ParseTuple converter: decode :class:`bytes` objects to :class:`str` using
|
ParseTuple converter: decode :class:`bytes` objects -- obtained either
|
||||||
:c:func:`PyUnicode_DecodeFSDefaultAndSize`; :class:`str` objects are output
|
directly or indirectly through the :class:`os.PathLike` interface -- to
|
||||||
as-is. *result* must be a :c:type:`PyUnicodeObject*` which must be released
|
:class:`str` using :c:func:`PyUnicode_DecodeFSDefaultAndSize`; :class:`str`
|
||||||
when it is no longer used.
|
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
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
.. versionchanged:: 3.6
|
||||||
|
Accepts a :term:`path-like object`.
|
||||||
|
|
||||||
|
|
||||||
.. c:function:: PyObject* PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
|
.. c:function:: PyObject* PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
|
||||||
|
|
||||||
|
|
|
@ -160,14 +160,18 @@ object.
|
||||||
|
|
||||||
The built-in :func:`open` function has been updated to accept
|
The built-in :func:`open` function has been updated to accept
|
||||||
:class:`os.PathLike` objects as have all relevant functions in the
|
: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
|
and relevant classes in :mod:`pathlib` have also been updated to
|
||||||
implement :class:`os.PathLike`. The hope is that updating the
|
implement :class:`os.PathLike`.
|
||||||
fundamental functions for operating on file system paths will lead
|
|
||||||
to third-party code to implicitly support all
|
The hope in is that updating the fundamental functions for operating
|
||||||
:term:`path-like objects <path-like object>` without any code changes
|
on file system paths will lead to third-party code to implicitly
|
||||||
or at least very minimal ones (e.g. calling :func:`os.fspath` at the
|
support all :term:`path-like objects <path-like object>` without any
|
||||||
beginning of code before operating on a path-like object).
|
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
|
Here are some examples of how the new interface allows for
|
||||||
:class:`pathlib.Path` to be used more easily and transparently with
|
:class:`pathlib.Path` to be used more easily and transparently with
|
||||||
|
|
|
@ -664,6 +664,16 @@ if 1:
|
||||||
self.assertTrue(f1(0))
|
self.assertTrue(f1(0))
|
||||||
self.assertTrue(f2(0.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):
|
class TestStackSize(unittest.TestCase):
|
||||||
# These tests check that the computed stack size for a code object
|
# These tests check that the computed stack size for a code object
|
||||||
|
|
|
@ -202,7 +202,8 @@ Library
|
||||||
C API
|
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
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -3882,37 +3882,60 @@ PyUnicode_FSConverter(PyObject* arg, void* addr)
|
||||||
int
|
int
|
||||||
PyUnicode_FSDecoder(PyObject* arg, void* addr)
|
PyUnicode_FSDecoder(PyObject* arg, void* addr)
|
||||||
{
|
{
|
||||||
|
int is_buffer = 0;
|
||||||
|
PyObject *path = NULL;
|
||||||
PyObject *output = NULL;
|
PyObject *output = NULL;
|
||||||
if (arg == NULL) {
|
if (arg == NULL) {
|
||||||
Py_DECREF(*(PyObject**)addr);
|
Py_DECREF(*(PyObject**)addr);
|
||||||
return 1;
|
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;
|
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,
|
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_TYPE(arg)->tp_name)) {
|
||||||
|
Py_DECREF(path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arg = PyBytes_FromObject(arg);
|
path_bytes = PyBytes_FromObject(path);
|
||||||
if (!arg)
|
Py_DECREF(path);
|
||||||
|
if (!path_bytes) {
|
||||||
return 0;
|
return 0;
|
||||||
output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(arg),
|
}
|
||||||
PyBytes_GET_SIZE(arg));
|
output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(path_bytes),
|
||||||
Py_DECREF(arg);
|
PyBytes_GET_SIZE(path_bytes));
|
||||||
if (!output)
|
Py_DECREF(path_bytes);
|
||||||
|
if (!output) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
PyErr_Format(PyExc_TypeError,
|
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_TYPE(arg)->tp_name);
|
||||||
|
Py_DECREF(path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (PyUnicode_READY(output) == -1) {
|
if (PyUnicode_READY(output) == -1) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue