| 112 | } |
| 113 | |
| 114 | py::object Graph_add_nodes_from(py::args args, py::kwargs kwargs) { |
| 115 | Graph& self = args[0].cast<Graph&>(); |
| 116 | self.dirty_nodes = true; |
| 117 | self.dirty_adj = true; |
| 118 | self.linkgraph_dirty = true; |
| 119 | py::list nodes_for_adding = py::list(args[1]); |
| 120 | for (int i = 0; i < py::len(nodes_for_adding); i++) { |
| 121 | bool newnode; |
| 122 | py::dict attr = kwargs; |
| 123 | py::dict newdict, ndict; |
| 124 | py::object n = nodes_for_adding[i]; |
| 125 | try { |
| 126 | newnode = !self.node_to_id.contains(n); |
| 127 | newdict = attr; |
| 128 | } |
| 129 | catch (const py::error_already_set&) { |
| 130 | PyObject *type, *value, *traceback; |
| 131 | PyErr_Fetch(&type, &value, &traceback); |
| 132 | if (PyErr_GivenExceptionMatches(PyExc_TypeError, type)) { |
| 133 | py::tuple n_pair = n.cast<py::tuple>(); |
| 134 | n = n_pair[0]; |
| 135 | ndict = n_pair[1].cast<py::dict>(); |
| 136 | newnode = !self.node_to_id.contains(n); |
| 137 | newdict = attr.attr("copy")(); |
| 138 | newdict.attr("update")(ndict); |
| 139 | } else { |
| 140 | PyErr_Restore(type, value, traceback); |
| 141 | return py::none(); |
| 142 | } |
| 143 | } |
| 144 | if (newnode) { |
| 145 | if (n.is_none()) { |
| 146 | PyErr_Format(PyExc_ValueError, "None cannot be a node"); |
| 147 | return py::none(); |
| 148 | } |
| 149 | _add_one_node(self, n); |
| 150 | } |
| 151 | node_t id = self.node_to_id[n].cast<node_t>(); |
| 152 | for (auto item : newdict) { |
| 153 | std::string weight_key = weight_to_string(item.first.cast<py::object>()); |
| 154 | weight_t value = item.second.cast<weight_t>(); |
| 155 | self.node[id].insert(std::make_pair(weight_key, value)); |
| 156 | } |
| 157 | } |
| 158 | return py::none(); |
| 159 | } |
| 160 | |
| 161 | py::object Graph_remove_node(Graph& self, py::object node_to_remove) { |
| 162 | self.dirty_nodes = true; |
nothing calls this directly
no test coverage detected