Skip to content

Commit

Permalink
Make I/O buffer size configurable.
Browse files Browse the repository at this point in the history
  • Loading branch information
vsajip committed Oct 10, 2023
1 parent 99ba650 commit 7cfc35d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 9 deletions.
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Released: Not yet

* Fix #228: Clarify documentation for encryption/decryption.

* Make I/O buffer size configurable via ``buffer_size`` attribute on a ``GPG`` instance.

0.5.1
-----
Expand Down
7 changes: 7 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ instantiation, like this::
environment settings (e.g. environment variables, code page etc.) but defaults to
latin-1.

From version 0.5.2 onwards, you can also control the buffer size for the I/O between
``gpg`` and ``python-gnupg`` by setting the ``buffer_size`` attribute on a GPG instance.

.. versionadded:: 0.5.2
The ``buffer_size`` attribute was added.


.. index:: Key; management

Key Management
Expand Down
23 changes: 14 additions & 9 deletions gnupg.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ def no_quote(s):
return s


def _copy_data(instream, outstream):
def _copy_data(instream, outstream, buffer_size):
# Copy one stream to another
assert buffer_size > 0
sent = 0
if hasattr(sys.stdin, 'encoding'):
enc = sys.stdin.encoding
Expand All @@ -146,7 +147,7 @@ def _copy_data(instream, outstream):
# See issue #39: read can fail when e.g. a text stream is provided
# for what is actually a binary file
try:
data = instream.read(1024)
data = instream.read(buffer_size)
except Exception: # pragma: no cover
logger.warning('Exception occurred while reading', exc_info=1)
break
Expand All @@ -170,8 +171,9 @@ def _copy_data(instream, outstream):
logger.debug('closed output, %d bytes sent', sent)


def _threaded_copy_data(instream, outstream):
wr = threading.Thread(target=_copy_data, args=(instream, outstream))
def _threaded_copy_data(instream, outstream, buffer_size):
assert buffer_size > 0
wr = threading.Thread(target=_copy_data, args=(instream, outstream, buffer_size))
wr.daemon = True
logger.debug('data copier: %r, %r, %r', wr, instream, outstream)
wr.start()
Expand Down Expand Up @@ -1011,6 +1013,8 @@ class GPG(object):

decode_errors = 'strict'

buffer_size = 1024 # override in instance if needed

result_map = {
'crypt': Crypt,
'delete': DeleteResult,
Expand Down Expand Up @@ -1189,11 +1193,12 @@ def _read_response(self, stream, result):
result.handle_status(keyword, value)
result.stderr = ''.join(lines)

def _read_data(self, stream, result, on_data=None):
def _read_data(self, stream, result, on_data=None, buffer_size=1024):
# Read the contents of the file from GPG's stdout
assert buffer_size > 0
chunks = []
while True:
data = stream.read(1024)
data = stream.read(buffer_size)
if len(data) == 0:
if on_data:
on_data(data)
Expand Down Expand Up @@ -1224,7 +1229,7 @@ def _collect_output(self, process, result, writer=None, stdin=None):
rr.start()

stdout = process.stdout
dr = threading.Thread(target=self._read_data, args=(stdout, result, self.on_data))
dr = threading.Thread(target=self._read_data, args=(stdout, result, self.on_data, self.buffer_size))
dr.daemon = True
logger.debug('stdout reader: %r', dr)
dr.start()
Expand Down Expand Up @@ -1281,7 +1286,7 @@ def _handle_io(self, args, fileobj_or_path, result, passphrase=None, binary=Fals
stdin = p.stdin
if passphrase:
_write_passphrase(stdin, passphrase, self.encoding)
writer = _threaded_copy_data(fileobj, stdin)
writer = _threaded_copy_data(fileobj, stdin, self.buffer_size)
self._collect_output(p, result, writer, stdin)
return result
finally:
Expand Down Expand Up @@ -1407,7 +1412,7 @@ def sign_file(self,
stdin = p.stdin
if passphrase:
_write_passphrase(stdin, passphrase, self.encoding)
writer = _threaded_copy_data(fileobj, stdin)
writer = _threaded_copy_data(fileobj, stdin, self.buffer_size)
except IOError: # pragma: no cover
logging.exception('error writing message')
writer = None
Expand Down

0 comments on commit 7cfc35d

Please sign in to comment.