1 module python.boilerplate;
2 
3 
4 import std.traits: isFunction;
5 
6 
7 string createModuleRecipe(Module module_, alias cfunctions, alias aggregates = Aggregates!())
8                          ()
9 {
10     import std.format: format;
11 
12     return q{
13         extern(C) export auto PyInit_%s() nothrow {
14             import python.cooked: createModule;
15             import python.boilerplate: commonInit, Module, CFunctions, Aggregates;
16 
17             commonInit;
18 
19             return createModule!(
20                 Module("%s"),
21                 %s,
22                 %s,
23             );
24         }
25 
26     }.format(
27         module_.name,
28         module_.name,
29         cfunctions.stringof,
30         aggregates.stringof,
31     );
32 }
33 
34 
35 void commonInit() nothrow {
36     import python.raw: pyDateTimeImport;
37     import core.runtime: rt_init;
38 
39     try
40         rt_init;
41     catch(Exception _)
42         assert(0);
43 }
44 
45 /// For a nicer API
46 struct Module {
47     string name;
48 }
49 
50 
51 /// For a nicer API
52 struct CFunctions(Args...) {
53 
54     import std.meta: staticMap;
55 
56     enum length = Args.length;
57 
58     private template toCFunction(alias F) {
59         static if(isFunction!F)
60             alias toCFunction = CFunction!F;
61         else
62             alias toCFunction = F;
63     }
64 
65     alias functions = staticMap!(toCFunction, Args);
66 
67     static string stringifySymbols() {
68         import std.array: join;
69 
70         string[] ret;
71 
72         static foreach(func; functions)
73             ret ~= `CFunction!(` ~ __traits(identifier, func.symbol) ~ `, "` ~ func.identifier ~ `")`;
74 
75         return ret.join(", ");
76     }
77 }
78 
79 /// For a nicer API
80 struct CFunction(alias F, string I = "") if(isFunction!F) {
81 
82     alias symbol = F;
83 
84     static if(I == "")
85         enum identifier = __traits(identifier, symbol);
86     else
87         enum
88             identifier = I;
89 }
90 
91 
92 /// A list of aggregates to wrap
93 struct Aggregates(T...) {
94     alias Types = T;
95 
96     static string stringifyTypes() {
97         import std.array: join;
98         string[] ret;
99 
100         static foreach(T; Types)
101             ret ~= T.stringof;
102 
103         return ret.join(", ");
104     }
105 }