File indexing completed on 2025-01-18 10:06:13
0001
0002
0003
0004
0005 #pragma once
0006
0007 #include <pybind11/cast.h>
0008 #include <pybind11/detail/common.h>
0009 #include <pybind11/detail/descr.h>
0010 #include <pybind11/pybind11.h>
0011 #include <pybind11/pytypes.h>
0012
0013 #include <string>
0014
0015 #ifdef __has_include
0016 # if defined(PYBIND11_CPP17)
0017 # if __has_include(<filesystem>)
0018 # include <filesystem>
0019 # define PYBIND11_HAS_FILESYSTEM 1
0020 # elif __has_include(<experimental/filesystem>)
0021 # include <experimental/filesystem>
0022 # define PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM 1
0023 # endif
0024 # endif
0025 #endif
0026
0027 #if !defined(PYBIND11_HAS_FILESYSTEM) && !defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM) \
0028 && !defined(PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL)
0029 # error \
0030 "Neither #include <filesystem> nor #include <experimental/filesystem is available. (Use -DPYBIND11_HAS_FILESYSTEM_IS_OPTIONAL to ignore.)"
0031 #endif
0032
0033 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0034 PYBIND11_NAMESPACE_BEGIN(detail)
0035
0036 #ifdef PYPY_VERSION
0037 # define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...) (__VA_ARGS__)
0038 #else
0039 # define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...) \
0040 (reinterpret_cast<void *>(__VA_ARGS__))
0041 #endif
0042
0043 #if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0044 template <typename T>
0045 struct path_caster {
0046
0047 private:
0048 static PyObject *unicode_from_fs_native(const std::string &w) {
0049 # if !defined(PYPY_VERSION)
0050 return PyUnicode_DecodeFSDefaultAndSize(w.c_str(), ssize_t(w.size()));
0051 # else
0052
0053 return PyUnicode_DecodeFSDefaultAndSize(const_cast<char *>(w.c_str()), ssize_t(w.size()));
0054 # endif
0055 }
0056
0057 static PyObject *unicode_from_fs_native(const std::wstring &w) {
0058 return PyUnicode_FromWideChar(w.c_str(), ssize_t(w.size()));
0059 }
0060
0061 public:
0062 static handle cast(const T &path, return_value_policy, handle) {
0063 if (auto py_str = unicode_from_fs_native(path.native())) {
0064 return module_::import("pathlib")
0065 .attr("Path")(reinterpret_steal<object>(py_str))
0066 .release();
0067 }
0068 return nullptr;
0069 }
0070
0071 bool load(handle handle, bool) {
0072
0073
0074
0075 PyObject *buf = PyOS_FSPath(handle.ptr());
0076 if (!buf) {
0077 PyErr_Clear();
0078 return false;
0079 }
0080 PyObject *native = nullptr;
0081 if constexpr (std::is_same_v<typename T::value_type, char>) {
0082 if (PyUnicode_FSConverter(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native))
0083 != 0) {
0084 if (auto *c_str = PyBytes_AsString(native)) {
0085
0086
0087 value = c_str;
0088 }
0089 }
0090 } else if constexpr (std::is_same_v<typename T::value_type, wchar_t>) {
0091 if (PyUnicode_FSDecoder(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native))
0092 != 0) {
0093 if (auto *c_str = PyUnicode_AsWideCharString(native, nullptr)) {
0094
0095 value = c_str;
0096 PyMem_Free(c_str);
0097 }
0098 }
0099 }
0100 Py_XDECREF(native);
0101 Py_DECREF(buf);
0102 if (PyErr_Occurred()) {
0103 PyErr_Clear();
0104 return false;
0105 }
0106 return true;
0107 }
0108
0109 PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
0110 };
0111
0112 #endif
0113
0114 #if defined(PYBIND11_HAS_FILESYSTEM)
0115 template <>
0116 struct type_caster<std::filesystem::path> : public path_caster<std::filesystem::path> {};
0117 #elif defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
0118 template <>
0119 struct type_caster<std::experimental::filesystem::path>
0120 : public path_caster<std::experimental::filesystem::path> {};
0121 #endif
0122
0123 PYBIND11_NAMESPACE_END(detail)
0124 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)