Hi,

please find attached the patch for the NMU I've just uploaded to fix the FTBFS.

The patch is rather large, and I think the best course of action would probably be to remove this package after the release of stretch. The applications which are currently using it are presumably better off using the python-gpg and python3-gpg bindings supplied by upstream:

https://tracker.debian.org/pkg/gpgme1.0

Regards,
Tobias
diff --git a/debian/changelog b/debian/changelog
index ac35e0a..0cb84da 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,21 @@
+pygpgme (0.3-1.2) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Fix FTBFS with newer gpgme library.
+    Remove deprecated functions context.edit and context.card_edit.
+    Both functions have been deprecated upstream and are not working
+    anymore. In order to not ship broken Python bindings for those
+    two functions, they are removed from the source altogether.
+    If an application uses them, it now will get an error about
+    the missing function instead of a function call with
+    undefined behaviour.
+    The best fix for those applications would be to switch over
+    to pyme, the now official Python bindings from GPGME upstream.
+    (Closes: #835174)
+  * Clean up patch from Daniel which fixed the previous FTBFS
+
+ -- Dr. Tobias Quathamer <to...@debian.org>  Thu, 24 Nov 2016 14:49:42 +0100
+
 pygpgme (0.3-1.1) unstable; urgency=medium
 
   * Non-maintainer upload
diff --git a/debian/patches/0001-reflect-2.1-reporting-for-key-imports.patch b/debian/patches/0001-reflect-2.1-reporting-for-key-imports.patch
index b453710..46a7f9a 100644
--- a/debian/patches/0001-reflect-2.1-reporting-for-key-imports.patch
+++ b/debian/patches/0001-reflect-2.1-reporting-for-key-imports.patch
@@ -1,7 +1,6 @@
-From 1c1812def711803382cc28caea1f35fb7ef774b0 Mon Sep 17 00:00:00 2001
 From: Daniel Kahn Gillmor <d...@fifthhorseman.net>
 Date: Tue, 26 Jan 2016 14:24:26 -0500
-Subject: [PATCH 1/5] reflect 2.1 reporting for key imports
+Subject: reflect 2.1 reporting for key imports
 
 GnuPG 2.1 changes how it reports key imports.  These changes should
 make the pygpgme test suite compatible with GnuPG 2.1.
@@ -9,33 +8,14 @@ make the pygpgme test suite compatible with GnuPG 2.1.
 See also:
 https://lists.gnupg.org/pipermail/gnupg-devel/2016-January/030718.html
 ---
- tests/test_import.py | 22 +++++++++++-----------
- 1 file changed, 11 insertions(+), 11 deletions(-)
+ tests/test_import.py | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
 
 diff --git a/tests/test_import.py b/tests/test_import.py
-index 10eb816..597eb47 100644
+index 10eb816..7c47019 100644
 --- a/tests/test_import.py
 +++ b/tests/test_import.py
-@@ -55,7 +55,7 @@ class ImportTestCase(GpgHomeTestCase):
-         ctx = gpgme.Context()
-         with self.keyfile('key1.sec') as fp:
-             result = ctx.import_(fp)
--        self.assertEqual(result.considered, 1)
-+        self.assertEqual(result.considered, 3)
-         self.assertEqual(result.no_user_id, 0)
-         self.assertEqual(result.imported, 1)
-         self.assertEqual(result.imported_rsa, 0)
-@@ -64,18 +64,18 @@ class ImportTestCase(GpgHomeTestCase):
-         self.assertEqual(result.new_sub_keys, 0)
-         self.assertEqual(result.new_signatures, 0)
-         self.assertEqual(result.new_revocations, 0)
--        self.assertEqual(result.secret_read, 1)
--        self.assertEqual(result.secret_imported, 1)
-+        self.assertEqual(result.secret_read, 3)
-+        self.assertEqual(result.secret_imported, 2)
-         self.assertEqual(result.secret_unchanged, 0)
-         self.assertEqual(result.skipped_new_keys, 0)
-         self.assertEqual(result.not_imported, 0)
+@@ -72,10 +72,10 @@ class ImportTestCase(GpgHomeTestCase):
          self.assertEqual(len(result.imports), 2)
          self.assertEqual(result.imports[0],
                           ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
@@ -48,12 +28,8 @@ index 10eb816..597eb47 100644
          # can we get the public key?
          key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
          # can we get the secret key?
-@@ -102,17 +102,17 @@ class ImportTestCase(GpgHomeTestCase):
-         fp = BytesIO(b'\n'.join(keys))
-         ctx = gpgme.Context()
-         result = ctx.import_(fp)
--        self.assertEqual(result.considered, 3)
-+        self.assertEqual(result.considered, 5)
+@@ -105,7 +105,7 @@ class ImportTestCase(GpgHomeTestCase):
+         self.assertEqual(result.considered, 3)
          self.assertEqual(result.no_user_id, 0)
          self.assertEqual(result.imported, 2)
 -        self.assertEqual(result.imported_rsa, 1)
@@ -61,15 +37,6 @@ index 10eb816..597eb47 100644
          self.assertEqual(result.unchanged, 0)
          self.assertEqual(result.new_user_ids, 0)
          self.assertEqual(result.new_sub_keys, 0)
-         self.assertEqual(result.new_signatures, 1)
-         self.assertEqual(result.new_revocations, 0)
--        self.assertEqual(result.secret_read, 1)
--        self.assertEqual(result.secret_imported, 1)
-+        self.assertEqual(result.secret_read, 3)
-+        self.assertEqual(result.secret_imported, 2)
-         self.assertEqual(result.secret_unchanged, 0)
-         self.assertEqual(result.skipped_new_keys, 0)
-         self.assertEqual(result.not_imported, 0)
 @@ -122,10 +122,10 @@ class ImportTestCase(GpgHomeTestCase):
                            None, gpgme.IMPORT_NEW))
          self.assertEqual(result.imports[1],
@@ -83,6 +50,3 @@ index 10eb816..597eb47 100644
          self.assertEqual(result.imports[3],
                           ('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F',
                            None, gpgme.IMPORT_NEW))
--- 
-2.7.0
-
diff --git a/debian/patches/0002-passphrase_cb-is-deprecated.patch b/debian/patches/0002-passphrase_cb-is-deprecated.patch
index fa6f8c5..eb24e8e 100644
--- a/debian/patches/0002-passphrase_cb-is-deprecated.patch
+++ b/debian/patches/0002-passphrase_cb-is-deprecated.patch
@@ -1,7 +1,6 @@
-From dc75482af095d667a4a92655c4e7eb312e80c42d Mon Sep 17 00:00:00 2001
 From: Daniel Kahn Gillmor <d...@fifthhorseman.net>
 Date: Mon, 1 Feb 2016 19:25:12 -0500
-Subject: [PATCH 2/5] passphrase_cb is deprecated
+Subject: passphrase_cb is deprecated
 
 https://bugs.gnupg.org/gnupg/issue767 indicates that
 gpgme_set_passphrase_cb is a deprecated corner of the API and that
@@ -45,6 +44,3 @@ index cd803c2..86892ca 100644
          # import requested keys into the keyring
          ctx = gpgme.Context()
          for key in self.import_keys:
--- 
-2.7.0
-
diff --git a/debian/patches/0003-handle-generic-error-when-no-passphrase-callback-pre.patch b/debian/patches/0003-handle-generic-error-when-no-passphrase-callback-pre.patch
index 2515793..9f31d5a 100644
--- a/debian/patches/0003-handle-generic-error-when-no-passphrase-callback-pre.patch
+++ b/debian/patches/0003-handle-generic-error-when-no-passphrase-callback-pre.patch
@@ -1,7 +1,6 @@
-From 024fe219582143017b2f02bc924c0ed107b63619 Mon Sep 17 00:00:00 2001
 From: Daniel Kahn Gillmor <d...@fifthhorseman.net>
 Date: Mon, 1 Feb 2016 19:27:59 -0500
-Subject: [PATCH 3/5] handle generic error when no passphrase callback present
+Subject: handle generic error when no passphrase callback present
 
 apparently gpg 2.1 returns ERR_GENERAL right now if the pinentry was
 in loopback mode and no passphrase callback was supplied.  Earlier
@@ -23,6 +22,3 @@ index 0a235e9..35b3c59 100644
          else:
              self.fail('gpgme.GpgmeError not raised')
  
--- 
-2.7.0
-
diff --git a/debian/patches/0004-Add-missing-pinentry_mode-methods.patch b/debian/patches/0004-Add-missing-pinentry_mode-methods.patch
new file mode 100644
index 0000000..bcc6b87
--- /dev/null
+++ b/debian/patches/0004-Add-missing-pinentry_mode-methods.patch
@@ -0,0 +1,73 @@
+From: "Dr. Tobias Quathamer" <to...@debian.org>
+Date: Thu, 24 Nov 2016 11:36:13 +0100
+Subject: Add missing pinentry_mode methods.
+
+Since GPGME 2.1, the loopback pinentry needs to be set in the
+context. pygpgme was missing those methods.
+---
+ src/pygpgme-constants.c |  7 +++++++
+ src/pygpgme-context.c   | 26 ++++++++++++++++++++++++++
+ 2 files changed, 33 insertions(+)
+
+diff --git a/src/pygpgme-constants.c b/src/pygpgme-constants.c
+index c8a2e9c..283f8fd 100644
+--- a/src/pygpgme-constants.c
++++ b/src/pygpgme-constants.c
+@@ -178,6 +178,13 @@ static const struct pygpgme_constant constants[] = {
+   CONST(IMPORT_SUBKEY),
+   CONST(IMPORT_SECRET),
+ 
++  /* gpgme_pinentry_mode_t */
++  CONST(PINENTRY_MODE_DEFAULT),
++  CONST(PINENTRY_MODE_ASK),
++  CONST(PINENTRY_MODE_CANCEL),
++  CONST(PINENTRY_MODE_ERROR),
++  CONST(PINENTRY_MODE_LOOPBACK),
++
+   /* gpg-error.h constants */
+ #undef CONST
+ #define CONST(name) { #name, GPG_##name }
+diff --git a/src/pygpgme-context.c b/src/pygpgme-context.c
+index 300c122..445164c 100644
+--- a/src/pygpgme-context.c
++++ b/src/pygpgme-context.c
+@@ -149,6 +149,30 @@ pygpgme_context_set_armor(PyGpgmeContext *self, PyObject *value)
+ }
+ 
+ static PyObject *
++pygpgme_context_get_pinentry_mode(PyGpgmeContext *self)
++{
++    return PyLong_FromLong(gpgme_get_pinentry_mode(self->ctx));
++}
++
++static int
++pygpgme_context_set_pinentry_mode(PyGpgmeContext *self, PyObject *value)
++{
++    int pinentry_mode;
++
++    if (value == NULL) {
++        PyErr_SetString(PyExc_AttributeError, "Can not delete attribute");
++        return -1;
++    }
++
++    pinentry_mode = PyLong_AsLong(value);
++    if (PyErr_Occurred())
++        return -1;
++
++    gpgme_set_pinentry_mode(self->ctx, pinentry_mode);
++    return 0;
++}
++
++static PyObject *
+ pygpgme_context_get_textmode(PyGpgmeContext *self)
+ {
+     return PyBool_FromLong(gpgme_get_textmode(self->ctx));
+@@ -371,6 +395,8 @@ static PyGetSetDef pygpgme_context_getsets[] = {
+       (setter)pygpgme_context_set_protocol },
+     { "armor", (getter)pygpgme_context_get_armor,
+       (setter)pygpgme_context_set_armor },
++    { "pinentry_mode", (getter)pygpgme_context_get_pinentry_mode,
++      (setter)pygpgme_context_set_pinentry_mode },
+     { "textmode", (getter)pygpgme_context_get_textmode,
+       (setter)pygpgme_context_set_textmode },
+     { "include_certs", (getter)pygpgme_context_get_include_certs,
diff --git a/debian/patches/0005-Fix-test-failures-with-pinentry.patch b/debian/patches/0005-Fix-test-failures-with-pinentry.patch
new file mode 100644
index 0000000..e2b0aff
--- /dev/null
+++ b/debian/patches/0005-Fix-test-failures-with-pinentry.patch
@@ -0,0 +1,52 @@
+From: "Dr. Tobias Quathamer" <to...@debian.org>
+Date: Thu, 24 Nov 2016 12:20:54 +0100
+Subject: Fix test failures with pinentry
+
+---
+ tests/test_encrypt_decrypt.py | 5 +++--
+ tests/test_passphrase.py      | 2 ++
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/tests/test_encrypt_decrypt.py b/tests/test_encrypt_decrypt.py
+index 21ae83e..05707e1 100644
+--- a/tests/test_encrypt_decrypt.py
++++ b/tests/test_encrypt_decrypt.py
+@@ -132,6 +132,7 @@ class EncryptDecryptTestCase(GpgHomeTestCase):
+             os.write(fd, b'Symmetric passphrase\n')
+         ctx = gpgme.Context()
+         ctx.armor = True
++        ctx.pinentry_mode = gpgme.PINENTRY_MODE_LOOPBACK
+         ctx.passphrase_cb = passphrase
+         ctx.encrypt(None, 0, plaintext, ciphertext)
+         self.assertTrue(
+@@ -182,8 +183,8 @@ class EncryptDecryptTestCase(GpgHomeTestCase):
+             ctx.encrypt([recipient], gpgme.ENCRYPT_ALWAYS_TRUST,
+                         plaintext, ciphertext)
+         except gpgme.GpgmeError as exc:
+-            self.assertEqual(exc.args[0], gpgme.ERR_SOURCE_UNKNOWN)
+-            self.assertEqual(exc.args[1], gpgme.ERR_GENERAL)
++            self.assertEqual(exc.args[0], gpgme.ERR_SOURCE_GPGME)
++            self.assertEqual(exc.args[1], gpgme.ERR_UNUSABLE_PUBKEY)
+         else:
+             self.fail('gpgme.GpgmeError not raised')
+ 
+diff --git a/tests/test_passphrase.py b/tests/test_passphrase.py
+index 35b3c59..05e6811 100644
+--- a/tests/test_passphrase.py
++++ b/tests/test_passphrase.py
+@@ -34,6 +34,7 @@ class PassphraseTestCase(GpgHomeTestCase):
+         ctx = gpgme.Context()
+         key = ctx.get_key('EFB052B4230BBBC51914BCBB54DCBBC8DBFB9EB3')
+         ctx.signers = [key]
++        ctx.pinentry_mode = gpgme.PINENTRY_MODE_LOOPBACK
+         plaintext = BytesIO(b'Hello World\n')
+         signature = BytesIO()
+ 
+@@ -55,6 +56,7 @@ class PassphraseTestCase(GpgHomeTestCase):
+         ctx = gpgme.Context()
+         key = ctx.get_key('EFB052B4230BBBC51914BCBB54DCBBC8DBFB9EB3')
+         ctx.signers = [key]
++        ctx.pinentry_mode = gpgme.PINENTRY_MODE_LOOPBACK
+         ctx.passphrase_cb = self.passphrase_cb
+         plaintext = BytesIO(b'Hello World\n')
+         signature = BytesIO()
diff --git a/debian/patches/0006-Remove-deprecated-functions-context.edit-and-context.patch b/debian/patches/0006-Remove-deprecated-functions-context.edit-and-context.patch
new file mode 100644
index 0000000..1e312c5
--- /dev/null
+++ b/debian/patches/0006-Remove-deprecated-functions-context.edit-and-context.patch
@@ -0,0 +1,113 @@
+From: "Dr. Tobias Quathamer" <to...@debian.org>
+Date: Thu, 24 Nov 2016 13:50:38 +0100
+Subject: Remove deprecated functions context.edit and context.card_edit.
+
+Both functions have been deprecated upstream and are not working
+anymore. In order to not ship broken Python bindings for those
+two functions, they are removed from the source altogether.
+If an application uses them, it now will get an error about
+the missing function instead of a function call with
+undefined behaviour:
+
+  AttributeError: 'gpgme.Context' object has no attribute 'edit'
+  AttributeError: 'gpgme.Context' object has no attribute 'card_edit'
+
+The best fix for those applications would be to switch over
+to pyme, the now official Python bindings from GPGME upstream.
+
+https://www.gnupg.org/blog/20160921-python-bindings-for-gpgme.html
+---
+ src/pygpgme-context.c | 73 ---------------------------------------------------
+ 1 file changed, 73 deletions(-)
+
+diff --git a/src/pygpgme-context.c b/src/pygpgme-context.c
+index 445164c..4b214d6 100644
+--- a/src/pygpgme-context.c
++++ b/src/pygpgme-context.c
+@@ -1188,77 +1188,6 @@ pygpgme_context_delete(PyGpgmeContext *self, PyObject *args)
+     Py_RETURN_NONE;
+ }
+ 
+-static gpgme_error_t
+-pygpgme_edit_cb(void *user_data, gpgme_status_code_t status,
+-                const char *args, int fd)
+-{
+-    PyObject *callback, *ret;
+-    PyGILState_STATE state;
+-    gpgme_error_t err;
+-
+-    state = PyGILState_Ensure();
+-    callback = (PyObject *)user_data;
+-    ret = PyObject_CallFunction(callback, "lzi", (long)status, args, fd);
+-    err = pygpgme_check_pyerror();
+-    Py_XDECREF(ret);
+-    PyGILState_Release(state);
+-    return err;
+-}
+-
+-static PyObject *
+-pygpgme_context_edit(PyGpgmeContext *self, PyObject *args)
+-{
+-    PyGpgmeKey *key;
+-    PyObject *callback, *py_out;
+-    gpgme_data_t out;
+-    gpgme_error_t err;
+-
+-    if (!PyArg_ParseTuple(args, "O!OO", &PyGpgmeKey_Type, &key, &callback,
+-                          &py_out))
+-        return NULL;
+-
+-    if (pygpgme_data_new(&out, py_out))
+-        return NULL;
+-
+-    Py_BEGIN_ALLOW_THREADS;
+-    err = gpgme_op_edit(self->ctx, key->key,
+-                        pygpgme_edit_cb, (void *)callback, out);
+-    Py_END_ALLOW_THREADS;
+-
+-    gpgme_data_release(out);
+-
+-    if (pygpgme_check_error(err))
+-        return NULL;
+-    Py_RETURN_NONE;
+-}
+-
+-static PyObject *
+-pygpgme_context_card_edit(PyGpgmeContext *self, PyObject *args)
+-{
+-    PyGpgmeKey *key;
+-    PyObject *callback, *py_out;
+-    gpgme_data_t out;
+-    gpgme_error_t err;
+-
+-    if (!PyArg_ParseTuple(args, "O!OO", &PyGpgmeKey_Type, &key, &callback,
+-                          &py_out))
+-        return NULL;
+-
+-    if (pygpgme_data_new(&out, py_out))
+-        return NULL;
+-
+-    Py_BEGIN_ALLOW_THREADS;
+-    err = gpgme_op_card_edit(self->ctx, key->key,
+-                             pygpgme_edit_cb, (void *)callback, out);
+-    Py_END_ALLOW_THREADS;
+-
+-    gpgme_data_release(out);
+-
+-    if (pygpgme_check_error(err))
+-        return NULL;
+-    Py_RETURN_NONE;
+-}
+-
+ static PyObject *
+ pygpgme_context_keylist(PyGpgmeContext *self, PyObject *args)
+ {
+@@ -1310,8 +1239,6 @@ static PyMethodDef pygpgme_context_methods[] = {
+     { "export", (PyCFunction)pygpgme_context_export, METH_VARARGS },
+     { "genkey", (PyCFunction)pygpgme_context_genkey, METH_VARARGS },
+     { "delete", (PyCFunction)pygpgme_context_delete, METH_VARARGS },
+-    { "edit", (PyCFunction)pygpgme_context_edit, METH_VARARGS },
+-    { "card_edit", (PyCFunction)pygpgme_context_card_edit, METH_VARARGS },
+     { "keylist", (PyCFunction)pygpgme_context_keylist, METH_VARARGS },
+     // trustlist
+     { NULL, 0, 0 }
diff --git a/debian/patches/0007-Disable-failing-test-of-deprecated-key-editing-funct.patch b/debian/patches/0007-Disable-failing-test-of-deprecated-key-editing-funct.patch
new file mode 100644
index 0000000..43095f6
--- /dev/null
+++ b/debian/patches/0007-Disable-failing-test-of-deprecated-key-editing-funct.patch
@@ -0,0 +1,30 @@
+From: "Dr. Tobias Quathamer" <to...@debian.org>
+Date: Thu, 24 Nov 2016 14:00:28 +0100
+Subject: Disable failing test of (deprecated) key editing function
+
+---
+ tests/__init__.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tests/__init__.py b/tests/__init__.py
+index 7ee8944..d899af5 100644
+--- a/tests/__init__.py
++++ b/tests/__init__.py
+@@ -28,7 +28,7 @@ def test_suite():
+     import tests.test_encrypt_decrypt
+     import tests.test_passphrase
+     import tests.test_progress
+-    import tests.test_editkey
++    # import tests.test_editkey
+     import tests.test_genkey
+ 
+     suite = unittest.TestSuite()
+@@ -43,7 +43,7 @@ def test_suite():
+     suite.addTest(tests.test_encrypt_decrypt.test_suite())
+     suite.addTest(tests.test_passphrase.test_suite())
+     suite.addTest(tests.test_progress.test_suite())
+-    suite.addTest(tests.test_editkey.test_suite())
++    # suite.addTest(tests.test_editkey.test_suite())
+     suite.addTest(tests.test_genkey.test_suite())
+ 
+     return suite
diff --git a/debian/patches/series b/debian/patches/series
index 60d90ad..afa3761 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,7 @@
 0001-reflect-2.1-reporting-for-key-imports.patch
 0002-passphrase_cb-is-deprecated.patch
 0003-handle-generic-error-when-no-passphrase-callback-pre.patch
+0004-Add-missing-pinentry_mode-methods.patch
+0005-Fix-test-failures-with-pinentry.patch
+0006-Remove-deprecated-functions-context.edit-and-context.patch
+0007-Disable-failing-test-of-deprecated-key-editing-funct.patch

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to