From c13e18528912950a3581cbbe1aee2c372ba734f2 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 31 Mar 2024 13:51:29 -0400 Subject: [PATCH 1/2] PyColor fix - Init corrections --- src/PyColor.cpp | 83 ++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/src/PyColor.cpp b/src/PyColor.cpp index 50eae73..4f7f5f8 100644 --- a/src/PyColor.cpp +++ b/src/PyColor.cpp @@ -65,77 +65,62 @@ PyObject* PyColor::repr(PyObject* obj) } -int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) -{ - using namespace mcrfpydef; +int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) { + //using namespace mcrfpydef; static const char* keywords[] = { "r", "g", "b", "a", nullptr }; PyObject* leader; int r = -1, g = -1, b = -1, a = 255; - if (!PyArg_ParseTupleAndKeywords, args, kwds, "O|iii", leader, &g, &b, &a) - { - PyErr_SetString(PyExc_TypeError, "mcrfpy.Color requires a color object, 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", const_cast(keywords), &leader, &g, &b, &a)) { + PyErr_SetString(PyExc_TypeError, "mcrfpy.Color requires a 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); return -1; } - // if the "r" arg is already a color, yoink that color value - if (PyObject_IsInstance(leader, (PyObject*)&PyColorType)) - { - self->data = ((PyColorObject*)leader)->data; - return 0; - } - // else if the "r" arg is a 3-tuple, initialize to (r, g, b, 255) - // (if the "r" arg is a 4-tuple, initialize to (r, g, b, a)) - else if (PyTuple_Check(leader)) - { - if (PyTuple_Size(leader) < 3 && PyTuple_Size(leader) > 4) - { - PyErr_SetString(PyExc_TypeError, "Invalid tuple length: mcrfpy.Color requires a color object, 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); + //std::cout << "Arg parsing succeeded. Values: " << r << " " << g << " " << b << " " << a < 4) { + PyErr_SetString(PyExc_TypeError, "Invalid tuple length: mcrfpy.Color requires a 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); return -1; } r = PyLong_AsLong(PyTuple_GetItem(leader, 0)); g = PyLong_AsLong(PyTuple_GetItem(leader, 1)); b = PyLong_AsLong(PyTuple_GetItem(leader, 2)); - //a = 255; //default value - - if (PyTuple_Size(leader) == 4) - { + if (tupleSize == 4) { a = PyLong_AsLong(PyTuple_GetItem(leader, 3)); } + } + // Color name (not implemented yet) + else if (PyUnicode_Check(leader)) { + PyErr_SetString(PyExc_NotImplementedError, "Color names aren't ready yet"); + return -1; + } + // Check if the leader is actually an integer for the r value + else if (PyLong_Check(leader)) { + r = PyLong_AsLong(leader); + // Additional validation not shown; g, b are required to be parsed + } else { + PyErr_SetString(PyExc_TypeError, "mcrfpy.Color requires a 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); + return -1; + } - // value validation - if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || a < 0 || a > 255) - { - PyErr_SetString(PyExc_ValueError, "Color values must be between 0 and 255."); - return -1; - } - self->data = sf::Color(r, g, b, a); - } - // else if the "r" arg is a string, initialize to {color lookup function value} - else if (PyUnicode_Check(leader)) - { - PyErr_SetString(Py_NotImplemented, "Color names aren't ready yet"); - return -1; - } - // else - - else if (!PyLong_Check(leader)) - { - PyErr_SetString(PyExc_TypeError, "mcrfpy.Color requires a color object, 3-tuple, 4-tuple, color name, or integer values within 0-255 (r, g, b, optionally a)"); - return -1; - } - r = PyLong_AsLong(leader); - // assert r, g, b are present and ints in range (0, 255) - if not enough ints were provided to the args/kwds parsed by init, g and/or b will still hold -1. - if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || a < 0 || a > 255) - { - PyErr_SetString(PyExc_ValueError, "R, G, B values are required, A value is optional; Color values must be between 0 and 255."); + // Validate color values + if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255 || a < 0 || a > 255) { + PyErr_SetString(PyExc_ValueError, "Color values must be between 0 and 255."); return -1; } + self->data = sf::Color(r, g, b, a); return 0; } PyObject* PyColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) { - return (PyObject*)type->tp_alloc(type, 0); + auto obj = (PyObject*)type->tp_alloc(type, 0); + //Py_INCREF(obj); + return obj; } PyObject* PyColor::get_member(PyObject* obj, void* closure) From 5edebdd64316abec6e941d49b210f93d7e88a2d1 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 31 Mar 2024 14:21:07 -0400 Subject: [PATCH 2/2] PyVector init should be pretty reliable now --- src/PyVector.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/PyVector.cpp b/src/PyVector.cpp index b76e038..adf2aff 100644 --- a/src/PyVector.cpp +++ b/src/PyVector.cpp @@ -56,28 +56,19 @@ int PyVector::init(PyVectorObject* self, PyObject* args, PyObject* kwds) using namespace mcrfpydef; static const char* keywords[] = { "x", "y", nullptr }; PyObject* leader = NULL; - double x=0, y=0; + float x=0, y=0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Of", const_cast(keywords), &leader, &y)) { //PyErr_SetString(PyExc_TypeError, "mcrfpy.Vector requires a 2-tuple or two numeric values"); - self->data = sf::Vector2f(); - return 0; + return -1; } - else if (leader == NULL || leader == Py_None) + if (leader == NULL || leader == Py_None) { self->data = sf::Vector2f(); return 0; } - // if the "r" arg is already a vector, yoink that color value - else if (PyObject_IsInstance(leader, (PyObject*)&PyVectorType)) - { - self->data = ((PyVectorObject*)leader)->data; - return 0; - } - // else if the "r" arg is a 3-tuple, initialize to (r, g, b, 255) - // (if the "r" arg is a 4-tuple, initialize to (r, g, b, a)) - else if (PyTuple_Check(leader)) + if (PyTuple_Check(leader)) { if (PyTuple_Size(leader) != 2) { @@ -88,6 +79,7 @@ int PyVector::init(PyVectorObject* self, PyObject* args, PyObject* kwds) y = PyFloat_AsDouble(PyTuple_GetItem(leader, 1)); self->data = sf::Vector2f(x, y); + return 0; } // else - else if (!PyFloat_Check(leader) && !(PyLong_Check(leader)))