Page MenuHome GnuPG

No OneTemporary

diff --git a/lang/python/Makefile.am b/lang/python/Makefile.am
index 2c84f2b5..18005bf9 100644
--- a/lang/python/Makefile.am
+++ b/lang/python/Makefile.am
@@ -1,61 +1,66 @@
# Makefile.am for the Python bindings.
# 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 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.
#
# 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 <http://www.gnu.org/licenses/>.
-EXTRA_DIST = README.rst
+EXTRA_DIST = README
SUBDIRS = tests
+COPY_FILES = \
+ $(srcdir)/README \
+ $(srcdir)/pyme \
+ $(srcdir)/helpers.c $(srcdir)/helpers.h
+
# Cleanup gpgme.h from deprecated functions and typedefs.
gpgme.h: ../../src/gpgme.h $(srcdir)/gpgme-h-clean.py
$(PYTHON) $(srcdir)/gpgme-h-clean.py $< >$@
# For VPATH builds we need to copy some files because Python's
# distutils are not VPATH-aware.
-copystamp: $(srcdir)/pyme $(srcdir)/helpers.c $(srcdir)/helpers.h
+copystamp: $(COPY_FILES)
if test "$(srcdir)" != "$(builddir)" ; then cp -r $^ . ; fi
touch $@
errors.i:
sed -n -e \
'/GPG_ERR_[^ ]* =/s/ *\(.*\) = .*/%constant long \1 = \1;/p' \
`$(GPG_ERROR_CONFIG) --prefix`/include/gpg-error.h >$@
gpgme_wrap.c pyme/pygpgme.py: gpgme.i errors.i gpgme.h copystamp
$(SWIG) -python -py3 $(SWIGOPT) \
-o $(builddir)/gpgme_wrap.c -outdir $(builddir)/pyme \
$<
all-local: gpgme_wrap.c pyme/pygpgme.py copystamp
CFLAGS="$(CFLAGS)" \
$(PYTHON) setup.py build --verbose
clean-local:
rm -rf -- build gpgme.h errors.i gpgme_wrap.c pyme/pygpgme.py \
copystamp
if test "$(srcdir)" != "$(builddir)" ; then \
rm -rf pyme helpers.c helpers.h ; \
fi
install-exec-local:
$(PYTHON) setup.py install \
--prefix $(DESTDIR)$(prefix) \
--record $(DESTDIR)$(pythondir)/pyme/install_files.txt \
--verbose
uninstall-local:
xargs <$(DESTDIR)$(pythondir)/pyme/install_files.txt -- rm -rf --
rm -rf -- $(DESTDIR)$(pythondir)/pyme
diff --git a/lang/python/README b/lang/python/README
new file mode 100644
index 00000000..7ce8894b
--- /dev/null
+++ b/lang/python/README
@@ -0,0 +1,57 @@
+PyME - GPGME for Python emacs, please switch to -*- org -*- mode
+=======================
+
+PyMe is a python interface to the GPGME library:
+https://www.gnupg.org/related_software/gpgme/
+
+PyMe uses SWIG to create wrapper functions with automatic type
+conversions. This way most of the functions and types are converted
+from C into Python 3 automatically by SWIG, reducing the maintenance
+cost of the binginds.
+
+* Authors
+
+PyME has been created by John Goerzen, and maintained, developed, and
+cherished by Igor Belyi, Martin Albrecht, Ben McGinnes, and everyone
+who contributed to it in any way.
+
+In 2016 we merged a port of PyME to into the GPGME repository, and
+development will continue there. Please see the VCS history for the
+list of contributors, and if you do find bugs, or want to contribute,
+please get in touch and help maintain PyME.
+
+Please see the section 'History' further down this document for
+references to previous versions.
+
+* Mailing List
+
+For general discussion and help see the gnupg-users mailing list:
+https://lists.gnupg.org/mailman/listinfo/gnupg-users
+
+For development see the gnupg-devel mailing list:
+https://lists.gnupg.org/mailman/listinfo/gnupg-devel
+
+* Bugs
+
+Please report bugs using our bug tracker using the category 'gpgme',
+and topic 'python':
+https://bugs.gnupg.org/gnupg/
+
+* History
+
+ - The bindings have been merged into the GPGME repository in 2016.
+
+ - The latest version of PyME for Python 3.2 and above (as of
+ May, 2015) is v0.9.1.
+ https://git.gnupg.org/gpgme.git/lang/py3-pyme
+
+ - The latest version of PyME for Python 2.6 and 2.7 (as of this
+ writing) is v0.9.0. https://bitbucket.org/malb/pyme
+
+ - A previous version of PyME v0.8.0 can be found on sourceforge:
+ http://pyme.sourceforge.net/
+
+ - A previous version of PyME v0.5.1 which works with GPGME v0.3.15
+ can be found on John Goerzen's PyMe page:
+ http://quux.org/devel/pyme/
+ http://www.complete.org/JohnGoerzen
diff --git a/lang/python/README.rst b/lang/python/README.rst
deleted file mode 100644
index 57df1f29..00000000
--- a/lang/python/README.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-====
-PyME
-====
-
-PyMe is a python interface to the `GPGME
-<https://www.gnupg.org/related_software/gpgme/>`_ library.
-
-PyMe's development model is a `GPGME
-<https://www.gnupg.org/related_software/gpgme/>`_ + Python 3 + `SWIG
-<http://www.swig.org/>`_ combination which means that most of the functions and
-types are converted from C into Python 3 automatically by SWIG. In short, to be
-able to use PyMe you need to be `familiar with GPGME
-<https://www.gnupg.org/documentation/manuals/gpgme/>`_.
-
-
--------
-Authors
--------
-
-* John Goerzen, `Complete.Org <http://www.complete.org/JohnGoerzen>`_, 2002.
-* Igor Belyi, `PyME 0.8 <http://pyme.sourceforge.net/>`_, 2004-2008.
-* Martin Albrecht, `PyME 0.9+ <https://bitbucket.org/malb/pyme>`_, 2014 to present.
-* Ben McGinnes, `PyME Python 3 Port <https://git.gnupg.org/gpgme.git/lang/py3-pyme>`_, 2015 to present.
-
-
-------------
-Mailing List
-------------
-
-PyME's support and development `mailing list
-<http://sourceforge.net/p/pyme/mailman/pyme-help/>`_ is hosted by sourceforge.
-
-
--------
-History
--------
-
-* The latest version of PyME for Python 3.2 and above (as of May, 2015) is v0.9.1.
- https://git.gnupg.org/gpgme.git/lang/py3-pyme
-
-* The latest version of PyME for Python 2.6 and 2.7 (as of this writing) is v0.9.0.
- https://bitbucket.org/malb/pyme
-
-* A previous version of PyME v0.8.0 can be found on sourceforge:
- http://pyme.sourceforge.net/
-
-* A previous version of PyME v0.5.1 which works with GPGME v0.3.15 can be found
- on John Goerzen's PyMe page: http://quux.org/devel/pyme/
diff --git a/lang/python/pyme/__init__.py b/lang/python/pyme/__init__.py
index d06866a8..e377f595 100644
--- a/lang/python/pyme/__init__.py
+++ b/lang/python/pyme/__init__.py
@@ -1,138 +1,136 @@
-"""
-Pyme: GPGME Interface for Python
-Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
-Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
-
- 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
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# 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
+
+"""Pyme: GPGME Interface for Python
Welcome to PyME, the GPGME Interface for Python. "Pyme", when prounced,
rhymes with "Pine".
The latest release of this package may be obtained from
+https://www.gnupg.org
+
+Previous releases of this package for Python 2 can 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.
+ all GPGME features. Callback functions may be written in pure
+ Python. Exceptions raised in callbacks are properly propagated.
* 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
import os
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: ")
sys.stdout.flush()
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, 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
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/core.py b/lang/python/pyme/core.py
index 4b3e08a4..293df097 100644
--- a/lang/python/pyme/core.py
+++ b/lang/python/pyme/core.py
@@ -1,640 +1,674 @@
+# Copyright (C) 2016 g10 Code GmbH
# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
#
# 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
+"""Core functionality
+
+Core functionality of GPGME wrapped in a object-oriented fashion.
+Provides the 'Context' class for performing cryptographic operations,
+and the 'Data' class describing buffers of data.
+
+"""
+
import weakref
from . import pygpgme
from .errors import errorcheck, GPGMEError
from . import errors
class GpgmeWrapper(object):
- """Base class all Pyme wrappers for GPGME functionality. Not to be
- instantiated directly."""
+ """Base wrapper class
+
+ Not to be instantiated directly.
+
+ """
def __init__(self, wrapped):
self._callback_excinfo = None
self.wrapped = wrapped
def __repr__(self):
return '<instance of %s.%s with GPG object at %s>' % \
(__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):
"""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, key):
- """On-the-fly function generation."""
+ """On-the-fly generation of wrapper methods."""
if key[0] == '_' or self._getnameprepend() == None:
return None
name = self._getnameprepend() + key
func = getattr(pygpgme, name)
if self._errorcheck(name):
def _funcwrap(slf, *args, **kwargs):
result = func(slf.wrapped, *args, **kwargs)
if slf._callback_excinfo:
pygpgme.pygpgme_raise_callback_exception(slf)
return errorcheck(result, "Invocation of " + name)
else:
def _funcwrap(slf, *args, **kwargs):
result = func(slf.wrapped, *args, **kwargs)
if slf._callback_excinfo:
pygpgme.pygpgme_raise_callback_exception(slf)
return result
_funcwrap.__doc__ = getattr(func, "__doc__")
# Monkey-patch the class.
setattr(self.__class__, key, _funcwrap)
# Bind the method to 'self'.
def wrapper(*args, **kwargs):
return _funcwrap(self, *args, **kwargs)
_funcwrap.__doc__ = getattr(func, "__doc__")
return wrapper
class Context(GpgmeWrapper):
- """From the GPGME C documentation:
+ """Context for cryptographic operations
+
+ 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.
- * 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.
+ Access to a context must be synchronized.
- 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.own = False
else:
tmp = pygpgme.new_gpgme_ctx_t_p()
errorcheck(pygpgme.gpgme_new(tmp))
wrapped = pygpgme.gpgme_ctx_t_p_value(tmp)
pygpgme.delete_gpgme_ctx_t_p(tmp)
self.own = True
super().__init__(wrapped)
self.last_passcb = None
self.last_progresscb = None
self.last_statuscb = None
def __del__(self):
if not pygpgme:
# At interpreter shutdown, pygpgme is set to NONE.
return
self._free_passcb()
self._free_progresscb()
self._free_statuscb()
if self.own and self.wrapped and pygpgme.gpgme_release:
pygpgme.gpgme_release(self.wrapped)
self.wrapped = None
# Implement the context manager protocol.
def __enter__(self):
return self
def __exit__(self, type, value, tb):
self.__del__()
def _free_passcb(self):
if self.last_passcb != None:
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:
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 _free_statuscb(self):
if self.last_statuscb != None:
if pygpgme.pygpgme_clear_generic_cb:
pygpgme.pygpgme_clear_generic_cb(self.last_statuscb)
if pygpgme.delete_PyObject_p_p:
pygpgme.delete_PyObject_p_p(self.last_statuscb)
self.last_statuscb = 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 = (weakref.ref(self), func)
else:
hookdata = (weakref.ref(self), 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 FUNC.
If FUNC is None, the callback will be cleared.
This function will be called to provide an interactive update
of the system's progress. The function will be called with
three arguments, type, total, and current. If HOOK is not
None, it will be supplied as fourth argument.
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 = (weakref.ref(self), func)
else:
hookdata = (weakref.ref(self), func, hook)
pygpgme.pygpgme_set_progress_cb(self.wrapped, hookdata, self.last_progresscb)
def set_status_cb(self, func, hook=None):
"""Sets the status callback to the function specified by FUNC. If
FUNC is None, the callback will be cleared.
The function will be called with two arguments, keyword and
args. If HOOK is not None, it will be supplied as third
argument.
Please see the GPGME manual for more information.
"""
self._free_statuscb()
if func == None:
hookdata = None
else:
self.last_statuscb = pygpgme.new_PyObject_p_p()
if hook == None:
hookdata = (weakref.ref(self), func)
else:
hookdata = (weakref.ref(self), func, hook)
pygpgme.pygpgme_set_status_cb(self.wrapped, hookdata,
self.last_statuscb)
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.
Raises an exception on errors.
Please read the GPGME manual for more information.
"""
ptr = pygpgme.new_gpgme_error_t_p()
pygpgme.gpgme_wait(self.wrapped, ptr, hang)
status = pygpgme.gpgme_error_t_p_value(ptr)
pygpgme.delete_gpgme_error_t_p(ptr)
errorcheck(status)
def op_edit(self, key, func, fnc_value, out):
"""Start key editing using supplied callback function"""
if key == None:
raise ValueError("op_edit: First argument cannot be None")
if fnc_value:
opaquedata = (weakref.ref(self), func, fnc_value)
else:
opaquedata = (weakref.ref(self), func)
result = pygpgme.gpgme_op_edit(self.wrapped, key, opaquedata, out)
if self._callback_excinfo:
pygpgme.pygpgme_raise_callback_exception(self)
errorcheck(result)
class Data(GpgmeWrapper):
- """From the GPGME C manual:
+ """Data buffer
-* 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.
+ 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.
+ This Data class is the implementation of the GpgmeData objects.
- Please see the information about __init__ for instantiation."""
+ 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"""
return name not in {
'gpgme_data_release_and_get_mem',
'gpgme_data_get_encoding',
'gpgme_data_seek',
'gpgme_data_get_file_name',
}
def __init__(self, string=None, file=None, offset=None,
length=None, cbs=None, copy=True):
"""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.
+ where the first four items are functions implementing reading,
+ writing, seeking the data, and releasing any resources once
+ the data object is deallocated. The functions must match the
+ following prototypes:
+
+ def read(amount, hook=None):
+ return <a b"bytes" object>
+
+ def write(data, hook=None):
+ return <the number of bytes written>
+
+ def seek(offset, whence, hook=None):
+ return <the new file position>
+
+ def release(hook=None):
+ <return value and exceptions are ignored>
+
+ The functions may be bound methods. In that case, you can
+ simply use the 'self' reference instead of using a hook.
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."""
+ """
super().__init__(None)
self.data_cbs = None
if cbs != None:
self.new_from_cbs(*cbs)
elif string != None:
self.new_from_mem(string, copy)
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, copy)
else:
self.new_from_fd(file)
else:
self.new()
def __del__(self):
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)
if self._callback_excinfo:
pygpgme.pygpgme_raise_callback_exception(self)
self.wrapped = None
self._free_datacbs()
# Implement the context manager protocol.
def __enter__(self):
return self
def __exit__(self, type, value, tb):
self.__del__()
def _free_datacbs(self):
if self.data_cbs != None:
if pygpgme.pygpgme_clear_generic_cb:
pygpgme.pygpgme_clear_generic_cb(self.data_cbs)
if pygpgme.delete_PyObject_p_p:
pygpgme.delete_PyObject_p_p(self.data_cbs)
self.data_cbs = 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=True):
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=True):
tmp = pygpgme.new_gpgme_data_t_p()
try:
errorcheck(pygpgme.gpgme_data_new_from_file(tmp, filename, copy))
except errors.GPGMEError as e:
if e.getcode() == errors.INV_VALUE and not copy:
raise ValueError("delayed reads are not yet supported")
else:
raise e
self.wrapped = pygpgme.gpgme_data_t_p_value(tmp)
pygpgme.delete_gpgme_data_t_p(tmp)
def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None):
assert self.data_cbs == None
self.data_cbs = pygpgme.new_PyObject_p_p()
tmp = pygpgme.new_gpgme_data_t_p()
if hook != None:
hookdata = (weakref.ref(self),
read_cb, write_cb, seek_cb, release_cb, hook)
else:
hookdata = (weakref.ref(self),
read_cb, write_cb, seek_cb, release_cb)
errorcheck(
pygpgme.pygpgme_data_new_from_cbs(tmp, hookdata, self.data_cbs))
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."""
+ * a string specifying a file name, or
+ * a file-like object supporting the fileno() 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" must be a file-like object, supporting the
fileno() method.
"""
tmp = pygpgme.new_gpgme_data_t_p()
errorcheck(pygpgme.gpgme_data_new_from_fd(tmp, file.fileno()))
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):
"""Write buffer given as string or bytes.
If a string is given, it is implicitly encoded using UTF-8."""
written = pygpgme.gpgme_data_write(self.wrapped, buffer)
if written < 0:
if self._callback_excinfo:
pygpgme.pygpgme_raise_callback_exception(self)
else:
raise GPGMEError.fromSyserror()
return written
def read(self, size = -1):
"""Read at most size bytes, returned as bytes.
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:
try:
result = pygpgme.gpgme_data_read(self.wrapped, size)
except:
if self._callback_excinfo:
pygpgme.pygpgme_raise_callback_exception(self)
else:
raise
return result
else:
chunks = []
while True:
try:
result = pygpgme.gpgme_data_read(self.wrapped, 4096)
except:
if self._callback_excinfo:
pygpgme.pygpgme_raise_callback_exception(self)
else:
raise
if len(result) == 0:
break
chunks.append(result)
return b''.join(chunks)
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)
# check_version also makes sure that several subsystems are properly
# initialized, and it must be run at least once before invoking any
# other function. We do it here so that the user does not have to do
# it unless she really wants to check for a certain version.
check_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)

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 26, 6:42 PM (20 h, 9 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
66/ea/7581f92cdd0360ea5f64bcbf357d

Event Timeline