//#include "PythonPublisher.ih"
// Custom includes
+#include <iostream>
+#include <boost/python.hpp>
#include "Publisher.hh"
+#include <QDesktopServices>
+#include <QWebHistory>
+#include "Viewer.hh"
//#include "PythonPublisher.mpp"
#define prefix_
namespace py = boost::python;
+struct pykit::PythonPublisher::Impl
+{
+ boost::python::dict mainNamespace;
+ Publisher * pythonPublisher;
+};
+
+#define PYTHON_EXTERN_MODULE(module) \
+ extern "C" { void init ## module (); }
+#define PYTHON_PREPARE_IMPORT(module) \
+ PyImport_AppendInittab(const_cast<char*>(#module), init ## module)
+
namespace {
struct PublisherPyWrapper
static PyObject * convert(QString const & s)
{
std::wstring ws (s.toStdWString());
- return PyUnicode_FromWideChar(ws.c_str(), ws.length());
+ return PyUnicode_FromWideChar(ws.data(), ws.length());
}
};
static void construct(PyObject * o,
py::converter::rvalue_from_python_stage1_data * data)
{
+ unsigned length (PyString_Size(o));
const char * value (PyString_AsString(o));
void * storage (((py::converter::rvalue_from_python_storage<QByteArray>*)
data)->storage.bytes);
- new (storage) QByteArray(value);
+ new (storage) QByteArray(value,length);
data->convertible = storage;
}
;
}
+namespace {
+
+ bool canGoBack()
+ {
+ return pykit::Viewer::instance()->page()->history()->canGoBack();
+ }
+
+ bool canGoForward()
+ {
+ return pykit::Viewer::instance()->page()->history()->canGoForward();
+ }
+
+ class ErrorCatcher
+ {
+ public:
+ explicit ErrorCatcher(std::string & out) : out_ (out) {}
+ void write(std::string const & msg)
+ { std::cerr << "append: " << msg; out_ += msg; }
+ private:
+ std::string & out_;
+ };
+
+}
+
BOOST_PYTHON_MODULE(_pykit)
{
py::class_<pykit::Request>("Request", py::no_init)
.def("reset", &pykit::Request::reset)
.def("setContentType", &pykit::Request::setContentType)
.def("setLocation", &pykit::Request::setLocation)
+ .def("setRawHeader", &pykit::Request::setHeader)
+ .def("setStatusCode", &pykit::Request::setStatusCode)
.def("url", &pykit::Request::url)
+ .def("postData", &pykit::Request::postData)
+ .def("operation", &pykit::Request::operation)
+ .def("postContentType", &pykit::Request::postContentType)
;
py::class_<PublisherPyWrapper, boost::noncopyable>("Publisher")
.def("publish", py::pure_virtual(&pykit::Publisher::publish))
;
+
+ py::class_<ErrorCatcher>("ErrorCatcher", py::no_init)
+ .def("write", &ErrorCatcher::write)
+ ;
+
+ py::def("openUrl", &QDesktopServices::openUrl);
+
+ py::def("canGoBack", &canGoBack);
+ py::def("canGoForward", &canGoForward);
+}
+
+PYTHON_EXTERN_MODULE(_httpapi);
+
+prefix_ pykit::PythonPublisher::PythonPublisher()
+ : impl_ (new Impl)
+{
+ std::string pyError;
+ try {
+ PYTHON_PREPARE_IMPORT(_pykit);
+ PYTHON_PREPARE_IMPORT(_qt);
+ PYTHON_PREPARE_IMPORT(_httpapi);
+ Py_Initialize();
+
+ py::import("_pykit");
+ py::object sysModule (py::import("sys"));
+ py::object origStderr (sysModule.attr("stderr"));
+ ErrorCatcher catcher (pyError);
+ sysModule.attr("stderr") = catcher;
+
+ py::object initModule (py::import("init"));
+ impl_->mainNamespace = py::extract<py::dict>(initModule.attr("__dict__"));
+ impl_->pythonPublisher = py::extract<Publisher*>(impl_->mainNamespace["initialize"]());
+
+ sysModule.attr("stderr") = origStderr;
+ }
+ catch (boost::python::error_already_set & ex) {
+ PyErr_Print();
+ throw PythonError(pyError);
+ }
}
-prefix_ pykit::PythonPublisher::PythonPublisher(std::string initPy)
+prefix_ pykit::PythonPublisher::~PythonPublisher()
{
- PYTHON_PREPARE_IMPORT(_pykit);
- PYTHON_PREPARE_IMPORT(_qt);
- Py_Initialize();
- py::object mainModule_ = py::import("__main__");
- mainNamespace_ = py::extract<py::dict>(mainModule_.attr("__dict__"));
- mainNamespace_["__file__"] = py::str(initPy.c_str());
- py::object ignored (
- py::exec_file(initPy.c_str(), mainNamespace_, mainNamespace_));
- pythonPublisher_ = py::extract<Publisher*>(mainNamespace_["publisher"]);
+ try {
+ impl_->mainNamespace["shutdown"]();
+ }
+ catch (...) {;}
}
prefix_ void pykit::PythonPublisher::publish(Request & request)
{
try {
- pythonPublisher_->publish(request);
+ impl_->pythonPublisher->publish(request);
}
catch (py::error_already_set & ex) {
PyErr_Print();
+ PyErr_Clear();
}
}