Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-python-gnupg for
openSUSE:Factory checked in at 2022-09-17 20:10:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-python-gnupg (Old)
and /work/SRC/openSUSE:Factory/.python-python-gnupg.new.2083 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-python-gnupg"
Sat Sep 17 20:10:48 2022 rev:13 rq:1004263 version:0.5.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-python-gnupg/python-python-gnupg.changes
2022-06-06 11:10:35.995314344 +0200
+++
/work/SRC/openSUSE:Factory/.python-python-gnupg.new.2083/python-python-gnupg.changes
2022-09-17 20:10:59.561269837 +0200
@@ -1,0 +2,18 @@
+Sat Sep 17 07:21:39 UTC 2022 - Dirk M??ller <[email protected]>
+
+- update to 0.5.0:
+ * Fixed #181: Added the ability to pass file paths to encrypt_file,
decrypt_file,
+ sign_file, verify_file, get_recipients_file and added import_keys_file.
+ * Fixed #183: Handle FAILURE and UNEXPECTED conditions correctly. Thanks to
sebbASF for
+ the patch.
+ * Fixed #185: Handle VALIDSIG arguments more robustly.
+ * Fixed #188: Remove handling of DECRYPTION_FAILED from Verify code, as not
required
+ there. Thanks to sebbASF for the patch.
+ * Fixed #190: Handle KEY_CREATED more robustly.
+ * Fixed #191: Handle NODATA messages during verification.
+ * Fixed #196: Don't log chunk data by default, as it could contain sensitive
+ information (during decryption, for example).
+ * Added the ability to pass an environment to the gpg executable. Thanks to
Edvard
+ Rejthar for the patch.
+
+-------------------------------------------------------------------
Old:
----
python-gnupg-0.4.9.tar.gz
New:
----
python-gnupg-0.5.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-python-gnupg.spec ++++++
--- /var/tmp/diff_new_pack.oJqALp/_old 2022-09-17 20:11:00.025271176 +0200
+++ /var/tmp/diff_new_pack.oJqALp/_new 2022-09-17 20:11:00.029271187 +0200
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%define oldpython python
Name: python-python-gnupg
-Version: 0.4.9
+Version: 0.5.0
Release: 0
Summary: A wrapper for the GNU Privacy Guard (GPG or GnuPG)
License: BSD-3-Clause
++++++ python-gnupg-0.4.9.tar.gz -> python-gnupg-0.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.9/PKG-INFO
new/python-gnupg-0.5.0/PKG-INFO
--- old/python-gnupg-0.4.9/PKG-INFO 2022-05-20 10:08:10.000000000 +0200
+++ new/python-gnupg-0.5.0/PKG-INFO 2022-08-23 17:52:00.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: python-gnupg
-Version: 0.4.9
+Version: 0.5.0
Summary: A wrapper for the Gnu Privacy Guard (GPG or GnuPG)
Home-page: https://github.com/vsajip/python-gnupg
Author: Vinay Sajip
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.9/README.rst
new/python-gnupg-0.5.0/README.rst
--- old/python-gnupg-0.4.9/README.rst 2022-05-20 09:14:52.000000000 +0200
+++ new/python-gnupg-0.5.0/README.rst 2022-08-23 10:08:24.000000000 +0200
@@ -4,6 +4,7 @@
:alt: GitHub test status
.. |badge2| image:: https://img.shields.io/codecov/c/github/vsajip/python-gnupg
+ :target: https://app.codecov.io/gh/vsajip/python-gnupg
:alt: GitHub coverage status
@@ -71,6 +72,27 @@
Released: Not yet.
+* Fixed #181: Added the ability to pass file paths to encrypt_file,
decrypt_file,
+ sign_file, verify_file, get_recipients_file and added import_keys_file.
+
+* Fixed #183: Handle FAILURE and UNEXPECTED conditions correctly. Thanks to
sebbASF for
+ the patch.
+
+* Fixed #185: Handle VALIDSIG arguments more robustly.
+
+* Fixed #188: Remove handling of DECRYPTION_FAILED from Verify code, as not
required
+ there. Thanks to sebbASF for the patch.
+
+* Fixed #190: Handle KEY_CREATED more robustly.
+
+* Fixed #191: Handle NODATA messages during verification.
+
+* Fixed #196: Don't log chunk data by default, as it could contain sensitive
+ information (during decryption, for example).
+
+* Added the ability to pass an environment to the gpg executable. Thanks to
Edvard
+ Rejthar for the patch.
+
0.4.9
-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.9/gnupg.py
new/python-gnupg-0.5.0/gnupg.py
--- old/python-gnupg-0.4.9/gnupg.py 2022-05-20 10:01:43.000000000 +0200
+++ new/python-gnupg-0.5.0/gnupg.py 2022-08-23 17:36:40.000000000 +0200
@@ -42,9 +42,9 @@
import sys
import threading
-__version__ = '0.4.9'
+__version__ = '0.5.0'
__author__ = 'Vinay Sajip'
-__date__ = '$20-May-2022 09:01:43$'
+__date__ = '$23-Aug-2022 16:36:40$'
STARTUPINFO = None
if os.name == 'nt': # pragma: no cover
@@ -58,15 +58,24 @@
_py3k = False
string_types = basestring
text_type = unicode
+ path_types = (bytes, str)
except NameError:
_py3k = True
string_types = str
text_type = str
+ path_types = (str,)
logger = logging.getLogger(__name__)
if not logger.handlers:
logger.addHandler(logging.NullHandler())
+# See gh-196: Logging could show sensitive data. It also produces some
voluminous
+# output. Hence, split into two tiers - stuff that's always logged, and stuff
that's
+# only logged if log_everything is True. (This is set by the test script.)
+#
+# For now, only debug logging of chunks falls into the optionally-logged
category.
+log_everything = False
+
# We use the test below because it works for Jython as well as CPython
if os.path.__name__ == 'ntpath': # pragma: no cover
# On Windows, we don't need shell quoting, other than worrying about
@@ -135,7 +144,7 @@
# for what is actually a binary file
try:
data = instream.read(1024)
- except UnicodeError:
+ except Exception: # pragma: no cover
logger.warning('Exception occurred while reading', exc_info=1)
break
if not data:
@@ -146,7 +155,7 @@
outstream.write(data)
except UnicodeError: # pragma: no cover
outstream.write(data.encode(enc))
- except Exception:
+ except Exception: # pragma: no cover
# Can sometimes get 'broken pipe' errors even when the data has all
# been sent
logger.exception('Error sending data')
@@ -291,11 +300,13 @@
self.key_id, self.username = value.split(None, 1)
update_sig_info(keyid=self.key_id, username=self.username,
status=self.status)
elif key == 'VALIDSIG':
- fingerprint, creation_date, sig_ts, expire_ts = value.split()[:4]
+ parts = value.split()
+ fingerprint, creation_date, sig_ts, expire_ts = parts[:4]
(self.fingerprint, self.creation_date, self.sig_timestamp,
self.expire_timestamp) = (fingerprint, creation_date, sig_ts,
expire_ts)
# may be different if signature is made with a subkey
- self.pubkey_fingerprint = value.split()[-1]
+ if len(parts) >= 10:
+ self.pubkey_fingerprint = parts[9]
self.status = 'signature valid'
update_sig_info(fingerprint=fingerprint,
creation_date=creation_date,
@@ -308,10 +319,6 @@
self.sig_info[sig_id] = {'creation_date': creation_date,
'timestamp': timestamp}
(self.signature_id, self.creation_date, self.timestamp) = (sig_id,
creation_date,
timestamp)
- elif key == 'DECRYPTION_FAILED': # pragma: no cover
- self.valid = False
- self.key_id = value
- self.status = 'decryption failed'
elif key == 'NO_PUBKEY': # pragma: no cover
self.valid = False
self.key_id = value
@@ -332,7 +339,6 @@
update_sig_info(status=self.status, keyid=self.key_id)
elif key in ('UNEXPECTED', 'FAILURE'): # pragma: no cover
self.valid = False
- self.key_id = value
if key == 'UNEXPECTED':
self.status = 'unexpected data'
else:
@@ -359,6 +365,10 @@
message = '%s: %s' % (operation, mapping[code])
if not self.status:
self.status = message
+ elif key == 'NODATA':
+ # See issue GH-191
+ self.valid = False
+ self.status = 'signature expected but not found'
elif key in ('DECRYPTION_INFO', 'PLAINTEXT', 'PLAINTEXT_LENGTH',
'BEGIN_SIGNING'):
pass
else: # pragma: no cover
@@ -382,7 +392,7 @@
setattr(self, result, 0)
def __nonzero__(self):
- if self.not_imported or not self.fingerprints:
+ if self.not_imported or not self.fingerprints: # pragma: no cover
return False
return True
@@ -406,7 +416,7 @@
}
def handle_status(self, key, value):
- if key in ('WARNING', 'ERROR'):
+ if key in ('WARNING', 'ERROR'): # pragma: no cover
logger.warning('potential problem: %s: %s', key, value)
elif key in ('IMPORTED', 'KEY_CONSIDERED'):
# this duplicates info we already see in import_ok & import_problem
@@ -718,7 +728,8 @@
if key in ('WARNING', 'ERROR'): # pragma: no cover
logger.warning('potential problem: %s: %s', key, value)
elif key == 'KEY_CREATED':
- (self.type, self.fingerprint) = value.split()
+ parts = value.split()
+ (self.type, self.fingerprint) = parts[:2]
self.status = 'ok'
elif key == 'KEY_NOT_CREATED':
self.status = key.replace('_', ' ').lower()
@@ -880,7 +891,8 @@
use_agent=False,
keyring=None,
options=None,
- secret_keyring=None):
+ secret_keyring=None,
+ env=None):
"""Initialize a GPG process wrapper. Options are:
gpgbinary -- full pathname for GPG binary.
@@ -892,9 +904,11 @@
options =-- a list of additional options to pass to the GPG binary.
secret_keyring -- name of alternative secret keyring file to use, or
list of such keyrings.
+ env -- a dict of environment variables
"""
self.gpgbinary = gpgbinary
self.gnupghome = gnupghome
+ self.env = env
# issue 112: fail if the specified value isn't a directory
if gnupghome and not os.path.isdir(gnupghome):
raise ValueError('gnupghome should be a directory (it isn\'t): %s'
% gnupghome)
@@ -990,7 +1004,7 @@
si = STARTUPINFO()
si.dwFlags = STARTF_USESHOWWINDOW
si.wShowWindow = SW_HIDE
- result = Popen(cmd, shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE,
startupinfo=si)
+ result = Popen(cmd, shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE,
startupinfo=si, env=self.env)
logger.debug('%s: %s', result.pid, debug_print(cmd))
return result
@@ -1031,7 +1045,8 @@
if on_data:
on_data(data)
break
- logger.debug('chunk: %r' % data[:256])
+ if log_everything:
+ logger.debug('chunk: %r' % data[:256])
append = True
if on_data:
append = on_data(data) is not False
@@ -1065,7 +1080,7 @@
dr.join()
rr.join()
if writer is not None:
- writer.join()
+ writer.join(0.01)
process.wait()
result.returncode = rc = process.returncode
if rc != 0:
@@ -1085,23 +1100,37 @@
"""
return hasattr(fileobj, 'read')
- def _handle_io(self, args, fileobj, result, passphrase=None, binary=False):
- "Handle a call to GPG - pass input data, collect output data"
- # Handle a basic data call - pass data to GPG, handle the output
- # including status information. Garbage In, Garbage Out :)
- if not self.is_valid_file(fileobj):
- raise TypeError('Not a valid file: %s' % fileobj)
- p = self._open_subprocess(args, passphrase is not None)
- if not binary: # pragma: no cover
- stdin = codecs.getwriter(self.encoding)(p.stdin)
+ def _get_fileobj(self, fileobj_or_path):
+ if self.is_valid_file(fileobj_or_path):
+ result = fileobj_or_path
+ elif not isinstance(fileobj_or_path, path_types):
+ raise TypeError('Not a valid file or path: %s' % fileobj_or_path)
+ elif not os.path.exists(fileobj_or_path):
+ raise ValueError('No such file: %s' % fileobj_or_path)
else:
- stdin = p.stdin
- if passphrase:
- _write_passphrase(stdin, passphrase, self.encoding)
- writer = _threaded_copy_data(fileobj, stdin)
- self._collect_output(p, result, writer, stdin)
+ result = open(fileobj_or_path, 'rb')
return result
+ def _handle_io(self, args, fileobj_or_path, result, passphrase=None,
binary=False):
+ "Handle a call to GPG - pass input data, collect output data"
+ # Handle a basic data call - pass data to GPG, handle the output
+ # including status information. Garbage In, Garbage Out :)
+ fileobj = self._get_fileobj(fileobj_or_path)
+ try:
+ p = self._open_subprocess(args, passphrase is not None)
+ if not binary: # pragma: no cover
+ stdin = codecs.getwriter(self.encoding)(p.stdin)
+ else:
+ stdin = p.stdin
+ if passphrase:
+ _write_passphrase(stdin, passphrase, self.encoding)
+ writer = _threaded_copy_data(fileobj, stdin)
+ self._collect_output(p, result, writer, stdin)
+ return result
+ finally:
+ writer.join(0.01)
+ if fileobj is not fileobj_or_path:
+ fileobj.close()
#
# SIGNATURE METHODS
#
@@ -1128,7 +1157,7 @@
return ('\n' not in passphrase and '\r' not in passphrase and '\x00'
not in passphrase)
def sign_file(self,
- file,
+ fileobj_or_path,
keyid=None,
passphrase=None,
clearsign=True,
@@ -1139,7 +1168,7 @@
"""sign file"""
if passphrase and not self.is_valid_passphrase(passphrase):
raise ValueError('Invalid passphrase')
- logger.debug('sign_file: %s', file)
+ logger.debug('sign_file: %s', fileobj_or_path)
if binary: # pragma: no cover
args = ['-s']
else:
@@ -1160,15 +1189,21 @@
result = self.result_map['sign'](self)
# We could use _handle_io here except for the fact that if the
# passphrase is bad, gpg bails and you can't write the message.
+ fileobj = self._get_fileobj(fileobj_or_path)
p = self._open_subprocess(args, passphrase is not None)
try:
stdin = p.stdin
if passphrase:
_write_passphrase(stdin, passphrase, self.encoding)
- writer = _threaded_copy_data(file, stdin)
+ writer = _threaded_copy_data(fileobj, stdin)
except IOError: # pragma: no cover
logging.exception('error writing message')
writer = None
+ finally:
+ if writer:
+ writer.join(0.01)
+ if fileobj is not fileobj_or_path:
+ fileobj.close()
self._collect_output(p, result, writer, stdin)
return result
@@ -1194,22 +1229,22 @@
f.close()
return result
- def verify_file(self, file, data_filename=None, close_file=True,
extra_args=None):
+ def verify_file(self, fileobj_or_path, data_filename=None,
close_file=True, extra_args=None):
"Verify the signature on the contents of the file-like object 'file'"
- logger.debug('verify_file: %r, %r', file, data_filename)
+ logger.debug('verify_file: %r, %r', fileobj_or_path, data_filename)
result = self.result_map['verify'](self)
args = ['--verify']
if extra_args:
args.extend(extra_args)
if data_filename is None:
- self._handle_io(args, file, result, binary=True)
+ self._handle_io(args, fileobj_or_path, result, binary=True)
else:
logger.debug('Handling detached verification')
import tempfile
- fd, fn = tempfile.mkstemp(prefix='pygpg')
- s = file.read()
+ fd, fn = tempfile.mkstemp(prefix='pygpg-')
+ s = fileobj_or_path.read()
if close_file:
- file.close()
+ fileobj_or_path.close()
logger.debug('Wrote to temp file: %r', s)
os.write(fd, s)
os.close(fd)
@@ -1219,7 +1254,7 @@
p = self._open_subprocess(args)
self._collect_output(p, result, stdin=p.stdin)
finally:
- os.unlink(fn)
+ os.remove(fn)
return result
def verify_data(self, sig_filename, data, extra_args=None):
@@ -1253,6 +1288,13 @@
data.close()
return result
+ def import_keys_file(self, key_path, **kwargs):
+ """
+ Import the key data in key_path into our keyring.
+ """
+ with open(key_path, 'rb') as f:
+ return self.import_keys(f.read(), **kwargs)
+
def recv_keys(self, keyserver, *keyids, **kwargs):
"""Import a key from a keyserver
@@ -1617,7 +1659,7 @@
# ENCRYPTION
#
def encrypt_file(self,
- file,
+ fileobj_or_path,
recipients,
sign=None,
always_trust=False,
@@ -1658,7 +1700,7 @@
if extra_args:
args.extend(extra_args)
result = self.result_map['crypt'](self)
- self._handle_io(args, file, result, passphrase=passphrase, binary=True)
+ self._handle_io(args, fileobj_or_path, result, passphrase=passphrase,
binary=True)
logger.debug('encrypt result[:100]: %r', result.data[:100])
return result
@@ -1717,7 +1759,7 @@
return result
def decrypt_file(self,
- file,
+ fileobj_or_path,
always_trust=False,
passphrase=None,
output=None,
@@ -1732,7 +1774,7 @@
if extra_args:
args.extend(extra_args)
result = self.result_map['crypt'](self)
- self._handle_io(args, file, result, passphrase, binary=True)
+ self._handle_io(args, fileobj_or_path, result, passphrase, binary=True)
logger.debug('decrypt result[:100]: %r', result.data[:100])
return result
@@ -1742,12 +1784,12 @@
data.close()
return result
- def get_recipients_file(self, file, extra_args=None):
+ def get_recipients_file(self, fileobj_or_path, extra_args=None):
args = ['--decrypt', '--list-only', '-v']
if extra_args:
args.extend(extra_args)
result = self.result_map['crypt'](self)
- self._handle_io(args, file, result, binary=True)
+ self._handle_io(args, fileobj_or_path, result, binary=True)
ids = []
for m in PUBLIC_KEY_RE.finditer(result.stderr):
ids.append(m.group(1))
@@ -1761,7 +1803,7 @@
trustlevel = levels[trustlevel] + 2
import tempfile
try:
- fd, fn = tempfile.mkstemp()
+ fd, fn = tempfile.mkstemp(prefix='pygpg-')
lines = []
if isinstance(fingerprints, string_types):
fingerprints = [fingerprints]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.9/python_gnupg.egg-info/PKG-INFO
new/python-gnupg-0.5.0/python_gnupg.egg-info/PKG-INFO
--- old/python-gnupg-0.4.9/python_gnupg.egg-info/PKG-INFO 2022-05-20
10:08:10.000000000 +0200
+++ new/python-gnupg-0.5.0/python_gnupg.egg-info/PKG-INFO 2022-08-23
17:52:00.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: python-gnupg
-Version: 0.4.9
+Version: 0.5.0
Summary: A wrapper for the Gnu Privacy Guard (GPG or GnuPG)
Home-page: https://github.com/vsajip/python-gnupg
Author: Vinay Sajip
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/python-gnupg-0.4.9/test_gnupg.py
new/python-gnupg-0.5.0/test_gnupg.py
--- old/python-gnupg-0.4.9/test_gnupg.py 2022-05-20 10:02:15.000000000
+0200
+++ new/python-gnupg-0.5.0/test_gnupg.py 2022-08-23 17:37:02.000000000
+0200
@@ -30,10 +30,12 @@
import gnupg
__author__ = 'Vinay Sajip'
-__date__ = '$20-May-2022 09:02:15$'
+__date__ = '$23-Aug-2022 16:37:02$'
ALL_TESTS = True
+gnupg.log_everything = True
+
logger = logging.getLogger(__name__)
GPGBINARY = os.environ.get('GPGBINARY', 'gpg')
@@ -979,8 +981,8 @@
self.assertTrue(sig, 'File signing should succeed')
self.assertTrue(sig.hash_algo)
try:
- file = gnupg._make_binary_stream(sig.data, self.gpg.encoding)
- verified = self.gpg.verify_file(file)
+ stream = gnupg._make_binary_stream(sig.data, self.gpg.encoding)
+ verified = self.gpg.verify_file(stream)
except UnicodeDecodeError: # pragma: no cover
# sometimes happens in Python 2.6
from io import BytesIO
@@ -1012,13 +1014,13 @@
data_file = open(self.test_fn, 'rb')
data = data_file.read()
data_file.close()
- fd, fn = tempfile.mkstemp()
+ fd, fn = tempfile.mkstemp(prefix='pygpg-test-')
os.write(fd, sig.data)
os.close(fd)
try:
verified = self.gpg.verify_data(fn, data)
finally:
- os.unlink(fn)
+ os.remove(fn)
self.assertEqual(0, verified.returncode, 'Non-zero return code')
if key.fingerprint != verified.fingerprint: # pragma: no cover
logger.debug('key: %r', key.fingerprint)
@@ -1049,7 +1051,7 @@
self.assertTrue(verified.username.startswith('Andrew Able'))
self.assertTrue(key.fingerprint.endswith(verified.key_id))
finally:
- os.unlink(sig_file)
+ os.remove(sig_file)
self.assertEqual(0, verified.returncode, 'Non-zero return code')
if key.fingerprint != verified.fingerprint:
logger.debug('key: %r', key.fingerprint)
@@ -1096,7 +1098,7 @@
self.assertTrue(verified.username.startswith('Charlie Clark'))
self.assertTrue(subkey.fingerprint.endswith(verified.key_id))
finally:
- os.unlink(sig_file)
+ os.remove(sig_file)
self.assertEqual(0, verified.returncode, 'Non-zero return code')
if subkey.fingerprint != verified.fingerprint:
logger.debug('key: %r', subkey.fingerprint)
@@ -1157,8 +1159,8 @@
self.assertEqual(0, key.returncode, 'Non-zero return code')
barbara = key.fingerprint
data = 'Hello, world!'
- file = gnupg._make_binary_stream(data, self.gpg.encoding)
- edata = self.gpg.encrypt_file(file, [andrew, barbara],
armor=False, output=encfname)
+ stream = gnupg._make_binary_stream(data, self.gpg.encoding)
+ edata = self.gpg.encrypt_file(stream, [andrew, barbara],
armor=False, output=encfname)
self.assertEqual(0, edata.returncode, 'Non-zero return code')
efile = open(encfname, 'rb')
ddata = self.gpg.decrypt_file(efile, passphrase='bbrown',
output=decfname)
@@ -1196,8 +1198,8 @@
def test_file_encryption_and_decryption(self):
"Test that encryption/decryption to/from file works"
- encfno, encfname = tempfile.mkstemp()
- decfno, decfname = tempfile.mkstemp()
+ encfno, encfname = tempfile.mkstemp(prefix='pygpg-test-')
+ decfno, decfname = tempfile.mkstemp(prefix='pygpg-test-')
# On Windows, if the handles aren't closed, the files can't be deleted
os.close(encfno)
os.close(decfno)
@@ -1206,7 +1208,7 @@
@skipIf(os.name == 'nt', 'Test not suitable for Windows')
def test_invalid_outputs(self):
"Test encrypting to invalid output files"
- encfno, encfname = tempfile.mkstemp()
+ encfno, encfname = tempfile.mkstemp(prefix='pygpg-test-')
os.close(encfno)
os.chmod(encfname, 0o400)
cases = (
@@ -1235,7 +1237,7 @@
self.gpg.error_map = messages
- encfno, encfname = tempfile.mkstemp()
+ encfno, encfname = tempfile.mkstemp(prefix='pygpg-test-')
os.close(encfno)
os.chmod(encfname, 0o400)
@@ -1421,9 +1423,14 @@
def test_invalid_fileobject(self):
# accidentally on purpose pass in a filename rather than the file
itself
- with self.assertRaises(TypeError) as ec:
- self.gpg.decrypt_file('foobar.txt', passphrase='',
output='/tmp/decrypted.txt')
- self.assertEqual(str(ec.exception), 'Not a valid file: foobar.txt')
+ bad = b'foobar.txt'
+ with self.assertRaises((TypeError, ValueError)) as ec:
+ self.gpg.decrypt_file(bad, passphrase='',
output='/tmp/decrypted.txt')
+ if gnupg._py3k:
+ expected = 'Not a valid file or path: %s' % bad
+ else:
+ expected = 'No such file: %s' % bad
+ self.assertEqual(str(ec.exception), expected)
def remove_all_existing_keys(self):
for root, dirs, files in os.walk(self.homedir):
@@ -1468,6 +1475,58 @@
expected = set((key1.fingerprint[-idlen:], key2.fingerprint[-idlen:]))
self.assertEqual(expected, ids)
+ def test_passing_paths(self):
+ key1 = self.generate_key('Andrew', 'Able', 'alpha.com',
passphrase='andy')
+ self.assertEqual(0, key1.returncode, 'Non-zero return code')
+ andrew = key1.fingerprint
+ key2 = self.generate_key('Barbara', 'Brown', 'beta.com')
+ self.assertEqual(0, key2.returncode, 'Non-zero return code')
+ barbara = key2.fingerprint
+ data = b'Hello, world!'
+ fd, fn = tempfile.mkstemp(prefix='pygpg-test-')
+ os.write(fd, data)
+ os.close(fd)
+ gpg = self.gpg
+ try:
+ # Check encryption
+ edata = gpg.encrypt_file(fn, [andrew, barbara], armor=False)
+ self.assertEqual(0, edata.returncode, 'Non-zero return code')
+ self.assertEqual(edata.status, 'encryption ok')
+ with open(fn, 'wb') as f:
+ f.write(edata.data)
+ # Check getting recipients
+ ids = gpg.get_recipients_file(fn)
+ idlen = len(ids[0])
+ keys = gpg.list_keys()
+ expected = set(d['subkeys'][0][0][-idlen:] for d in keys)
+ self.assertEqual(set(ids), expected)
+ # Check decryption
+ ddata = gpg.decrypt_file(fn, passphrase='andy')
+ self.assertEqual(0, ddata.returncode, 'Non-zero return code')
+ self.assertEqual(ddata.status, 'decryption ok')
+ self.assertEqual(ddata.data, data)
+ # Check signing
+ with open(fn, 'wb') as f:
+ f.write(data)
+ sig = gpg.sign_file(fn, keyid=andrew, passphrase='andy',
binary=True)
+ self.assertEqual(0, sig.returncode, 'Non-zero return code')
+ self.assertEqual(sig.status, 'signature created')
+ # Check verification
+ with open(fn, 'wb') as f:
+ f.write(sig.data)
+ verified = gpg.verify_file(fn)
+ self.assertEqual(0, verified.returncode, 'Non-zero return code')
+ self.assertEqual(verified.status, 'signature valid')
+ self.assertTrue(verified.valid)
+ # Check importing keys
+ with open(fn, 'wb') as f:
+ f.write(KEYS_TO_IMPORT.encode('ascii'))
+ result = gpg.import_keys_file(fn)
+ self.assertEqual(0, result.returncode, 'Non-zero return code')
+ self.assertEqual(result.imported, 2)
+ finally:
+ os.remove(fn)
+
TEST_GROUPS = {
'sign':
@@ -1494,7 +1553,7 @@
'test_quote_with_shell'
]),
'test':
- set(['test_key_generation_failure']),
+ set(['test_passing_paths']),
}