File indexing completed on 2025-01-18 10:17:46
0001
0002
0003
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
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
0067
0068
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
0079
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
0087 value = c_str;
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
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)