[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#680971: python3-apt: apt_inst.TarFile.extractdata could accepts bytes



On Mon, Sep 09, 2013 at 02:14:56PM +0200, Jakub Wilk wrote:
> * Julian Andres Klode <jak@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 <mvo@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 <LL@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


Reply to: