graph_bind.cc 19.8 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) 2006-2019 Tiago de Paula Peixoto <tiago@skewed.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/>.

18 19
#include "graph.hh"
#include "graph_util.hh"
20

21
#define NUMPY_EXPORT
22 23
#include "numpy_bind.hh"

Tiago Peixoto's avatar
Tiago Peixoto committed
24
#include "graph_python_interface.hh"
Tiago Peixoto's avatar
Tiago Peixoto committed
25

26 27
#include "random.hh"

Tiago Peixoto's avatar
Tiago Peixoto committed
28 29
#ifdef HAVE_SCIPY // integration with scipy weave
#include "weave/scxx/object.h"
30 31 32 33
#include "weave/scxx/list.h"
#include "weave/scxx/tuple.h"
#include "weave/scxx/dict.h"
#include "weave/scxx/str.h"
Tiago Peixoto's avatar
Tiago Peixoto committed
34 35
#endif

Tiago Peixoto's avatar
Tiago Peixoto committed
36 37
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
38
#include <boost/python/stl_iterator.hpp>
Tiago Peixoto's avatar
Tiago Peixoto committed
39 40
#include "bytesobject.h"

Tiago Peixoto's avatar
Tiago Peixoto committed
41 42 43 44 45
using namespace std;
using namespace graph_tool;
using namespace boost;
using namespace boost::python;

46
struct LibInfo
Tiago Peixoto's avatar
Tiago Peixoto committed
47
{
48 49 50 51 52 53
    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";}
Tiago Peixoto's avatar
Tiago Peixoto committed
54
    string GetCXXFLAGS()  const {return CPPFLAGS " " CXXFLAGS " " LDFLAGS;}
55 56
    string GetInstallPrefix() const {return INSTALL_PREFIX;}
    string GetPythonDir() const {return PYTHON_DIR;}
Tiago Peixoto's avatar
Tiago Peixoto committed
57 58 59 60 61 62
    string GetGCCVersion() const
    {
        stringstream s;
        s << __GNUC__ << "." << __GNUC_MINOR__ << "." <<  __GNUC_PATCHLEVEL__;
        return s.str();
    }
Tiago Peixoto's avatar
Tiago Peixoto committed
63 64
};

65

66 67
template <class ValueType>
struct vector_from_list
Tiago Peixoto's avatar
Tiago Peixoto committed
68
{
69
    vector_from_list()
Tiago Peixoto's avatar
Tiago Peixoto committed
70
    {
Tiago Peixoto's avatar
Tiago Peixoto committed
71
         boost::python::converter::registry::push_back
72
            (&convertible, &construct,
73
             boost::python::type_id<vector<ValueType> >());
Tiago Peixoto's avatar
Tiago Peixoto committed
74 75 76 77
    }

    static void* convertible(PyObject* obj_ptr)
    {
78
        // can't verify without potentially exhausting an iterator
79
        return obj_ptr;
Tiago Peixoto's avatar
Tiago Peixoto committed
80 81
    }

82
    static void construct(PyObject* obj_ptr,
Tiago Peixoto's avatar
Tiago Peixoto committed
83
                          boost::python::converter::rvalue_from_python_stage1_data* data)
84
    {
85 86
        python::handle<> x(python::borrowed(obj_ptr));
        python::object o(x);
87
        vector<ValueType> value;
88 89 90
        python::stl_input_iterator<ValueType> iter(o), end;
        for (; iter != end; ++iter)
            value.push_back(*iter);
91
        void* storage =
92
            ( (boost::python::converter::rvalue_from_python_storage
93 94
               <vector<ValueType> >*) data)->storage.bytes;
        new (storage) vector<ValueType>(value);
95
        data->convertible = storage;
Tiago Peixoto's avatar
Tiago Peixoto committed
96 97 98
    }
};

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
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);
}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
template <class T>
python::object get_vector_state(std::vector<T>& v)
{
    return wrap_vector_owned(v);
}

template <class T>
void set_vector_state(std::vector<T>& v, python::object state)
{
    auto a = get_array<T,1>(state);
    v.clear();
    v.reserve(a.size());
    v.insert(v.end(), a.begin(), a.end());
}

135
struct export_vector_types
Tiago Peixoto's avatar
Tiago Peixoto committed
136
{
137
    template <class ValueType>
138
    void operator()(ValueType, std::string type_name = "") const
Tiago Peixoto's avatar
Tiago Peixoto committed
139
    {
140
        if (type_name.empty())
141 142
            type_name = get_type_name<>()(typeid(ValueType));
        std::replace(type_name.begin(), type_name.end(), ' ', '_');
143
        string name = "Vector_" + type_name;
144
        class_<vector<ValueType> > vc(name.c_str());
145
        std::function<size_t(const vector<ValueType>&)> hasher =
146 147 148 149 150 151 152 153 154 155
            [] (const vector<ValueType>& v) -> size_t
            { return std::hash<vector<ValueType>>()(v); };
        std::function<void(vector<ValueType>&, size_t size)> resize =
            [] (vector<ValueType>& v, size_t n) { v.resize(n); };
        std::function<void(vector<ValueType>&, size_t n)> reserve =
            [] (vector<ValueType>& v, size_t n) { v.reserve(n); };
        std::function<void(vector<ValueType>&)> shrink_to_fit =
            [] (vector<ValueType>& v) { v.shrink_to_fit(); };
        std::function<bool(vector<ValueType>&)> empty =
            [] (vector<ValueType>& v) -> bool { return v.empty(); };
Tiago Peixoto's avatar
Tiago Peixoto committed
156 157
        std::function<void(vector<ValueType>&)> clear =
            [] (vector<ValueType>& v) { v.clear(); };
158
        vc.def(vector_indexing_suite<vector<ValueType> >())
159
            .def("__eq__", &vector_equal_compare<ValueType>)
160
            .def("__ne__", &vector_nequal_compare<ValueType>)
161 162 163
            .def("__hash__", hasher)
            .def("resize", resize)
            .def("shrink_to_fit", shrink_to_fit)
Tiago Peixoto's avatar
Tiago Peixoto committed
164
            .def("clear", clear)
165
            .def("empty", empty);
Tiago Peixoto's avatar
Tiago Peixoto committed
166
        wrap_array(vc, typename boost::mpl::has_key<numpy_types,ValueType>::type());
167
        vector_from_list<ValueType>();
Tiago Peixoto's avatar
Tiago Peixoto committed
168
    }
169 170

    template <class ValueType>
Tiago Peixoto's avatar
Tiago Peixoto committed
171
    void wrap_array(class_<vector<ValueType> >& vc, boost::mpl::true_) const
172
    {
173 174 175 176
        vc.def("get_array", &wrap_vector_not_owned<ValueType>)
            .def("__getstate__", &get_vector_state<ValueType>)
            .def("__setstate__", &set_vector_state<ValueType>)
            .enable_pickling();
177 178 179
    }

    template <class ValueType>
180
    void wrap_array(class_<vector<ValueType> >&, boost::mpl::false_) const
181 182
    {
    }
183
};
Tiago Peixoto's avatar
Tiago Peixoto committed
184

185 186
// exception translation
template <class Exception>
Tiago Peixoto's avatar
Tiago Peixoto committed
187
void graph_exception_translator(const Exception& e)
188
{
Tiago Peixoto's avatar
Tiago Peixoto committed
189
    PyObject* error;
Tiago Peixoto's avatar
Tiago Peixoto committed
190
    if (std::is_same<Exception, GraphException>::value)
Tiago Peixoto's avatar
Tiago Peixoto committed
191
        error = PyExc_RuntimeError;
Tiago Peixoto's avatar
Tiago Peixoto committed
192
    if (std::is_same<Exception, IOException>::value)
Tiago Peixoto's avatar
Tiago Peixoto committed
193
        error = PyExc_IOError;
Tiago Peixoto's avatar
Tiago Peixoto committed
194
    if (std::is_same<Exception, ValueException>::value)
Tiago Peixoto's avatar
Tiago Peixoto committed
195 196
        error = PyExc_ValueError;
    PyErr_SetString(error, e.what());
197
}
Tiago Peixoto's avatar
Tiago Peixoto committed
198

199 200 201 202
void raise_error(const string& msg)
{
    throw GraphException(msg);
}
Tiago Peixoto's avatar
Tiago Peixoto committed
203

204 205
template <class T1, class T2>
struct pair_to_tuple
Tiago Peixoto's avatar
Tiago Peixoto committed
206
{
207
    static PyObject* convert(const pair<T1,T2>& p)
Tiago Peixoto's avatar
Tiago Peixoto committed
208
    {
209 210
        boost::python::tuple t = boost::python::make_tuple(p.first,p.second);
        return incref(t.ptr());
Tiago Peixoto's avatar
Tiago Peixoto committed
211 212 213
    }
};

214 215 216 217 218 219 220 221 222 223 224 225 226
template <class T1, class T2>
struct pair_from_tuple
{
    pair_from_tuple()
    {
        converter::registry::push_back(&convertible, &construct,
                                       boost::python::type_id<pair<T1,T2> >());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        handle<> x(borrowed(obj_ptr));
        object o(x);
Tiago Peixoto's avatar
Tiago Peixoto committed
227
        if (boost::python::len(o) < 2)
228
            return 0;
229 230 231 232 233 234 235 236 237 238 239 240 241
        extract<T1> first(o[0]);
        extract<T2> second(o[1]);
        if (!first.check() || !second.check())
            return 0;
        return obj_ptr;
    }

    static void construct(PyObject* obj_ptr,
                          converter::rvalue_from_python_stage1_data* data)
    {
        handle<> x(borrowed(obj_ptr));
        object o(x);
        pair<T1,T2> value;
242 243
        value.first = extract<T1>(o[0])();
        value.second = extract<T2>(o[1])();
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
        void* storage =
            ( (boost::python::converter::rvalue_from_python_storage
               <pair<T1,T2> >*) data)->storage.bytes;
        new (storage) pair<T1,T2>(value);
        data->convertible = storage;
    }
};

template <class ValueType>
struct variant_from_python
{
    variant_from_python()
    {
        converter::registry::push_back
            (&convertible, &construct,
             boost::python::type_id<GraphInterface::deg_t>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        handle<> x(borrowed(obj_ptr));
        object o(x);
        extract<ValueType> str(o);
        if (!str.check())
            return 0;
        return obj_ptr;
    }

    static void construct(PyObject* obj_ptr,
                          converter::rvalue_from_python_stage1_data* data)
    {
        handle<> x(borrowed(obj_ptr));
        object o(x);
277
        ValueType value = extract<ValueType>(o)();
278 279 280 281 282 283 284 285 286
        GraphInterface::deg_t deg = value;
        void* storage =
            ( (boost::python::converter::rvalue_from_python_storage
               <GraphInterface::deg_t>*) data)->storage.bytes;
        new (storage) GraphInterface::deg_t(deg);
        data->convertible = storage;
    }
};

Tiago Peixoto's avatar
Tiago Peixoto committed
287 288
// scipy weave integration
#ifdef HAVE_SCIPY
289
template <class ScxxType>
Tiago Peixoto's avatar
Tiago Peixoto committed
290 291
struct scxx_to_python
{
292
    static PyObject* convert(const ScxxType& o)
Tiago Peixoto's avatar
Tiago Peixoto committed
293 294 295 296 297 298
    {
        return incref((PyObject*)(o));
    }
};
#endif

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
template <class T>
struct integer_from_convertible
{
    integer_from_convertible()
    {
        converter::registry::push_back(&convertible, &construct,
                                       boost::python::type_id<T>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (PyObject_HasAttrString(obj_ptr, "__int__"))
            return obj_ptr;
        return 0;
    }

    static void construct(PyObject* obj_ptr,
                          converter::rvalue_from_python_stage1_data* data)
    {
        handle<> x(borrowed(obj_ptr));
        object o(x);
320
        T value = extract<T>(o.attr("__int__")())();
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
        void* storage =
            ( (boost::python::converter::rvalue_from_python_storage<T>*) data)->storage.bytes;
        new (storage) T(value);
        data->convertible = storage;
    }
};

template <class T>
struct float_from_convertible
{
    float_from_convertible()
    {
        converter::registry::push_back(&convertible, &construct,
                                       boost::python::type_id<T>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
        if (PyObject_HasAttrString(obj_ptr, "__float__"))
            return obj_ptr;
        return 0;
    }

    static void construct(PyObject* obj_ptr,
                          converter::rvalue_from_python_stage1_data* data)
    {
        handle<> x(borrowed(obj_ptr));
        object o(x);
349
        T value = extract<T>(o.attr("__float__")())();
350 351 352 353 354 355 356 357
        void* storage =
            ( (boost::python::converter::rvalue_from_python_storage<T>*) data)->storage.bytes;
        new (storage) T(value);
        data->convertible = storage;
    }
};


358 359 360 361 362 363 364
// persistent python object IO
namespace graph_tool
{
extern python::object object_pickler;
extern python::object object_unpickler;
}

Tiago Peixoto's avatar
Tiago Peixoto committed
365
void set_pickler(boost::python::object o)
366 367 368 369
{
    graph_tool::object_pickler = o;
}

Tiago Peixoto's avatar
Tiago Peixoto committed
370
void set_unpickler(boost::python::object o)
371 372 373 374
{
    graph_tool::object_unpickler = o;
}

Tiago Peixoto's avatar
Tiago Peixoto committed
375
boost::python::list get_property_types()
Tiago Peixoto's avatar
Tiago Peixoto committed
376
{
Tiago Peixoto's avatar
Tiago Peixoto committed
377 378
    boost::python::list plist;
    for (int i = 0; i < boost::mpl::size<value_types>::value; ++i)
Tiago Peixoto's avatar
Tiago Peixoto committed
379 380 381 382
        plist.append(string(type_names[i]));
    return plist;
}

Tiago Peixoto's avatar
Tiago Peixoto committed
383 384
struct graph_type_name
{
Tiago Peixoto's avatar
Tiago Peixoto committed
385
    typedef void result_type;
Tiago Peixoto's avatar
Tiago Peixoto committed
386
    template <class Graph>
387
    void operator()(const Graph&, string& name) const
Tiago Peixoto's avatar
Tiago Peixoto committed
388
    {
389
        name = name_demangle(typeid(Graph).name());
Tiago Peixoto's avatar
Tiago Peixoto committed
390 391 392 393 394 395
    }
};

string get_graph_type(GraphInterface& g)
{
    string name;
Tiago Peixoto's avatar
Tiago Peixoto committed
396 397
    run_action<>()(g, std::bind(graph_type_name(), std::placeholders::_1,
                                std::ref(name)))();
Tiago Peixoto's avatar
Tiago Peixoto committed
398 399 400
    return name;
}

401 402 403 404 405 406
size_t get_ptr(std::shared_ptr<GraphInterface::multigraph_t>& p)
{
    return size_t(p.get());
};


407 408 409 410 411 412 413
// numpy array interface weirdness
void* do_import_array()
{
    import_array1(NULL);
    return NULL;
}

414 415 416 417
void ungroup_vector_property(GraphInterface& g, boost::any vector_prop,
                             boost::any prop, size_t pos, bool edge);
void group_vector_property(GraphInterface& g, boost::any vector_prop,
                           boost::any prop, size_t pos, bool edge);
418 419 420
void property_map_values(GraphInterface& g, boost::any src_prop,
                         boost::any tgt_prop, boost::python::object mapper,
                         bool edge);
421
void infect_vertex_property(GraphInterface& gi, boost::any prop,
Tiago Peixoto's avatar
Tiago Peixoto committed
422
                            boost::python::object val);
423 424
void edge_endpoint(GraphInterface& gi, boost::any prop,
                   boost::any eprop, std::string endpoint);
425 426
void out_edges_op(GraphInterface& gi, boost::any eprop, boost::any vprop,
                  std::string op);
427 428
void mark_edges(GraphInterface& gi, boost::any prop);

429 430 431 432
void perfect_ehash(GraphInterface& gi, boost::any prop, boost::any hprop,
                   boost::any& dict);
void perfect_vhash(GraphInterface& gi, boost::any prop, boost::any hprop,
                   boost::any& dict);
433 434 435 436
void set_vertex_property(GraphInterface& gi, boost::any prop,
                         boost::python::object val);
void set_edge_property(GraphInterface& gi, boost::any prop,
                       boost::python::object val);
437

438 439 440 441
void copy_external_edge_property(const GraphInterface& src,
                                 const GraphInterface& tgt,
                                 boost::any prop_src,
                                 boost::any prop_tgt);
442

443
void export_python_interface();
444

445 446
void export_openmp();

447
BOOST_PYTHON_MODULE(libgraph_tool_core)
Tiago Peixoto's avatar
Tiago Peixoto committed
448
{
449
    python::docstring_options dopt(true, false);
Tiago Peixoto's avatar
Tiago Peixoto committed
450

451
    // numpy
452
    do_import_array();
453
    export_python_interface();
Tiago Peixoto's avatar
Tiago Peixoto committed
454

455 456 457 458
    // random numbers
    class_<rng_t>("rng_t");
    def("get_rng", get_rng);

Tiago Peixoto's avatar
Tiago Peixoto committed
459 460 461 462 463 464
    register_exception_translator<GraphException>
        (graph_exception_translator<GraphException>);
    register_exception_translator<IOException>
        (graph_exception_translator<IOException>);
    register_exception_translator<ValueException>
        (graph_exception_translator<ValueException>);
Tiago Peixoto's avatar
Tiago Peixoto committed
465

466
    def("raise_error", &raise_error);
Tiago Peixoto's avatar
Tiago Peixoto committed
467
    def("get_property_types", &get_property_types);
468
    class_<boost::any>("any")
469 470 471 472 473 474
        .def("empty", &boost::any::empty)
        .def("type",  &boost::any::type,
             return_value_policy<reference_existing_object>());
    class_<std::type_info, boost::noncopyable>("type_info", no_init)
        .def("name", &std::type_info::name)
        .def("hash_code", &std::type_info::hash_code);
475
    def("name_demangle", &name_demangle);
476

477
    def("graph_filtering_enabled", &graph_filtering_enabled);
478
    export_openmp();
479

Tiago Peixoto's avatar
Tiago Peixoto committed
480
    boost::mpl::for_each<boost::mpl::push_back<scalar_types,string>::type>(export_vector_types());
481
    export_vector_types()(size_t(), "size_t");
482
    export_vector_types()(std::vector<double>(), "Vector_double");
Tiago Peixoto's avatar
Tiago Peixoto committed
483
    export_vector_types()(std::complex<double>(), "cdouble");
484 485

    class_<GraphInterface>("GraphInterface", init<>())
Tiago Peixoto's avatar
Tiago Peixoto committed
486 487
        .def(init<GraphInterface,bool,boost::python::object,
                  boost::python::object, boost::python::object>())
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
        .def("get_num_vertices", &GraphInterface::get_num_vertices)
        .def("get_num_edges", &GraphInterface::get_num_edges)
        .def("set_directed", &GraphInterface::set_directed)
        .def("get_directed", &GraphInterface::get_directed)
        .def("set_reversed", &GraphInterface::set_reversed)
        .def("get_reversed", &GraphInterface::get_reversed)
        .def("set_keep_epos", &GraphInterface::set_keep_epos)
        .def("get_keep_epos", &GraphInterface::get_keep_epos)
        .def("set_vertex_filter_property",
             &GraphInterface::set_vertex_filter_property)
        .def("is_vertex_filter_active", &GraphInterface::is_vertex_filter_active)
        .def("set_edge_filter_property",
             &GraphInterface::set_edge_filter_property)
        .def("is_edge_filter_active", &GraphInterface::is_edge_filter_active)
        .def("purge_vertices",  &GraphInterface::purge_vertices)
        .def("purge_edges",  &GraphInterface::purge_edges)
        .def("shift_vertex_property",  &GraphInterface::shift_vertex_property)
        .def("move_vertex_property",  &GraphInterface::move_vertex_property)
        .def("re_index_vertex_property",  &GraphInterface::re_index_vertex_property)
        .def("write_to_file", &GraphInterface::write_to_file)
        .def("read_from_file",&GraphInterface::read_from_file)
        .def("degree_map", &GraphInterface::degree_map)
        .def("clear", &GraphInterface::clear)
        .def("clear_edges", &GraphInterface::clear_edges)
        .def("get_vertex_index", &GraphInterface::get_vertex_index)
        .def("get_edge_index", &GraphInterface::get_edge_index)
514
        .def("get_edge_index_range", &GraphInterface::get_edge_index_range)
515
        .def("re_index_edges", &GraphInterface::re_index_edges)
516
        .def("shrink_to_fit", &GraphInterface::shrink_to_fit)
517 518
        .def("get_graph_index", &GraphInterface::get_graph_index)
        .def("copy_vertex_property", &GraphInterface::copy_vertex_property)
519
        .def("copy_edge_property", &GraphInterface::copy_edge_property)
520 521
        .def("get_graph_ptr", &GraphInterface::get_graph_ptr)
        .def("get_graph_view", &GraphInterface::get_graph_view);
522

523 524 525 526
    class_<GraphInterface::vertex_index_map_t>("vertex_index_map", no_init);
    class_<GraphInterface::edge_index_map_t>("edge_index_map", no_init);
    class_<GraphInterface::graph_index_map_t>("graph_index_map", no_init);

527 528 529 530 531
    enum_<GraphInterface::degree_t>("Degree")
        .value("In", GraphInterface::IN_DEGREE)
        .value("Out", GraphInterface::OUT_DEGREE)
        .value("Total", GraphInterface::TOTAL_DEGREE);

532
    variant_from_python<boost::any>();
533
    variant_from_python<GraphInterface::degree_t>();
534
    to_python_converter<pair<string,bool>, pair_to_tuple<string,bool> >();
535
    to_python_converter<pair<size_t,size_t>, pair_to_tuple<size_t,size_t> >();
536
    to_python_converter<pair<double,double>, pair_to_tuple<double,double> >();
537 538
    pair_from_tuple<double,double>();
    pair_from_tuple<size_t,size_t>();
539 540 541 542 543 544 545 546 547 548 549
    integer_from_convertible<uint8_t>();
    integer_from_convertible<int32_t>();
    integer_from_convertible<int64_t>();
    integer_from_convertible<uint32_t>();
    integer_from_convertible<uint64_t>();
    integer_from_convertible<size_t>();
    integer_from_convertible<bool>();
    float_from_convertible<float>();
    float_from_convertible<double>();
    float_from_convertible<long double>();

550 551 552 553
    class_<std::shared_ptr<GraphInterface::multigraph_t>>
        ("shared_ptr<multigraph_t>", no_init)
        .def("get", &get_ptr);

554 555 556
    class_<IStream>("IStream", no_init).def("read", &IStream::read);
    class_<OStream>("OStream", no_init).def("write", &OStream::write).
        def("flush", &OStream::flush);
557 558 559
    def("set_pickler", &set_pickler);
    def("set_unpickler", &set_unpickler);

560 561
    def("group_vector_property", &group_vector_property);
    def("ungroup_vector_property", &ungroup_vector_property);
562
    def("property_map_values", &property_map_values);
563
    def("infect_vertex_property", &infect_vertex_property);
564
    def("edge_endpoint", &edge_endpoint);
565
    def("out_edges_op", &out_edges_op);
566
    def("mark_edges", &mark_edges);
567 568
    def("perfect_ehash", &perfect_ehash);
    def("perfect_vhash", &perfect_vhash);
569 570
    def("set_vertex_property", &set_vertex_property);
    def("set_edge_property", &set_edge_property);
571
    def("copy_external_edge_property", &copy_external_edge_property);
572

Tiago Peixoto's avatar
Tiago Peixoto committed
573
    class_<LibInfo>("mod_info")
574 575 576
        .add_property("name", &LibInfo::GetName)
        .add_property("author", &LibInfo::GetAuthor)
        .add_property("copyright", &LibInfo::GetCopyright)
577
        .add_property("version", &LibInfo::GetVersion)
578 579 580
        .add_property("license", &LibInfo::GetLicense)
        .add_property("cxxflags", &LibInfo::GetCXXFLAGS)
        .add_property("install_prefix", &LibInfo::GetInstallPrefix)
Tiago Peixoto's avatar
Tiago Peixoto committed
581 582
        .add_property("python_dir", &LibInfo::GetPythonDir)
        .add_property("gcc_version", &LibInfo::GetGCCVersion);
Tiago Peixoto's avatar
Tiago Peixoto committed
583 584

    def("get_graph_type", &get_graph_type);
585 586 587

    def("get_null_vertex",
        +[](){ return graph_traits<GraphInterface::multigraph_t>::null_vertex();});
Tiago Peixoto's avatar
Tiago Peixoto committed
588
}