Skip to content

Commit 1681ce3

Browse files
authored
Merge pull request #3547 from Matiiss/add-color-bytes-method
Add `Color.__bytes__`
2 parents a88e23b + 68e8f05 commit 1681ce3

File tree

4 files changed

+40
-0
lines changed

4 files changed

+40
-0
lines changed

buildconfig/stubs/pygame/color.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class Color(Collection[int]):
4242
def __mod__(self, other: Color) -> Color: ...
4343
def __int__(self) -> int: ...
4444
def __float__(self) -> float: ...
45+
def __bytes__(self) -> bytes: ...
4546
def __len__(self) -> int: ...
4647
def __index__(self) -> int: ...
4748
def __invert__(self) -> Color: ...

docs/reST/ref/color.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@
9292
:returns: a newly created :class:`Color` object
9393
:rtype: Color
9494

95+
.. versionchanged:: 2.5.6
96+
``bytes(Color(...))`` (assuming `bytes <https://docs.python.org/3/library/stdtypes.html#bytes>`_ is
97+
the built-in type) now returns a ``bytes`` object (of length 4) with the RGBA values of the color,
98+
as opposed to :class:`Color` being interpreted as an integer (think ``int(Color(...))``) causing it
99+
to return a ``bytes`` object filled with 0s the length of said integer.
95100
.. versionchangedold:: 2.0.0
96101
Support for tuples, lists, and :class:`Color` objects when creating
97102
:class:`Color` objects.

src_c/color.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ _color_int(pgColorObject *);
181181
static PyObject *
182182
_color_float(pgColorObject *);
183183

184+
static PyObject *
185+
_color_bytes(pgColorObject *);
186+
184187
/* Sequence protocol methods */
185188
static Py_ssize_t
186189
_color_length(pgColorObject *);
@@ -256,6 +259,17 @@ static PyMethodDef _color_methods[] = {
256259
{"premul_alpha", (PyCFunction)_premul_alpha, METH_NOARGS,
257260
DOC_COLOR_PREMULALPHA},
258261
{"update", (PyCFunction)_color_update, METH_FASTCALL, DOC_COLOR_UPDATE},
262+
263+
/**
264+
* While object.__bytes__(self) is listed in the Data Model reference (see:
265+
* https://docs.python.org/3/reference/datamodel.html#object.__bytes__) it
266+
* does not appear to have a PyTypeObject struct analog (see:
267+
* https://docs.python.org/3/c-api/typeobj.html), so we declare it for the
268+
* type as any other custom method.
269+
*/
270+
{"__bytes__", (PyCFunction)_color_bytes, METH_NOARGS,
271+
"Get a byte representation of the color"},
272+
259273
{NULL, NULL, 0, NULL}};
260274

261275
/**
@@ -1753,6 +1767,15 @@ _color_float(pgColorObject *color)
17531767
return PyFloat_FromDouble((double)tmp);
17541768
}
17551769

1770+
/**
1771+
* bytes(color)
1772+
*/
1773+
static PyObject *
1774+
_color_bytes(pgColorObject *color)
1775+
{
1776+
return PyBytes_FromStringAndSize((char *)color->data, 4);
1777+
}
1778+
17561779
/* Sequence protocol methods */
17571780

17581781
/**

test/color_test.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,17 @@ def test_long(self):
773773
self.assertEqual(c.a, 146)
774774
self.assertEqual(int(c), int(0x33727592))
775775

776+
def test_bytes(self):
777+
c = pygame.Color(0x00012345)
778+
self.assertEqual(c.r, 0x00)
779+
self.assertEqual(c.g, 0x01)
780+
self.assertEqual(c.b, 0x23)
781+
self.assertEqual(c.a, 0x45)
782+
783+
as_bytes = bytes(c)
784+
self.assertEqual(as_bytes, bytes([0x00, 0x01, 0x23, 0x45]))
785+
self.assertEqual(len(as_bytes), 4)
786+
776787
def test_from_cmy(self):
777788
cmy = pygame.Color.from_cmy(0.5, 0.5, 0.5)
778789
cmy_tuple = pygame.Color.from_cmy((0.5, 0.5, 0.5))

0 commit comments

Comments
 (0)