graph_bind.cc 8.53 KB
Newer Older
Tiago Peixoto's avatar
Tiago Peixoto committed
1
2
// graph-tool -- a general graph modification and manipulation thingy
//
Tiago Peixoto's avatar
Tiago Peixoto committed
3
// Copyright (C) 2007  Tiago de Paula Peixoto <tiago@forked.de>
Tiago Peixoto's avatar
Tiago Peixoto committed
4
5
6
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
Tiago Peixoto's avatar
Tiago Peixoto committed
7
// as published by the Free Software Foundation; either version 3
Tiago Peixoto's avatar
Tiago Peixoto committed
8
9
10
11
12
13
14
15
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
16
17
// along with this program. If not, see <http://www.gnu.org/licenses/>.

Tiago Peixoto's avatar
Tiago Peixoto committed
18
#include "graph.hh"
19
#include "graph_python_interface.hh"
20
#include "graph_util.hh"
Tiago Peixoto's avatar
Tiago Peixoto committed
21

22
23
24
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

Tiago Peixoto's avatar
Tiago Peixoto committed
25
26
27
28
29
using namespace std;
using namespace graph_tool;
using namespace boost;
using namespace boost::python;

30
struct LibInfo
Tiago Peixoto's avatar
Tiago Peixoto committed
31
{
32
33
34
35
36
37
38
39
40
    string GetName()      const {return PACKAGE_NAME;}
    string GetAuthor()    const {return AUTHOR;}
    string GetCopyright() const {return COPYRIGHT;}
    string GetVersion()   const {return VERSION " (commit " GIT_COMMIT
                                        ", " GIT_COMMIT_DATE ")";}
    string GetLicense()   const {return "GPL version 3 or above";}
    string GetCXXFLAGS()  const {return CXXFLAGS;}
    string GetInstallPrefix() const {return INSTALL_PREFIX;}
    string GetPythonDir() const {return PYTHON_DIR;}
Tiago Peixoto's avatar
Tiago Peixoto committed
41
42
};

43
44
template <class ValueType>
struct vector_from_list
Tiago Peixoto's avatar
Tiago Peixoto committed
45
{
46
    vector_from_list()
Tiago Peixoto's avatar
Tiago Peixoto committed
47
    {
48
        converter::registry::push_back
49
            (&convertible, &construct,
50
             boost::python::type_id<vector<ValueType> >());
Tiago Peixoto's avatar
Tiago Peixoto committed
51
52
53
54
    }

    static void* convertible(PyObject* obj_ptr)
    {
55
56
        handle<> x(borrowed(obj_ptr));
        object o(x);
57
58
59
60
61
62
63
        size_t N = len(o);
        for (size_t i = 0; i < N; ++i)
        {
            extract<ValueType> elem(o[i]);
            if (!elem.check())
                return 0;
        }
64
        return obj_ptr;
Tiago Peixoto's avatar
Tiago Peixoto committed
65
66
    }

67
    static void construct(PyObject* obj_ptr,
68
                          converter::rvalue_from_python_stage1_data* data)
69
    {
70
71
        handle<> x(borrowed(obj_ptr));
        object o(x);
72
73
74
75
        vector<ValueType> value;
        size_t N = len(o);
        for (size_t i = 0; i < N; ++i)
            value.push_back(extract<ValueType>(o[i]));
76
        void* storage =
77
            ( (boost::python::converter::rvalue_from_python_storage
78
79
               <vector<ValueType> >*) data)->storage.bytes;
        new (storage) vector<ValueType>(value);
80
        data->convertible = storage;
Tiago Peixoto's avatar
Tiago Peixoto committed
81
82
83
    }
};

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
template <class ValueType>
bool vector_equal_compare(const vector<ValueType>& v1,
                          const vector<ValueType>& v2)
{
    if (v1.size() != v2.size())
        return false;
    for (size_t i = 0; i < v1.size(); ++i)
    {
        if (v1[i] != v2[i])
            return false;
    }
    return true;
}

template <class ValueType>
bool vector_nequal_compare(const vector<ValueType>& v1,
                           const vector<ValueType>& v2)
{
    return !vector_equal_compare(v1,v2);
}

105
struct export_vector_types
Tiago Peixoto's avatar
Tiago Peixoto committed
106
{
107
108
    template <class ValueType>
    void operator()(ValueType) const
Tiago Peixoto's avatar
Tiago Peixoto committed
109
    {
110
111
112
113
114
        string type_name = get_type_name<>()(typeid(ValueType));
        if (type_name == "long double")
            type_name = "long_double";
        string name = "Vector_" + type_name;
        class_<vector<ValueType> >(name.c_str())
115
116
117
            .def(vector_indexing_suite<vector<ValueType> >())
            .def("__eq__", &vector_equal_compare<ValueType>)
            .def("__ne__", &vector_nequal_compare<ValueType>);
118
        vector_from_list<ValueType>();
Tiago Peixoto's avatar
Tiago Peixoto committed
119
    }
120
};
Tiago Peixoto's avatar
Tiago Peixoto committed
121

122
123
124
125
// exception translation
static PyObject* pyex =
    PyErr_NewException((char *) "libgraph_tool_core.GraphError",
                       PyExc_Exception, NULL);
Tiago Peixoto's avatar
Tiago Peixoto committed
126

127
128
129
130
131
132
void graph_exception_translator(const GraphException& e)
{
    PyObject* message = PyString_FromString(e.what());
    PyObject_SetAttrString(pyex, "message", message);
    PyErr_SetString(pyex, e.what());
}
Tiago Peixoto's avatar
Tiago Peixoto committed
133

134
135
136
137
138
template <class Exception>
void translate(const Exception& e)
{
    PyErr_SetString(PyExc_RuntimeError, e.what());
}
Tiago Peixoto's avatar
Tiago Peixoto committed
139

140
141
142
143
void raise_error(const string& msg)
{
    throw GraphException(msg);
}
Tiago Peixoto's avatar
Tiago Peixoto committed
144

145
146
template <class T1, class T2>
struct pair_to_tuple
Tiago Peixoto's avatar
Tiago Peixoto committed
147
{
148
    static PyObject* convert(const pair<T1,T2>& p)
Tiago Peixoto's avatar
Tiago Peixoto committed
149
    {
150
151
        boost::python::tuple t = boost::python::make_tuple(p.first,p.second);
        return incref(t.ptr());
Tiago Peixoto's avatar
Tiago Peixoto committed
152
153
154
    }
};

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// persistent python object IO
namespace graph_tool
{
extern python::object object_pickler;
extern python::object object_unpickler;
}

void set_pickler(python::object o)
{
    graph_tool::object_pickler = o;
}

void set_unpickler(python::object o)
{
    graph_tool::object_unpickler = o;
}

172
BOOST_PYTHON_MODULE(libgraph_tool_core)
Tiago Peixoto's avatar
Tiago Peixoto committed
173
{
174
    GraphInterface().ExportPythonInterface();
Tiago Peixoto's avatar
Tiago Peixoto committed
175

176
177
    PyModule_AddObject(python::detail::current_scope, "GraphError", pyex);
    register_exception_translator<GraphException>(graph_exception_translator);
Tiago Peixoto's avatar
Tiago Peixoto committed
178

179
    def("raise_error", &raise_error);
180

181
182
183
184
    mpl::for_each<mpl::push_back<scalar_types,string>::type>(export_vector_types());

    class_<GraphInterface>("GraphInterface", init<>())
        .def(init<GraphInterface>())
185
186
187
188
189
190
191
192
        .def("GetNumberOfVertices", &GraphInterface::GetNumberOfVertices)
        .def("GetNumberOfEdges", &GraphInterface::GetNumberOfEdges)
        .def("SetDirected", &GraphInterface::SetDirected)
        .def("GetDirected", &GraphInterface::GetDirected)
        .def("SetReversed", &GraphInterface::SetReversed)
        .def("GetReversed", &GraphInterface::GetReversed)
        .def("SetVertexFilterProperty",
             &GraphInterface::SetVertexFilterProperty)
193
194
        .def("GetVertexFilterProperty",
             &GraphInterface::GetVertexFilterProperty)
195
        .def("IsVertexFilterActive", &GraphInterface::IsVertexFilterActive)
196
        .def("SetEdgeFilterProperty",
197
             &GraphInterface::SetEdgeFilterProperty)
198
199
        .def("GetEdgeFilterProperty",
             &GraphInterface::GetEdgeFilterProperty)
200
        .def("IsEdgeFilterActive", &GraphInterface::IsEdgeFilterActive)
201
202
203
        .def("AddEdgeProperty",  &GraphInterface::AddEdgeProperty)
        .def("AddVertexProperty",  &GraphInterface::AddVertexProperty)
        .def("AddGraphProperty",  &GraphInterface::AddGraphProperty)
204
205
206
207
208
        .def("RemoveEdgeProperty",  &GraphInterface::RemoveEdgeProperty)
        .def("RemoveVertexProperty",  &GraphInterface::RemoveVertexProperty)
        .def("RemoveGraphProperty",  &GraphInterface::RemoveGraphProperty)
        .def("PurgeVertices",  &GraphInterface::PurgeVertices)
        .def("PurgeEdges",  &GraphInterface::PurgeEdges)
209
        .def("ReIndexEdges",  &GraphInterface::ReIndexEdges)
210
211
212
213
        .def("InsertEdgeIndexProperty",
             &GraphInterface::InsertEdgeIndexProperty)
        .def("InsertVertexIndexProperty",
             &GraphInterface::InsertVertexIndexProperty)
214
215
        .def("WriteToFile", &GraphInterface::WriteToFile)
        .def("ReadFromFile",&GraphInterface::ReadFromFile)
216
        .def("Vertices", &GraphInterface::Vertices)
217
        .def("Vertex", &GraphInterface::Vertex)
218
219
220
221
222
        .def("Edges", &GraphInterface::Edges)
        .def("AddVertex", &GraphInterface::AddVertex)
        .def("AddEdge", &GraphInterface::AddEdge)
        .def("RemoveVertex", &GraphInterface::RemoveVertex)
        .def("RemoveEdge", &GraphInterface::RemoveEdge)
223
        .def("Clear", &GraphInterface::Clear)
224
225
226
        .def("GetVertexProperties", &GraphInterface::GetVertexProperties)
        .def("GetEdgeProperties", &GraphInterface::GetEdgeProperties)
        .def("GetGraphProperties", &GraphInterface::GetGraphProperties)
227
228
        .def("InitSignalHandling", &GraphInterface::InitSignalHandling);

229
    to_python_converter<pair<string,bool>, pair_to_tuple<string,bool> >();
Tiago Peixoto's avatar
Tiago Peixoto committed
230

231
232
233
234
235
236
    class_<IStream>("IStream", no_init).def("Read", &IStream::Read);
    class_<OStream>("OStream", no_init).def("Write", &OStream::Write).
        def("Flush", &OStream::Flush);
    def("set_pickler", &set_pickler);
    def("set_unpickler", &set_unpickler);

Tiago Peixoto's avatar
Tiago Peixoto committed
237
    class_<LibInfo>("mod_info")
238
239
240
        .add_property("name", &LibInfo::GetName)
        .add_property("author", &LibInfo::GetAuthor)
        .add_property("copyright", &LibInfo::GetCopyright)
241
        .add_property("version", &LibInfo::GetVersion)
242
243
244
245
        .add_property("license", &LibInfo::GetLicense)
        .add_property("cxxflags", &LibInfo::GetCXXFLAGS)
        .add_property("install_prefix", &LibInfo::GetInstallPrefix)
        .add_property("python_dir", &LibInfo::GetPythonDir);
Tiago Peixoto's avatar
Tiago Peixoto committed
246
}