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, isArray, 7 isStaticArray, isAssociativeArray, isPointer, isSomeChar, 8 isCallable, isSomeString, isFunctionPointer, isDelegate; 9 import std.range: isInputRange; 10 import std.datetime: Date, DateTime; 11 import core.time: Duration; 12 13 14 PyObject* toPython(T)(T value) @trusted if(isIntegral!T && !is(T == enum)) { 15 import python.raw: PyLong_FromLong; 16 return PyLong_FromLong(value); 17 } 18 19 20 PyObject* toPython(T)(T value) @trusted if(isFloatingPoint!T) { 21 import python.raw: PyFloat_FromDouble; 22 return PyFloat_FromDouble(value); 23 } 24 25 26 PyObject* toPython(T)(T value) if(isInputRange!T && !isSomeString!T && !isStaticArray!T) { 27 import python.raw: PyList_New, PyList_SetItem, PyList_Append; 28 import std.range: isForwardRange, enumerate; 29 30 static if(__traits(hasMember, T, "length")) { 31 const length = value.length; 32 enum append = false; 33 } else static if(isForwardRange!T){ 34 import std.range: walkLength; 35 import std.array: save; 36 const length = walkLength(value.save); 37 enum append = false; 38 } else { 39 enum length = 0; 40 enum append = true; 41 } 42 43 auto ret = PyList_New(length); 44 45 foreach(i, elt; value.enumerate) { 46 static if(append) 47 PyList_Append(ret, toPython(elt)); 48 else 49 PyList_SetItem(ret, i, toPython(elt)); 50 } 51 52 return ret; 53 54 } 55 56 57 PyObject* toPython(T)(auto ref T value) if(isNonRangeUDT!T) { 58 import python.type: pythonClass; 59 return pythonClass(value); 60 } 61 62 63 PyObject* toPython(T)(T value) if(isPointer!T && !isFunctionPointer!T && !isDelegate!T) { 64 static if(__traits(compiles, toPython(*value))) 65 return toPython(*value); 66 else { 67 import std.traits: fullyQualifiedName; 68 enum msg = "could not convert " ~ fullyQualifiedName!T ~ " to Python"; 69 pragma(msg, "WARNING: ", msg); 70 throw new Exception(msg); 71 } 72 } 73 74 75 PyObject* toPython(T)(T value) if(is(Unqual!T == DateTime)) { 76 import python.raw: pyDateTimeFromDateAndTime; 77 return pyDateTimeFromDateAndTime(value.year, value.month, value.day, 78 value.hour, value.minute, value.second); 79 } 80 81 82 PyObject* toPython(T)(T value) if(is(Unqual!T == Date)) { 83 import python.raw: pyDateFromDate; 84 return pyDateFromDate(value.year, value.month, value.day); 85 } 86 87 88 PyObject* toPython(T)(T value) if(isSomeString!T) { 89 import python.raw: pyUnicodeFromStringAndSize; 90 import std.conv: to; 91 auto str = value.to!string; 92 return pyUnicodeFromStringAndSize(str.ptr, str.length); 93 } 94 95 96 PyObject* toPython(T)(T value) if(is(Unqual!T == bool)) { 97 import python.raw: PyBool_FromLong; 98 return PyBool_FromLong(value); 99 } 100 101 102 PyObject* toPython(T)(T value) if(isStaticArray!T) { 103 return toPython(value[]); 104 } 105 106 107 PyObject* toPython(T)(T value) if(isAssociativeArray!T) { 108 import python.raw: PyDict_New, PyDict_SetItem; 109 110 auto ret = PyDict_New; 111 112 foreach(k, v; value) { 113 PyDict_SetItem(ret, k.toPython, v.toPython); 114 } 115 116 return ret; 117 } 118 119 PyObject* toPython(T)(T value) if(isTuple!T) { 120 import python.raw: PyTuple_New, PyTuple_SetItem; 121 122 auto ret = PyTuple_New(value.length); 123 124 static foreach(i; 0 .. T.length) { 125 PyTuple_SetItem(ret, i, value[i].toPython); 126 } 127 128 return ret; 129 } 130 131 132 PyObject* toPython(T)(T value) if(is(Unqual!T == char) || is(Unqual!T == wchar) || is(Unqual!T == dchar)) { 133 return [value].toPython; 134 } 135 136 137 PyObject* toPython(T)(T value) if(isCallable!T && !isUserAggregate!T) { 138 import python.type: pythonCallable; 139 return pythonCallable(value); 140 } 141 142 143 PyObject* toPython(T)(T value) if(is(Unqual!T == Duration)) { 144 import python.raw: pyDeltaFromDSU; 145 int days, seconds, useconds; 146 value.split!("days", "seconds", "usecs")(days, seconds, useconds); 147 return pyDeltaFromDSU(days, seconds, useconds); 148 } 149 150 151 PyObject* toPython(T)(T value) if(is(T == enum)) { 152 import std.traits: OriginalType; 153 return toPython(cast(OriginalType!T) value); 154 }