aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <[email protected]>2016-09-13 08:44:14 +0000
committerJustus Winter <[email protected]>2016-09-13 11:29:43 +0000
commit70a3be27a509a1b5ea7372bee93d83c5019427ff (patch)
tree26424006293c90a51baec2276c633850fa2f539b
parentpython: Fix types and error handling. (diff)
downloadgpgme-70a3be27a509a1b5ea7372bee93d83c5019427ff.tar.gz
gpgme-70a3be27a509a1b5ea7372bee93d83c5019427ff.zip
python: Handle slight differences between Python 2 and 3.
* lang/python/helpers.c (pyDataWriteCb): Handle Python integers being returned on Python 2. (pyDataSeekCb): Likewise. * lang/python/pyme/core.py (Data.__init__): Fix testing for string argument. (Data.new_from_filepart): Likewise. * lang/python/pyme/util.py (is_a_string): New function. * lang/python/tests/t-encrypt-large.py (read_cb): Force evaluation of generator. * lang/python/tests/t-idiomatic.py: Partly skip test on Python 2. * lang/python/tests/t-verify.py (check_result): Here, the difference between 2 and 3 really matters. We cannot change the char * conversion in Python 2 without breaking all existing applications, and using bytestrings in Python 3 would be very inconvenient. Signed-off-by: Justus Winter <[email protected]>
-rw-r--r--lang/python/helpers.c36
-rw-r--r--lang/python/pyme/core.py4
-rw-r--r--lang/python/pyme/util.py12
-rwxr-xr-xlang/python/tests/t-encrypt-large.py2
-rwxr-xr-xlang/python/tests/t-idiomatic.py31
-rwxr-xr-xlang/python/tests/t-verify.py8
6 files changed, 61 insertions, 32 deletions
diff --git a/lang/python/helpers.c b/lang/python/helpers.c
index 5b13fee0..bc8aed40 100644
--- a/lang/python/helpers.c
+++ b/lang/python/helpers.c
@@ -833,17 +833,21 @@ static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size)
goto leave;
}
- if (! PyLong_Check(retval)) {
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check(retval))
+ result = PyInt_AsSsize_t(retval);
+ else
+#endif
+ if (PyLong_Check(retval))
+ result = PyLong_AsSsize_t(retval);
+ else {
PyErr_Format(PyExc_TypeError,
- "expected int from read callback, got %s",
+ "expected int from write callback, got %s",
retval->ob_type->tp_name);
_pyme_stash_callback_exception(self);
result = -1;
- goto leave;
}
- result = PyLong_AsSsize_t(retval);
-
leave:
Py_XDECREF(retval);
return result;
@@ -894,21 +898,25 @@ static off_t pyDataSeekCb(void *hook, off_t offset, int whence)
goto leave;
}
- if (! PyLong_Check(retval)) {
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check(retval))
+ result = PyInt_AsLong(retval);
+ else
+#endif
+ if (PyLong_Check(retval))
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+ result = PyLong_AsLongLong(retval);
+#else
+ result = PyLong_AsLong(retval);
+#endif
+ else {
PyErr_Format(PyExc_TypeError,
- "expected int from read callback, got %s",
+ "expected int from seek callback, got %s",
retval->ob_type->tp_name);
_pyme_stash_callback_exception(self);
result = -1;
- goto leave;
}
-#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
- result = PyLong_AsLongLong(retval);
-#else
- result = PyLong_AsLong(retval);
-#endif
-
leave:
Py_XDECREF(retval);
return result;
diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py
index 4bbbc170..a71426b9 100644
--- a/lang/python/pyme/core.py
+++ b/lang/python/pyme/core.py
@@ -884,7 +884,7 @@ class Data(GpgmeWrapper):
elif file != None and offset != None and length != None:
self.new_from_filepart(file, offset, length)
elif file != None:
- if type(file) == type("x"):
+ if util.is_a_string(file):
self.new_from_file(file, copy)
else:
self.new_from_fd(file)
@@ -961,7 +961,7 @@ class Data(GpgmeWrapper):
filename = None
fp = None
- if type(file) == type("x"):
+ if util.is_a_string(file):
filename = file
else:
fp = gpgme.fdopen(file.fileno(), file.mode)
diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py
index c4c9e180..bf25ccb0 100644
--- a/lang/python/pyme/util.py
+++ b/lang/python/pyme/util.py
@@ -16,6 +16,8 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+import sys
+
def process_constants(prefix, scope):
"""Called by the constant modules to load up the constants from the C
library starting with PREFIX. Matching constants will be inserted
@@ -36,3 +38,13 @@ def percent_escape(s):
'%{0:2x}'.format(ord(c))
if c == '+' or c == '"' or c == '%' or ord(c) <= 0x20 else c
for c in s)
+
+# Python2/3 compatibility
+if sys.version_info[0] == 3:
+ # Python3
+ def is_a_string(x):
+ return isinstance(x, str)
+else:
+ # Python2
+ def is_a_string(x):
+ return isinstance(x, basestring)
diff --git a/lang/python/tests/t-encrypt-large.py b/lang/python/tests/t-encrypt-large.py
index 69aed483..29f9de21 100755
--- a/lang/python/tests/t-encrypt-large.py
+++ b/lang/python/tests/t-encrypt-large.py
@@ -37,7 +37,7 @@ def read_cb(amount):
ntoread -= chunk
assert ntoread >= 0
assert chunk >= 0
- return bytes(random.randrange(256) for i in range(chunk))
+ return bytes(bytearray(random.randrange(256) for i in range(chunk)))
nwritten = 0
def write_cb(data):
diff --git a/lang/python/tests/t-idiomatic.py b/lang/python/tests/t-idiomatic.py
index 1989c922..726bbb93 100755
--- a/lang/python/tests/t-idiomatic.py
+++ b/lang/python/tests/t-idiomatic.py
@@ -17,6 +17,7 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+import sys
import io
import os
import tempfile
@@ -60,17 +61,21 @@ with tempfile.TemporaryFile() as source, \
sign_and_verify(source, signed, sink)
-# XXX: Python's io.BytesIo.truncate does not work as advertised.
-# http://bugs.python.org/issue27261
-bio = io.BytesIO()
-bio.truncate(1)
-if len(bio.getvalue()) != 1:
- # This version of Python is affected, preallocate buffer.
- preallocate = 128*b'\x00'
-else:
- preallocate = b''
+if sys.version_info[0] == 3:
+ # Python2's io.BytesIO does not implement the buffer interface,
+ # hence we cannot use it as sink.
-# Demonstrate automatic wrapping of objects implementing the buffer
-# interface, and the use of data objects with the 'with' statement.
-with io.BytesIO(preallocate) as signed, pyme.Data() as sink:
- sign_and_verify(b"Hallo Leute\n", signed, sink)
+ # XXX: Python's io.BytesIo.truncate does not work as advertised.
+ # http://bugs.python.org/issue27261
+ bio = io.BytesIO()
+ bio.truncate(1)
+ if len(bio.getvalue()) != 1:
+ # This version of Python is affected, preallocate buffer.
+ preallocate = 128*b'\x00'
+ else:
+ preallocate = b''
+
+ # Demonstrate automatic wrapping of objects implementing the buffer
+ # interface, and the use of data objects with the 'with' statement.
+ with io.BytesIO(preallocate) as signed, pyme.Data() as sink:
+ sign_and_verify(b"Hallo Leute\n", signed, sink)
diff --git a/lang/python/tests/t-verify.py b/lang/python/tests/t-verify.py
index b88bd07c..ed5a91a2 100755
--- a/lang/python/tests/t-verify.py
+++ b/lang/python/tests/t-verify.py
@@ -17,6 +17,7 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+import sys
import os
import pyme
from pyme import core, constants, errors
@@ -67,8 +68,11 @@ def check_result(result, summary, validity, fpr, status, notation):
if notation:
expected_notations = {
- "bar": b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f".decode() +
- " das waren Umlaute und jetzt ein prozent%-Zeichen",
+ "bar": (b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f" +
+ b" das waren Umlaute und jetzt ein prozent%-Zeichen"
+ if sys.version_info[0] < 3 else
+ b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f".decode() +
+ " das waren Umlaute und jetzt ein prozent%-Zeichen"),
"foobar.1": "this is a notation data with 2 lines",
None: "http://www.gu.org/policy/",
}