Skip to content

Commit

Permalink
tuple subclasses: use tp_getset instead of tp_getattro for member access
Browse files Browse the repository at this point in the history
With tp_getset things will show up in the class __dict__ which helps
with auto completion and also allows us to compare things with
the annotation stubs.
  • Loading branch information
lazka committed Feb 25, 2018
1 parent de7e156 commit 4ad2228
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 45 deletions.
37 changes: 32 additions & 5 deletions cairo/glyph.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,38 @@ glyph_repr(PyObject *self) {
return result;
}

static PyObject*
glyph_getattro (PyObject *self, PyObject *name) {
return Pycairo_tuple_getattro (self, KWDS, name);
static PyObject *
glyph_get_index(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 0);
Py_XINCREF (obj);
return obj;
}

static PyObject *
glyph_get_x(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 1);
Py_XINCREF (obj);
return obj;
}

static PyObject *
glyph_get_y(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 2);
Py_XINCREF (obj);
return obj;
}

static PyGetSetDef glyph_getset[] = {
{"index", (getter)glyph_get_index},
{"x", (getter)glyph_get_x},
{"y", (getter)glyph_get_y},
{NULL,},
};


PyTypeObject PycairoGlyph_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"cairo.Glyph", /* tp_name */
Expand All @@ -177,7 +204,7 @@ PyTypeObject PycairoGlyph_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
glyph_getattro, /* tp_getattro */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
Expand All @@ -190,7 +217,7 @@ PyTypeObject PycairoGlyph_Type = {
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
glyph_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
Expand Down
24 changes: 0 additions & 24 deletions cairo/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,30 +240,6 @@ Pycairo_fspath_none_converter (PyObject *obj, char** result) {
return Pycairo_fspath_converter (obj, result);
}

PyObject*
Pycairo_tuple_getattro (PyObject *self, char **kwds, PyObject *name) {
PyObject *value, *item;
int res;
Py_ssize_t i;

for (i = 0; kwds[i] != NULL; i++) {
value = PYCAIRO_PyUnicode_FromString (kwds[i]);
res = PyObject_RichCompareBool (name, value, Py_EQ);
Py_DECREF (value);
if (res == -1) {
return NULL;
} else if (res == 1) {
item = PyTuple_GetItem (self, i);
if (item == NULL)
return NULL;
Py_INCREF (item);
return item;
}
}

return PyTuple_Type.tp_getattro (self, name);
}

PyObject*
Pycairo_richcompare (void* a, void *b, int op)
{
Expand Down
1 change: 0 additions & 1 deletion cairo/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ int _PyTextCluster_AsTextCluster (PyObject *pyobj,
int _conv_pyobject_to_ulong (PyObject *pyobj, unsigned long *result);

PyObject* Pycairo_richcompare (void* a, void *b, int op);
PyObject* Pycairo_tuple_getattro (PyObject *self, char **kwds, PyObject *name);

extern PyTypeObject PycairoContext_Type;
PyObject *PycairoContext_FromContext (cairo_t *ctx, PyTypeObject *type,
Expand Down
45 changes: 40 additions & 5 deletions cairo/rectangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,46 @@ rectangle_repr(PyObject *self) {
return result;
}

static PyObject*
rectangle_getattro (PyObject *self, PyObject *name) {
return Pycairo_tuple_getattro (self, KWDS, name);
static PyObject *
rectangle_get_x(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 0);
Py_XINCREF (obj);
return obj;
}

static PyObject *
rectangle_get_y(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 1);
Py_XINCREF (obj);
return obj;
}

static PyObject *
rectangle_get_width(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 2);
Py_XINCREF (obj);
return obj;
}

static PyObject *
rectangle_get_height(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 3);
Py_XINCREF (obj);
return obj;
}

static PyGetSetDef rectangle_getset[] = {
{"x", (getter)rectangle_get_x},
{"y", (getter)rectangle_get_y},
{"width", (getter)rectangle_get_width},
{"height", (getter)rectangle_get_height},
{NULL,},
};

PyTypeObject PycairoRectangle_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"cairo.Rectangle", /* tp_name */
Expand All @@ -87,7 +122,7 @@ PyTypeObject PycairoRectangle_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
rectangle_getattro, /* tp_getattro */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
Expand All @@ -100,7 +135,7 @@ PyTypeObject PycairoRectangle_Type = {
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
rectangle_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
Expand Down
27 changes: 22 additions & 5 deletions cairo/textcluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,28 @@ text_cluster_repr(PyObject *self) {
return result;
}

static PyObject*
text_cluster_getattro (PyObject *self, PyObject *name) {
return Pycairo_tuple_getattro (self, KWDS, name);
static PyObject *
text_cluster_get_num_bytes(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 0);
Py_XINCREF (obj);
return obj;
}

static PyObject *
text_cluster_get_num_glyphs(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 1);
Py_XINCREF (obj);
return obj;
}

static PyGetSetDef text_cluster_getset[] = {
{"num_bytes", (getter)text_cluster_get_num_bytes},
{"num_glyphs", (getter)text_cluster_get_num_glyphs},
{NULL,},
};

PyTypeObject PycairoTextCluster_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"cairo.TextCluster", /* tp_name */
Expand All @@ -121,7 +138,7 @@ PyTypeObject PycairoTextCluster_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
text_cluster_getattro, /* tp_getattro */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
Expand All @@ -134,7 +151,7 @@ PyTypeObject PycairoTextCluster_Type = {
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
text_cluster_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
Expand Down
63 changes: 58 additions & 5 deletions cairo/textextents.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,64 @@ text_extents_repr(PyObject *self) {
return result;
}

static PyObject*
text_extents_getattro (PyObject *self, PyObject *name) {
return Pycairo_tuple_getattro (self, KWDS, name);
static PyObject *
text_extents_get_x_bearing(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 0);
Py_XINCREF (obj);
return obj;
}

static PyObject *
text_extents_get_y_bearing(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 1);
Py_XINCREF (obj);
return obj;
}

static PyObject *
text_extents_get_width(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 2);
Py_XINCREF (obj);
return obj;
}

static PyObject *
text_extents_get_height(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 3);
Py_XINCREF (obj);
return obj;
}

static PyObject *
text_extents_get_x_advance(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 4);
Py_XINCREF (obj);
return obj;
}

static PyObject *
text_extents_get_y_advance(PyObject *self, void *closure)
{
PyObject *obj = PyTuple_GetItem (self, 5);
Py_XINCREF (obj);
return obj;
}

static PyGetSetDef text_cluster_getset[] = {
{"x_bearing", (getter)text_extents_get_x_bearing},
{"y_bearing", (getter)text_extents_get_y_bearing},
{"width", (getter)text_extents_get_width},
{"height", (getter)text_extents_get_height},
{"x_advance", (getter)text_extents_get_x_advance},
{"y_advance", (getter)text_extents_get_y_advance},
{NULL,},
};

PyTypeObject PycairoTextExtents_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"cairo.TextExtents", /* tp_name */
Expand All @@ -91,7 +144,7 @@ PyTypeObject PycairoTextExtents_Type = {
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
text_extents_getattro, /* tp_getattro */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
Expand All @@ -104,7 +157,7 @@ PyTypeObject PycairoTextExtents_Type = {
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
text_cluster_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
Expand Down
4 changes: 4 additions & 0 deletions tests/test_glyph.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ def test_type():
"cairo.Glyph(index=0, x=0.0, y=0.0)"
assert eval(repr(g)) == g

assert cairo.Glyph.index
assert cairo.Glyph.x
assert cairo.Glyph.y


def test_context():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
Expand Down
5 changes: 5 additions & 0 deletions tests/test_rectangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ def test_type():
assert str(r) == repr(r)
assert eval(repr(r)) == r

assert cairo.Rectangle.x
assert cairo.Rectangle.y
assert cairo.Rectangle.width
assert cairo.Rectangle.height


def test_context():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
Expand Down
3 changes: 3 additions & 0 deletions tests/test_textcluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ def test_type():
assert repr(r) == "cairo.TextCluster(num_bytes=2, num_glyphs=1)"
assert str(r) == "cairo.TextCluster(num_bytes=2, num_glyphs=1)"
assert eval(repr(r)) == r

assert cairo.TextCluster.num_bytes
assert cairo.TextCluster.num_glyphs
7 changes: 7 additions & 0 deletions tests/test_textextents.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ def test_type():
assert str(r) == repr(r)
assert eval(repr(r)) == r

assert cairo.TextExtents.x_bearing
assert cairo.TextExtents.y_bearing
assert cairo.TextExtents.width
assert cairo.TextExtents.height
assert cairo.TextExtents.x_advance
assert cairo.TextExtents.y_advance


def test_methods():
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
Expand Down

0 comments on commit 4ad2228

Please sign in to comment.