Commit f257d426 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Reorganize exceptions thrown

No longer only thrown GraphError upon any error, but instead throw
specific exceptions which are more meaninful and are mapped to standard
python exceptions, such as IOError, ValueError and RuntimeError.
parent 54f5c469
...@@ -37,9 +37,9 @@ void absolute_trust(GraphInterface& g, int64_t source, boost::any c, ...@@ -37,9 +37,9 @@ void absolute_trust(GraphInterface& g, int64_t source, boost::any c,
rng_t rng(static_cast<rng_t::result_type>(seed)); rng_t rng(static_cast<rng_t::result_type>(seed));
if (!belongs<edge_floating_properties>()(c)) if (!belongs<edge_floating_properties>()(c))
throw GraphException("edge property must be of floating point value type"); throw ValueException("edge property must be of floating point value type");
if (!belongs<vertex_floating_vector_properties>()(t)) if (!belongs<vertex_floating_vector_properties>()(t))
throw GraphException("vertex property must be of floating point vector value type"); throw ValueException("vertex property must be of floating point vector value type");
run_action<>()(g, run_action<>()(g,
bind<void>(get_absolute_trust(), _1, g.GetVertexIndex(), bind<void>(get_absolute_trust(), _1, g.GetVertexIndex(),
......
...@@ -129,11 +129,11 @@ void betweenness(GraphInterface& g, boost::any weight, ...@@ -129,11 +129,11 @@ void betweenness(GraphInterface& g, boost::any weight,
bool normalize) bool normalize)
{ {
if (!belongs<edge_floating_properties>()(edge_betweenness)) if (!belongs<edge_floating_properties>()(edge_betweenness))
throw GraphException("edge property must be of floating point value" throw ValueException("edge property must be of floating point value"
" type"); " type");
if (!belongs<vertex_floating_properties>()(vertex_betweenness)) if (!belongs<vertex_floating_properties>()(vertex_betweenness))
throw GraphException("vertex property must be of floating point value" throw ValueException("vertex property must be of floating point value"
" type"); " type");
if (!weight.empty()) if (!weight.empty())
......
...@@ -32,9 +32,9 @@ size_t eigentrust(GraphInterface& g, boost::any c, boost::any t, ...@@ -32,9 +32,9 @@ size_t eigentrust(GraphInterface& g, boost::any c, boost::any t,
double epslon, size_t max_iter) double epslon, size_t max_iter)
{ {
if (!belongs<writable_edge_scalar_properties>()(c)) if (!belongs<writable_edge_scalar_properties>()(c))
throw GraphException("edge property must be writable"); throw ValueException("edge property must be writable");
if (!belongs<vertex_floating_properties>()(t)) if (!belongs<vertex_floating_properties>()(t))
throw GraphException("vertex property must be of floating point" throw ValueException("vertex property must be of floating point"
" value type"); " value type");
size_t iter = 0; size_t iter = 0;
......
...@@ -33,7 +33,7 @@ size_t pagerank(GraphInterface& g, boost::any rank, double d, double epslon, ...@@ -33,7 +33,7 @@ size_t pagerank(GraphInterface& g, boost::any rank, double d, double epslon,
size_t max_iter) size_t max_iter)
{ {
if (!belongs<writable_vertex_scalar_properties>()(rank)) if (!belongs<writable_vertex_scalar_properties>()(rank))
throw GraphException("vertex property must be writable"); throw ValueException("vertex property must be writable");
size_t iter; size_t iter;
run_action<>() run_action<>()
......
...@@ -86,7 +86,7 @@ void extended_clustering(GraphInterface& g, python::list props) ...@@ -86,7 +86,7 @@ void extended_clustering(GraphInterface& g, python::list props)
prop_vector<writable_vertex_scalar_properties>() prop_vector<writable_vertex_scalar_properties>()
(cmaps, num_vertices(g.GetGraph())); (cmaps, num_vertices(g.GetGraph()));
if (vprop.empty()) if (vprop.empty())
throw GraphException("all vertex properties must be of the same" throw ValueException("all vertex properties must be of the same"
" floating point type"); " floating point type");
typedef mpl::transform<writable_vertex_scalar_properties, typedef mpl::transform<writable_vertex_scalar_properties,
......
...@@ -95,7 +95,7 @@ void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list, ...@@ -95,7 +95,7 @@ void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list,
} }
catch (bad_any_cast&) catch (bad_any_cast&)
{ {
throw GraphException("All motif graphs must be either directed or " throw ValueException("All motif graphs must be either directed or "
"undirected!"); "undirected!");
} }
......
...@@ -50,7 +50,7 @@ void community_structure(GraphInterface& g, double gamma, string corr_name, ...@@ -50,7 +50,7 @@ void community_structure(GraphInterface& g, double gamma, string corr_name,
allowed_spin_properties; allowed_spin_properties;
if (!belongs<allowed_spin_properties>()(property)) if (!belongs<allowed_spin_properties>()(property))
throw GraphException("vertex property is not of integer type int32_t " throw ValueException("vertex property is not of integer type int32_t "
"or int64_t"); "or int64_t");
typedef DynamicPropertyMapWrap<double,GraphInterface::edge_t> weight_map_t; typedef DynamicPropertyMapWrap<double,GraphInterface::edge_t> weight_map_t;
...@@ -70,7 +70,7 @@ void community_structure(GraphInterface& g, double gamma, string corr_name, ...@@ -70,7 +70,7 @@ void community_structure(GraphInterface& g, double gamma, string corr_name,
else if (corr_name == "correlated") else if (corr_name == "correlated")
corr = CORRELATED; corr = CORRELATED;
else else
throw GraphException("invalid correlation type: " + corr_name); throw ValueException("invalid correlation type: " + corr_name);
bool directed = g.GetDirected(); bool directed = g.GetDirected();
g.SetDirected(false); g.SetDirected(false);
......
...@@ -70,8 +70,8 @@ struct get_communities ...@@ -70,8 +70,8 @@ struct get_communities
{ {
out_file.open(verbose.second.c_str()); out_file.open(verbose.second.c_str());
if (!out_file.is_open()) if (!out_file.is_open())
throw GraphException("error opening file " + verbose.second + throw IOException("error opening file " + verbose.second +
" for writing"); " for writing");
out_file.exceptions (ifstream::eofbit | ifstream::failbit | out_file.exceptions (ifstream::eofbit | ifstream::failbit |
ifstream::badbit); ifstream::badbit);
} }
...@@ -200,8 +200,8 @@ struct get_communities ...@@ -200,8 +200,8 @@ struct get_communities
} }
catch (ifstream::failure e) catch (ifstream::failure e)
{ {
throw GraphException("error writing to file " + throw IOException("error writing to file " +
verbose.second + ": " + e.what()); verbose.second + ": " + e.what());
} }
} }
} }
......
...@@ -57,7 +57,7 @@ void community_network(GraphInterface& gi, GraphInterface& cgi, ...@@ -57,7 +57,7 @@ void community_network(GraphInterface& gi, GraphInterface& cgi,
} }
catch (bad_any_cast&) catch (bad_any_cast&)
{ {
throw GraphException("invalid vertex count property"); throw ValueException("invalid vertex count property");
} }
typedef property_map_types::apply<mpl::vector<int32_t,double>, typedef property_map_types::apply<mpl::vector<int32_t,double>,
...@@ -66,7 +66,7 @@ void community_network(GraphInterface& gi, GraphInterface& cgi, ...@@ -66,7 +66,7 @@ void community_network(GraphInterface& gi, GraphInterface& cgi,
ecount_properties; ecount_properties;
if (!belongs<ecount_properties>()(edge_count)) if (!belongs<ecount_properties>()(edge_count))
throw GraphException("invalid edge count property"); throw ValueException("invalid edge count property");
run_action<>()(gi, bind<void>(get_community_network(), _1, run_action<>()(gi, bind<void>(get_community_network(), _1,
ref(cgi.GetGraph()), cgi.GetVertexIndex(), ref(cgi.GetGraph()), cgi.GetVertexIndex(),
......
...@@ -47,5 +47,5 @@ void random_rewire(GraphInterface& gi, string strat, bool self_loops, ...@@ -47,5 +47,5 @@ void random_rewire(GraphInterface& gi, string strat, bool self_loops,
_1, edge_index, ref(rng), self_loops, _1, edge_index, ref(rng), self_loops,
parallel_edges))(); parallel_edges))();
else else
throw GraphException("invalid random rewire stategy: " + strat); throw ValueException("invalid random rewire strategy: " + strat);
} }
...@@ -191,7 +191,7 @@ struct graph_rewire ...@@ -191,7 +191,7 @@ struct graph_rewire
has_self_loops = true; has_self_loops = true;
} }
if (has_self_loops) if (has_self_loops)
throw GraphException("Self-loop detected. Can't rewire graph " throw ValueException("Self-loop detected. Can't rewire graph "
"without self-loops if it already contains" "without self-loops if it already contains"
" self-loops!"); " self-loops!");
} }
...@@ -221,7 +221,7 @@ struct graph_rewire ...@@ -221,7 +221,7 @@ struct graph_rewire
} }
if (has_parallel_edges) if (has_parallel_edges)
throw GraphException("Parallel edge detected. Can't rewire " throw ValueException("Parallel edge detected. Can't rewire "
"graph without parallel edges if it " "graph without parallel edges if it "
"already contains parallel edges!"); "already contains parallel edges!");
} }
......
...@@ -234,6 +234,19 @@ protected: ...@@ -234,6 +234,19 @@ protected:
virtual void SetError(const string& error) {_error = error;} virtual void SetError(const string& error) {_error = error;}
}; };
class IOException : public GraphException
{
public:
IOException(const string& error): GraphException(error) {}
};
class ValueException : public GraphException
{
public:
ValueException(const string& error): GraphException(error) {}
};
} //namespace graph_tool } //namespace graph_tool
#endif #endif
......
...@@ -136,21 +136,20 @@ struct export_vector_types ...@@ -136,21 +136,20 @@ struct export_vector_types
}; };
// exception translation // exception translation
static PyObject* pyex =
PyErr_NewException((char *) "libgraph_tool_core.GraphError",
PyExc_Exception, NULL);
void graph_exception_translator(const GraphException& e)
{
PyObject* message = PyString_FromString(e.what());
PyObject_SetAttrString(pyex, "message", message);
PyErr_SetString(pyex, e.what());
}
template <class Exception> template <class Exception>
void translate(const Exception& e) void graph_exception_translator(const Exception& e)
{ {
PyErr_SetString(PyExc_RuntimeError, e.what()); PyObject* error;
if (is_same<Exception, GraphException>::value)
error = PyExc_RuntimeError;
if (is_same<Exception, IOException>::value)
error = PyExc_IOError;
if (is_same<Exception, ValueException>::value)
error = PyExc_ValueError;
PyObject* message = PyString_FromString(e.what());
PyObject_SetAttrString(error, "message", message);
PyErr_SetString(error, e.what());
} }
void raise_error(const string& msg) void raise_error(const string& msg)
...@@ -310,8 +309,12 @@ BOOST_PYTHON_MODULE(libgraph_tool_core) ...@@ -310,8 +309,12 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
GraphInterface().ExportPythonInterface(); GraphInterface().ExportPythonInterface();
PyModule_AddObject(python::detail::current_scope, "GraphError", pyex); register_exception_translator<GraphException>
register_exception_translator<GraphException>(graph_exception_translator); (graph_exception_translator<GraphException>);
register_exception_translator<IOException>
(graph_exception_translator<IOException>);
register_exception_translator<ValueException>
(graph_exception_translator<ValueException>);
def("raise_error", &raise_error); def("raise_error", &raise_error);
def("get_property_types", &get_property_types); def("get_property_types", &get_property_types);
......
...@@ -216,7 +216,7 @@ struct copy_property ...@@ -216,7 +216,7 @@ struct copy_property
for (tie(vs, vs_end) = IteratorSel::range(src); vs != vs_end; ++vs) for (tie(vs, vs_end) = IteratorSel::range(src); vs != vs_end; ++vs)
{ {
if (vt == vt_end) if (vt == vt_end)
throw GraphException("Error copying properties: " throw ValueException("Error copying properties: "
"graphs not identical"); "graphs not identical");
dst_map[*vt] = c(src_map[*vs]); dst_map[*vt] = c(src_map[*vs]);
++vt; ++vt;
...@@ -224,7 +224,7 @@ struct copy_property ...@@ -224,7 +224,7 @@ struct copy_property
} }
catch (bad_lexical_cast&) catch (bad_lexical_cast&)
{ {
throw GraphException("property values are not convertible"); throw ValueException("property values are not convertible");
} }
} }
}; };
......
...@@ -482,7 +482,7 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile, ...@@ -482,7 +482,7 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile,
if (format == "dot") if (format == "dot")
graphviz = true; graphviz = true;
else if (format != "xml") else if (format != "xml")
throw GraphException("error reading from file '" + file + throw ValueException("error reading from file '" + file +
"': requested invalid format '" + format + "'"); "': requested invalid format '" + format + "'");
try try
{ {
...@@ -542,8 +542,7 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile, ...@@ -542,8 +542,7 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile,
} }
catch (ios_base::failure &e) catch (ios_base::failure &e)
{ {
throw GraphException("error reading from file '" + file + "':" + throw IOException("error reading from file '" + file + "':" + e.what());
e.what());
} }
}; };
...@@ -621,7 +620,7 @@ void GraphInterface::WriteToFile(string file, python::object pfile, ...@@ -621,7 +620,7 @@ void GraphInterface::WriteToFile(string file, python::object pfile,
if (format == "dot") if (format == "dot")
graphviz = true; graphviz = true;
else if (format != "xml") else if (format != "xml")
throw GraphException("error writing to file '" + file + throw ValueException("error writing to file '" + file +
"': requested invalid format '" + format + "'"); "': requested invalid format '" + format + "'");
try try
{ {
...@@ -711,7 +710,6 @@ void GraphInterface::WriteToFile(string file, python::object pfile, ...@@ -711,7 +710,6 @@ void GraphInterface::WriteToFile(string file, python::object pfile,
} }
catch (ios_base::failure &e) catch (ios_base::failure &e)
{ {
throw GraphException("error writing to file '" + file + "':" + throw IOException("error writing to file '" + file + "':" + e.what());
e.what());
} }
} }
...@@ -225,7 +225,7 @@ void GraphInterface::RemoveEdge(const python::object& e) ...@@ -225,7 +225,7 @@ void GraphInterface::RemoveEdge(const python::object& e)
lambda::var(e), lambda::var(de), lambda::var(e), lambda::var(de),
lambda::var(found)))(); lambda::var(found)))();
if (!found) if (!found)
throw GraphException("invalid edge descriptor"); throw ValueException("invalid edge descriptor");
RemoveEdgeIndex(de); RemoveEdgeIndex(de);
} }
......
...@@ -93,7 +93,7 @@ public: ...@@ -93,7 +93,7 @@ public:
void CheckValid() const void CheckValid() const
{ {
if (!IsValid()) if (!IsValid())
throw GraphException("invalid vertex descriptor"); throw ValueException("invalid vertex descriptor");
} }
GraphInterface::vertex_t GetDescriptor() const GraphInterface::vertex_t GetDescriptor() const
...@@ -253,7 +253,7 @@ public: ...@@ -253,7 +253,7 @@ public:
void CheckValid() const void CheckValid() const
{ {
if (!_valid) if (!_valid)
throw GraphException("invalid edge descriptor"); throw ValueException("invalid edge descriptor");
} }
GraphInterface::edge_t GetDescriptor() const GraphInterface::edge_t GetDescriptor() const
...@@ -403,7 +403,7 @@ public: ...@@ -403,7 +403,7 @@ public:
void set_value(const PythonDescriptor& key, const value_type& val, void set_value(const PythonDescriptor& key, const value_type& val,
false_type) false_type)
{ {
throw GraphException("property is read-only"); throw ValueException("property is read-only");
} }
size_t GetHash() const size_t GetHash() const
...@@ -497,7 +497,7 @@ python::object new_property(const string& type, IndexMap index_map) ...@@ -497,7 +497,7 @@ python::object new_property(const string& type, IndexMap index_map)
lambda::var(prop), lambda::var(prop),
lambda::var(found))); lambda::var(found)));
if (!found) if (!found)
throw GraphException("Invalid property type " + type); throw ValueException("Invalid property type: " + type);
return prop; return prop;
} }
......
...@@ -43,7 +43,7 @@ boost::any graph_tool::degree_selector(GraphInterface::deg_t deg) ...@@ -43,7 +43,7 @@ boost::any graph_tool::degree_selector(GraphInterface::deg_t deg)
mpl::for_each<vertex_properties> mpl::for_each<vertex_properties>
(bind<void>(get_scalar_selector(), _1, *d, var(sel), var(found))); (bind<void>(get_scalar_selector(), _1, *d, var(sel), var(found)));
if (!found) if (!found)
throw GraphException("invalid degree selector"); throw ValueException("invalid degree selector");
} }
return sel; return sel;
} }
...@@ -92,12 +92,11 @@ import numpy ...@@ -92,12 +92,11 @@ import numpy
import scipy import scipy
import scipy.stats import scipy.stats
from . core import __version__, Graph, GraphError, Vector_bool, \ from . core import __version__, Graph, Vector_bool, Vector_int32_t, \
Vector_int32_t, Vector_int64_t, Vector_double, Vector_long_double,\ Vector_int64_t, Vector_double, Vector_long_double, Vector_string, \
Vector_string, value_types, load_graph, PropertyMap, Vertex, Edge,\ value_types, load_graph, PropertyMap, Vertex, Edge, show_config
show_config
__all__ = ["Graph", "Vertex", "Edge", "Vector_bool", "Vector_int32_t",
__all__ = ["Graph", "Vertex", "Edge", "GraphError", "Vector_bool", "Vector_int64_t", "Vector_double", "Vector_long_double",
"Vector_int32_t", "Vector_int64_t", "Vector_double", "Vector_string", "value_types", "load_graph", "PropertyMap",
"Vector_long_double", "Vector_string", "value_types", "load_graph", "show_config"]
"PropertyMap", "show_config"]
...@@ -26,7 +26,7 @@ import sys, os, os.path, re, struct, fcntl, termios, gzip, bz2, string,\ ...@@ -26,7 +26,7 @@ import sys, os, os.path, re, struct, fcntl, termios, gzip, bz2, string,\
textwrap, time, signal, traceback, shutil, time, math, inspect, \ textwrap, time, signal, traceback, shutil, time, math, inspect, \
functools, types, weakref, copy functools, types, weakref, copy
from StringIO import StringIO from StringIO import StringIO
from decorators import _wraps, _require, _attrs, _handle_exceptions, _limit_args from decorators import _wraps, _require, _attrs, _limit_args
################################################################################ ################################################################################
# Utility functions # Utility functions
...@@ -39,9 +39,9 @@ def _prop(t, g, prop): ...@@ -39,9 +39,9 @@ def _prop(t, g, prop):
try: try:
pmap = g.properties[(t,prop)] pmap = g.properties[(t,prop)]
except KeyError: except KeyError:
raise GraphError("no internal %s property named: %s" %\ raise KeyError("no internal %s property named: %s" %\
("vertex" if t == "v" else \ ("vertex" if t == "v" else \
("edge" if t == "e" else "graph"),prop)) ("edge" if t == "e" else "graph"), prop))
else: else:
pmap = prop pmap = prop
if pmap == None: if pmap == None:
...@@ -228,10 +228,9 @@ class PropertyDict(dict): ...@@ -228,10 +228,9 @@ class PropertyDict(dict):
# The main graph interface # The main graph interface
################################################################################ ################################################################################
from libgraph_tool_core import Vertex, Edge, GraphError,\ from libgraph_tool_core import Vertex, Edge, Vector_bool, Vector_int32_t, \
Vector_bool, Vector_int32_t, Vector_int64_t, Vector_double,\ Vector_int64_t, Vector_double, Vector_long_double, Vector_string, \
Vector_long_double, Vector_string, new_vertex_property, new_edge_property,\ new_vertex_property, new_edge_property, new_graph_property
new_graph_property
class Graph(object): class Graph(object):
"""This class encapsulates either a directed multigraph (default or if """This class encapsulates either a directed multigraph (default or if
...@@ -298,7 +297,6 @@ class Graph(object): ...@@ -298,7 +297,6 @@ class Graph(object):
self.__edge_index = \ self.__edge_index = \
PropertyMap(libcore.get_edge_index(self.__graph), self, "e") PropertyMap(libcore.get_edge_index(self.__graph), self, "e")
@_handle_exceptions
def copy(self): def copy(self):
"""Returns a deep copy of self. All internal property maps are also """Returns a deep copy of self. All internal property maps are also
copied.""" copied."""
...@@ -307,7 +305,6 @@ class Graph(object): ...@@ -307,7 +305,6 @@ class Graph(object):
# Graph access # Graph access
# ============ # ============
@_handle_exceptions
def vertices(self): def vertices(self):
"""Return an iterator over the vertices """Return an iterator over the vertices
...@@ -325,17 +322,14 @@ class Graph(object): ...@@ -325,17 +322,14 @@ class Graph(object):
""" """
return self.__graph.Vertices() return self.__graph.Vertices()
@_handle_exceptions
def vertex(self, i): def vertex(self, i):
"""Return the i-th vertex from the graph.""" """Return the i-th vertex from the graph."""
return self.__graph.Vertex(int(i)) return self.__graph.Vertex(int(i))
@_handle_exceptions
def edges(self): def edges(self):
"""Return iterator over the edges.""" """Return iterator over the edges."""
return self.__graph.Edges() return self.__graph.Edges()
@_handle_exceptions
def add_vertex(self, n=1):