On Mon, Sep 09, 2013 at 02:14:56PM +0200, Jakub Wilk wrote: > * Julian Andres Klode <j...@debian.org>, 2013-08-26, 13:48: > >>The apt_inst.TarFile.extractdata method requires that it's > >>argument is a str. It would be nice if it also accepted bytes > >>objects. This would be consistent with e.g. built-in open > >>function, which accepts one or the other as filename. > > > >Thank you for your bug report; and yes, you're right. We are using > >PyArg_ParseTuple() to parse the string. We currently use the > >format string "s" for parsing file names. If you happen to know > >the best format string we could use that accepts bytes strings as > >well, please let us know. It has to work with Python 2.7 as well. > > The documentation for the "s" format reads: "This format does not > accept bytes-like objects. If you want to accept filesystem paths > and convert them to C character strings, it is preferable to use the > O& format with PyUnicode_FSConverter() as converter." > > PyUnicode_FSConverter is not available in Python 2.X, though.
The attached patch should implement this for Python 3.1+, python2.X is unchanged (for now). Feedback/review welcome! Cheers, Michael
>From 5b3887123da762eb9d92635adb755beac479ff40 Mon Sep 17 00:00:00 2001 From: Michael Vogt <m...@debian.org> Date: Tue, 10 Sep 2013 17:21:33 +0200 Subject: [PATCH] make apt_inst.TarFile.extractdata accept bytes --- po/python-apt.pot | 2 +- python/tarfile.cc | 7 +++++++ tests/data/test_1.tar.gz | Bin 0 -> 124 bytes tests/test_extract.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/data/test_1.tar.gz create mode 100644 tests/test_extract.py diff --git a/po/python-apt.pot b/po/python-apt.pot index d9cc96c..7b68f5a 100644 --- a/po/python-apt.pot +++ b/po/python-apt.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-08-05 22:44+0200\n" +"POT-Creation-Date: 2013-09-10 17:20+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <l...@li.org>\n" diff --git a/python/tarfile.cc b/python/tarfile.cc index 920f032..6ccc4ec 100644 --- a/python/tarfile.cc +++ b/python/tarfile.cc @@ -407,9 +407,16 @@ static const char *tarfile_extractdata_doc = "LookupError if there is no member with the given name."; static PyObject *tarfile_extractdata(PyObject *self, PyObject *args) { + PyObject *py_member; const char *member; +#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1 + if (PyArg_ParseTuple(args,"O&",PyUnicode_FSConverter, &py_member) == 0) + return 0; + member = PyBytes_AS_STRING(py_member); +#else if (PyArg_ParseTuple(args,"s",&member) == 0) return 0; +#endif PyDirStream stream(NULL, member); ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min); // Go through the stream. diff --git a/tests/data/test_1.tar.gz b/tests/data/test_1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..eb74134a0e06cceed89a772b4661e633a6642ba9 GIT binary patch literal 124 zcmb2|=3w||tRKX{{Pvt7SA&6o%f&16l-zIh8d~}vNLbo*@%QQ*5t?F3hw9IY7$5!e z_|B~9C)HT?FF)pXt}-C~isf48wT5}tqWTvjDu3U|(=48~#&oB2`|7)~|AS9{+d1XR W(^s$68IVDPdRUbCCP4-b1_l7F?=)%v literal 0 HcmV?d00001 diff --git a/tests/test_extract.py b/tests/test_extract.py new file mode 100644 index 0000000..0afd8da --- /dev/null +++ b/tests/test_extract.py @@ -0,0 +1,28 @@ +#!/usr/bin/python + +import os +import unittest + +import apt_inst + +class TarFileTestCase(unittest.TestCase): + + def test_extractdata_bytes(self): + tar_path = os.path.join( + os.path.dirname(__file__), "data", "test_1.tar.gz") + tar_file = apt_inst.TarFile(tar_path) + member = b"motd" + content = tar_file.extractdata(member).decode("utf-8") + self.assertEqual(content, "a message\n") + + def test_extractdata_string(self): + tar_path = os.path.join( + os.path.dirname(__file__), "data", "test_1.tar.gz") + tar_file = apt_inst.TarFile(tar_path) + member = u"motd" + content = tar_file.extractdata(member).decode("utf-8") + self.assertEqual(content, "a message\n") + + +if __name__ == "__main__": + unittest.main() -- 1.8.3.2