From f4ba16b31ea282d0787a40be3f37b951584143a1 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Tue, 10 May 2016 13:19:26 +0200 Subject: python: Rename bindings. -- Signed-off-by: Justus Winter --- lang/python/pyme/__init__.py | 137 ++++++++ lang/python/pyme/callbacks.py | 47 +++ lang/python/pyme/constants/__init__.py | 7 + lang/python/pyme/constants/data/__init__.py | 4 + lang/python/pyme/constants/data/encoding.py | 20 ++ lang/python/pyme/constants/event.py | 20 ++ lang/python/pyme/constants/import.py | 20 ++ lang/python/pyme/constants/keylist/__init__.py | 4 + lang/python/pyme/constants/keylist/mode.py | 20 ++ lang/python/pyme/constants/md.py | 20 ++ lang/python/pyme/constants/pk.py | 20 ++ lang/python/pyme/constants/protocol.py | 20 ++ lang/python/pyme/constants/sig/__init__.py | 4 + lang/python/pyme/constants/sig/mode.py | 20 ++ lang/python/pyme/constants/sigsum.py | 20 ++ lang/python/pyme/constants/status.py | 20 ++ lang/python/pyme/constants/validity.py | 20 ++ lang/python/pyme/core.py | 463 +++++++++++++++++++++++++ lang/python/pyme/errors.py | 46 +++ lang/python/pyme/util.py | 72 ++++ lang/python/pyme/version.py | 43 +++ 21 files changed, 1047 insertions(+) create mode 100644 lang/python/pyme/__init__.py create mode 100644 lang/python/pyme/callbacks.py create mode 100644 lang/python/pyme/constants/__init__.py create mode 100644 lang/python/pyme/constants/data/__init__.py create mode 100644 lang/python/pyme/constants/data/encoding.py create mode 100644 lang/python/pyme/constants/event.py create mode 100644 lang/python/pyme/constants/import.py create mode 100644 lang/python/pyme/constants/keylist/__init__.py create mode 100644 lang/python/pyme/constants/keylist/mode.py create mode 100644 lang/python/pyme/constants/md.py create mode 100644 lang/python/pyme/constants/pk.py create mode 100644 lang/python/pyme/constants/protocol.py create mode 100644 lang/python/pyme/constants/sig/__init__.py create mode 100644 lang/python/pyme/constants/sig/mode.py create mode 100644 lang/python/pyme/constants/sigsum.py create mode 100644 lang/python/pyme/constants/status.py create mode 100644 lang/python/pyme/constants/validity.py create mode 100644 lang/python/pyme/core.py create mode 100644 lang/python/pyme/errors.py create mode 100644 lang/python/pyme/util.py create mode 100644 lang/python/pyme/version.py (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/__init__.py b/lang/python/pyme/__init__.py new file mode 100644 index 00000000..4934afe7 --- /dev/null +++ b/lang/python/pyme/__init__.py @@ -0,0 +1,137 @@ +# $Id$ +""" +Pyme: GPGME Interface for Python +Copyright (C) 2004 Igor Belyi +Copyright (C) 2002 John Goerzen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Welcome to PyME, the GPGME Interface for Python. "Pyme", when prounced, +rhymes with "Pine". + +The latest release of this package may be obtained from +http://pyme.sourceforge.net +Previous releases of this package can be obtained from +http://quux.org/devel/pyme/ + +FEATURES +-------- + + * Feature-rich, full implementation of the GPGME library. Supports + all GPGME features except interactive editing (coming soon). + Callback functions may be written in pure Python. + + * Ability to sign, encrypt, decrypt, and verify data. + + * Ability to list keys, export and import keys, and manage the keyring. + + * Fully object-oriented with convenient classes and modules. + +GENERAL OVERVIEW +---------------- + +For those of you familiar with GPGME, you will be right at home here. + +Pyme is, for the most part, a direct interface to the C GPGME +library. However, it is re-packaged in a more Pythonic way -- +object-oriented with classes and modules. Take a look at the classes +defined here -- they correspond directly to certain object types in GPGME +for C. For instance, the following C code: + +gpgme_ctx_t context; + +gpgme_new(&context); + +... +gpgme_op_encrypt(context, recp, 1, plain, cipher); + +Translates into the following Python code: + +context = core.Context() +... +context.op_encrypt(recp, 1, plain, cipher) + +The Python module automatically does error-checking and raises Python +exception pyme.errors.GPGMEError when GPGME signals an error. getcode() +and getsource() of this exception return code and source of the error. + +IMPORTANT NOTE +-------------- +This documentation only covers a small subset of available GPGME functions and +methods. Please consult the documentation for the C library +for comprehensive coverage. + +This library uses Python's reflection to automatically detect the methods +that are available for each class, and as such, most of those methods +do not appear explicitly anywhere. You can use dir() python built-in command +on an object to see what methods and fields it has but their meaning can +be found only in GPGME documentation. + +QUICK START SAMPLE PROGRAM +-------------------------- +This program is not for serious encryption, but for example purposes only! + +import sys +from pyme import core, constants + +# Set up our input and output buffers. + +plain = core.Data('This is my message.') +cipher = core.Data() + +# Initialize our context. + +c = core.Context() +c.set_armor(1) + +# Set up the recipients. + +sys.stdout.write("Enter name of your recipient: ") +name = sys.stdin.readline().strip() +c.op_keylist_start(name, 0) +r = c.op_keylist_next() + +# Do the encryption. + +c.op_encrypt([r], 1, plain, cipher) +cipher.seek(0,0) +print cipher.read() + +Note that although there is no explicit error checking done here, the +Python GPGME library is automatically doing error-checking, and will +raise an exception if there is any problem. + +This program is in the Pyme distribution as examples/simple.py. The examples +directory contains more advanced samples as well. + +FOR MORE INFORMATION +-------------------- +PYME homepage: http://pyme.sourceforge.net +GPGME documentation: http://pyme.sourceforge.net/doc/gpgme/index.html +GPGME homepage: http://www.gnupg.org/gpgme.html + +Base classes: pyme.core (START HERE!) +Error classes: pyme.errors +Constants: pyme.constants +Version information: pyme.version +Utilities: pyme.util + +Base classes are documented at pyme.core. +Classes of pyme.util usually are not instantiated by users +directly but return by methods of base classes. + +""" + +__all__ = ['core', 'errors', 'constants', 'util', 'callbacks', 'version'] diff --git a/lang/python/pyme/callbacks.py b/lang/python/pyme/callbacks.py new file mode 100644 index 00000000..e3c810cd --- /dev/null +++ b/lang/python/pyme/callbacks.py @@ -0,0 +1,47 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from getpass import getpass + +def passphrase_stdin(hint, desc, prev_bad, hook=None): + """This is a sample callback that will read a passphrase from + the terminal. The hook here, if present, will be used to describe + why the passphrase is needed.""" + why = '' + if hook != None: + why = ' ' + hook + if prev_bad: + why += ' (again)' + print("Please supply %s' password%s:" % (hint, why)) + return getpass() + +def progress_stdout(what, type, current, total, hook=None): + print("PROGRESS UPDATE: what = %s, type = %d, current = %d, total = %d" %\ + (what, type, current, total)) + +def readcb_fh(count, hook): + """A callback for data. hook should be a Python file-like object.""" + if count: + # Should return '' on EOF + return hook.read(count) + else: + # Wants to rewind. + if not hasattr(hook, 'seek'): + return None + hook.seek(0, 0) + return None diff --git a/lang/python/pyme/constants/__init__.py b/lang/python/pyme/constants/__init__.py new file mode 100644 index 00000000..b557da87 --- /dev/null +++ b/lang/python/pyme/constants/__init__.py @@ -0,0 +1,7 @@ +# $Id$ + +from pyme import util +util.process_constants('GPGME_', globals()) + +__all__ = ['data', 'event', 'import', 'keylist', 'md', 'pk', + 'protocol', 'sig', 'sigsum', 'status', 'validity'] diff --git a/lang/python/pyme/constants/data/__init__.py b/lang/python/pyme/constants/data/__init__.py new file mode 100644 index 00000000..f172e0c7 --- /dev/null +++ b/lang/python/pyme/constants/data/__init__.py @@ -0,0 +1,4 @@ +# $Id$ + +from . import encoding +__all__ = ['encoding'] diff --git a/lang/python/pyme/constants/data/encoding.py b/lang/python/pyme/constants/data/encoding.py new file mode 100644 index 00000000..d1485ad4 --- /dev/null +++ b/lang/python/pyme/constants/data/encoding.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_DATA_ENCODING_', globals()) diff --git a/lang/python/pyme/constants/event.py b/lang/python/pyme/constants/event.py new file mode 100644 index 00000000..1a4fac6e --- /dev/null +++ b/lang/python/pyme/constants/event.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_EVENT_', globals()) diff --git a/lang/python/pyme/constants/import.py b/lang/python/pyme/constants/import.py new file mode 100644 index 00000000..628177d8 --- /dev/null +++ b/lang/python/pyme/constants/import.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_IMPORT_', globals()) diff --git a/lang/python/pyme/constants/keylist/__init__.py b/lang/python/pyme/constants/keylist/__init__.py new file mode 100644 index 00000000..2f2152a5 --- /dev/null +++ b/lang/python/pyme/constants/keylist/__init__.py @@ -0,0 +1,4 @@ +# $Id$ + +from . import mode +__all__ = ['mode'] diff --git a/lang/python/pyme/constants/keylist/mode.py b/lang/python/pyme/constants/keylist/mode.py new file mode 100644 index 00000000..137ce17a --- /dev/null +++ b/lang/python/pyme/constants/keylist/mode.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_KEYLIST_MODE_', globals()) diff --git a/lang/python/pyme/constants/md.py b/lang/python/pyme/constants/md.py new file mode 100644 index 00000000..2db01a52 --- /dev/null +++ b/lang/python/pyme/constants/md.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_MD_', globals()) diff --git a/lang/python/pyme/constants/pk.py b/lang/python/pyme/constants/pk.py new file mode 100644 index 00000000..5f39235a --- /dev/null +++ b/lang/python/pyme/constants/pk.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_PK_', globals()) diff --git a/lang/python/pyme/constants/protocol.py b/lang/python/pyme/constants/protocol.py new file mode 100644 index 00000000..3d3c790a --- /dev/null +++ b/lang/python/pyme/constants/protocol.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_PROTOCOL_', globals()) diff --git a/lang/python/pyme/constants/sig/__init__.py b/lang/python/pyme/constants/sig/__init__.py new file mode 100644 index 00000000..2f2152a5 --- /dev/null +++ b/lang/python/pyme/constants/sig/__init__.py @@ -0,0 +1,4 @@ +# $Id$ + +from . import mode +__all__ = ['mode'] diff --git a/lang/python/pyme/constants/sig/mode.py b/lang/python/pyme/constants/sig/mode.py new file mode 100644 index 00000000..fa090ab9 --- /dev/null +++ b/lang/python/pyme/constants/sig/mode.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_SIG_MODE_', globals()) diff --git a/lang/python/pyme/constants/sigsum.py b/lang/python/pyme/constants/sigsum.py new file mode 100644 index 00000000..7be40ae6 --- /dev/null +++ b/lang/python/pyme/constants/sigsum.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_SIGSUM_', globals()) diff --git a/lang/python/pyme/constants/status.py b/lang/python/pyme/constants/status.py new file mode 100644 index 00000000..60c0c90d --- /dev/null +++ b/lang/python/pyme/constants/status.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_STATUS_', globals()) diff --git a/lang/python/pyme/constants/validity.py b/lang/python/pyme/constants/validity.py new file mode 100644 index 00000000..9590b27a --- /dev/null +++ b/lang/python/pyme/constants/validity.py @@ -0,0 +1,20 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from pyme import util +util.process_constants('GPGME_VALIDITY_', globals()) diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py new file mode 100644 index 00000000..b03cedb0 --- /dev/null +++ b/lang/python/pyme/core.py @@ -0,0 +1,463 @@ +# $Id$ +# Copyright (C) 2004,2008 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# 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 generators for portability with python2.2 + + +from . import pygpgme +from .errors import errorcheck +from . import errors +from .util import GpgmeWrapper + +class Context(GpgmeWrapper): + """From the GPGME C documentation: + + * All cryptographic operations in GPGME are performed within a + * context, which contains the internal state of the operation as well as + * configuration parameters. By using several contexts you can run + * several cryptographic operations in parallel, with different + * configuration. + + Thus, this is the place that you will usually start.""" + + def _getctype(self): + return 'gpgme_ctx_t' + + def _getnameprepend(self): + return 'gpgme_' + + def _errorcheck(self, name): + """This function should list all functions returning gpgme_error_t""" + if (name.startswith('gpgme_op_') and \ + not name.endswith('_result')) or \ + name == 'gpgme_signers_add' or \ + name == 'gpgme_set_locale' or \ + name == 'gpgme_set_keylist_mode' or \ + name == 'gpgme_set_protocol': + return 1 + return 0 + + def __init__(self, wrapped=None): + if wrapped: + self.wrapped = wrapped + self.own = False + else: + tmp = pygpgme.new_gpgme_ctx_t_p() + errorcheck(pygpgme.gpgme_new(tmp)) + self.wrapped = pygpgme.gpgme_ctx_t_p_value(tmp) + pygpgme.delete_gpgme_ctx_t_p(tmp) + self.own = True + self.last_passcb = None + self.last_progresscb = None + + def __del__(self): + self._free_passcb() + self._free_progresscb() + if self.own: + pygpgme.gpgme_release(self.wrapped) + + def _free_passcb(self): + if self.last_passcb != None: + pygpgme.pygpgme_clear_generic_cb(self.last_passcb) + pygpgme.delete_PyObject_p_p(self.last_passcb) + self.last_passcb = None + + def _free_progresscb(self): + if self.last_progresscb != None: + pygpgme.pygpgme_clear_generic_cb(self.last_progresscb) + pygpgme.delete_PyObject_p_p(self.last_progresscb) + self.last_progresscb = None + + def op_keylist_all(self, *args, **kwargs): + self.op_keylist_start(*args, **kwargs) + key = self.op_keylist_next() + while key: + yield key + key = self.op_keylist_next() + + def op_keylist_next(self): + """Returns the next key in the list created + by a call to op_keylist_start(). The object returned + is of type Key.""" + ptr = pygpgme.new_gpgme_key_t_p() + try: + errorcheck(pygpgme.gpgme_op_keylist_next(self.wrapped, ptr)) + key = pygpgme.gpgme_key_t_p_value(ptr) + except errors.GPGMEError as excp: + key = None + if excp.getcode() != errors.EOF: + raise excp + pygpgme.delete_gpgme_key_t_p(ptr) + if key: + key.__del__ = lambda self: pygpgme.gpgme_key_unref(self) + return key + + def get_key(self, fpr, secret): + """Return the key corresponding to the fingerprint 'fpr'""" + ptr = pygpgme.new_gpgme_key_t_p() + errorcheck(pygpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret)) + key = pygpgme.gpgme_key_t_p_value(ptr) + pygpgme.delete_gpgme_key_t_p(ptr) + if key: + key.__del__ = lambda self: pygpgme.gpgme_key_unref(self) + return key + + def op_trustlist_all(self, *args, **kwargs): + self.op_trustlist_start(*args, **kwargs) + trust = self.ctx.op_trustlist_next() + while trust: + yield trust + trust = self.ctx.op_trustlist_next() + + def op_trustlist_next(self): + """Returns the next trust item in the list created + by a call to op_trustlist_start(). The object returned + is of type TrustItem.""" + ptr = pygpgme.new_gpgme_trust_item_t_p() + try: + errorcheck(pygpgme.gpgme_op_trustlist_next(self.wrapped, ptr)) + trust = pygpgme.gpgme_trust_item_t_p_value(ptr) + except errors.GPGMEError as excp: + trust = None + if excp.getcode() != errors.EOF: + raise + pygpgme.delete_gpgme_trust_item_t_p(ptr) + return trust + + def set_passphrase_cb(self, func, hook=None): + """Sets the passphrase callback to the function specified by func. + + When the system needs a passphrase, it will call func with three args: + hint, a string describing the key it needs the passphrase for; + desc, a string describing the passphrase it needs; + prev_bad, a boolean equal True if this is a call made after + unsuccessful previous attempt. + + If hook has a value other than None it will be passed into the func + as a forth argument. + + Please see the GPGME manual for more information. + """ + self._free_passcb() + if func == None: + hookdata = None + else: + self.last_passcb = pygpgme.new_PyObject_p_p() + if hook == None: + hookdata = func + else: + hookdata = (func, hook) + pygpgme.pygpgme_set_passphrase_cb(self.wrapped, hookdata, self.last_passcb) + + def set_progress_cb(self, func, hook=None): + """Sets the progress meter callback to the function specified by + + This function will be called to provide an interactive update of + the system's progress. + + Please see the GPGME manual for more information.""" + self._free_progresscb() + if func == None: + hookdata = None + else: + self.last_progresscb = pygpgme.new_PyObject_p_p() + if hook == None: + hookdata = func + else: + hookdata = (func, hook) + pygpgme.pygpgme_set_progress_cb(self.wrapped, hookdata, self.last_progresscb) + + def get_engine_info(self): + """Returns this context specific engine info""" + return pygpgme.gpgme_ctx_get_engine_info(self.wrapped) + + def set_engine_info(self, proto, file_name, home_dir=None): + """Changes the configuration of the crypto engine implementing the + protocol 'proto' for the context. 'file_name' is the file name of + the executable program implementing this protocol. 'home_dir' is the + directory name of the configuration directory (engine's default is + used if omitted).""" + errorcheck(pygpgme.gpgme_ctx_set_engine_info(self.wrapped, proto, file_name, home_dir)) + + def wait(self, hang): + """Wait for asynchronous call to finish. Wait forever if hang is True + + Return: + On an async call completion its return status. + On timeout - None. + + Please read the GPGME manual for more information.""" + ptr = pygpgme.new_gpgme_error_t_p() + context = pygpgme.gpgme_wait(self.wrapped, ptr, hang) + status = pygpgme.gpgme_error_t_p_value(ptr) + pygpgme.delete_gpgme_error_t_p(ptr) + + if context == None: + errorcheck(status) + return None + else: + return 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") + opaquedata = (func, fnc_value) + errorcheck(pygpgme.gpgme_op_edit(self.wrapped, key, opaquedata, out)) + +class Data(GpgmeWrapper): + """From the GPGME C manual: + +* A lot of data has to be exchanged between the user and the crypto +* engine, like plaintext messages, ciphertext, signatures and information +* about the keys. The technical details about exchanging the data +* information are completely abstracted by GPGME. The user provides and +* receives the data via `gpgme_data_t' objects, regardless of the +* communication protocol between GPGME and the crypto engine in use. + + This Data class is the implementation of the GpgmeData objects. + + Please see the information about __init__ for instantiation.""" + + def _getctype(self): + return 'gpgme_data_t' + + def _getnameprepend(self): + return 'gpgme_data_' + + def _errorcheck(self, name): + """This function should list all functions returning gpgme_error_t""" + if name == 'gpgme_data_release_and_get_mem' or \ + name == 'gpgme_data_get_encoding' or \ + name == 'gpgme_data_seek': + return 0 + return 1 + + def __init__(self, string = None, file = None, offset = None, + length = None, cbs = None): + """Initialize a new gpgme_data_t object. + + If no args are specified, make it an empty object. + + If string alone is specified, initialize it with the data + contained there. + + If file, offset, and length are all specified, file must + be either a filename or a file-like object, and the object + will be initialized by reading the specified chunk from the file. + + If cbs is specified, it MUST be a tuple of the form: + + ((read_cb, write_cb, seek_cb, release_cb), hook) + + where func is a callback function taking two arguments (count, + hook) and returning a string of read data, or None on EOF. + This will supply the read() method for the system. + + If file is specified without any other arguments, then + it must be a filename, and the object will be initialized from + that file. + + Any other use will result in undefined or erroneous behavior.""" + self.wrapped = None + self.last_readcb = None + + if cbs != None: + self.new_from_cbs(*cbs) + elif string != None: + self.new_from_mem(string) + elif file != None and offset != None and length != None: + self.new_from_filepart(file, offset, length) + elif file != None: + if type(file) == type("x"): + self.new_from_file(file) + else: + self.new_from_fd(file) + else: + self.new() + + def __del__(self): + if self.wrapped != None: + pygpgme.gpgme_data_release(self.wrapped) + self._free_readcb() + + def _free_readcb(self): + if self.last_readcb != None: + pygpgme.pygpgme_clear_generic_cb(self.last_readcb) + pygpgme.delete_PyObject_p_p(self.last_readcb) + self.last_readcb = None + + def new(self): + tmp = pygpgme.new_gpgme_data_t_p() + errorcheck(pygpgme.gpgme_data_new(tmp)) + self.wrapped = pygpgme.gpgme_data_t_p_value(tmp) + pygpgme.delete_gpgme_data_t_p(tmp) + + def new_from_mem(self, string, copy = 1): + tmp = pygpgme.new_gpgme_data_t_p() + errorcheck(pygpgme.gpgme_data_new_from_mem(tmp,string,len(string),copy)) + self.wrapped = pygpgme.gpgme_data_t_p_value(tmp) + pygpgme.delete_gpgme_data_t_p(tmp) + + def new_from_file(self, filename, copy = 1): + tmp = pygpgme.new_gpgme_data_t_p() + errorcheck(pygpgme.gpgme_data_new_from_file(tmp, filename, copy)) + self.wrapped = pygpgme.gpgme_data_t_p_value(tmp) + pygpgme.delete_gpgme_data_t_p(tmp) + + def new_from_cbs(self, funcs, hook): + """Argument funcs must be a 4 element tuple with callbacks: + (read_cb, write_cb, seek_cb, release_cb)""" + tmp = pygpgme.new_gpgme_data_t_p() + self._free_readcb() + self.last_readcb = pygpgme.new_PyObject_p_p() + hookdata = (funcs, hook) + pygpgme.pygpgme_data_new_from_cbs(tmp, hookdata, self.last_readcb) + self.wrapped = pygpgme.gpgme_data_t_p_value(tmp) + pygpgme.delete_gpgme_data_t_p(tmp) + + def new_from_filepart(self, file, offset, length): + """This wraps the GPGME gpgme_data_new_from_filepart() function. + The argument "file" may be: + + 1. a string specifying a file name, or + 3. a a file-like object. supporting the fileno() call and the mode + attribute.""" + + tmp = pygpgme.new_gpgme_data_t_p() + filename = None + fp = None + + if type(file) == type("x"): + filename = file + else: + fp = pygpgme.fdopen(file.fileno(), file.mode) + if fp == None: + raise ValueError("Failed to open file from %s arg %s" % \ + (str(type(file)), str(file))) + + errorcheck(pygpgme.gpgme_data_new_from_filepart(tmp, filename, fp, + offset, length)) + self.wrapped = pygpgme.gpgme_data_t_p_value(tmp) + pygpgme.delete_gpgme_data_t_p(tmp) + + def new_from_fd(self, file): + """This wraps the GPGME gpgme_data_new_from_fd() function. + The argument "file" may be a file-like object, supporting the fileno() + call and the mode attribute.""" + + tmp = pygpgme.new_gpgme_data_t_p() + fp = pygpgme.fdopen(file.fileno(), file.mode) + if fp == None: + raise ValueError("Failed to open file from %s arg %s" % \ + (str(type(file)), str(file))) + errorcheck(gpgme_data_new_from_fd(tmp, fp)) + self.wrapped = pygpgme.gpgme_data_t_p_value(tmp) + pygpgme.delete_gpgme_data_t_p(tmp) + + def new_from_stream(self, file): + """This wrap around gpgme_data_new_from_stream is an alias for + new_from_fd() method since in python there's not difference + between file stream and file descriptor""" + self.new_from_fd(file) + + def write(self, buffer): + errorcheck(pygpgme.gpgme_data_write(self.wrapped, buffer, len(buffer))) + + def read(self, size = -1): + """Read at most size bytes, returned as a string. + + If the size argument is negative or omitted, read until EOF is reached. + + Returns the data read, or the empty string if there was no data + to read before EOF was reached.""" + + if size == 0: + return '' + + if size > 0: + return pygpgme.gpgme_data_read(self.wrapped, size) + else: + retval = '' + while 1: + result = pygpgme.gpgme_data_read(self.wrapped, 10240) + if len(result) == 0: + break + retval += result + return retval + +def pubkey_algo_name(algo): + return pygpgme.gpgme_pubkey_algo_name(algo) + +def hash_algo_name(algo): + return pygpgme.gpgme_hash_algo_name(algo) + +def get_protocol_name(proto): + return pygpgme.gpgme_get_protocol_name(proto) + +def check_version(version=None): + return pygpgme.gpgme_check_version(version) + +def engine_check_version (proto): + try: + errorcheck(pygpgme.gpgme_engine_check_version(proto)) + return True + except errors.GPGMEError: + return False + +def get_engine_info(): + ptr = pygpgme.new_gpgme_engine_info_t_p() + try: + errorcheck(pygpgme.gpgme_get_engine_info(ptr)) + info = pygpgme.gpgme_engine_info_t_p_value(ptr) + except errors.GPGMEError: + info = None + pygpgme.delete_gpgme_engine_info_t_p(ptr) + return info + +def set_engine_info(proto, file_name, home_dir=None): + """Changes the default configuration of the crypto engine implementing + the protocol 'proto'. 'file_name' is the file name of + the executable program implementing this protocol. 'home_dir' is the + directory name of the configuration directory (engine's default is + used if omitted).""" + errorcheck(pygpgme.gpgme_set_engine_info(proto, file_name, home_dir)) + +def set_locale(category, value): + """Sets the default locale used by contexts""" + errorcheck(pygpgme.gpgme_set_locale(None, category, value)) + +def wait(hang): + """Wait for asynchronous call on any Context to finish. + Wait forever if hang is True. + + For finished anynch calls it returns a tuple (status, context): + status - status return by asnynchronous call. + context - context which caused this call to return. + + Please read the GPGME manual of more information.""" + ptr = pygpgme.new_gpgme_error_t_p() + context = pygpgme.gpgme_wait(None, ptr, hang) + status = pygpgme.gpgme_error_t_p_value(ptr) + pygpgme.delete_gpgme_error_t_p(ptr) + if context == None: + errorcheck(status) + else: + context = Context(context) + return (status, context) + diff --git a/lang/python/pyme/errors.py b/lang/python/pyme/errors.py new file mode 100644 index 00000000..0ad22f2b --- /dev/null +++ b/lang/python/pyme/errors.py @@ -0,0 +1,46 @@ +# $Id$ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from . import pygpgme + +class GPGMEError(Exception): + def __init__(self, error = None, message = None): + self.error = error + self.message = message + + def getstring(self): + message = "%s: %s" % (pygpgme.gpgme_strsource(self.error), + pygpgme.gpgme_strerror(self.error)) + if self.message != None: + message = "%s: %s" % (self.message, message) + return message + + def getcode(self): + return pygpgme.gpgme_err_code(self.error) + + def getsource(self): + return pygpgme.gpgme_err_source(self.error) + + def __str__(self): + return "%s (%d,%d)"%(self.getstring(), self.getsource(), self.getcode()) + +EOF = getattr(pygpgme, "EOF") + +def errorcheck(retval, extradata = None): + if retval: + raise GPGMEError(retval, extradata) diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py new file mode 100644 index 00000000..c5f02a96 --- /dev/null +++ b/lang/python/pyme/util.py @@ -0,0 +1,72 @@ +# $Id$ +# Copyright (C) 2004,2008 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from . import pygpgme +from .errors import errorcheck + +def process_constants(starttext, dict): + """Called by the constant libraries to load up the appropriate constants + from the C library.""" + index = len(starttext) + for identifier in dir(pygpgme): + if not identifier.startswith(starttext): + continue + name = identifier[index:] + dict[name] = getattr(pygpgme, identifier) + +class GpgmeWrapper(object): + """Base class all Pyme wrappers for GPGME functionality. Not to be + instantiated directly.""" + def __repr__(self): + return '' % \ + (__name__, self.__class__.__name__, + self.wrapped) + + def __str__(self): + return repr(self) + + def __hash__(self): + return hash(repr(self.wrapped)) + + def __eq__(self, other): + if other == None: + return False + else: + return repr(self.wrapped) == repr(other.wrapped) + + def _getctype(self): + raise NotImplementedException + + def __getattr__(self, name): + """On-the-fly function generation.""" + if name[0] == '_' or self._getnameprepend() == None: + return None + name = self._getnameprepend() + name + if self._errorcheck(name): + def _funcwrap(*args, **kwargs): + args = [self.wrapped] + list(args) + return errorcheck(getattr(pygpgme, name)(*args, **kwargs), + "Invocation of " + name) + else: + def _funcwrap(*args, **kwargs): + args = [self.wrapped] + list(args) + return getattr(pygpgme, name)(*args, **kwargs) + + _funcwrap.__doc__ = getattr(getattr(pygpgme, name), "__doc__") + return _funcwrap + diff --git a/lang/python/pyme/version.py b/lang/python/pyme/version.py new file mode 100644 index 00000000..3dd8d3ac --- /dev/null +++ b/lang/python/pyme/version.py @@ -0,0 +1,43 @@ +# $Id$ + +productname = 'pyme' +versionstr = "0.9.1" +revno = int('$Rev: 281 $'[6:-2]) +revstr = "Rev %d" % revno +datestr = '$Date$' + +versionlist = versionstr.split(".") +major = versionlist[0] +minor = versionlist[1] +patch = versionlist[2] +copyright = "Copyright (C) 2015 Ben McGinnes, 2014-2015 Martin Albrecht, 2004-2008 Igor Belyi, 2002 John Goerzen" +author = "Ben McGinnes" +author_email = "ben@adversary.org" +description = "Python 3 support for GPGME GnuPG cryptography library" +bigcopyright = """%(productname)s %(versionstr)s (%(revstr)s) +%(copyright)s <%(author_email)s>""" % locals() + +banner = bigcopyright + """ +This software comes with ABSOLUTELY NO WARRANTY; see the file +COPYING for details. This is free software, and you are welcome +to distribute it under the conditions laid out in COPYING.""" + +homepage = "https://gnupg.org" +license = """Copyright (C) 2015 Ben McGinnes +Copyright (C) 2014, 2015 Martin Albrecht +Copyright (C) 2004, 2008 Igor Belyi +Copyright (C) 2002 John Goerzen + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA""" -- cgit From aade53a12b9716997684b872bc2ac87229f73fb3 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Tue, 10 May 2016 13:30:30 +0200 Subject: python: Delete trailing whitespace. -- Signed-off-by: Justus Winter --- lang/python/README.rst | 2 +- lang/python/docs/old-commits.log | 84 +++++++++++++++++----------------- lang/python/examples/encrypt-to-all.py | 2 +- lang/python/examples/signverify.py | 2 +- lang/python/examples/t-edit.py | 2 +- lang/python/examples/testCMSgetkey.py | 4 +- lang/python/examples/verifydetails.py | 2 - lang/python/gpgme.i | 4 +- lang/python/helpers.c | 6 +-- lang/python/pyme/callbacks.py | 2 +- lang/python/pyme/core.py | 26 +++++------ lang/python/pyme/errors.py | 4 +- lang/python/pyme/util.py | 4 +- lang/python/setup.py | 8 ++-- 14 files changed, 74 insertions(+), 78 deletions(-) (limited to 'lang/python/pyme') diff --git a/lang/python/README.rst b/lang/python/README.rst index 4cad03a0..57df1f29 100644 --- a/lang/python/README.rst +++ b/lang/python/README.rst @@ -22,7 +22,7 @@ Authors * Martin Albrecht, `PyME 0.9+ `_, 2014 to present. * Ben McGinnes, `PyME Python 3 Port `_, 2015 to present. - + ------------ Mailing List ------------ diff --git a/lang/python/docs/old-commits.log b/lang/python/docs/old-commits.log index 4d2bfe09..0db59a08 100644 --- a/lang/python/docs/old-commits.log +++ b/lang/python/docs/old-commits.log @@ -4,7 +4,7 @@ Author: Ben McGinnes Date: Wed May 6 03:04:19 2015 +1000 Merge pull request #4 from Hasimir/master - + history commit 2036f1a0a670a0561993e195c458059220b36114 @@ -19,7 +19,7 @@ Author: Ben McGinnes Date: Wed May 6 02:52:23 2015 +1000 Added a short history - + * A (very) brief summary of the project's history since 2002. * Deals with why the commit log in the GPGME repo does not include the history of PyME. @@ -36,7 +36,7 @@ Author: Ben McGinnes Date: Wed May 6 02:21:34 2015 +1000 Merge pull request #3 from Hasimir/master - + Version release preparation commit 7c37a27a6845c58222d4d947c2efbe38e955b612 @@ -51,7 +51,7 @@ Author: Ben McGinnes Date: Wed May 6 02:09:44 2015 +1000 TODO update - + * Removed reference to GitHub, replaced with impending new home at gnupg.org. docs/TODO.rst | 4 ++-- @@ -62,7 +62,7 @@ Author: Ben McGinnes Date: Wed May 6 02:00:44 2015 +1000 Version bump - + * Bumped version number to 0.9.1 to keep it somewhat in line with the existing PyME project, even though there will be some divergence at some point (or even re-merging, depending on how many of the Python 3 @@ -80,7 +80,7 @@ Author: Ben McGinnes Date: Wed May 6 01:48:01 2015 +1000 README preparation. - + * Changes in preparation for impending move of code to the GnuPG git server as a part of GPGME. @@ -92,7 +92,7 @@ Author: Ben McGinnes Date: Wed May 6 01:43:53 2015 +1000 TODO moved to docs - + * As it says. TODO.rst | 25 ------------------------- @@ -114,7 +114,7 @@ Author: Ben McGinnes Date: Sun May 3 14:59:44 2015 +1000 Merge pull request #2 from Hasimir/master - + Minor editing. commit 44837f6e50fc539c86aef1f75a6a3538b02029ea @@ -122,7 +122,7 @@ Author: Ben McGinnes Date: Sun May 3 14:56:55 2015 +1000 Minor editing. - + * Fixed another URL. * Changed Py3 version's version number to v0.9.1-beta0. @@ -135,7 +135,7 @@ Author: Ben McGinnes Date: Sun May 3 14:26:11 2015 +1000 Merge pull request #1 from Hasimir/master - + Links commit 48eb1856cb0739cc9f0b9084da9d965e1fc7fddd @@ -143,7 +143,7 @@ Author: Ben McGinnes Date: Sun May 3 14:22:30 2015 +1000 Links - + * Fixed URLs for authors. * Updated my entry to point to github location. ** I strongly suspect the result of this work will be concurrent @@ -157,9 +157,9 @@ Author: Ben McGinnes Date: Sun May 3 11:29:00 2015 +1000 Explicit over Implicit ... - + ... isn't just for code. - + * Removed the 2to3 working directory and its contents. * Made the README.rst file a little more clear that this branch is for Python 3 (set Python 3.2 as a fairly arbitrary requirement for the @@ -176,7 +176,7 @@ Author: Ben McGinnes Date: Sun May 3 11:19:41 2015 +1000 Added authors. - + * In alphabetical order. * Mine will need updating once Martin and I have decided what to do regarding the two main branches. @@ -189,7 +189,7 @@ Author: Ben McGinnes Date: Sun May 3 10:23:00 2015 +1000 Docs and other things. - + * Now able to import pyme.core without error, indicates port process is successful. * Code is *not* compatible with the Python 2 version. @@ -227,7 +227,7 @@ Author: Ben McGinnes Date: Sun May 3 10:08:22 2015 +1000 Bytes vs. Unicode - + * Trying PyBytes instead of PyUnicode. gpgme.i | 14 +++++++------- @@ -239,7 +239,7 @@ Author: Ben McGinnes Date: Sun May 3 09:22:58 2015 +1000 String to Unicode - + * Replaced all instances of PyString with PyUnicode (and hoping there's no byte data in there). @@ -252,7 +252,7 @@ Author: Ben McGinnes Date: Sun May 3 09:17:06 2015 +1000 PyInt_AsLong - + * Replaced all instances of PyInt with PyLong, as per C API docs. gpgme.i | 4 ++-- @@ -264,7 +264,7 @@ Author: Ben McGinnes Date: Sun May 3 05:59:36 2015 +1000 Import correction - + * Once pygpgme.py is generated and moved, it will be in the right directory for the explicit "from . import pygpgme" to be correct. @@ -303,10 +303,10 @@ Author: Ben McGinnes Date: Sun May 3 04:53:21 2015 +1000 Pet Peeve - + def pet_peeve(self): peeve = print("people who don't press return after a colon!") - + FFS! pyme/core.py | 5 +++-- @@ -371,7 +371,7 @@ Author: Ben McGinnes Date: Sun May 3 03:51:48 2015 +1000 Linking swig to py3 - + * Changed the swig invocations to run with the -python -py3 flags explicitly. Makefile | 4 ++-- @@ -383,7 +383,7 @@ Author: Ben McGinnes Date: Sat May 2 11:12:00 2015 +1000 String fun - + * streamlined confdata details, including decoding strom binary to string. setup.py | 4 +--- @@ -394,7 +394,7 @@ Author: Ben McGinnes Date: Sat May 2 10:46:59 2015 +1000 Open File - + * Removed deprecated file() and replaced with open(). examples/PyGtkGpgKeys.py | 2 +- @@ -407,7 +407,7 @@ Author: Ben McGinnes Date: Sat May 2 10:36:15 2015 +1000 print() fix - + * Makefile includes a python print, changed from statement to function. Makefile | 2 +- @@ -418,7 +418,7 @@ Author: Ben McGinnes Date: Sat May 2 10:28:42 2015 +1000 Updated Makefile - + * set make to use python3 instead. * This will mean a successful port may need to be maintained seperately from the original python2 code instead of merged, but ought to be able @@ -434,7 +434,7 @@ Author: Ben McGinnes Date: Sat May 2 10:15:20 2015 +1000 Env and a little license issue - + * Updated all the /usr/bin/env paths to point to python3. * Also fixed the hard coded /usr/bin/python paths. * Updated part of setup.py which gave the impression this package was @@ -463,7 +463,7 @@ Author: Ben McGinnes Date: Sat May 2 08:50:54 2015 +1000 Removed extraneous files. - + * The two .bak files. pyme/errors.py.bak | 46 --------------------- @@ -475,7 +475,7 @@ Author: Ben McGinnes Date: Sat May 2 08:19:37 2015 +1000 Added TODO.org - + * TODO list in Emacs org-mode. * Will eventually be removed along with this entire directory when the porting process is complete. @@ -488,7 +488,7 @@ Author: Ben McGinnes Date: Sat May 2 07:58:40 2015 +1000 2to3 conversion of remaining files - + * Ran the extended version against all the unmodified python files. * Only pyme/errors.py required additional work. @@ -502,7 +502,7 @@ Author: Ben McGinnes Date: Sat May 2 07:50:39 2015 +1000 2to3 conversion of setup.py - + * Ran extended 2to3 command to produce python 3 code for setup.py. * Effectively testing for what to run against the other originally unmodified py2 files. @@ -517,7 +517,7 @@ Author: Ben McGinnes Date: Fri May 1 21:50:07 2015 +1000 Removing 2to3 generated .bak files. - + * Not really needed with a real VCS, but couldn't hurt to have them for a couple of revisions. ;) @@ -548,7 +548,7 @@ Author: Ben McGinnes Date: Fri May 1 21:45:50 2015 +1000 2to3 conversion log - + * The output of the command to convert the code from Python 2 to 3. * Note: this contains the list of files which were not modified and which will or may need to be modified. @@ -561,7 +561,7 @@ Author: Ben McGinnes Date: Fri May 1 21:36:58 2015 +1000 2to3 conversion of pyme master - + * Branch from commit 459f3eca659b4949e394c4a032d9ce2053e6c721 * Ran this: or x in `find . | egrep .py$` ; do 2to3 -w $x; done ; * Multiple files not modified, will record elsewhere (see next commit). @@ -614,7 +614,7 @@ Author: Martin Albrecht Date: Wed Jul 9 10:48:33 2014 +0100 Merged in jerrykan/pyme/fix_setup_26 (pull request #1) - + Provide support for using setup.py with Python v2.6 commit dae7f14a54e6c2bde0ad4da7308cc7fc0d0c0469 @@ -622,7 +622,7 @@ Author: John Kristensen Date: Wed Jul 9 15:54:39 2014 +1000 Provide support for using setup.py with Python v2.6 - + The setup.py script uses subprocess.check_output() which was introduced in Python v2.7. The equivalent functionality can be achieved without adding much extra code and provide support for Python v2.6. @@ -701,7 +701,7 @@ Author: Martin Albrecht Date: Sat May 10 15:41:02 2014 +0100 Merge branch 'master' of bitbucket.org:malb/pyme - + Conflicts: setup.py @@ -1018,10 +1018,10 @@ Author: Martin Albrecht Date: Mon Jan 6 17:44:20 2014 +0100 fixing op_export_keys() - + the conversion of gpgme_key_t [] was restricted to gpgme_key_t [] with the name recv, i.e. only the use-cases of encryption were covered. - + see: http://sourceforge.net/mailarchive/forum.php?forum_name=pyme-help&max_rows=25&style=nested&viewmonth=201309 pyme/gpgme.i | 6 +++--- @@ -1618,9 +1618,9 @@ Date: Fri Jun 10 03:01:22 2005 +0000 Update 'docs' rule in Makefile to build packages first to ensure that documentation is build for the current version of pyme and not for the installed one. - + Added 'callbacks' into the list of visible pyme modules (__all__ var.) - + Slightly updated INSTALL file. pyme/INSTALL | 11 ++++++++--- @@ -2100,7 +2100,7 @@ Author: belyi Date: Fri Mar 18 19:09:33 2005 +0000 Added package building for python2.4 - + Updated copyright notes to include myslef and avoid confusion who's the maintainer. In John's own words: "I'd prefer to just step out of the picture". Jonh's copyright notice left intact. diff --git a/lang/python/examples/encrypt-to-all.py b/lang/python/examples/encrypt-to-all.py index 8f9d2500..c890df4f 100755 --- a/lang/python/examples/encrypt-to-all.py +++ b/lang/python/examples/encrypt-to-all.py @@ -54,7 +54,7 @@ for key in c.op_keylist_all(None, 0): (keyid, can_encrypt and "enabled" or "disabled")) except UnicodeEncodeError as e: print(e) - + if valid: names.append(key) else: diff --git a/lang/python/examples/signverify.py b/lang/python/examples/signverify.py index f8804ca9..7194157b 100755 --- a/lang/python/examples/signverify.py +++ b/lang/python/examples/signverify.py @@ -43,7 +43,7 @@ if not c.signers_enum(0): passlist = { b"": b"Crypt0R0cks" } - + # callback will return password based on the e-mail listed in the hint. c.set_passphrase_cb(lambda x,y,z: passlist[x[x.rindex("<"):]]) diff --git a/lang/python/examples/t-edit.py b/lang/python/examples/t-edit.py index 6c533429..5553190c 100644 --- a/lang/python/examples/t-edit.py +++ b/lang/python/examples/t-edit.py @@ -32,7 +32,7 @@ class KeyEditor: out.seek(0,0) print(out.read(), end=' ') print("[-- Code: %d, %s --]" % (status, args)) - + if args == "keyedit.prompt": result = self.steps[self.step] self.step += 1 diff --git a/lang/python/examples/testCMSgetkey.py b/lang/python/examples/testCMSgetkey.py index 53fdef77..7c953012 100644 --- a/lang/python/examples/testCMSgetkey.py +++ b/lang/python/examples/testCMSgetkey.py @@ -22,7 +22,7 @@ from pyme.constants import protocol def printgetkeyresults(keyfpr): """Run gpgme_get_key().""" - # gpgme_check_version() necessary for initialisation according to + # gpgme_check_version() necessary for initialisation according to # gogme 1.1.6 and this is not done automatically in pyme-0.7.0 print("gpgme version:", core.check_version(None)) c = core.Context() @@ -45,5 +45,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/lang/python/examples/verifydetails.py b/lang/python/examples/verifydetails.py index 0d47ba54..a8d840e7 100755 --- a/lang/python/examples/verifydetails.py +++ b/lang/python/examples/verifydetails.py @@ -96,5 +96,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i index 0115caf3..87efce73 100644 --- a/lang/python/gpgme.i +++ b/lang/python/gpgme.i @@ -241,14 +241,14 @@ gpgme_error_t pyEditCb(void *opaque, gpgme_status_code_t status, func = pyopaque; pyargs = PyTuple_New(2); } - + PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) status)); PyTuple_SetItem(pyargs, 1, PyBytes_FromString(args)); if (dataarg) { Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */ PyTuple_SetItem(pyargs, 2, dataarg); } - + retval = PyObject_CallObject(func, pyargs); Py_DECREF(pyargs); if (PyErr_Occurred()) { diff --git a/lang/python/helpers.c b/lang/python/helpers.c index b53dbdd8..96c844fb 100644 --- a/lang/python/helpers.c +++ b/lang/python/helpers.c @@ -66,7 +66,7 @@ static gpgme_error_t pyPassphraseCb(void *hook, PyObject *args = NULL; PyObject *retval = NULL; PyObject *dataarg = NULL; - gpgme_error_t err_status = 0; + gpgme_error_t err_status = 0; pygpgme_exception_init(); @@ -119,7 +119,7 @@ static void pyProgressCb(void *hook, const char *what, int type, int current, int total) { PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL; PyObject *pyhook = (PyObject *) hook; - + if (PyTuple_Check(pyhook)) { func = PyTuple_GetItem(pyhook, 0); dataarg = PyTuple_GetItem(pyhook, 1); @@ -137,7 +137,7 @@ static void pyProgressCb(void *hook, const char *what, int type, int current, Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */ PyTuple_SetItem(args, 4, dataarg); } - + retval = PyObject_CallObject(func, args); Py_DECREF(args); Py_XDECREF(retval); diff --git a/lang/python/pyme/callbacks.py b/lang/python/pyme/callbacks.py index e3c810cd..3a507b99 100644 --- a/lang/python/pyme/callbacks.py +++ b/lang/python/pyme/callbacks.py @@ -33,7 +33,7 @@ def passphrase_stdin(hint, desc, prev_bad, hook=None): def progress_stdout(what, type, current, total, hook=None): print("PROGRESS UPDATE: what = %s, type = %d, current = %d, total = %d" %\ (what, type, current, total)) - + def readcb_fh(count, hook): """A callback for data. hook should be a Python file-like object.""" if count: diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py index b03cedb0..09f0fa88 100644 --- a/lang/python/pyme/core.py +++ b/lang/python/pyme/core.py @@ -37,7 +37,7 @@ class Context(GpgmeWrapper): def _getctype(self): return 'gpgme_ctx_t' - + def _getnameprepend(self): return 'gpgme_' @@ -106,7 +106,7 @@ class Context(GpgmeWrapper): if key: key.__del__ = lambda self: pygpgme.gpgme_key_unref(self) return key - + def get_key(self, fpr, secret): """Return the key corresponding to the fingerprint 'fpr'""" ptr = pygpgme.new_gpgme_key_t_p() @@ -147,7 +147,7 @@ class Context(GpgmeWrapper): desc, a string describing the passphrase it needs; prev_bad, a boolean equal True if this is a call made after unsuccessful previous attempt. - + If hook has a value other than None it will be passed into the func as a forth argument. @@ -206,7 +206,7 @@ class Context(GpgmeWrapper): context = pygpgme.gpgme_wait(self.wrapped, ptr, hang) status = pygpgme.gpgme_error_t_p_value(ptr) pygpgme.delete_gpgme_error_t_p(ptr) - + if context == None: errorcheck(status) return None @@ -219,7 +219,7 @@ class Context(GpgmeWrapper): raise ValueError("op_edit: First argument cannot be None") opaquedata = (func, fnc_value) errorcheck(pygpgme.gpgme_op_edit(self.wrapped, key, opaquedata, out)) - + class Data(GpgmeWrapper): """From the GPGME C manual: @@ -236,7 +236,7 @@ class Data(GpgmeWrapper): def _getctype(self): return 'gpgme_data_t' - + def _getnameprepend(self): return 'gpgme_data_' @@ -247,7 +247,7 @@ class Data(GpgmeWrapper): name == 'gpgme_data_seek': return 0 return 1 - + def __init__(self, string = None, file = None, offset = None, length = None, cbs = None): """Initialize a new gpgme_data_t object. @@ -360,7 +360,7 @@ class Data(GpgmeWrapper): """This wraps the GPGME gpgme_data_new_from_fd() function. The argument "file" may be a file-like object, supporting the fileno() call and the mode attribute.""" - + tmp = pygpgme.new_gpgme_data_t_p() fp = pygpgme.fdopen(file.fileno(), file.mode) if fp == None: @@ -375,18 +375,18 @@ class Data(GpgmeWrapper): new_from_fd() method since in python there's not difference between file stream and file descriptor""" self.new_from_fd(file) - + def write(self, buffer): errorcheck(pygpgme.gpgme_data_write(self.wrapped, buffer, len(buffer))) def read(self, size = -1): """Read at most size bytes, returned as a string. - + If the size argument is negative or omitted, read until EOF is reached. Returns the data read, or the empty string if there was no data to read before EOF was reached.""" - + if size == 0: return '' @@ -445,11 +445,11 @@ def set_locale(category, value): def wait(hang): """Wait for asynchronous call on any Context to finish. Wait forever if hang is True. - + For finished anynch calls it returns a tuple (status, context): status - status return by asnynchronous call. context - context which caused this call to return. - + Please read the GPGME manual of more information.""" ptr = pygpgme.new_gpgme_error_t_p() context = pygpgme.gpgme_wait(None, ptr, hang) diff --git a/lang/python/pyme/errors.py b/lang/python/pyme/errors.py index 0ad22f2b..37d0fe67 100644 --- a/lang/python/pyme/errors.py +++ b/lang/python/pyme/errors.py @@ -22,7 +22,7 @@ class GPGMEError(Exception): def __init__(self, error = None, message = None): self.error = error self.message = message - + def getstring(self): message = "%s: %s" % (pygpgme.gpgme_strsource(self.error), pygpgme.gpgme_strerror(self.error)) @@ -35,7 +35,7 @@ class GPGMEError(Exception): def getsource(self): return pygpgme.gpgme_err_source(self.error) - + def __str__(self): return "%s (%d,%d)"%(self.getstring(), self.getsource(), self.getcode()) diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py index c5f02a96..32e2f556 100644 --- a/lang/python/pyme/util.py +++ b/lang/python/pyme/util.py @@ -28,7 +28,7 @@ def process_constants(starttext, dict): continue name = identifier[index:] dict[name] = getattr(pygpgme, identifier) - + class GpgmeWrapper(object): """Base class all Pyme wrappers for GPGME functionality. Not to be instantiated directly.""" @@ -51,7 +51,7 @@ class GpgmeWrapper(object): def _getctype(self): raise NotImplementedException - + def __getattr__(self, name): """On-the-fly function generation.""" if name[0] == '_' or self._getnameprepend() == None: diff --git a/lang/python/setup.py b/lang/python/setup.py index b0ed3b2c..562c08f4 100755 --- a/lang/python/setup.py +++ b/lang/python/setup.py @@ -60,7 +60,7 @@ for item in getconfig('cflags'): # Adjust include and library locations in case of win32 uname_s = os.popen("uname -s").read() if uname_s.startswith("MINGW32"): - mnts = [x.split()[0:3:2] for x in os.popen("mount").read().split("\n") if x] + mnts = [x.split()[0:3:2] for x in os.popen("mount").read().split("\n") if x] tmplist = sorted([(len(x[1]), x[1], x[0]) for x in mnts]) tmplist.reverse() extra_dirs = [] @@ -89,9 +89,9 @@ except OSError as e: raise RuntimeError("Could not call swig, perhaps install swig.") else: raise - + subprocess.call(["make swig"], shell=True) - + swige = Extension("pyme._pygpgme", ["gpgme_wrap.c", "helpers.c"], include_dirs = include_dirs, define_macros = define_macros, @@ -106,7 +106,7 @@ setup(name = "pyme", url = version.homepage, ext_modules=[swige], packages = ['pyme', 'pyme.constants', 'pyme.constants.data', - 'pyme.constants.keylist', 'pyme.constants.sig'], + 'pyme.constants.keylist', 'pyme.constants.sig'], license = version.copyright + \ ", Licensed under the GPL version 2 and the LGPL version 2.1" ) -- cgit From d60deb8a127fb35c01acc729f33b014840af0e7b Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 11:21:58 +0200 Subject: python: Fix type translation. * lang/python/gpgme.i: Adjust to Python3's string type being 'Unicode', not 'bytes'. Fix type checking. * lang/python/core.py (Data.write): Add docstring mentioning the expected type of parameter 'buffer'. (Data.read): Adjust read loop. Also, use a saner chunk size, and join all chunks at the end instead of adding them. * lang/python/examples/simple.py: Adjust example. Signed-off-by: Justus Winter --- lang/python/examples/simple.py | 6 ++--- lang/python/gpgme.i | 51 ++++++++++++++++++++++++++---------------- lang/python/pyme/core.py | 11 ++++----- 3 files changed, 41 insertions(+), 27 deletions(-) (limited to 'lang/python/pyme') diff --git a/lang/python/examples/simple.py b/lang/python/examples/simple.py index 739291ed..4ff6d285 100755 --- a/lang/python/examples/simple.py +++ b/lang/python/examples/simple.py @@ -25,7 +25,7 @@ core.check_version(None) # Set up our input and output buffers. -plain = core.Data(b'This is my message.') +plain = core.Data('This is my message.') cipher = core.Data() # Initialize our context. @@ -38,7 +38,7 @@ c.set_armor(1) sys.stdout.write("Enter name of your recipient: ") sys.stdout.flush() name = sys.stdin.readline().strip() -c.op_keylist_start(name.encode(), 0) +c.op_keylist_start(name, 0) r = c.op_keylist_next() if r == None: @@ -48,6 +48,6 @@ else: try: c.op_encrypt([r], 1, plain, cipher) cipher.seek(0,0) - print(cipher.read()) + sys.stdout.buffer.write(cipher.read()) except errors.GPGMEError as ex: print(ex.getstring()) diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i index 87efce73..7c11943c 100644 --- a/lang/python/gpgme.i +++ b/lang/python/gpgme.i @@ -24,16 +24,18 @@ // Generate doc strings for all methods. %feature("autodoc", "0"); -// Allow use of None for strings. +/* Allow use of Unicode objects, bytes, and None for strings. */ %typemap(in) const char * { if ($input == Py_None) $1 = NULL; + else if (PyUnicode_Check($input)) + $1 = PyUnicode_AsUTF8($input); else if (PyBytes_Check($input)) $1 = PyBytes_AsString($input); else { PyErr_Format(PyExc_TypeError, - "arg %d: expected string or None, got %s", + "arg %d: expected str, bytes, or None, got %s", $argnum, $input->ob_type->tp_name); return NULL; } @@ -49,20 +51,27 @@ PyObject* object_to_gpgme_t(PyObject* input, const char* objtype, int argnum) { PyObject *pyname = NULL, *pypointer = NULL; pyname = PyObject_CallMethod(input, "_getctype", NULL); - if (pyname == NULL) { - PyErr_Format(PyExc_TypeError, - "arg %d: Expected an instance of type %s, but got %s", - argnum, objtype, - input == Py_None ? "None" : input->ob_type->tp_name); - return NULL; - } - if (strcmp(PyBytes_AsString(pyname), objtype) != 0) { - PyErr_Format(PyExc_TypeError, - "arg %d: Expected value of type %s, but got %s", - argnum, objtype, PyBytes_AsString(pyname)); - Py_DECREF(pyname); - return NULL; - } + if (pyname && PyUnicode_Check(pyname)) + { + if (strcmp(PyUnicode_AsUTF8(pyname), objtype) != 0) + { + PyErr_Format(PyExc_TypeError, + "arg %d: Expected value of type %s, but got %s", + argnum, objtype, PyUnicode_AsUTF8(pyname)); + Py_DECREF(pyname); + return NULL; + } + } + else + { + PyErr_Format(PyExc_TypeError, + "Protocol violation: Expected an instance of type str " + "from _getctype, but got %s", + pyname == NULL ? "NULL" + : (pyname == Py_None ? "None" : pyname->ob_type->tp_name)); + return NULL; + } + Py_DECREF(pyname); pypointer = PyObject_GetAttrString(input, "wrapped"); if (pypointer == NULL) { @@ -243,7 +252,7 @@ gpgme_error_t pyEditCb(void *opaque, gpgme_status_code_t status, } PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) status)); - PyTuple_SetItem(pyargs, 1, PyBytes_FromString(args)); + PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args)); if (dataarg) { Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */ PyTuple_SetItem(pyargs, 2, dataarg); @@ -254,8 +263,12 @@ gpgme_error_t pyEditCb(void *opaque, gpgme_status_code_t status, if (PyErr_Occurred()) { err_status = pygpgme_exception2code(); } else { - if (fd>=0 && retval) { - write(fd, PyBytes_AsString(retval), PyBytes_Size(retval)); + if (fd>=0 && retval && PyUnicode_Check(retval)) { + const char *buffer; + Py_ssize_t size; + + buffer = PyUnicode_AsUTF8AndSize(retval, &size); + write(fd, buffer, size); write(fd, "\n", 1); } } diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py index 09f0fa88..fd4802ec 100644 --- a/lang/python/pyme/core.py +++ b/lang/python/pyme/core.py @@ -377,10 +377,11 @@ class Data(GpgmeWrapper): self.new_from_fd(file) def write(self, buffer): + """Write buffer given as bytes.""" errorcheck(pygpgme.gpgme_data_write(self.wrapped, buffer, len(buffer))) def read(self, size = -1): - """Read at most size bytes, returned as a string. + """Read at most size bytes, returned as bytes. If the size argument is negative or omitted, read until EOF is reached. @@ -393,13 +394,13 @@ class Data(GpgmeWrapper): if size > 0: return pygpgme.gpgme_data_read(self.wrapped, size) else: - retval = '' + chunks = [] while 1: - result = pygpgme.gpgme_data_read(self.wrapped, 10240) + result = pygpgme.gpgme_data_read(self.wrapped, 4096) if len(result) == 0: break - retval += result - return retval + chunks.append(result) + return b''.join(chunks) def pubkey_algo_name(algo): return pygpgme.gpgme_pubkey_algo_name(algo) -- cgit From ce5121ad53b0e17fbf9150b354c80da73f7fe190 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 11:53:43 +0200 Subject: python: Handle interpreter shutdown. * lang/python/pyme/core.py: Avoid races at interpreter shutdown. This silences the most annoying occurrences, however this problem also affects the SWIG generated code, which might indicate that the real problem is somewhere else. If so, this change can be easily reverted. Signed-off-by: Justus Winter --- lang/python/pyme/core.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py index fd4802ec..2a37ba35 100644 --- a/lang/python/pyme/core.py +++ b/lang/python/pyme/core.py @@ -66,21 +66,29 @@ class Context(GpgmeWrapper): self.last_progresscb = None def __del__(self): + if not pygpgme: + # At interpreter shutdown, pygpgme is set to NONE. + return + self._free_passcb() self._free_progresscb() - if self.own: + if self.own and pygpgme.gpgme_release: pygpgme.gpgme_release(self.wrapped) def _free_passcb(self): if self.last_passcb != None: - pygpgme.pygpgme_clear_generic_cb(self.last_passcb) - pygpgme.delete_PyObject_p_p(self.last_passcb) + if pygpgme.pygpgme_clear_generic_cb: + pygpgme.pygpgme_clear_generic_cb(self.last_passcb) + if pygpgme.delete_PyObject_p_p: + pygpgme.delete_PyObject_p_p(self.last_passcb) self.last_passcb = None def _free_progresscb(self): if self.last_progresscb != None: - pygpgme.pygpgme_clear_generic_cb(self.last_progresscb) - pygpgme.delete_PyObject_p_p(self.last_progresscb) + if pygpgme.pygpgme_clear_generic_cb: + pygpgme.pygpgme_clear_generic_cb(self.last_progresscb) + if pygpgme.delete_PyObject_p_p: + pygpgme.delete_PyObject_p_p(self.last_progresscb) self.last_progresscb = None def op_keylist_all(self, *args, **kwargs): @@ -292,14 +300,20 @@ class Data(GpgmeWrapper): self.new() def __del__(self): - if self.wrapped != None: + if not pygpgme: + # At interpreter shutdown, pygpgme is set to NONE. + return + + if self.wrapped != None and pygpgme.gpgme_data_release: pygpgme.gpgme_data_release(self.wrapped) self._free_readcb() def _free_readcb(self): if self.last_readcb != None: - pygpgme.pygpgme_clear_generic_cb(self.last_readcb) - pygpgme.delete_PyObject_p_p(self.last_readcb) + if pygpgme.pygpgme_clear_generic_cb: + pygpgme.pygpgme_clear_generic_cb(self.last_readcb) + if pygpgme.delete_PyObject_p_p: + pygpgme.delete_PyObject_p_p(self.last_readcb) self.last_readcb = None def new(self): -- cgit From af9371eb63664c92fb67e8e7e03cc984e7d38a7f Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 12:51:30 +0200 Subject: python: Fix name of exception, make slot methods explicit. * lang/python/pyme/util.py (GpgmeWrapper._getctype): Fix exception, add docstring. (GpgmeWrapper._getnameprepend): New function. (GpgmeWrapper._errorcheck): Likewise. Signed-off-by: Justus Winter --- lang/python/pyme/util.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py index 32e2f556..19bbb7f6 100644 --- a/lang/python/pyme/util.py +++ b/lang/python/pyme/util.py @@ -50,7 +50,24 @@ class GpgmeWrapper(object): return repr(self.wrapped) == repr(other.wrapped) def _getctype(self): - raise NotImplementedException + """Must be implemented by child classes. + + Must return the name of the c type.""" + raise NotImplementedError() + + def _getnameprepend(self): + """Must be implemented by child classes. + + Must return the prefix of all c functions mapped to methods of + this class.""" + raise NotImplementedError() + + def _errorcheck(self, name): + """Must be implemented by child classes. + + This function must return a trueish value for all c functions + returning gpgme_error_t.""" + raise NotImplementedError() def __getattr__(self, name): """On-the-fly function generation.""" -- cgit From e3d3d366bd1a1aea8a38ae5dcbf71ea3c784e920 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 12:54:15 +0200 Subject: python: Fix function invocation. * lang/python/pyme/core.py (Data.new_from_fd): Fix function invocation. Signed-off-by: Justus Winter --- lang/python/pyme/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py index 2a37ba35..e822704a 100644 --- a/lang/python/pyme/core.py +++ b/lang/python/pyme/core.py @@ -380,7 +380,7 @@ class Data(GpgmeWrapper): if fp == None: raise ValueError("Failed to open file from %s arg %s" % \ (str(type(file)), str(file))) - errorcheck(gpgme_data_new_from_fd(tmp, fp)) + errorcheck(pygpgme.gpgme_data_new_from_fd(tmp, fp)) self.wrapped = pygpgme.gpgme_data_t_p_value(tmp) pygpgme.delete_gpgme_data_t_p(tmp) -- cgit From ed0ce84fbd2904bf59ac66ae7422716db3624efa Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 14:57:42 +0200 Subject: python: Cache generated wrapper functions. * lang/python/util.py (GpgmeWrap.__getattr__): Cache generated wrapper functions. Signed-off-by: Justus Winter --- lang/python/pyme/util.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py index 19bbb7f6..a8560992 100644 --- a/lang/python/pyme/util.py +++ b/lang/python/pyme/util.py @@ -69,11 +69,11 @@ class GpgmeWrapper(object): returning gpgme_error_t.""" raise NotImplementedError() - def __getattr__(self, name): + def __getattr__(self, key): """On-the-fly function generation.""" - if name[0] == '_' or self._getnameprepend() == None: + if key[0] == '_' or self._getnameprepend() == None: return None - name = self._getnameprepend() + name + name = self._getnameprepend() + key if self._errorcheck(name): def _funcwrap(*args, **kwargs): args = [self.wrapped] + list(args) @@ -85,5 +85,8 @@ class GpgmeWrapper(object): return getattr(pygpgme, name)(*args, **kwargs) _funcwrap.__doc__ = getattr(getattr(pygpgme, name), "__doc__") + + # Cache the wrapper function. + setattr(self, key, _funcwrap) return _funcwrap -- cgit From f7094d8358e933f3ce074eade7a40b2a7d291180 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 17:44:54 +0200 Subject: python: Fix writing to data buffers. * lang/python/gpgme.i: Add typemap for buffers. * lang/python/pyme/core.py (Data.write): Fix function. * lang/python/tests/Makefile.am: Add new test. * lang/python/tests/t-data.py: New file. Signed-off-by: Justus Winter --- lang/python/gpgme.i | 17 +++++++++++++++ lang/python/pyme/core.py | 6 ++++-- lang/python/tests/Makefile.am | 2 +- lang/python/tests/t-data.py | 49 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100755 lang/python/tests/t-data.py (limited to 'lang/python/pyme') diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i index 7c11943c..c5b5bc97 100644 --- a/lang/python/gpgme.i +++ b/lang/python/gpgme.i @@ -173,6 +173,23 @@ PyObject* object_to_gpgme_t(PyObject* input, const char* objtype, int argnum) { free($1); } +/* For gpgme_data_write, but should be universal. */ +%typemap(in) (const void *buffer, size_t size) { + if ($input == Py_None) + $1 = NULL, $2 = 0; + else if (PyUnicode_Check($input)) + $1 = PyUnicode_AsUTF8AndSize($input, (size_t *) &$2); + else if (PyBytes_Check($input)) + PyBytes_AsStringAndSize($input, (char **) &$1, (size_t *) &$2); + else { + PyErr_Format(PyExc_TypeError, + "arg %d: expected str, bytes, or None, got %s", + $argnum, $input->ob_type->tp_name); + return NULL; + } +} +%typemap(freearg) (const void *buffer, size_t size) ""; + // Make types containing 'next' field to be lists %ignore next; %typemap(out) gpgme_sig_notation_t, gpgme_engine_info_t, gpgme_subkey_t, gpgme_key_sig_t, diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py index e822704a..dafbd9b3 100644 --- a/lang/python/pyme/core.py +++ b/lang/python/pyme/core.py @@ -391,8 +391,10 @@ class Data(GpgmeWrapper): self.new_from_fd(file) def write(self, buffer): - """Write buffer given as bytes.""" - errorcheck(pygpgme.gpgme_data_write(self.wrapped, buffer, len(buffer))) + """Write buffer given as string or bytes. + + If a string is given, it is implicitly encoded using UTF-8.""" + return pygpgme.gpgme_data_write(self.wrapped, buffer) def read(self, size = -1): """Read at most size bytes, returned as bytes. diff --git a/lang/python/tests/Makefile.am b/lang/python/tests/Makefile.am index 56ff74ce..50c78e35 100644 --- a/lang/python/tests/Makefile.am +++ b/lang/python/tests/Makefile.am @@ -19,4 +19,4 @@ TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) \ PYTHONPATH=`echo $(abs_builddir)/../build/lib.*` -TESTS = t-wrapper.py +TESTS = t-wrapper.py t-data.py diff --git a/lang/python/tests/t-data.py b/lang/python/tests/t-data.py new file mode 100755 index 00000000..af2eb986 --- /dev/null +++ b/lang/python/tests/t-data.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2016 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# GPGME is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . + +import os + +from pyme import core + +data = core.Data('Hello world!') +assert data.read() == b'Hello world!' +assert data.read() == b'' + +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' +assert data.read() == b'' + +data = core.Data(b'Hello world!') +assert data.read() == b'Hello world!' + +data = core.Data() +data.write('Hello world!') +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' + +data = core.Data() +data.write(b'Hello world!') +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' + +binjunk = bytes(range(256)) +data = core.Data() +data.write(binjunk) +data.seek(0, os.SEEK_SET) +assert data.read() == binjunk -- cgit From c5d118b2a76e9528df780d11da9566ff7c22e4f5 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 18:00:16 +0200 Subject: python: Raise exceptions on write errors. * lang/python/pyme/core.py (Data.write): Handle errors. * lang/python/pyme/errors.py (GPGMEError.fromSyserror): New function. Signed-off-by: Justus Winter --- lang/python/pyme/core.py | 5 ++++- lang/python/pyme/errors.py | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py index dafbd9b3..1d6e3847 100644 --- a/lang/python/pyme/core.py +++ b/lang/python/pyme/core.py @@ -394,7 +394,10 @@ class Data(GpgmeWrapper): """Write buffer given as string or bytes. If a string is given, it is implicitly encoded using UTF-8.""" - return pygpgme.gpgme_data_write(self.wrapped, buffer) + written = pygpgme.gpgme_data_write(self.wrapped, buffer) + if written < 0: + raise GPGMEError.fromSyserror() + return written def read(self, size = -1): """Read at most size bytes, returned as bytes. diff --git a/lang/python/pyme/errors.py b/lang/python/pyme/errors.py index 37d0fe67..5c8f9223 100644 --- a/lang/python/pyme/errors.py +++ b/lang/python/pyme/errors.py @@ -23,6 +23,10 @@ class GPGMEError(Exception): self.error = error self.message = message + @classmethod + def fromSyserror(cls): + return cls(pygpgme.gpgme_err_code_from_syserror()) + def getstring(self): message = "%s: %s" % (pygpgme.gpgme_strsource(self.error), pygpgme.gpgme_strerror(self.error)) -- cgit From 11314f0db6e57597e3f56351a86fdb36a7a17dd7 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 May 2016 18:29:04 +0200 Subject: python: Share generated methods between objects. * lang/python/pyme/util.py (GpgmeWrapper.__getattr__): Monkey-patch the class. * lang/python/tests/t-wrapper.py: Demonstrate the sharing. Signed-off-by: Justus Winter --- lang/python/pyme/util.py | 26 ++++++++++++++++---------- lang/python/tests/t-wrapper.py | 2 ++ 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py index a8560992..a9fa19d2 100644 --- a/lang/python/pyme/util.py +++ b/lang/python/pyme/util.py @@ -74,19 +74,25 @@ class GpgmeWrapper(object): if key[0] == '_' or self._getnameprepend() == None: return None name = self._getnameprepend() + key + func = getattr(pygpgme, name) + if self._errorcheck(name): - def _funcwrap(*args, **kwargs): - args = [self.wrapped] + list(args) - return errorcheck(getattr(pygpgme, name)(*args, **kwargs), + def _funcwrap(slf, *args, **kwargs): + return errorcheck(func(slf.wrapped, *args, **kwargs), "Invocation of " + name) else: - def _funcwrap(*args, **kwargs): - args = [self.wrapped] + list(args) - return getattr(pygpgme, name)(*args, **kwargs) + def _funcwrap(slf, *args, **kwargs): + return func(slf.wrapped, *args, **kwargs) + + _funcwrap.__doc__ = getattr(func, "__doc__") + + # Monkey-patch the class. + setattr(self.__class__, key, _funcwrap) - _funcwrap.__doc__ = getattr(getattr(pygpgme, name), "__doc__") + # Bind the method to 'self'. + def wrapper(*args, **kwargs): + return _funcwrap(self, *args, **kwargs) + _funcwrap.__doc__ = getattr(func, "__doc__") - # Cache the wrapper function. - setattr(self, key, _funcwrap) - return _funcwrap + return wrapper diff --git a/lang/python/tests/t-wrapper.py b/lang/python/tests/t-wrapper.py index acc2ecfd..fab0d811 100755 --- a/lang/python/tests/t-wrapper.py +++ b/lang/python/tests/t-wrapper.py @@ -20,4 +20,6 @@ from pyme import core d0 = core.Data() +d0.seek # trigger on-demand-wrapping assert d0.seek == d0.seek, "Generated wrapper functions are not cached" +assert hasattr(core.Data, 'seek'), "Generated wrapper functions are not shared" -- cgit From 64e5fe767f45e9ccb0fb3fe919171c222132a54c Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Tue, 17 May 2016 14:14:25 +0200 Subject: python: Import GPGMEError. * pyme/core.py: Import GPGMEError. Fixes c5d118b2. Signed-off-by: Justus Winter --- lang/python/pyme/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lang/python/pyme') diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py index 1d6e3847..f3829d5f 100644 --- a/lang/python/pyme/core.py +++ b/lang/python/pyme/core.py @@ -20,7 +20,7 @@ from . import pygpgme -from .errors import errorcheck +from .errors import errorcheck, GPGMEError from . import errors from .util import GpgmeWrapper -- cgit From 10328324c8fc9725cd0c885eaebfc80dc32c1ff6 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Tue, 17 May 2016 14:15:21 +0200 Subject: python: Clean up examples. * lang/python/examples/delkey.py: Clean up example. * lang/python/examples/encrypt-to-all.py: Likewise. * lang/python/examples/genkey.py: Likewise. * lang/python/examples/inter-edit.py: Likewise. * lang/python/examples/sign.py: Likewise. * lang/python/examples/signverify.py: Likewise. * lang/python/examples/simple.py: Likewise. * lang/python/examples/t-edit.py: Likewise. * lang/python/examples/verifydetails.py: Likewise. * lang/python/pyme/__init__.py: Likewise. Signed-off-by: Justus Winter --- lang/python/examples/delkey.py | 2 +- lang/python/examples/encrypt-to-all.py | 9 +++++---- lang/python/examples/genkey.py | 4 ++-- lang/python/examples/inter-edit.py | 9 ++++----- lang/python/examples/sign.py | 6 ++++-- lang/python/examples/signverify.py | 18 +++++++++--------- lang/python/examples/simple.py | 6 +++--- lang/python/examples/t-edit.py | 8 ++++---- lang/python/examples/verifydetails.py | 21 ++++++++++----------- lang/python/pyme/__init__.py | 6 ++++-- 10 files changed, 46 insertions(+), 43 deletions(-) (limited to 'lang/python/pyme') diff --git a/lang/python/examples/delkey.py b/lang/python/examples/delkey.py index 600e0c07..773b2623 100755 --- a/lang/python/examples/delkey.py +++ b/lang/python/examples/delkey.py @@ -31,6 +31,6 @@ core.check_version(None) c = core.Context() # 0 in keylist means to list not only public but secret keys as well. -for thekey in [x for x in c.op_keylist_all(b"joe@example.org", 0)]: +for thekey in [x for x in c.op_keylist_all("joe+pyme@example.org", 0)]: # 1 in delete means to delete not only public but secret keys as well. c.op_delete(thekey, 1) diff --git a/lang/python/examples/encrypt-to-all.py b/lang/python/examples/encrypt-to-all.py index 672e6614..331933e4 100755 --- a/lang/python/examples/encrypt-to-all.py +++ b/lang/python/examples/encrypt-to-all.py @@ -23,13 +23,14 @@ This program will try to encrypt a simple message to each key on your keyring. If your keyring has any invalid keys on it, those keys will be skipped and it will re-try the encryption.""" +import sys +import os from pyme import core from pyme.core import Data, Context -from pyme.constants import validity core.check_version(None) -plain = Data(b'This is my message.') +plain = Data('This is my message.') c = Context() c.set_armor(1) @@ -37,7 +38,7 @@ c.set_armor(1) def sendto(keylist): cipher = Data() c.op_encrypt(keylist, 1, plain, cipher) - cipher.seek(0,0) + cipher.seek(0, os.SEEK_SET) return cipher.read() names = [] @@ -64,4 +65,4 @@ for key in c.op_keylist_all(None, 0): passno = 0 print("Encrypting to %d recipients" % len(names)) -print(sendto(names)) +sys.stdout.buffer.write(sendto(names)) diff --git a/lang/python/examples/genkey.py b/lang/python/examples/genkey.py index 14497eb7..bc708339 100755 --- a/lang/python/examples/genkey.py +++ b/lang/python/examples/genkey.py @@ -28,14 +28,14 @@ c.set_progress_cb(callbacks.progress_stdout, None) # This example from the GPGME manual -parms = b""" +parms = """ Key-Type: RSA Key-Length: 2048 Subkey-Type: RSA Subkey-Length: 2048 Name-Real: Joe Tester Name-Comment: with stupid passphrase -Name-Email: joe@example.org +Name-Email: joe+pyme@example.org Passphrase: Crypt0R0cks Expire-Date: 2020-12-31 diff --git a/lang/python/examples/inter-edit.py b/lang/python/examples/inter-edit.py index 32f8edd9..f00928b0 100644 --- a/lang/python/examples/inter-edit.py +++ b/lang/python/examples/inter-edit.py @@ -17,7 +17,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA -import os import sys from pyme import core from pyme.core import Data, Context @@ -40,21 +39,21 @@ def edit_fnc(stat, args, helper): helper["data"].seek(helper["skip"], 0) data = helper["data"].read() helper["skip"] += len(data) - print(data) + sys.stdout.buffer.write(data) return input("(%s) %s > " % (stat2str[stat], args)) except EOFError: pass # Simple interactive editor to test editor scripts if len(sys.argv) != 2: - sys.stderr.write("Usage: %s \n" % sys.argv[0]) + sys.stderr.write("Usage: %s \n" % sys.argv[0]) else: c = Context() out = Data() - c.op_keylist_start(sys.argv[1].encode('utf-8'), 0) + c.op_keylist_start(sys.argv[1], 0) key = c.op_keylist_next() helper = {"skip": 0, "data": out} c.op_edit(key, edit_fnc, helper, out) print("[-- Final output --]") out.seek(helper["skip"], 0) - print(out.read()) + sys.stdout.buffer.write(out.read()) diff --git a/lang/python/examples/sign.py b/lang/python/examples/sign.py index 5667cc2b..ca439586 100755 --- a/lang/python/examples/sign.py +++ b/lang/python/examples/sign.py @@ -17,6 +17,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +import sys +import os from pyme import core, callbacks from pyme.constants.sig import mode @@ -27,5 +29,5 @@ sig = core.Data() c = core.Context() c.set_passphrase_cb(callbacks.passphrase_stdin, b'for signing') c.op_sign(plain, sig, mode.CLEAR) -sig.seek(0,0) -print(sig.read()) +sig.seek(0, os.SEEK_SET) +sys.stdout.buffer.write(sig.read()) diff --git a/lang/python/examples/signverify.py b/lang/python/examples/signverify.py index 7194157b..292deee9 100755 --- a/lang/python/examples/signverify.py +++ b/lang/python/examples/signverify.py @@ -20,7 +20,8 @@ # It uses keys for joe@example.org generated by genkey.pl script import sys -from pyme import core, callbacks +import os +from pyme import core from pyme.constants.sig import mode core.check_version(None) @@ -28,7 +29,7 @@ core.check_version(None) plain = core.Data(b"Test message") sig = core.Data() c = core.Context() -user = b"joe@example.org" +user = "joe" c.signers_clear() # Add joe@example.org's keys in the list of signers @@ -50,9 +51,9 @@ c.set_passphrase_cb(lambda x,y,z: passlist[x[x.rindex("<"):]]) c.op_sign(plain, sig, mode.CLEAR) # Print out the signature (don't forget to rewind since signing put sig at EOF) -sig.seek(0,0) +sig.seek(0, os.SEEK_SET) signedtext = sig.read() -print(signedtext) +sys.stdout.buffer.write(signedtext) # Create Data with signed text. sig2 = core.Data(signedtext) @@ -63,9 +64,7 @@ c.op_verify(sig2, None, plain2) result = c.op_verify_result() # List results for all signatures. Status equal 0 means "Ok". -index = 0 -for sign in result.signatures: - index += 1 +for index, sign in enumerate(result.signatures): print("signature", index, ":") print(" summary: ", sign.summary) print(" status: ", sign.status) @@ -74,5 +73,6 @@ for sign in result.signatures: print(" uid: ", c.get_key(sign.fpr, 0).uids[0].uid) # Print "unsigned" text. Rewind since verify put plain2 at EOF. -plain2.seek(0,0) -print("\n", plain2.read()) +plain2.seek(0, os.SEEK_SET) +print("\n") +sys.stdout.buffer.write(plain2.read()) diff --git a/lang/python/examples/simple.py b/lang/python/examples/simple.py index 4ff6d285..faa0f4cd 100755 --- a/lang/python/examples/simple.py +++ b/lang/python/examples/simple.py @@ -18,8 +18,8 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import sys -from pyme import core, constants, errors -import pyme.constants.validity +import os +from pyme import core, errors core.check_version(None) @@ -47,7 +47,7 @@ else: # Do the encryption. try: c.op_encrypt([r], 1, plain, cipher) - cipher.seek(0,0) + cipher.seek(0, os.SEEK_SET) sys.stdout.buffer.write(cipher.read()) except errors.GPGMEError as ex: print(ex.getstring()) diff --git a/lang/python/examples/t-edit.py b/lang/python/examples/t-edit.py index 5e5857a2..5c35f966 100644 --- a/lang/python/examples/t-edit.py +++ b/lang/python/examples/t-edit.py @@ -30,8 +30,8 @@ class KeyEditor: def edit_fnc(self, status, args, out): print("[-- Response --]") - out.seek(0,0) - print(out.read(), end=' ') + out.seek(0, os.SEEK_SET) + sys.stdout.buffer.write(out.read()) print("[-- Code: %d, %s --]" % (status, args)) if args == "keyedit.prompt": @@ -59,5 +59,5 @@ else: "Did you point GNUPGHOME to GPGME's tests/gpg dir?") c.op_edit(key, KeyEditor().edit_fnc, out, out) print("[-- Last response --]") - out.seek(0,0) - print(out.read(), end=' ') + out.seek(0, os.SEEK_SET) + sys.stdout.buffer.write(out.read()) diff --git a/lang/python/examples/verifydetails.py b/lang/python/examples/verifydetails.py index a8d840e7..0aa6f15b 100755 --- a/lang/python/examples/verifydetails.py +++ b/lang/python/examples/verifydetails.py @@ -25,8 +25,8 @@ # along with this program. If not, see . import sys -from pyme import core, callbacks, constants -from pyme.constants.sig import mode +import os +from pyme import core from pyme.constants import protocol def print_engine_infos(): @@ -58,9 +58,7 @@ def verifyprintdetails(sigfilename, filefilename=None): result = c.op_verify_result() # List results for all signatures. Status equal 0 means "Ok". - index = 0 - for sign in result.signatures: - index += 1 + for index, sign in enumerate(result.signatures): print("signature", index, ":") print(" summary: %#0x" % (sign.summary)) print(" status: %#0x" % (sign.status)) @@ -71,8 +69,9 @@ def verifyprintdetails(sigfilename, filefilename=None): # Print "unsigned" text if inline signature if plain2: #Rewind since verify put plain2 at EOF. - plain2.seek(0,0) - print("\n", plain2.read()) + plain2.seek(0, os.SEEK_SET) + print("\n") + sys.stdout.buffer.write(plain2.read()) def main(): print_engine_infos() @@ -86,13 +85,13 @@ def main(): sys.exit(1) if argc == 2: - print("trying to verify file: " + sys.argv[1].encode('utf-8')) - verifyprintdetails(sys.argv[1].encode('utf-8')) + print("trying to verify file: " + sys.argv[1]) + verifyprintdetails(sys.argv[1]) if argc == 3: print("trying to verify signature %s for file %s" \ - % (sys.argv[1].encode('utf-8'), sys.argv[2].encode('utf-8'))) + % (sys.argv[1], sys.argv[2])) - verifyprintdetails(sys.argv[1].encode('utf-8'), sys.argv[2].encode('utf-8')) + verifyprintdetails(sys.argv[1], sys.argv[2]) if __name__ == "__main__": main() diff --git a/lang/python/pyme/__init__.py b/lang/python/pyme/__init__.py index 4934afe7..7716e51c 100644 --- a/lang/python/pyme/__init__.py +++ b/lang/python/pyme/__init__.py @@ -84,6 +84,7 @@ QUICK START SAMPLE PROGRAM This program is not for serious encryption, but for example purposes only! import sys +import os from pyme import core, constants # Set up our input and output buffers. @@ -99,6 +100,7 @@ c.set_armor(1) # Set up the recipients. sys.stdout.write("Enter name of your recipient: ") +sys.stdout.flush() name = sys.stdin.readline().strip() c.op_keylist_start(name, 0) r = c.op_keylist_next() @@ -106,8 +108,8 @@ r = c.op_keylist_next() # Do the encryption. c.op_encrypt([r], 1, plain, cipher) -cipher.seek(0,0) -print cipher.read() +cipher.seek(0, os.SEEK_SET) +sys.stdout.buffer.write(cipher.read()) Note that although there is no explicit error checking done here, the Python GPGME library is automatically doing error-checking, and will -- cgit