Skip to content

Commit 836d7b7

Browse files
Prerak SinghPrerak Singh
authored andcommitted
conflict resolution
2 parents c5307c7 + e520be3 commit 836d7b7

File tree

5 files changed

+81
-31
lines changed

5 files changed

+81
-31
lines changed

pydatastructs/graphs/_backend/cpp/algorithms.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
static PyMethodDef AlgorithmsMethods[] = {
77
{"bfs_adjacency_list", (PyCFunction)breadth_first_search_adjacency_list, METH_VARARGS | METH_KEYWORDS, "Run BFS on adjacency list with callback"},
88
{"bfs_adjacency_matrix", (PyCFunction)breadth_first_search_adjacency_matrix, METH_VARARGS | METH_KEYWORDS, "Run BFS on adjacency matrix with callback"},
9-
{"minimum_spanning_tree_prim_adjacency_list", (PyCFunction)minimum_spanning_tree_prim_adjacency_list, METH_VARARGS | METH_KEYWORDS, "Run Prim's algorithm on adjacency list"},
109
{NULL, NULL, 0, NULL}
1110
};
1211

pydatastructs/utils/_backend/cpp/AdjacencyListGraphNode.hpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,29 @@ extern PyTypeObject AdjacencyListGraphNodeType;
1313
typedef struct {
1414
PyObject_HEAD
1515
std::string name;
16-
std::variant<std::monostate, int64_t, double, std::string> data;
16+
std::variant<std::monostate, int64_t, double, std::string, PyObject*> data;
1717
DataType data_type;
1818
std::unordered_map<std::string, PyObject*> adjacent;
1919
} AdjacencyListGraphNode;
2020

2121
static void AdjacencyListGraphNode_dealloc(AdjacencyListGraphNode* self) {
22+
if (self->data_type == DataType::PyObject) {
23+
Py_XDECREF(std::get<PyObject*>(self->data));
24+
}
25+
2226
for (auto& pair : self->adjacent) {
2327
Py_XDECREF(pair.second);
2428
}
2529
self->adjacent.clear();
26-
Py_TYPE(self)->tp_free(reinterpret_cast<PyTypeObject*>(self));
30+
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
2731
}
2832

2933
static PyObject* AdjacencyListGraphNode_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
3034
AdjacencyListGraphNode* self = PyObject_New(AdjacencyListGraphNode, &AdjacencyListGraphNodeType);
3135
if (!self) return NULL;
3236
new (&self->adjacent) std::unordered_map<std::string, PyObject*>();
3337
new (&self->name) std::string();
34-
new (&self->data) std::variant<std::monostate, int64_t, double, std::string>();
38+
new (&self->data) std::variant<std::monostate, int64_t, double, std::string, PyObject*>();
3539
self->data_type = DataType::None;
3640
self->data = std::monostate{};
3741

@@ -61,16 +65,16 @@ static PyObject* AdjacencyListGraphNode_new(PyTypeObject* type, PyObject* args,
6165
self->data_type = DataType::String;
6266
self->data = std::string(str);
6367
} else {
64-
PyErr_SetString(PyExc_TypeError, "Unsupported data type. Must be int, float, str, or None.");
65-
return NULL;
68+
self->data_type = DataType::PyObject;
69+
Py_INCREF(data);
70+
self->data = data;
6671
}
6772

6873
if (PyList_Check(adjacency_list)) {
6974
Py_ssize_t size = PyList_Size(adjacency_list);
7075
for (Py_ssize_t i = 0; i < size; i++) {
7176
PyObject* node = PyList_GetItem(adjacency_list, i);
7277

73-
7478
if (PyType_Ready(&AdjacencyListGraphNodeType) < 0) {
7579
PyErr_SetString(PyExc_RuntimeError, "Failed to initialize AdjacencyListGraphNodeType");
7680
return NULL;
@@ -85,7 +89,7 @@ static PyObject* AdjacencyListGraphNode_new(PyTypeObject* type, PyObject* args,
8589
std::string str = std::string(adj_name);
8690
Py_INCREF(node);
8791
self->adjacent[str] = node;
88-
}
92+
}
8993
}
9094

9195
return reinterpret_cast<PyObject*>(self);
@@ -154,13 +158,20 @@ static PyObject* AdjacencyListGraphNode_get_data(AdjacencyListGraphNode* self, v
154158
return PyFloat_FromDouble(std::get<double>(self->data));
155159
case DataType::String:
156160
return PyUnicode_FromString(std::get<std::string>(self->data).c_str());
161+
case DataType::PyObject:
162+
Py_INCREF(std::get<PyObject*>(self->data));
163+
return std::get<PyObject*>(self->data);
157164
case DataType::None:
158165
default:
159166
Py_RETURN_NONE;
160167
}
161168
}
162169

163170
static int AdjacencyListGraphNode_set_data(AdjacencyListGraphNode* self, PyObject* value, void* closure) {
171+
if (self->data_type == DataType::PyObject) {
172+
Py_XDECREF(std::get<PyObject*>(self->data));
173+
}
174+
164175
if (value == Py_None) {
165176
self->data_type = DataType::None;
166177
self->data = std::monostate{};
@@ -179,8 +190,9 @@ static int AdjacencyListGraphNode_set_data(AdjacencyListGraphNode* self, PyObjec
179190
self->data_type = DataType::String;
180191
self->data = std::string(str);
181192
} else {
182-
PyErr_SetString(PyExc_TypeError, "Unsupported data type. Must be int, float, str, or None.");
183-
return -1;
193+
self->data_type = DataType::PyObject;
194+
Py_INCREF(value);
195+
self->data = value;
184196
}
185197
return 0;
186198
}
@@ -227,7 +239,6 @@ static PyGetSetDef AdjacencyListGraphNode_getsetters[] = {
227239
{NULL}
228240
};
229241

230-
231242
static PyMethodDef AdjacencyListGraphNode_methods[] = {
232243
{"add_adjacent_node", (PyCFunction)AdjacencyListGraphNode_add_adjacent_node, METH_VARARGS, "Add adjacent node"},
233244
{"remove_adjacent_node", (PyCFunction)AdjacencyListGraphNode_remove_adjacent_node, METH_VARARGS, "Remove adjacent node"},

pydatastructs/utils/_backend/cpp/GraphNode.hpp

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,31 @@ enum class DataType {
1010
None,
1111
Int,
1212
Double,
13-
String
13+
String,
14+
PyObject
1415
};
1516

1617
typedef struct {
1718
PyObject_HEAD
1819
std::string name;
19-
std::variant<std::monostate, int64_t, double, std::string> data;
20+
std::variant<std::monostate, int64_t, double, std::string, PyObject*> data;
2021
DataType data_type;
2122
} GraphNode;
2223

23-
static void GraphNode_dealloc(GraphNode* self){
24-
self->name.~basic_string();
25-
self->data.~decltype(self->data)();
26-
Py_TYPE(self)->tp_free(reinterpret_cast<PyTypeObject*>(self));
24+
static void GraphNode_dealloc(GraphNode* self) {
25+
if (self->data_type == DataType::PyObject) {
26+
Py_XDECREF(std::get<PyObject*>(self->data));
27+
}
28+
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
2729
}
2830

29-
static PyObject* GraphNode_new(PyTypeObject* type, PyObject* args, PyObject* kwds){
30-
GraphNode* self;
31-
self = reinterpret_cast<GraphNode*>(type->tp_alloc(type,0));
31+
static PyObject* GraphNode_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
32+
GraphNode* self = reinterpret_cast<GraphNode*>(type->tp_alloc(type, 0));
33+
if (!self) return NULL;
34+
3235
new (&self->name) std::string();
33-
new (&self->data) std::variant<std::monostate, int64_t, double, std::string>();
36+
new (&self->data) std::variant<std::monostate, int64_t, double, std::string, PyObject*>();
3437
self->data_type = DataType::None;
35-
if (!self) return NULL;
3638

3739
static char* kwlist[] = { "name", "data", NULL };
3840
const char* name;
@@ -59,8 +61,9 @@ static PyObject* GraphNode_new(PyTypeObject* type, PyObject* args, PyObject* kwd
5961
self->data = std::string(s);
6062
self->data_type = DataType::String;
6163
} else {
62-
PyErr_SetString(PyExc_TypeError, "data must be int, float, str, or None");
63-
return NULL;
64+
self->data = data;
65+
self->data_type = DataType::PyObject;
66+
Py_INCREF(data);
6467
}
6568

6669
return reinterpret_cast<PyObject*>(self);
@@ -82,15 +85,28 @@ static PyObject* GraphNode_str(GraphNode* self) {
8285
case DataType::String:
8386
repr += "'" + std::get<std::string>(self->data) + "'";
8487
break;
88+
case DataType::PyObject: {
89+
PyObject* repr_obj = PyObject_Repr(std::get<PyObject*>(self->data));
90+
if (repr_obj) {
91+
const char* repr_cstr = PyUnicode_AsUTF8(repr_obj);
92+
repr += repr_cstr ? repr_cstr : "<unprintable>";
93+
Py_DECREF(repr_obj);
94+
} else {
95+
repr += "<error in repr>";
96+
}
97+
break;
98+
}
8599
}
100+
86101
repr += ")";
87102
return PyUnicode_FromString(repr.c_str());
88103
}
89104

90105
static PyObject* GraphNode_get(GraphNode* self, void *closure) {
91-
if (closure == (void*)"name") {
106+
const char* attr = reinterpret_cast<const char*>(closure);
107+
if (strcmp(attr, "name") == 0) {
92108
return PyUnicode_FromString(self->name.c_str());
93-
} else if (closure == (void*)"data") {
109+
} else if (strcmp(attr, "data") == 0) {
94110
switch (self->data_type) {
95111
case DataType::None:
96112
Py_RETURN_NONE;
@@ -100,25 +116,32 @@ static PyObject* GraphNode_get(GraphNode* self, void *closure) {
100116
return PyFloat_FromDouble(std::get<double>(self->data));
101117
case DataType::String:
102118
return PyUnicode_FromString(std::get<std::string>(self->data).c_str());
119+
case DataType::PyObject:
120+
Py_INCREF(std::get<PyObject*>(self->data));
121+
return std::get<PyObject*>(self->data);
103122
}
104123
}
105124
Py_RETURN_NONE;
106125
}
107126

108127
static int GraphNode_set(GraphNode* self, PyObject *value, void *closure) {
128+
const char* attr = reinterpret_cast<const char*>(closure);
109129
if (!value) {
110130
PyErr_SetString(PyExc_ValueError, "Cannot delete attributes");
111131
return -1;
112132
}
113133

114-
if (closure == (void*)"name") {
134+
if (strcmp(attr, "name") == 0) {
115135
if (!PyUnicode_Check(value)) {
116136
PyErr_SetString(PyExc_TypeError, "name must be a string");
117137
return -1;
118138
}
119139
self->name = PyUnicode_AsUTF8(value);
120-
}
121-
else if (closure == (void*)"data") {
140+
} else if (strcmp(attr, "data") == 0) {
141+
if (self->data_type == DataType::PyObject) {
142+
Py_XDECREF(std::get<PyObject*>(self->data));
143+
}
144+
122145
if (value == Py_None) {
123146
self->data = std::monostate{};
124147
self->data_type = DataType::None;
@@ -132,8 +155,9 @@ static int GraphNode_set(GraphNode* self, PyObject *value, void *closure) {
132155
self->data = std::string(PyUnicode_AsUTF8(value));
133156
self->data_type = DataType::String;
134157
} else {
135-
PyErr_SetString(PyExc_TypeError, "data must be int, float, str, or None");
136-
return -1;
158+
Py_INCREF(value);
159+
self->data = value;
160+
self->data_type = DataType::PyObject;
137161
}
138162
} else {
139163
PyErr_SetString(PyExc_AttributeError, "Unknown attribute");

pydatastructs/utils/_extensions.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from setuptools import Extension
22
import os
33
import sys
4+
import os
5+
import sys
46

57
project = 'pydatastructs'
68
module = 'utils'
@@ -10,11 +12,21 @@
1012
nodes = '.'.join([project, module, backend, cpp, '_nodes'])
1113
nodes_sources = [os.path.join(project, module, backend, cpp, 'nodes.cpp')]
1214

15+
nodes_sources = [os.path.join(project, module, backend, cpp, 'nodes.cpp')]
16+
1317
graph_utils = '.'.join([project, module, backend, cpp, '_graph_utils'])
1418
graph_utils_sources = [os.path.join(project, module, backend, cpp, 'graph_utils.cpp')]
1519

1620
extra_compile_args = ["-std=c++17"]
1721

22+
if sys.platform == "darwin":
23+
extra_compile_args.append("-mmacosx-version-min=10.13")
24+
elif sys.platform == "win32":
25+
extra_compile_args = ["/std:c++17"]
26+
graph_utils_sources = [os.path.join(project, module, backend, cpp, 'graph_utils.cpp')]
27+
28+
extra_compile_args = ["-std=c++17"]
29+
1830
if sys.platform == "darwin":
1931
extra_compile_args.append("-mmacosx-version-min=10.13")
2032
elif sys.platform == "win32":

pydatastructs/utils/tests/test_misc_util.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,16 @@ def test_AdjacencyListGraphNode():
3636
h.add_adjacent_node('h_1', 4)
3737
assert h.adjacent['h_1'] == 4
3838
assert str(h) == "('h', 0)"
39+
h_5 = AdjacencyListGraphNode('h_5', h_1, backend = Backend.CPP)
40+
assert h_5.data == h_1
3941

4042
def test_AdjacencyMatrixGraphNode():
4143
g = AdjacencyMatrixGraphNode("1", 3)
4244
g2 = AdjacencyMatrixGraphNode("1", 3, backend = Backend.CPP)
4345
assert str(g) == "('1', 3)"
4446
assert str(g2) == "('1', 3)"
47+
g3 = AdjacencyListGraphNode("3", g2, backend = Backend.CPP)
48+
assert g3.data == g2
4549

4650

4751
def test_GraphEdge():

0 commit comments

Comments
 (0)