43#ifndef LASS_GUARDIAN_OF_INCLUSION_PYTHON_EXPORT_TRAITS_H
44#define LASS_GUARDIAN_OF_INCLUSION_PYTHON_EXPORT_TRAITS_H
292 template <
typename T>
struct ShadowTraits;
294 template <
typename In,
typename Out>
295 [[deprecated]]
int pyNumCast(In in, Out& out)
299 out = num::numCast<Out>(in);
301 catch (
const std::exception& error)
303 PyErr_SetString(PyExc_TypeError, error.what());
309 template <
typename T>
310 using NoNone [[deprecated(
"lass::python::NoNone<T> instead.")]] = lass::python::NoNone<T>;
312 LASS_PYTHON_DLL PyObject* buildStringImpl(
const char* s,
size_t n);
313 LASS_PYTHON_DLL PyObject* buildStringImpl(
const wchar_t* s,
size_t n);
314#if LASS_HAVE_STD_U8STRING
316 LASS_PYTHON_DLL PyObject* buildStringImpl(
const char8_t* s,
size_t n);
319 LASS_PYTHON_DLL PyObject* buildStringImpl(
const char16_t* s,
size_t n);
320 LASS_PYTHON_DLL PyObject* buildStringImpl(
const char32_t* s,
size_t n);
329 typedef impl::ShadowTraits<typename ShadoweeTraits<T>::TShadow> TShadowTraits;
330 static PyObject* build(
const T& v)
334 static int get(PyObject* obj, T& v)
336 return TShadowTraits::getObject(obj, v);
346 static PyObject* build(
const T& v)
348 return PyExportTraits<T>::build(v);
360 typedef impl::ShadowTraits<typename ShadoweeTraits<T>::TShadow> TShadowTraits;
361 static PyObject* build(T* value)
369 static int get(PyObject* obj, T*& value)
376 return TShadowTraits::getObject(obj, value);
390template <
typename T,
template <
typename,
typename>
class S,
typename C>
393 constexpr static const char* py_typing =
"T | None";
395 typedef impl::ShadowTraits<typename ShadoweeTraits<T>::TShadow> TShadowTraits;
396 typedef util::SharedPtr<T, S, C> TPtr;
397 static PyObject* build(
const TPtr& value)
405 static int get(PyObject* obj, TPtr& value)
412 return TShadowTraits::getObject(obj, value);
430 constexpr static const char* py_typing =
"Any";
432 static PyObject* build(
const TPyObjPtr& v)
440 static int get(PyObject* obj,
TPyObjPtr& v)
487template <
typename T,
typename Deleter>
490 constexpr static const char* py_typing =
"T | None";
492 typedef impl::ShadowTraits<typename ShadoweeTraits<T>::TShadow> TShadowTraits;
493 static PyObject* build(std::unique_ptr<T, Deleter>&& value)
510 constexpr static const char* py_typing =
"T | None";
512 typedef impl::ShadowTraits<typename ShadoweeTraits<T>::TShadow> TShadowTraits;
513 typedef std::shared_ptr<T> TPtr;
514 static PyObject* build(
const TPtr& value)
522 static int get(PyObject* obj, TPtr& value)
529 return TShadowTraits::getObject(obj, value);
540 constexpr static const char* py_typing =
"Any";
542 LASS_PYTHON_DLL
static PyObject* build(
void* value);
543 LASS_PYTHON_DLL
static int get(PyObject* obj,
void*& value);
551struct PyExportTraits<std::nullptr_t>
553 constexpr static const char* py_typing =
"None";
555 LASS_PYTHON_DLL
static PyObject* build(std::nullptr_t value);
556 LASS_PYTHON_DLL
static int get(PyObject* obj, std::nullptr_t& value);
594 constexpr static const char* py_typing =
"T";
599 const T& v =
static_cast<const T&
>(value);
602 PyErr_SetString(PyExc_TypeError,
"value must be not be None");
605 return PyExportTraits<T>::build(value);
612 PyErr_SetString(PyExc_TypeError,
"argument must be not be None");
615 return PyExportTraits<T>::get(obj, value);
637template <
typename T,
template <
typename,
typename>
class S,
typename C>
694 constexpr static const char* py_typing =
"T | MaybeNone";
695 constexpr static const char* py_typing_preamble =
"from _typeshed import MaybeNone";
699 return PyExportTraits<T>::build(value);
721template <
typename T,
template <
typename,
typename>
class S,
typename C>
749 constexpr static const char* py_typing =
"Self";
750#if PY_VERSION_HEX < 0x030b0000
751 constexpr static const char* py_typing_preamble =
"from typing_extensions import Self";
753 constexpr static const char* py_typing_preamble =
"from typing import Self";
766 constexpr static const char* py_typing =
"bool";
768 LASS_PYTHON_DLL
static PyObject* build(
bool v);
769 LASS_PYTHON_DLL
static int get(PyObject* obj,
bool& v);
781template <
typename Integer>
784 constexpr static const char* py_typing =
"int";
786 static_assert(
sizeof(Integer) <=
sizeof(long),
"integer must fit in long");
787 static PyObject* build(Integer v)
789 return PyLong_FromLong(v);
791 static int get(PyObject* obj, Integer& v)
793#if LASS_USE_OLD_EXPORTRAITS_INT
794 if (PyLong_Check(obj))
797 const PY_LONG_LONG x = PyLong_AsLongLong(obj);
799 const long x = PyLong_AsLong(obj);
801 if (PyErr_Occurred())
803 PyErr_Format(PyExc_TypeError,
"not a %s: overflow", num::NumTraits<Integer>::name().c_str());
806 return impl::pyNumCast(x, v);
808 PyErr_SetString(PyExc_TypeError,
"not an integer");
812 const PY_LONG_LONG x = PyLong_AsLongLong(obj);
814 const long x = PyLong_AsLong(obj);
816 if (x == -1 && PyErr_Occurred())
822 v = num::numCast<Integer>(x);
824 catch (
const num::BadNumCast& err)
826 PyErr_SetString(PyExc_OverflowError, err.what());
888template <
typename Integer>
891 constexpr static const char* py_typing =
"int";
893 static_assert(
sizeof(Integer) <=
sizeof(
unsigned long),
"integer must fit in unsigned long");
894 static PyObject* build(Integer v)
896 return PyLong_FromUnsignedLong(v);
898 static int get(PyObject* obj, Integer& v)
900#if LASS_USE_OLD_EXPORTRAITS_INT
901 if (PyLong_Check(obj))
904 const unsigned PY_LONG_LONG x = PyLong_AsUnsignedLongLong(obj);
906 const unsigned long x = PyLong_AsUnsignedLong(obj);
908 if (PyErr_Occurred())
910 PyErr_Format(PyExc_TypeError,
"not a %s: overflow", num::NumTraits<Integer>::name().c_str());
913 return impl::pyNumCast(x, v);
915 PyErr_SetString(PyExc_TypeError,
"not an integer");
918 if (!PyLong_Check(obj))
928 return PyExportTraits<Integer>::get(o.get(), v);
931 const unsigned PY_LONG_LONG x = PyLong_AsUnsignedLongLong(obj);
932 if (x == ((
unsigned PY_LONG_LONG) - 1) && PyErr_Occurred())
937 const unsigned long x = PyLong_AsUnsignedLong(obj);
938 if (x == ((
unsigned long) - 1) && PyErr_Occurred())
945 v = num::numCast<Integer>(x);
947 catch (
const num::BadNumCast& err)
949 PyErr_SetString(PyExc_OverflowError, err.what());
1003#ifdef HAVE_LONG_LONG
1014 constexpr static const char* py_typing =
"int";
1016 LASS_PYTHON_DLL
static PyObject* build(
signed PY_LONG_LONG v);
1017 LASS_PYTHON_DLL
static int get(PyObject* obj,
signed PY_LONG_LONG& v);
1027struct PyExportTraits<unsigned PY_LONG_LONG>
1029 constexpr static const char* py_typing =
"int";
1031 LASS_PYTHON_DLL
static PyObject* build(
unsigned PY_LONG_LONG v);
1032 LASS_PYTHON_DLL
static int get(PyObject* obj,
unsigned PY_LONG_LONG& v);
1044template <
typename Float>
1047 constexpr static const char* py_typing =
"float";
1048 constexpr static const char* py_typing_param =
"_Float";
1049 constexpr static const char* py_typing_preamble =
1050 "from typing import SupportsFloat, SupportsIndex\n"
1051 "type _Float = float | SupportsFloat | SupportsIndex\n";
1053 static PyObject* build(Float v)
1055 return PyFloat_FromDouble(v);
1057 static int get(PyObject* obj, Float& v)
1059#if LASS_USE_OLD_EXPORTRAITS_FLOAT
1060 if (PyFloat_Check(obj))
1062 return impl::pyNumCast(PyFloat_AS_DOUBLE(obj), v);
1064 if (PyLong_Check(obj))
1066 const double x = PyLong_AsDouble(obj);
1067 if (PyErr_Occurred())
1069 PyErr_Format(PyExc_TypeError,
"not a %s: overflow", num::NumTraits<Float>::name().c_str());
1072 return impl::pyNumCast(x, v);
1074 PyErr_SetString(PyExc_TypeError,
"not a float or integer");
1078 if (PyFloat_CheckExact(obj))
1080 x = PyFloat_AS_DOUBLE(obj);
1082 else if (PyLong_Check(obj))
1084 x = PyLong_AsDouble(obj);
1085 if (x == -1.0 && PyErr_Occurred())
1092 x = PyFloat_AsDouble(obj);
1093 if (x == -1.0 && PyErr_Occurred())
1098 v =
static_cast<Float
>(x);
1171template <
typename T>
1174 constexpr static const char* py_typing =
"complex";
1175 constexpr static const char* py_typing_param =
"_Complex";
1176 constexpr static const char* py_typing_preamble =
1177 "from typing import SupportsComplex, SupportsFloat, SupportsIndex\n"
1178 "type _Complex = complex | SupportsComplex | SupportsFloat | SupportsIndex\n";
1180 static PyObject* build(
const std::complex<T>& v)
1182 return PyComplex_FromDoubles(
1183 static_cast<double>(v.real()),
1184 static_cast<double>(v.imag()));
1186 static int get(PyObject* obj, std::complex<T>& v)
1188#if LASS_USE_OLD_EXPORTRAITS_COMPLEX
1190 if (PyExportTraits<T>::get(obj, re) == 0)
1192 v = std::complex<T>(re, 0);
1196 if (!PyComplex_Check(obj))
1198 PyErr_SetString(PyExc_TypeError,
"not a complex number");
1201 if (impl::pyNumCast(PyComplex_RealAsDouble(obj), re) != 0)
1205 if (impl::pyNumCast(PyComplex_ImagAsDouble(obj), im) != 0)
1209 v = std::complex<T>(re, im);
1212 Py_complex c = PyComplex_AsCComplex(obj);
1213 if (c.real == -1.0 && PyErr_Occurred())
1217 v = std::complex<T>(
static_cast<T
>(c.real),
static_cast<T
>(c.imag));
1235 static constexpr const char* py_typing =
"slice";
1237 LASS_PYTHON_DLL
static PyObject* build(
const Slice &slice);
1238 LASS_PYTHON_DLL
static int get(PyObject* obj,
Slice& slice);
1252template <
typename T>
1255 constexpr static const char* py_typing =
"str";
1257 static PyObject* build(std::basic_string_view<T> v)
1259 return impl::buildStringImpl(v.data(), v.size());
1269 constexpr static const char* py_typing =
"str | None";
1271 LASS_PYTHON_DLL
static PyObject* build(
const char* v);
1278struct PyExportTraits<const char [N]>
1280 static PyObject* build(
const char* v)
1282 static_assert(N > 1,
"N should include the null-terminator");
1283 return impl::buildStringImpl(v, N - 1);
1301 constexpr static const char* py_typing =
"str";
1303 LASS_PYTHON_DLL
static PyObject* build(
const std::string& v);
1304 LASS_PYTHON_DLL
static int get(PyObject* obj, std::string& v);
1313 constexpr static const char* py_typing =
"str | None";
1315 LASS_PYTHON_DLL
static PyObject* build(
const wchar_t* v);
1324 static PyObject* build(
const wchar_t* v)
1326 return impl::buildStringImpl(v, N);
1344 constexpr static const char* py_typing =
"str";
1346 LASS_PYTHON_DLL
static PyObject* build(
const std::wstring& v);
1347 LASS_PYTHON_DLL
static int get(PyObject* obj, std::wstring& v);
1351#if LASS_HAVE_STD_U8STRING
1352#if __cpp_lib_char8_t
1366 constexpr static const char* py_typing =
"str | None";
1368 LASS_PYTHON_DLL
static PyObject* build(
const char8_t* v);
1377 static PyObject* build(
const char8_t* v)
1379 return impl::buildStringImpl(v, N);
1399 constexpr static const char* py_typing =
"str";
1401 LASS_PYTHON_DLL
static PyObject* build(
const std::u8string& v);
1402 LASS_PYTHON_DLL
static int get(PyObject* obj, std::u8string& v);
1421 constexpr static const char* py_typing =
"str | None";
1423 LASS_PYTHON_DLL
static PyObject* build(
const char16_t* v);
1432 static PyObject* build(
const char16_t* v)
1434 return impl::buildStringImpl(v, N);
1442struct PyExportTraits<char16_t[N]> : PyExportTraits<const char16_t[N]>
1454 constexpr static const char* py_typing =
"str";
1456 LASS_PYTHON_DLL
static PyObject* build(
const std::u16string& v);
1457 LASS_PYTHON_DLL
static int get(PyObject* obj, std::u16string& v);
1473 constexpr static const char* py_typing =
"str | None";
1475 LASS_PYTHON_DLL
static PyObject* build(
const char32_t* v);
1484 static PyObject* build(
const char32_t* v)
1486 return impl::buildStringImpl(v, N);
1494struct PyExportTraits<char32_t[N]> : PyExportTraits<const char32_t[N]>
1506 constexpr static const char* py_typing =
"str";
1508 LASS_PYTHON_DLL
static PyObject* build(
const std::u32string& v);
1509 LASS_PYTHON_DLL
static int get(PyObject* obj, std::u32string& v);
Wrapper to type-hint return values in Python that maybe None but not likely.
Wrapper to prevent None values being passed to and from Python.
Wrapper to type-hint a return value as Self.
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
PyObject * fromSharedPtrToNakedCast(const util::SharedPtr< T, PyObjectStorage, PyObjectCounter > &object)
fromSharedPtrToNakedCast.
lass::util::SharedPtr< T, PyObjectStorage, PyObjectCounter > fromNakedToSharedPtrCast(PyObject *object)
fromNakedToSharedPtrCast.
ColorRGBA out(const ColorRGBA &a, const ColorRGBA &b)
a held out by b, part of a outside b.
Comprehensive C++ to Python binding library.
general utility, debug facilities, ...
Library for Assembled Shared Sources.
Helper class to create PyExportTraits for floating point numbers.
Helper class to create PyExportTraits for MaybeNone wrapped types.
Helper class to create PyExportTraits for NoNone wrapped types.
static PyObject * build(const NoNone< T > &value)
Raise a Python TypeError if value is equal to nullptr
static int get(PyObject *obj, NoNone< T > &value)
Raise a Python TypeError if obj is equal to None
Helper class to create PyExportTraits for signed integers.
Helper class to create PyExportTraits for unsigned integers.
by copy, general case assumes shadow type or PyObjectPlus based type.
Helper type to get or return Python slice objects.