implement _httpapi python module
[pykit.git] / PythonPublisher.cc
1 // $Id$
2 //
3 // Copyright (C) 2010
4 //     Stefan Bund <info@j32.de>
5
6 /** \file
7     \brief PythonPublisher non-inline non-template implementation */
8
9 #include "PythonPublisher.hh"
10 //#include "PythonPublisher.ih"
11
12 // Custom includes
13 #include <iostream>
14 #include <boost/python.hpp>
15 #include "Publisher.hh"
16
17 //#include "PythonPublisher.mpp"
18 #define prefix_
19 ///////////////////////////////cc.p////////////////////////////////////////
20
21 namespace py = boost::python;
22
23 struct pykit::PythonPublisher::Impl
24 {
25     boost::python::dict mainNamespace;
26     Publisher * pythonPublisher;
27 };
28
29 #define PYTHON_EXTERN_MODULE(module) \
30     extern "C" { void init ## module (); }
31 #define PYTHON_PREPARE_IMPORT(module) \
32     PyImport_AppendInittab(const_cast<char*>(#module), init ## module)
33
34 namespace {
35
36     struct PublisherPyWrapper
37         : public pykit::Publisher, py::wrapper<pykit::Publisher>
38     {
39         virtual void publish(pykit::Request & request)
40             { get_override("publish")(request); }
41     };
42
43     namespace pyconvert {
44
45         struct QString_PyUnicode
46         {
47             static PyObject * convert(QString const & s)
48                 {
49                     std::wstring ws (s.toStdWString());
50                     return PyUnicode_FromWideChar(ws.data(), ws.length());
51                 }
52         };
53
54         struct PyUnicode_QString
55         {
56             static void * convertible(PyObject * o)
57                 {
58                     return PyUnicode_Check(o) ? o : 0;
59                 }
60
61             static void construct(PyObject * o,
62                                   py::converter::rvalue_from_python_stage1_data * data)
63                 {
64                     unsigned length (PyUnicode_GetSize(o));
65                     std::wstring ws (length, 0);
66                     // Hmm ... I don't want to copy the stupid data TWICE but this
67                     // breaks the standard ... who cares ?
68                     PyUnicode_AsWideChar(reinterpret_cast<PyUnicodeObject *>(o),
69                                          const_cast<wchar_t*>(ws.data()),
70                                          length);
71                     void * storage (((py::converter::rvalue_from_python_storage<QString>*)
72                                      data)->storage.bytes);
73                     *(new (storage) QString()) = QString::fromStdWString(ws);
74                     data->convertible = storage;
75                 }
76
77             PyUnicode_QString()
78                 {
79                     py::converter::registry::push_back(
80                         &convertible,
81                         &construct,
82                         py::type_id<QString>());
83                 }
84         };
85
86         struct QByteArray_PyString
87         {
88             static PyObject * convert(QByteArray const & s)
89                 {
90                     return boost::python::incref(boost::python::object(s.constData()).ptr());
91                 }
92         };
93
94         struct PyString_QByteArray
95         {
96             static void * convertible(PyObject * o)
97                 {
98                     return PyString_Check(o) ? o : 0;
99                 }
100
101             static void construct(PyObject * o,
102                                   py::converter::rvalue_from_python_stage1_data * data)
103                 {
104                     unsigned length (PyString_Size(o));
105                     const char * value (PyString_AsString(o));
106                     void * storage (((py::converter::rvalue_from_python_storage<QByteArray>*)
107                                      data)->storage.bytes);
108                     new (storage) QByteArray(value,length);
109                     data->convertible = storage;
110                 }
111
112             PyString_QByteArray()
113                 {
114                     py::converter::registry::push_back(
115                         &convertible,
116                         &construct,
117                         py::type_id<QByteArray>());
118                 }
119         };
120
121     }
122
123     QString QUrl_toString_noargs(QUrl const & url)
124     { return url.toString(); }
125
126 }
127
128 #define MEMFNP(ret, cls, nam, arg) static_cast<ret (cls::*)arg>(&cls::nam)
129
130 BOOST_PYTHON_MODULE(_qt)
131 {
132     py::to_python_converter<QString, pyconvert::QString_PyUnicode>();
133     pyconvert::PyUnicode_QString register_PyUnicode_QString;
134
135     py::to_python_converter<QByteArray, pyconvert::QByteArray_PyString>();
136     pyconvert::PyString_QByteArray register_PyString_QByteArray;
137
138     // Missing converters:
139     //    QPair <-> tuple
140     //    QList <-> vector
141
142         // QUrl ()
143     py::class_<QUrl>("QUrl", py::init<>())
144         // QUrl ( const QString & url )
145         .def(py::init<QString const &>())
146         // QUrl ( const QUrl & other )
147         .def(py::init<QUrl const &>())
148         // QUrl ( const QString & url, ParsingMode parsingMode )
149         // .def(init<QString const &, ParsingMode>())
150         // ~QUrl ()
151         // void   addEncodedQueryItem ( const QByteArray & key, const QByteArray & value )
152         .def("addEncodedQueryItem",
153              MEMFNP(void, QUrl, addEncodedQueryItem,
154                     ( const QByteArray & key, const QByteArray & value )))
155         // void   addQueryItem ( const QString & key, const QString & value )
156         .def("addQueryItem",
157              MEMFNP(void, QUrl, addQueryItem,
158                     ( const QString & key, const QString & value )))
159         // QList<QByteArray>   allEncodedQueryItemValues ( const QByteArray & key ) const
160         // .def("allEncodedQueryItemValues",
161         //      MEMFNP(QList<QByteArray>, QUrl, allEncodedQueryItemValues,
162         //             ( const QByteArray & key ) const))
163         // QStringList   allQueryItemValues ( const QString & key ) const
164         // .def("allQueryItemValues",
165         //      MEMFNP(QStringList, QUrl, allQueryItemValues,
166         //             ( const QString & key ) const))
167         // QString   authority () const
168         .def("authority",
169              MEMFNP(QString, QUrl, authority,
170                     () const))
171         // void   clear ()
172         .def("clear",
173              MEMFNP(void, QUrl, clear,
174                     ()))
175         // QByteArray   encodedFragment () const
176         .def("encodedFragment",
177              MEMFNP(QByteArray, QUrl, encodedFragment,
178                     () const))
179         // QByteArray   encodedHost () const
180         .def("encodedHost",
181              MEMFNP(QByteArray, QUrl, encodedHost,
182                     () const))
183         // QByteArray   encodedPassword () const
184         .def("encodedPassword",
185              MEMFNP(QByteArray, QUrl, encodedPassword,
186                     () const))
187         // QByteArray   encodedPath () const
188         .def("encodedPath",
189              MEMFNP(QByteArray, QUrl, encodedPath,
190                     () const))
191         // QByteArray   encodedQuery () const
192         .def("encodedQuery",
193              MEMFNP(QByteArray, QUrl, encodedQuery,
194                     () const))
195         // QByteArray   encodedQueryItemValue ( const QByteArray & key ) const
196         .def("encodedQueryItemValue",
197              MEMFNP(QByteArray, QUrl, encodedQueryItemValue,
198                     ( const QByteArray & key ) const))
199         // QList<QPair<QByteArray, QByteArray> >   encodedQueryItems () const
200         // .def("encodedQueryItems",
201         //      MEMFNP(QList<QPair<QByteArray, QByteArray> >, QUrl, encodedQueryItems,
202         //             () const))
203         // QByteArray   encodedUserName () const
204         .def("encodedUserName",
205              MEMFNP(QByteArray, QUrl, encodedUserName,
206                     () const))
207         // QString   errorString () const
208         .def("errorString",
209              MEMFNP(QString, QUrl, errorString,
210                     () const))
211         // QString   fragment () const
212         .def("fragment",
213              MEMFNP(QString, QUrl, fragment,
214                     () const))
215         // bool   hasEncodedQueryItem ( const QByteArray & key ) const
216         .def("hasEncodedQueryItem",
217              MEMFNP(bool, QUrl, hasEncodedQueryItem,
218                     ( const QByteArray & key ) const))
219         // bool   hasFragment () const
220         .def("hasFragment",
221              MEMFNP(bool, QUrl, hasFragment,
222                     () const))
223         // bool   hasQuery () const
224         .def("hasQuery",
225              MEMFNP(bool, QUrl, hasQuery,
226                     () const))
227         // bool   hasQueryItem ( const QString & key ) const
228         .def("hasQueryItem",
229              MEMFNP(bool, QUrl, hasQueryItem,
230                     ( const QString & key ) const))
231         // QString   host () const
232         .def("host",
233              MEMFNP(QString, QUrl, host,
234                     () const))
235         // bool   isEmpty () const
236         .def("isEmpty",
237              MEMFNP(bool, QUrl, isEmpty,
238                     () const))
239         // bool   isParentOf ( const QUrl & childUrl ) const
240         .def("isParentOf",
241              MEMFNP(bool, QUrl, isParentOf,
242                     ( const QUrl & childUrl ) const))
243         // bool   isRelative () const
244         .def("isRelative",
245              MEMFNP(bool, QUrl, isRelative,
246                     () const))
247         // bool   isValid () const
248         .def("isValid",
249              MEMFNP(bool, QUrl, isValid,
250                     () const))
251         // QString   password () const
252         .def("password",
253              MEMFNP(QString, QUrl, password,
254                     () const))
255         // QString   path () const
256         .def("path",
257              MEMFNP(QString, QUrl, path,
258                     () const))
259         // int   port () const
260         .def("port",
261              MEMFNP(int, QUrl, port,
262                     () const))
263         // int   port ( int defaultPort ) const
264         .def("port",
265              MEMFNP(int, QUrl, port,
266                     ( int defaultPort ) const))
267         // QString   queryItemValue ( const QString & key ) const
268         .def("queryItemValue",
269              MEMFNP(QString, QUrl, queryItemValue,
270                     ( const QString & key ) const))
271         // QList<QPair<QString, QString> >   queryItems () const
272         // .def("queryItems",
273         //      MEMFNP(QList<QPair<QString, QString> >, QUrl, queryItems,
274         //             () const))
275         // char   queryPairDelimiter () const
276         .def("queryPairDelimiter",
277              MEMFNP(char, QUrl, queryPairDelimiter,
278                     () const))
279         // char   queryValueDelimiter () const
280         .def("queryValueDelimiter",
281              MEMFNP(char, QUrl, queryValueDelimiter,
282                     () const))
283         // void   removeAllEncodedQueryItems ( const QByteArray & key )
284         .def("removeAllEncodedQueryItems",
285              MEMFNP(void, QUrl, removeAllEncodedQueryItems,
286                     ( const QByteArray & key )))
287         // void   removeAllQueryItems ( const QString & key )
288         .def("removeAllQueryItems",
289              MEMFNP(void, QUrl, removeAllQueryItems,
290                     ( const QString & key )))
291         // void   removeEncodedQueryItem ( const QByteArray & key )
292         .def("removeEncodedQueryItem",
293              MEMFNP(void, QUrl, removeEncodedQueryItem,
294                     ( const QByteArray & key )))
295         // void   removeQueryItem ( const QString & key )
296         .def("removeQueryItem",
297              MEMFNP(void, QUrl, removeQueryItem,
298                     ( const QString & key )))
299         // QUrl   resolved ( const QUrl & relative ) const
300         .def("resolved",
301              MEMFNP(QUrl, QUrl, resolved,
302                     ( const QUrl & relative ) const))
303         // QString   scheme () const
304         .def("scheme",
305              MEMFNP(QString, QUrl, scheme,
306                     () const))
307         // void   setAuthority ( const QString & authority )
308         .def("setAuthority",
309              MEMFNP(void, QUrl, setAuthority,
310                     ( const QString & authority )))
311         // void   setEncodedFragment ( const QByteArray & fragment )
312         .def("setEncodedFragment",
313              MEMFNP(void, QUrl, setEncodedFragment,
314                     ( const QByteArray & fragment )))
315         // void   setEncodedHost ( const QByteArray & host )
316         .def("setEncodedHost",
317              MEMFNP(void, QUrl, setEncodedHost,
318                     ( const QByteArray & host )))
319         // void   setEncodedPassword ( const QByteArray & password )
320         .def("setEncodedPassword",
321              MEMFNP(void, QUrl, setEncodedPassword,
322                     ( const QByteArray & password )))
323         // void   setEncodedPath ( const QByteArray & path )
324         .def("setEncodedPath",
325              MEMFNP(void, QUrl, setEncodedPath,
326                     ( const QByteArray & path )))
327         // void   setEncodedQuery ( const QByteArray & query )
328         .def("setEncodedQuery",
329              MEMFNP(void, QUrl, setEncodedQuery,
330                     ( const QByteArray & query )))
331         // void   setEncodedQueryItems ( const QList<QPair<QByteArray, QByteArray> > & query )
332         // .def("setEncodedQueryItems",
333         //      MEMFNP(void, QUrl, setEncodedQueryItems,
334         //             ( const QList<QPair<QByteArray, QByteArray> > & query )))
335         // void   setEncodedUrl ( const QByteArray & encodedUrl )
336         .def("setEncodedUrl",
337              MEMFNP(void, QUrl, setEncodedUrl,
338                     ( const QByteArray & encodedUrl )))
339         // void   setEncodedUrl ( const QByteArray & encodedUrl, ParsingMode parsingMode )
340         // .def("setEncodedUrl",
341         //      MEMFNP(void, QUrl, setEncodedUrl,
342         //             ( const QByteArray & encodedUrl, ParsingMode parsingMode )))
343         // void   setEncodedUserName ( const QByteArray & userName )
344         .def("setEncodedUserName",
345              MEMFNP(void, QUrl, setEncodedUserName,
346                     ( const QByteArray & userName )))
347         // void   setFragment ( const QString & fragment )
348         .def("setFragment",
349              MEMFNP(void, QUrl, setFragment,
350                     ( const QString & fragment )))
351         // void   setHost ( const QString & host )
352         .def("setHost",
353              MEMFNP(void, QUrl, setHost,
354                     ( const QString & host )))
355         // void   setPassword ( const QString & password )
356         .def("setPassword",
357              MEMFNP(void, QUrl, setPassword,
358                     ( const QString & password )))
359         // void   setPath ( const QString & path )
360         .def("setPath",
361              MEMFNP(void, QUrl, setPath,
362                     ( const QString & path )))
363         // void   setPort ( int port )
364         .def("setPort",
365              MEMFNP(void, QUrl, setPort,
366                     ( int port )))
367         // void   setQueryDelimiters ( char valueDelimiter, char pairDelimiter )
368         .def("setQueryDelimiters",
369              MEMFNP(void, QUrl, setQueryDelimiters,
370                     ( char valueDelimiter, char pairDelimiter )))
371         // void   setQueryItems ( const QList<QPair<QString, QString> > & query )
372         // .def("setQueryItems",
373         //      MEMFNP(void, QUrl, setQueryItems,
374         //             ( const QList<QPair<QString, QString> > & query )))
375         // void   setScheme ( const QString & scheme )
376         .def("setScheme",
377              MEMFNP(void, QUrl, setScheme,
378                     ( const QString & scheme )))
379         // void   setUrl ( const QString & url )
380         .def("setUrl",
381              MEMFNP(void, QUrl, setUrl,
382                     ( const QString & url )))
383         // void   setUrl ( const QString & url, ParsingMode parsingMode )
384         // .def("setUrl",
385         //      MEMFNP(void, QUrl, setUrl,
386         //             ( const QString & url, ParsingMode parsingMode )))
387         // void   setUserInfo ( const QString & userInfo )
388         .def("setUserInfo",
389              MEMFNP(void, QUrl, setUserInfo,
390                     ( const QString & userInfo )))
391         // void   setUserName ( const QString & userName )
392         .def("setUserName",
393              MEMFNP(void, QUrl, setUserName,
394                     ( const QString & userName )))
395         // QByteArray   toEncoded ( FormattingOptions options = None ) const
396         // .def("toEncoded",
397         //      MEMFNP(QByteArray, QUrl, toEncoded,
398         //             ( FormattingOptions options = None ) const))
399         // QString   toLocalFile () const
400         .def("toLocalFile",
401              MEMFNP(QString, QUrl, toLocalFile,
402                     () const))
403         // QString   toString ( FormattingOptions options = None ) const
404         .def("__unicode__", &QUrl_toString_noargs)
405         // QString   userInfo () const
406         .def("userInfo",
407              MEMFNP(QString, QUrl, userInfo,
408                     () const))
409         // QString   userName () const
410         .def("userName",
411              MEMFNP(QString, QUrl, userName,
412                     () const))
413
414         // bool   operator!= ( const QUrl & url ) const
415         // QUrl &   operator= ( const QUrl & url )
416         // QUrl &   operator= ( const QString & url )
417         // bool   operator== ( const QUrl & url ) const
418         ;
419 }
420
421 BOOST_PYTHON_MODULE(_pykit)
422 {
423     py::class_<pykit::Request>("Request", py::no_init)
424         .def("write", &pykit::Request::write)
425         .def("reset", &pykit::Request::reset)
426         .def("setContentType", &pykit::Request::setContentType)
427         .def("setLocation", &pykit::Request::setLocation)
428         .def("setRawHeader", &pykit::Request::setHeader)
429         .def("setStatusCode", &pykit::Request::setStatusCode)
430         .def("url", &pykit::Request::url)
431         .def("postData", &pykit::Request::postData)
432         .def("operation", &pykit::Request::operation)
433         .def("postContentType", &pykit::Request::postContentType)
434         ;
435
436     py::class_<PublisherPyWrapper, boost::noncopyable>("Publisher")
437         .def("publish", py::pure_virtual(&pykit::Publisher::publish))
438         ;
439 }
440
441 PYTHON_EXTERN_MODULE(_httpapi);
442
443 prefix_ pykit::PythonPublisher::PythonPublisher()
444     : impl_ (new Impl)
445 {
446     try {
447         PYTHON_PREPARE_IMPORT(_pykit);
448         PYTHON_PREPARE_IMPORT(_qt);
449         PYTHON_PREPARE_IMPORT(_httpapi);
450         Py_Initialize();
451         py::object initModule = py::import("init");
452         impl_->mainNamespace = py::extract<py::dict>(initModule.attr("__dict__"));
453         impl_->pythonPublisher = py::extract<Publisher*>(impl_->mainNamespace["initialize"]());
454     }
455     catch (boost::python::error_already_set & ex) {
456         PyErr_Print();
457         throw;
458     }
459 }
460
461 prefix_ pykit::PythonPublisher::~PythonPublisher()
462 {}
463
464 prefix_ void pykit::PythonPublisher::publish(Request & request)
465 {
466     try {
467         impl_->pythonPublisher->publish(request);
468     }
469     catch (py::error_already_set & ex) {
470         PyErr_Print();
471     }
472 }
473
474 ///////////////////////////////cc.e////////////////////////////////////////
475 #undef prefix_
476 //#include "PythonPublisher.mpp"
477
478 \f
479 // Local Variables:
480 // mode: c++
481 // fill-column: 100
482 // comment-column: 40
483 // c-file-style: "j32"
484 // indent-tabs-mode: nil
485 // ispell-local-dictionary: "american"
486 // compile-command: "scons -U"
487 // End: