1 module python.conv.d_to_python; 2 3 4 import python.raw: PyObject; 5 import python.type: isUserAggregate, isTuple, isNonRangeUDT; 6 import std.traits: Unqual, isIntegral, isFloatingPoint, isAggregateType, 7 isStaticArray, isAssociativeArray, isPointer, isSomeChar, 8 isCallable, isSomeString, isFunctionPointer, isDelegate, 9 PointerTarget; 10 import std.range: isInputRange, isInfinite; 11 import std.datetime: Date, DateTime; 12 import core.time: Duration; 13 14 15 PyObject* toPython(in bool val) @trusted @nogc { 16 import python.raw: pyIncRef, _Py_TrueStruct, _Py_FalseStruct; 17 18 auto pyTrue = cast(PyObject*) &_Py_TrueStruct; 19 auto pyFalse = cast(PyObject*) &_Py_FalseStruct; 20 21 static PyObject* incAndRet(PyObject* obj) { 22 pyIncRef(obj); 23 return obj; 24 } 25 26 return val ? incAndRet(pyTrue) : incAndRet(pyFalse); 27 } 28 29 30 PyObject* toPython(T)(T value) @trusted if(isIntegral!T && !is(T == enum)) { 31 import python.raw: PyLong_FromLong; 32 return PyLong_FromLong(value); 33 } 34 35 36 PyObject* toPython(T)(T value) @trusted if(isFloatingPoint!T) { 37 import python.raw: PyFloat_FromDouble; 38 return PyFloat_FromDouble(value); 39 } 40 41 42 PyObject* toPython(T)(T value) if(is(Unqual!T == void[])) { 43 auto bytes = cast(ubyte[]) value; 44 return bytes.toPython; 45 } 46 47 48 PyObject* toPython(T)(T value) 49 if(isInputRange!T && !isInfinite!T && !isSomeString!T && !isStaticArray!T) 50 { 51 import python.raw: PyList_New, PyList_SetItem, PyList_Append; 52 import std.range: isForwardRange, enumerate; 53 54 static if(__traits(hasMember, T, "length")) { 55 const length = value.length; 56 enum append = false; 57 } else static if(isForwardRange!T) { 58 import std.range: walkLength; 59 import std.array: save; 60 const length = walkLength(value.save); 61 enum append = false; 62 } else { 63 enum length = 0; 64 enum append = true; 65 } 66 67 auto ret = PyList_New(length); 68 69 foreach(i, elt; value.enumerate) { 70 static if(append) 71 PyList_Append(ret, toPython(elt)); 72 else 73 PyList_SetItem(ret, i, toPython(elt)); 74 } 75 76 return ret; 77 } 78 79 PyObject* toPython(T)(T value) 80 if(isInputRange!T && isInfinite!T) 81 { 82 import python.type: pythonClass; 83 return pythonClass(value); 84 } 85 86 87 PyObject* toPython(T)(auto ref T value) if(isNonRangeUDT!T) { 88 import python.type: pythonClass; 89 return pythonClass(value); 90 } 91 92 93 PyObject* toPython(T)(T value) 94 if(isPointer!T && !isFunctionPointer!T && !isDelegate!T && !is(Unqual!(PointerTarget!T) == void)) 95 { 96 import autowrap.common: AlwaysTry; 97 98 static if(AlwaysTry || __traits(compiles, toPython(*value))) { 99 import std.traits: PointerTarget; 100 import std..string: fromStringz; 101 102 static if(is(PointerTarget!T == const(char)) || is(PointerTarget!T == immutable(char))) 103 return value.fromStringz.toPython; 104 else 105 return toPython(*value); 106 } else { 107 import std.traits: fullyQualifiedName; 108 enum msg = "could not convert " ~ fullyQualifiedName!T ~ " to Python"; 109 pragma(msg, "WARNING: ", msg); 110 throw new Exception(msg); 111 } 112 } 113 114 115 PyObject* toPython(T)(T value) 116 if(isPointer!T && is(Unqual!(PointerTarget!T) == void)) 117 { 118 throw new Exception("Converting void* to Python is not supported"); 119 } 120 121 122 PyObject* toPython(T)(T value) if(is(Unqual!T == DateTime)) { 123 import python.raw: pyDateTimeFromDateAndTime; 124 return pyDateTimeFromDateAndTime(value.year, value.month, value.day, 125 value.hour, value.minute, value.second); 126 } 127 128 129 PyObject* toPython(T)(T value) if(is(Unqual!T == Date)) { 130 import python.raw: pyDateFromDate; 131 return pyDateFromDate(value.year, value.month, value.day); 132 } 133 134 135 PyObject* toPython(T)(T value) if(isSomeString!T) { 136 import python.raw: pyUnicodeFromStringAndSize; 137 import std.conv: to; 138 auto str = value.to!string; 139 return pyUnicodeFromStringAndSize(str.ptr, str.length); 140 } 141 142 143 PyObject* toPython(T)(T value) if(is(Unqual!T == bool)) { 144 import python.raw: PyBool_FromLong; 145 return PyBool_FromLong(value); 146 } 147 148 149 PyObject* toPython(T)(T value) if(isStaticArray!T) { 150 return toPython(value[]); 151 } 152 153 154 PyObject* toPython(T)(T value) if(isAssociativeArray!T) { 155 import python.raw: PyDict_New, PyDict_SetItem; 156 157 auto ret = PyDict_New; 158 159 foreach(k, v; value) { 160 PyDict_SetItem(ret, k.toPython, v.toPython); 161 } 162 163 return ret; 164 } 165 166 PyObject* toPython(T)(T value) if(isTuple!T) { 167 import python.raw: PyTuple_New, PyTuple_SetItem; 168 169 auto ret = PyTuple_New(value.length); 170 171 static foreach(i; 0 .. T.length) { 172 PyTuple_SetItem(ret, i, value[i].toPython); 173 } 174 175 return ret; 176 } 177 178 179 PyObject* toPython(T)(T value) if(is(Unqual!T == char) || is(Unqual!T == wchar) || is(Unqual!T == dchar)) { 180 return [value].toPython; 181 } 182 183 184 PyObject* toPython(T)(T value) if(isCallable!T && !isUserAggregate!T) { 185 import python.type: pythonCallable; 186 return pythonCallable(value); 187 } 188 189 190 PyObject* toPython(T)(T value) if(is(Unqual!T == Duration)) { 191 import python.raw: pyDeltaFromDSU; 192 int days, seconds, useconds; 193 value.split!("days", "seconds", "usecs")(days, seconds, useconds); 194 return pyDeltaFromDSU(days, seconds, useconds); 195 } 196 197 198 PyObject* toPython(T)(T value) if(is(T == enum)) { 199 import std.traits: OriginalType; 200 return toPython(cast(OriginalType!T) value); 201 }