changeset: 91947:818989a48e96 branch: 2.7 parent: 91943:6b7f189daa62 user: Serhiy Storchaka date: Thu Jul 31 07:48:14 2014 +0300 files: Lib/lib-tk/Tkinter.py Lib/lib-tk/test/test_tkinter/test_images.py Misc/NEWS Modules/_tkinter.c description: Issue #21580: Now Tkinter correctly handles binary "data" and "maskdata" configure options of tkinter.PhotoImage. Added private Tkapp method _createbytearray(). diff -r 6b7f189daa62 -r 818989a48e96 Lib/lib-tk/Tkinter.py --- a/Lib/lib-tk/Tkinter.py Wed Jul 30 19:24:26 2014 -0400 +++ b/Lib/lib-tk/Tkinter.py Thu Jul 31 07:48:14 2014 +0300 @@ -3282,6 +3282,8 @@ for k, v in cnf.items(): if hasattr(v, '__call__'): v = self._register(v) + elif k in ('data', 'maskdata'): + v = self.tk._createbytearray(v) options = options + ('-'+k, v) self.tk.call(('image', 'create', imgtype, name,) + options) self.name = name @@ -3305,6 +3307,8 @@ if k[-1] == '_': k = k[:-1] if hasattr(v, '__call__'): v = self._register(v) + elif k in ('data', 'maskdata'): + v = self.tk._createbytearray(v) res = res + ('-'+k, v) self.tk.call((self.name, 'config') + res) config = configure diff -r 6b7f189daa62 -r 818989a48e96 Lib/lib-tk/test/test_tkinter/test_images.py --- a/Lib/lib-tk/test/test_tkinter/test_images.py Wed Jul 30 19:24:26 2014 -0400 +++ b/Lib/lib-tk/test/test_tkinter/test_images.py Thu Jul 31 07:48:14 2014 +0300 @@ -151,7 +151,8 @@ self.assertEqual(image.type(), 'photo') self.assertEqual(image.width(), 16) self.assertEqual(image.height(), 16) - self.assertEqual(image['data'], data) + self.assertEqual(image['data'], data if self.wantobjects + else data.decode('latin1')) self.assertEqual(image['file'], '') self.assertIn('::img::test', self.root.image_names()) del image @@ -160,21 +161,18 @@ def test_create_from_ppm_file(self): self.check_create_from_file('ppm') - @unittest.skip('issue #21580') def test_create_from_ppm_data(self): self.check_create_from_data('ppm') def test_create_from_pgm_file(self): self.check_create_from_file('pgm') - @unittest.skip('issue #21580') def test_create_from_pgm_data(self): self.check_create_from_data('pgm') def test_create_from_gif_file(self): self.check_create_from_file('gif') - @unittest.skip('issue #21580') def test_create_from_gif_data(self): self.check_create_from_data('gif') @@ -182,19 +180,18 @@ def test_create_from_png_file(self): self.check_create_from_file('png') - @unittest.skip('issue #21580') @requires_tcl(8, 6) def test_create_from_png_data(self): self.check_create_from_data('png') - @unittest.skip('issue #21580') def test_configure_data(self): image = tkinter.PhotoImage('::img::test', master=self.root) self.assertEqual(image['data'], '') with open(self.testfile, 'rb') as f: data = f.read() image.configure(data=data) - self.assertEqual(image['data'], data) + self.assertEqual(image['data'], data if self.wantobjects + else data.decode('latin1')) self.assertEqual(image.width(), 16) self.assertEqual(image.height(), 16) diff -r 6b7f189daa62 -r 818989a48e96 Misc/NEWS --- a/Misc/NEWS Wed Jul 30 19:24:26 2014 -0400 +++ b/Misc/NEWS Thu Jul 31 07:48:14 2014 +0300 @@ -19,6 +19,9 @@ Library ------- +- Issue #21580: Now Tkinter correctly handles binary "data" and "maskdata" + configure options of tkinter.PhotoImage. + - Issue #19612: subprocess.communicate() now also ignores EINVAL when using at least two pipes. diff -r 6b7f189daa62 -r 818989a48e96 Modules/_tkinter.c --- a/Modules/_tkinter.c Wed Jul 30 19:24:26 2014 -0400 +++ b/Modules/_tkinter.c Thu Jul 31 07:48:14 2014 +0300 @@ -2939,6 +2939,33 @@ return Py_None; } +/* Convert Python string or any buffer compatible object to Tcl byte-array + * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands. + */ +static PyObject * +Tkapp_CreateByteArray(PyObject *self, PyObject *args) +{ + Py_buffer view; + Tcl_Obj* obj; + PyObject *res = NULL; + + if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view)) + return NULL; + + if (view.len >= INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "string is too long"); + return NULL; + } + obj = Tcl_NewByteArrayObj(view.buf, (int)view.len); + if (obj == NULL) { + PyBuffer_Release(&view); + return Tkinter_Error(self); + } + res = newPyTclObject(obj); + PyBuffer_Release(&view); + return res; +} + /**** Tkapp Method List ****/ @@ -2981,6 +3008,7 @@ {"quit", Tkapp_Quit, METH_VARARGS}, {"interpaddr", Tkapp_InterpAddr, METH_VARARGS}, {"loadtk", Tkapp_TkInit, METH_NOARGS}, + {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS}, {NULL, NULL} };