python: Adapt to 'gpgme_op_interact'.
* lang/python/examples/inter-edit.py: Update example. * lang/python/gpgme.i (gpgme_edit_cb_t): Turn into 'gpgme_interact_cb_t'. * lang/python/helpers.c (_pyme_edit_cb): Turn into '_pyme_interact_cb_t'. * lang/python/private.h (_pyme_edit_cb): Likewise. * lang/python/pyme/constants/__init__.py: Replace numeric status codes with the keywords. * lang/python/pyme/constants/status.py: Likewise. * lang/python/pyme/core.py (Context.interact): New method. (Context.op_edit): Deprecate, update docstring, implement using Context.interact. * lang/python/tests/t-edit.py: Test both interfaces. Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
parent
5259f9de46
commit
a458e7fe20
@ -23,13 +23,6 @@ del absolute_import, print_function, unicode_literals
|
||||
|
||||
import sys
|
||||
import pyme
|
||||
import pyme.constants.status
|
||||
|
||||
# Get names for the status codes
|
||||
status2str = {}
|
||||
for name in dir(pyme.constants.status):
|
||||
if not name.startswith('__') and name != "util":
|
||||
status2str[getattr(pyme.constants.status, name)] = name
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit("Usage: %s <Gpg key pattern>\n" % sys.argv[0])
|
||||
@ -46,11 +39,11 @@ with pyme.Context() as c:
|
||||
key = keys[0]
|
||||
print("Editing key {} ({}):".format(key.uids[0].uid, key.subkeys[0].fpr))
|
||||
|
||||
def edit_fnc(status, args):
|
||||
def edit_fnc(keyword, args):
|
||||
print("Status: {} ({}), args: {} > ".format(
|
||||
status2str[status], status, args), end='', flush=True)
|
||||
keyword, status, args), end='', flush=True)
|
||||
|
||||
if not 'GET' in status2str[status]:
|
||||
if not 'GET' in keyword:
|
||||
# no prompt
|
||||
print()
|
||||
return None
|
||||
@ -60,4 +53,4 @@ with pyme.Context() as c:
|
||||
except EOFError:
|
||||
return "quit"
|
||||
|
||||
c.op_edit(key, edit_fnc, None, sys.stdout)
|
||||
c.interact(key, edit_fnc, sink=sys.stdout)
|
||||
|
@ -476,15 +476,15 @@
|
||||
|
||||
|
||||
|
||||
// Include mapper for edit callbacks
|
||||
%typemap(in) (gpgme_edit_cb_t fnc, void *fnc_value) {
|
||||
/* Include mapper for interact callbacks. */
|
||||
%typemap(in) (gpgme_interact_cb_t fnc, void *fnc_value) {
|
||||
if (! PyTuple_Check($input))
|
||||
return PyErr_Format(PyExc_TypeError, "edit callback must be a tuple");
|
||||
return PyErr_Format(PyExc_TypeError, "interact callback must be a tuple");
|
||||
if (PyTuple_Size($input) != 2 && PyTuple_Size($input) != 3)
|
||||
return PyErr_Format(PyExc_TypeError,
|
||||
"edit callback must be a tuple of size 2 or 3");
|
||||
"interact callback must be a tuple of size 2 or 3");
|
||||
|
||||
$1 = (gpgme_edit_cb_t) _pyme_edit_cb;
|
||||
$1 = (gpgme_interact_cb_t) _pyme_interact_cb;
|
||||
$2 = $input;
|
||||
}
|
||||
|
||||
|
@ -656,11 +656,16 @@ pyme_set_status_cb(PyObject *self, PyObject *cb) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
/* Edit callbacks. */
|
||||
gpgme_error_t _pyme_edit_cb(void *opaque, gpgme_status_code_t status,
|
||||
const char *args, int fd) {
|
||||
|
||||
/* Interact callbacks. */
|
||||
gpgme_error_t
|
||||
_pyme_interact_cb(void *opaque, const char *keyword,
|
||||
const char *args, int fd)
|
||||
{
|
||||
PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
|
||||
PyObject *py_keyword;
|
||||
PyObject *pyopaque = (PyObject *) opaque;
|
||||
gpgme_error_t err_status = 0;
|
||||
PyObject *self = NULL;
|
||||
@ -678,7 +683,15 @@ gpgme_error_t _pyme_edit_cb(void *opaque, gpgme_status_code_t status,
|
||||
pyargs = PyTuple_New(2);
|
||||
}
|
||||
|
||||
PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) status));
|
||||
if (keyword)
|
||||
py_keyword = PyUnicode_FromString(keyword);
|
||||
else
|
||||
{
|
||||
Py_INCREF(Py_None);
|
||||
py_keyword = Py_None;
|
||||
}
|
||||
|
||||
PyTuple_SetItem(pyargs, 0, py_keyword);
|
||||
PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
|
||||
if (dataarg) {
|
||||
Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
|
||||
@ -726,7 +739,9 @@ gpgme_error_t _pyme_edit_cb(void *opaque, gpgme_status_code_t status,
|
||||
Py_XDECREF(retval);
|
||||
return err_status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Data callbacks. */
|
||||
|
||||
/* Read up to SIZE bytes into buffer BUFFER from the data object with
|
||||
|
@ -34,9 +34,8 @@ PyObject *_pyme_obj2gpgme_data_t(PyObject *input, int argnum,
|
||||
|
||||
PyObject *_pyme_wrap_result(PyObject *fragile, const char *classname);
|
||||
|
||||
gpgme_error_t _pyme_edit_cb(void *opaque, gpgme_status_code_t status,
|
||||
const char *args, int fd);
|
||||
|
||||
gpgme_error_t _pyme_interact_cb(void *opaque, const char *keyword,
|
||||
const char *args, int fd);
|
||||
gpgme_error_t _pyme_assuan_data_cb (void *hook,
|
||||
const void *data, size_t datalen);
|
||||
gpgme_error_t _pyme_assuan_inquire_cb (void *hook,
|
||||
|
@ -7,3 +7,108 @@ util.process_constants('GPGME_', globals())
|
||||
|
||||
__all__ = ['data', 'event', 'import', 'keylist', 'md', 'pk',
|
||||
'protocol', 'sig', 'sigsum', 'status', 'validity']
|
||||
|
||||
# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We
|
||||
# implement pyme.Context.op_edit using gpgme_op_interact, so the
|
||||
# callbacks will be called with string keywords instead of numeric
|
||||
# status messages. Code that is using these constants will continue
|
||||
# to work.
|
||||
|
||||
STATUS_ABORT = "ABORT"
|
||||
STATUS_ALREADY_SIGNED = "ALREADY_SIGNED"
|
||||
STATUS_ATTRIBUTE = "ATTRIBUTE"
|
||||
STATUS_BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED"
|
||||
STATUS_BAD_PASSPHRASE = "BAD_PASSPHRASE"
|
||||
STATUS_BADARMOR = "BADARMOR"
|
||||
STATUS_BADMDC = "BADMDC"
|
||||
STATUS_BADSIG = "BADSIG"
|
||||
STATUS_BEGIN_DECRYPTION = "BEGIN_DECRYPTION"
|
||||
STATUS_BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION"
|
||||
STATUS_BEGIN_SIGNING = "BEGIN_SIGNING"
|
||||
STATUS_BEGIN_STREAM = "BEGIN_STREAM"
|
||||
STATUS_CARDCTRL = "CARDCTRL"
|
||||
STATUS_DECRYPTION_FAILED = "DECRYPTION_FAILED"
|
||||
STATUS_DECRYPTION_INFO = "DECRYPTION_INFO"
|
||||
STATUS_DECRYPTION_OKAY = "DECRYPTION_OKAY"
|
||||
STATUS_DELETE_PROBLEM = "DELETE_PROBLEM"
|
||||
STATUS_ENC_TO = "ENC_TO"
|
||||
STATUS_END_DECRYPTION = "END_DECRYPTION"
|
||||
STATUS_END_ENCRYPTION = "END_ENCRYPTION"
|
||||
STATUS_END_STREAM = "END_STREAM"
|
||||
STATUS_ENTER = "ENTER"
|
||||
STATUS_ERRMDC = "ERRMDC"
|
||||
STATUS_ERROR = "ERROR"
|
||||
STATUS_ERRSIG = "ERRSIG"
|
||||
STATUS_EXPKEYSIG = "EXPKEYSIG"
|
||||
STATUS_EXPSIG = "EXPSIG"
|
||||
STATUS_FAILURE = "FAILURE"
|
||||
STATUS_FILE_DONE = "FILE_DONE"
|
||||
STATUS_FILE_ERROR = "FILE_ERROR"
|
||||
STATUS_FILE_START = "FILE_START"
|
||||
STATUS_GET_BOOL = "GET_BOOL"
|
||||
STATUS_GET_HIDDEN = "GET_HIDDEN"
|
||||
STATUS_GET_LINE = "GET_LINE"
|
||||
STATUS_GOOD_PASSPHRASE = "GOOD_PASSPHRASE"
|
||||
STATUS_GOODMDC = "GOODMDC"
|
||||
STATUS_GOODSIG = "GOODSIG"
|
||||
STATUS_GOT_IT = "GOT_IT"
|
||||
STATUS_IMPORT_OK = "IMPORT_OK"
|
||||
STATUS_IMPORT_PROBLEM = "IMPORT_PROBLEM"
|
||||
STATUS_IMPORT_RES = "IMPORT_RES"
|
||||
STATUS_IMPORTED = "IMPORTED"
|
||||
STATUS_INQUIRE_MAXLEN = "INQUIRE_MAXLEN"
|
||||
STATUS_INV_RECP = "INV_RECP"
|
||||
STATUS_INV_SGNR = "INV_SGNR"
|
||||
STATUS_KEY_CONSIDERED = "KEY_CONSIDERED"
|
||||
STATUS_KEY_CREATED = "KEY_CREATED"
|
||||
STATUS_KEY_NOT_CREATED = "KEY_NOT_CREATED"
|
||||
STATUS_KEYEXPIRED = "KEYEXPIRED"
|
||||
STATUS_KEYREVOKED = "KEYREVOKED"
|
||||
STATUS_LEAVE = "LEAVE"
|
||||
STATUS_MISSING_PASSPHRASE = "MISSING_PASSPHRASE"
|
||||
STATUS_MOUNTPOINT = "MOUNTPOINT"
|
||||
STATUS_NEED_PASSPHRASE = "NEED_PASSPHRASE"
|
||||
STATUS_NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN"
|
||||
STATUS_NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM"
|
||||
STATUS_NEWSIG = "NEWSIG"
|
||||
STATUS_NO_PUBKEY = "NO_PUBKEY"
|
||||
STATUS_NO_RECP = "NO_RECP"
|
||||
STATUS_NO_SECKEY = "NO_SECKEY"
|
||||
STATUS_NO_SGNR = "NO_SGNR"
|
||||
STATUS_NODATA = "NODATA"
|
||||
STATUS_NOTATION_DATA = "NOTATION_DATA"
|
||||
STATUS_NOTATION_FLAGS = "NOTATION_FLAGS"
|
||||
STATUS_NOTATION_NAME = "NOTATION_NAME"
|
||||
STATUS_PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED"
|
||||
STATUS_PKA_TRUST_BAD = "PKA_TRUST_BAD"
|
||||
STATUS_PKA_TRUST_GOOD = "PKA_TRUST_GOOD"
|
||||
STATUS_PLAINTEXT = "PLAINTEXT"
|
||||
STATUS_PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH"
|
||||
STATUS_POLICY_URL = "POLICY_URL"
|
||||
STATUS_PROGRESS = "PROGRESS"
|
||||
STATUS_REVKEYSIG = "REVKEYSIG"
|
||||
STATUS_RSA_OR_IDEA = "RSA_OR_IDEA"
|
||||
STATUS_SC_OP_FAILURE = "SC_OP_FAILURE"
|
||||
STATUS_SC_OP_SUCCESS = "SC_OP_SUCCESS"
|
||||
STATUS_SESSION_KEY = "SESSION_KEY"
|
||||
STATUS_SHM_GET = "SHM_GET"
|
||||
STATUS_SHM_GET_BOOL = "SHM_GET_BOOL"
|
||||
STATUS_SHM_GET_HIDDEN = "SHM_GET_HIDDEN"
|
||||
STATUS_SHM_INFO = "SHM_INFO"
|
||||
STATUS_SIG_CREATED = "SIG_CREATED"
|
||||
STATUS_SIG_ID = "SIG_ID"
|
||||
STATUS_SIG_SUBPACKET = "SIG_SUBPACKET"
|
||||
STATUS_SIGEXPIRED = "SIGEXPIRED"
|
||||
STATUS_SUCCESS = "SUCCESS"
|
||||
STATUS_TOFU_STATS = "TOFU_STATS"
|
||||
STATUS_TOFU_STATS_LONG = "TOFU_STATS_LONG"
|
||||
STATUS_TOFU_USER = "TOFU_USER"
|
||||
STATUS_TRUNCATED = "TRUNCATED"
|
||||
STATUS_TRUST_FULLY = "TRUST_FULLY"
|
||||
STATUS_TRUST_MARGINAL = "TRUST_MARGINAL"
|
||||
STATUS_TRUST_NEVER = "TRUST_NEVER"
|
||||
STATUS_TRUST_ULTIMATE = "TRUST_ULTIMATE"
|
||||
STATUS_TRUST_UNDEFINED = "TRUST_UNDEFINED"
|
||||
STATUS_UNEXPECTED = "UNEXPECTED"
|
||||
STATUS_USERID_HINT = "USERID_HINT"
|
||||
STATUS_VALIDSIG = "VALIDSIG"
|
||||
|
@ -18,5 +18,107 @@
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
del absolute_import, print_function, unicode_literals
|
||||
|
||||
from pyme import util
|
||||
util.process_constants('GPGME_STATUS_', globals())
|
||||
# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We
|
||||
# implement pyme.Context.op_edit using gpgme_op_interact, so the
|
||||
# callbacks will be called with string keywords instead of numeric
|
||||
# status messages. Code that is using these constants will continue
|
||||
# to work.
|
||||
|
||||
ABORT = "ABORT"
|
||||
ALREADY_SIGNED = "ALREADY_SIGNED"
|
||||
ATTRIBUTE = "ATTRIBUTE"
|
||||
BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED"
|
||||
BAD_PASSPHRASE = "BAD_PASSPHRASE"
|
||||
BADARMOR = "BADARMOR"
|
||||
BADMDC = "BADMDC"
|
||||
BADSIG = "BADSIG"
|
||||
BEGIN_DECRYPTION = "BEGIN_DECRYPTION"
|
||||
BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION"
|
||||
BEGIN_SIGNING = "BEGIN_SIGNING"
|
||||
BEGIN_STREAM = "BEGIN_STREAM"
|
||||
CARDCTRL = "CARDCTRL"
|
||||
DECRYPTION_FAILED = "DECRYPTION_FAILED"
|
||||
DECRYPTION_INFO = "DECRYPTION_INFO"
|
||||
DECRYPTION_OKAY = "DECRYPTION_OKAY"
|
||||
DELETE_PROBLEM = "DELETE_PROBLEM"
|
||||
ENC_TO = "ENC_TO"
|
||||
END_DECRYPTION = "END_DECRYPTION"
|
||||
END_ENCRYPTION = "END_ENCRYPTION"
|
||||
END_STREAM = "END_STREAM"
|
||||
ENTER = "ENTER"
|
||||
ERRMDC = "ERRMDC"
|
||||
ERROR = "ERROR"
|
||||
ERRSIG = "ERRSIG"
|
||||
EXPKEYSIG = "EXPKEYSIG"
|
||||
EXPSIG = "EXPSIG"
|
||||
FAILURE = "FAILURE"
|
||||
FILE_DONE = "FILE_DONE"
|
||||
FILE_ERROR = "FILE_ERROR"
|
||||
FILE_START = "FILE_START"
|
||||
GET_BOOL = "GET_BOOL"
|
||||
GET_HIDDEN = "GET_HIDDEN"
|
||||
GET_LINE = "GET_LINE"
|
||||
GOOD_PASSPHRASE = "GOOD_PASSPHRASE"
|
||||
GOODMDC = "GOODMDC"
|
||||
GOODSIG = "GOODSIG"
|
||||
GOT_IT = "GOT_IT"
|
||||
IMPORT_OK = "IMPORT_OK"
|
||||
IMPORT_PROBLEM = "IMPORT_PROBLEM"
|
||||
IMPORT_RES = "IMPORT_RES"
|
||||
IMPORTED = "IMPORTED"
|
||||
INQUIRE_MAXLEN = "INQUIRE_MAXLEN"
|
||||
INV_RECP = "INV_RECP"
|
||||
INV_SGNR = "INV_SGNR"
|
||||
KEY_CONSIDERED = "KEY_CONSIDERED"
|
||||
KEY_CREATED = "KEY_CREATED"
|
||||
KEY_NOT_CREATED = "KEY_NOT_CREATED"
|
||||
KEYEXPIRED = "KEYEXPIRED"
|
||||
KEYREVOKED = "KEYREVOKED"
|
||||
LEAVE = "LEAVE"
|
||||
MISSING_PASSPHRASE = "MISSING_PASSPHRASE"
|
||||
MOUNTPOINT = "MOUNTPOINT"
|
||||
NEED_PASSPHRASE = "NEED_PASSPHRASE"
|
||||
NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN"
|
||||
NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM"
|
||||
NEWSIG = "NEWSIG"
|
||||
NO_PUBKEY = "NO_PUBKEY"
|
||||
NO_RECP = "NO_RECP"
|
||||
NO_SECKEY = "NO_SECKEY"
|
||||
NO_SGNR = "NO_SGNR"
|
||||
NODATA = "NODATA"
|
||||
NOTATION_DATA = "NOTATION_DATA"
|
||||
NOTATION_FLAGS = "NOTATION_FLAGS"
|
||||
NOTATION_NAME = "NOTATION_NAME"
|
||||
PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED"
|
||||
PKA_TRUST_BAD = "PKA_TRUST_BAD"
|
||||
PKA_TRUST_GOOD = "PKA_TRUST_GOOD"
|
||||
PLAINTEXT = "PLAINTEXT"
|
||||
PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH"
|
||||
POLICY_URL = "POLICY_URL"
|
||||
PROGRESS = "PROGRESS"
|
||||
REVKEYSIG = "REVKEYSIG"
|
||||
RSA_OR_IDEA = "RSA_OR_IDEA"
|
||||
SC_OP_FAILURE = "SC_OP_FAILURE"
|
||||
SC_OP_SUCCESS = "SC_OP_SUCCESS"
|
||||
SESSION_KEY = "SESSION_KEY"
|
||||
SHM_GET = "SHM_GET"
|
||||
SHM_GET_BOOL = "SHM_GET_BOOL"
|
||||
SHM_GET_HIDDEN = "SHM_GET_HIDDEN"
|
||||
SHM_INFO = "SHM_INFO"
|
||||
SIG_CREATED = "SIG_CREATED"
|
||||
SIG_ID = "SIG_ID"
|
||||
SIG_SUBPACKET = "SIG_SUBPACKET"
|
||||
SIGEXPIRED = "SIGEXPIRED"
|
||||
SUCCESS = "SUCCESS"
|
||||
TOFU_STATS = "TOFU_STATS"
|
||||
TOFU_STATS_LONG = "TOFU_STATS_LONG"
|
||||
TOFU_USER = "TOFU_USER"
|
||||
TRUNCATED = "TRUNCATED"
|
||||
TRUST_FULLY = "TRUST_FULLY"
|
||||
TRUST_MARGINAL = "TRUST_MARGINAL"
|
||||
TRUST_NEVER = "TRUST_NEVER"
|
||||
TRUST_ULTIMATE = "TRUST_ULTIMATE"
|
||||
TRUST_UNDEFINED = "TRUST_UNDEFINED"
|
||||
UNEXPECTED = "UNEXPECTED"
|
||||
USERID_HINT = "USERID_HINT"
|
||||
VALIDSIG = "VALIDSIG"
|
||||
|
@ -29,6 +29,7 @@ del absolute_import, print_function, unicode_literals
|
||||
|
||||
import re
|
||||
import os
|
||||
import warnings
|
||||
import weakref
|
||||
from . import gpgme
|
||||
from .errors import errorcheck, GPGMEError
|
||||
@ -536,6 +537,39 @@ class Context(GpgmeWrapper):
|
||||
|
||||
return GPGMEError(status) if status != 0 else None
|
||||
|
||||
def interact(self, key, func, sink=None, flags=0, fnc_value=None):
|
||||
"""Interact with the engine
|
||||
|
||||
This method can be used to edit keys and cards interactively.
|
||||
KEY is the key to edit, FUNC is called repeatedly with two
|
||||
unicode arguments, 'keyword' and 'args'. See the GPGME manual
|
||||
for details.
|
||||
|
||||
Keyword arguments:
|
||||
sink -- if given, additional output is written here
|
||||
flags -- use constants.INTERACT_CARD to edit a card
|
||||
|
||||
Raises:
|
||||
GPGMEError -- as signaled by the underlying library
|
||||
|
||||
"""
|
||||
if key == None:
|
||||
raise ValueError("First argument cannot be None")
|
||||
|
||||
if sink == None:
|
||||
sink = Data()
|
||||
|
||||
if fnc_value:
|
||||
opaquedata = (weakref.ref(self), func, fnc_value)
|
||||
else:
|
||||
opaquedata = (weakref.ref(self), func)
|
||||
|
||||
result = gpgme.gpgme_op_interact(self.wrapped, key, flags,
|
||||
opaquedata, sink)
|
||||
if self._callback_excinfo:
|
||||
gpgme.pyme_raise_callback_exception(self)
|
||||
errorcheck(result)
|
||||
|
||||
@property
|
||||
def signers(self):
|
||||
"""Keys used for signing"""
|
||||
@ -793,18 +827,21 @@ class Context(GpgmeWrapper):
|
||||
errorcheck(status)
|
||||
|
||||
def op_edit(self, key, func, fnc_value, out):
|
||||
"""Start key editing using supplied callback function"""
|
||||
if key == None:
|
||||
raise ValueError("op_edit: First argument cannot be None")
|
||||
if fnc_value:
|
||||
opaquedata = (weakref.ref(self), func, fnc_value)
|
||||
else:
|
||||
opaquedata = (weakref.ref(self), func)
|
||||
"""Start key editing using supplied callback function
|
||||
|
||||
Note: This interface is deprecated and will be removed with
|
||||
GPGME 1.8. Please use .interact instead. Furthermore, we
|
||||
implement this using gpgme_op_interact, so callbacks will get
|
||||
called with string keywords instead of numeric status
|
||||
messages. Code that is using constants.STATUS_X or
|
||||
constants.status.X will continue to work, whereas code using
|
||||
magic numbers will break as a result.
|
||||
|
||||
"""
|
||||
warnings.warn("Call to deprecated method op_edit.",
|
||||
category=DeprecationWarning)
|
||||
return self.interact(key, func, sink=out, fnc_value=fnc_value)
|
||||
|
||||
result = gpgme.gpgme_op_edit(self.wrapped, key, opaquedata, out)
|
||||
if self._callback_excinfo:
|
||||
gpgme.pyme_raise_callback_exception(self)
|
||||
errorcheck(result)
|
||||
|
||||
class Data(GpgmeWrapper):
|
||||
"""Data buffer
|
||||
|
@ -33,7 +33,7 @@ class KeyEditor(object):
|
||||
self.done = False
|
||||
self.verbose = int(os.environ.get('verbose', 0)) > 1
|
||||
|
||||
def edit_fnc(self, status, args, out):
|
||||
def edit_fnc(self, status, args, out=None):
|
||||
if args == "keyedit.prompt":
|
||||
result = self.steps[self.step]
|
||||
self.step += 1
|
||||
@ -57,8 +57,15 @@ c = core.Context()
|
||||
c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK)
|
||||
c.set_passphrase_cb(lambda *args: "abc")
|
||||
c.set_armor(True)
|
||||
sink = core.Data()
|
||||
|
||||
# The deprecated interface.
|
||||
editor = KeyEditor()
|
||||
c.interact(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False),
|
||||
editor.edit_fnc)
|
||||
assert editor.done
|
||||
|
||||
# The deprecated interface.
|
||||
sink = core.Data()
|
||||
editor = KeyEditor()
|
||||
c.op_edit(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False),
|
||||
editor.edit_fnc, sink, sink)
|
||||
|
Loading…
Reference in New Issue
Block a user