Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:46

0001 // Copyright (c) 2021 The Pybind Development Team.
0002 // All rights reserved. Use of this source code is governed by a
0003 // BSD-style license that can be found in the LICENSE file.
0004 
0005 #pragma once
0006 
0007 #include "../pybind11.h"
0008 #include "../detail/common.h"
0009 #include "../detail/descr.h"
0010 #include "../cast.h"
0011 #include "../pytypes.h"
0012 
0013 #include <string>
0014 
0015 #ifdef __has_include
0016 #    if defined(PYBIND11_CPP17)
0017 #        if __has_include(<filesystem>) && \
0018           PY_VERSION_HEX >= 0x03060000
0019 #            include <filesystem>
0020 #            define PYBIND11_HAS_FILESYSTEM 1
0021 #        elif __has_include(<experimental/filesystem>)
0022 #            include <experimental/filesystem>
0023 #            define PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM 1
0024 #        endif
0025 #    endif
0026 #endif
0027 
0028 #if !defined(PYBIND11_HAS_FILESYSTEM) && !defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)           \
0029     && !defined(PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL)
0030 #    error                                                                                        \
0031         "Neither #include <filesystem> nor #include <experimental/filesystem is available. (Use -DPYBIND11_HAS_FILESYSTEM_IS_OPTIONAL to ignore.)"
0032 #endif
0033 
0034 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0035 PYBIND11_NAMESPACE_BEGIN(detail)
0036 
0037 #if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0038 template <typename T>
0039 struct path_caster {
0040 
0041 private:
0042     static PyObject *unicode_from_fs_native(const std::string &w) {
0043 #    if !defined(PYPY_VERSION)
0044         return PyUnicode_DecodeFSDefaultAndSize(w.c_str(), ssize_t(w.size()));
0045 #    else
0046         // PyPy mistakenly declares the first parameter as non-const.
0047         return PyUnicode_DecodeFSDefaultAndSize(const_cast<char *>(w.c_str()), ssize_t(w.size()));
0048 #    endif
0049     }
0050 
0051     static PyObject *unicode_from_fs_native(const std::wstring &w) {
0052         return PyUnicode_FromWideChar(w.c_str(), ssize_t(w.size()));
0053     }
0054 
0055 public:
0056     static handle cast(const T &path, return_value_policy, handle) {
0057         if (auto py_str = unicode_from_fs_native(path.native())) {
0058             return module_::import("pathlib")
0059                 .attr("Path")(reinterpret_steal<object>(py_str))
0060                 .release();
0061         }
0062         return nullptr;
0063     }
0064 
0065     bool load(handle handle, bool) {
0066         // PyUnicode_FSConverter and PyUnicode_FSDecoder normally take care of
0067         // calling PyOS_FSPath themselves, but that's broken on PyPy (PyPy
0068         // issue #3168) so we do it ourselves instead.
0069         PyObject *buf = PyOS_FSPath(handle.ptr());
0070         if (!buf) {
0071             PyErr_Clear();
0072             return false;
0073         }
0074         PyObject *native = nullptr;
0075         if constexpr (std::is_same_v<typename T::value_type, char>) {
0076             if (PyUnicode_FSConverter(buf, &native) != 0) {
0077                 if (auto *c_str = PyBytes_AsString(native)) {
0078                     // AsString returns a pointer to the internal buffer, which
0079                     // must not be free'd.
0080                     value = c_str;
0081                 }
0082             }
0083         } else if constexpr (std::is_same_v<typename T::value_type, wchar_t>) {
0084             if (PyUnicode_FSDecoder(buf, &native) != 0) {
0085                 if (auto *c_str = PyUnicode_AsWideCharString(native, nullptr)) {
0086                     // AsWideCharString returns a new string that must be free'd.
0087                     value = c_str; // Copies the string.
0088                     PyMem_Free(c_str);
0089                 }
0090             }
0091         }
0092         Py_XDECREF(native);
0093         Py_DECREF(buf);
0094         if (PyErr_Occurred()) {
0095             PyErr_Clear();
0096             return false;
0097         }
0098         return true;
0099     }
0100 
0101     PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
0102 };
0103 
0104 #endif // PYBIND11_HAS_FILESYSTEM || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0105 
0106 #if defined(PYBIND11_HAS_FILESYSTEM)
0107 template <>
0108 struct type_caster<std::filesystem::path> : public path_caster<std::filesystem::path> {};
0109 #elif defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0110 template <>
0111 struct type_caster<std::experimental::filesystem::path>
0112     : public path_caster<std::experimental::filesystem::path> {};
0113 #endif
0114 
0115 PYBIND11_NAMESPACE_END(detail)
0116 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)