cpython: 780cbe18082e (original) (raw)
Mercurial > cpython
changeset 101707:780cbe18082e
issue27186: add C version of os.fspath(); patch by Jelle Zijlstra [#27186]
Ethan Furman ethan@stoneleaf.us | |
---|---|
date | Sat, 04 Jun 2016 12:06:26 -0700 |
parents | 52e331b86f2b |
children | 21ae58b77924 |
files | Include/Python.h Include/osmodule.h Lib/os.py Lib/test/test_os.py Modules/clinic/posixmodule.c.h Modules/posixmodule.c |
diffstat | 6 files changed, 125 insertions(+), 18 deletions(-)[+] [-] Include/Python.h 1 Include/osmodule.h 15 Lib/os.py 35 Lib/test/test_os.py 7 Modules/clinic/posixmodule.c.h 34 Modules/posixmodule.c 51 |
line wrap: on
line diff
--- a/Include/Python.h +++ b/Include/Python.h @@ -116,6 +116,7 @@ #include "pylifecycle.h" #include "ceval.h" #include "sysmodule.h" +#include "osmodule.h" #include "intrcheck.h" #include "import.h"
new file mode 100644 --- /dev/null +++ b/Include/osmodule.h @@ -0,0 +1,15 @@ + +/* os module interface */ + +#ifndef Py_OSMODULE_H +#define Py_OSMODULE_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(PyObject *) PyOS_FSPath(PyObject path); + +#ifdef __cplusplus +} +#endif +#endif / !Py_OSMODULE_H */
--- a/Lib/os.py +++ b/Lib/os.py @@ -1104,23 +1104,24 @@ def fdopen(fd, *args, **kwargs): import io return io.open(fd, *args, **kwargs) -# Supply os.fspath() -def fspath(path):
+# Supply os.fspath() if not defined in C +if not _exists('fspath'):
- If str or bytes is passed in, it is returned unchanged.
- """
- if isinstance(path, (str, bytes)):
return path[](#l3.18)
If str or bytes is passed in, it is returned unchanged.[](#l3.19)
"""[](#l3.20)
if isinstance(path, (str, bytes)):[](#l3.21)
return path[](#l3.22)
Work from the object's type to match method resolution of other magic
methods.
- path_type = type(path)
- try:
return path_type.__fspath__(path)[](#l3.28)
- except AttributeError:
if hasattr(path_type, '__fspath__'):[](#l3.30)
raise[](#l3.31)
# Work from the object's type to match method resolution of other magic[](#l3.32)
# methods.[](#l3.33)
path_type = type(path)[](#l3.34)
try:[](#l3.35)
return path_type.__fspath__(path)[](#l3.36)
except AttributeError:[](#l3.37)
if hasattr(path_type, '__fspath__'):[](#l3.38)
raise[](#l3.39)
raise TypeError("expected str, bytes or os.PathLike object, not "[](#l3.41)
+ path_type.__name__)[](#l3.42)
raise TypeError("expected str, bytes or os.PathLike object, not "[](#l3.43)
+ path_type.__name__)[](#l3.44)
--- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3121,6 +3121,13 @@ class TestPEP519(unittest.TestCase): self.assertEqual(b"path/like/object", os.fsencode(pathlike)) self.assertEqual("path/like/object", os.fsdecode(pathlike))
- def test_fspathlike(self):
class PathLike(object):[](#l4.8)
def __fspath__(self):[](#l4.9)
return '#feelthegil'[](#l4.10)
self.assertEqual('#feelthegil', os.fspath(PathLike()))[](#l4.12)
+ def test_garbage_in_exception_out(self): vapor = type('blah', (), {}) for o in int, type, os, vapor():
--- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -5321,6 +5321,38 @@ exit: #endif /* defined(MS_WINDOWS) */ +PyDoc_STRVAR(os_fspath__doc__, +"fspath($module, /, path)\n" +"--\n" +"\n" +"Return the file system path representation of the object.\n" +"\n" +"If the object is str or bytes, then allow it to pass through with\n" +"an incremented refcount. If the object defines fspath(), then\n" +"return the result of that method. All other types raise a TypeError."); + +#define OS_FSPATH_METHODDEF [](#l5.17)
+ +static PyObject * +os_fspath_impl(PyModuleDef *module, PyObject *path); + +static PyObject * +os_fspath(PyModuleDef *module, PyObject *args, PyObject *kwargs) +{
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:fspath", _keywords,
&path))[](#l5.31)
goto exit;[](#l5.32)
- return_value = os_fspath_impl(module, path);
+} + #ifndef OS_TTYNAME_METHODDEF #define OS_TTYNAME_METHODDEF #endif /* !defined(OS_TTYNAME_METHODDEF) / @@ -5792,4 +5824,4 @@ exit: #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif / !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) / -/[clinic end generated code: output=a5c9bef9ad11a20b input=a9049054013a1b77]/ +/[clinic end generated code: output=e64e246b8270abda input=a9049054013a1b77]*/
--- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12284,6 +12284,56 @@ error: return NULL; } +/*
- If the object is str or bytes, then allow it to pass through with
- an incremented refcount. If the object defines fspath(), then
- return the result of that method. All other types raise a TypeError.
+*/ +PyObject * +PyOS_FSPath(PyObject *path) +{
- if (PyUnicode_Check(path) || PyBytes_Check(path)) {
Py_INCREF(path);[](#l6.22)
return path;[](#l6.23)
- }
- func = PyObject_LookupSpecial(path, &PyId___fspath_);
- if (NULL == func) {
return PyErr_Format(PyExc_TypeError,[](#l6.28)
"expected str, bytes or os.PathLike object, "[](#l6.29)
"not %S",[](#l6.30)
path->ob_type);[](#l6.31)
- }
+} + +/*[clinic input] +os.fspath +
+ +Return the file system path representation of the object. + +If the object is str or bytes, then allow it to pass through with +an incremented refcount. If the object defines fspath(), then +return the result of that method. All other types raise a TypeError. +[clinic start generated code]*/ + +static PyObject * +os_fspath_impl(PyModuleDef module, PyObject path) +/[clinic end generated code: output=51ef0c2772c1932a input=652c7c37e4be1c13]/ +{
+} #include "clinic/posixmodule.c.h" @@ -12484,6 +12534,7 @@ static PyMethodDef posix_methods[] = { {"scandir", (PyCFunction)posix_scandir, METH_VARARGS | METH_KEYWORDS, posix_scandir__doc__},