From 13cba7ad0bfcbb8eacfffaf1913d11897c8f91c2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 26 Jan 2021 11:38:03 +0100 Subject: addressbook/external: stop using call_cmd() It does not actually save any code. The new code also uses a shell as is documented. Remove call_cmd(), as it no longer has any callers. --- alot/addressbook/external.py | 33 +++++++++++++++++++-------------- alot/commands/globals.py | 1 - alot/helper.py | 41 ----------------------------------------- 3 files changed, 19 insertions(+), 56 deletions(-) diff --git a/alot/addressbook/external.py b/alot/addressbook/external.py index cd300a42..c01a525e 100644 --- a/alot/addressbook/external.py +++ b/alot/addressbook/external.py @@ -1,13 +1,14 @@ # Copyright (C) 2011-2015 Patrick Totzke # This file is released under the GNU GPL, version 3 or a later revision. # For further details see the COPYING file -import re -from ..helper import call_cmd -from ..helper import split_commandstring -from . import AddressBook, AddressbookError import logging +import re +import subprocess +from urwid.util import detected_encoding + +from . import AddressBook, AddressbookError class ExternalAddressbook(AddressBook): """:class:`AddressBook` that parses a shell command's output""" @@ -49,20 +50,24 @@ class ExternalAddressbook(AddressBook): else: return AddressBook.lookup(self, prefix) - def _call_and_parse(self, commandline): - cmdlist = split_commandstring(commandline) - resultstring, errmsg, retval = call_cmd(cmdlist) - if retval != 0: - msg = 'abook command "%s" returned with ' % commandline - msg += 'return code %d' % retval - if errmsg: - msg += ':\n%s' % errmsg + def _call_and_parse(self, cmd): + try: + result = subprocess.run(cmd, shell = True, check = True, + capture_output = True, + stdin = subprocess.DEVNULL) + except subprocess.CalledProcessError as e: + msg = 'abook command "%s" failed with code %s' % (e.cmd, e.returncode) + if e.stderr: + msg += '; stderr:\n%s' % \ + e.stderr.decode(detected_encoding, errors = 'backslashreplace') raise AddressbookError(msg) - if not resultstring: + output = result.stdout.decode(detected_encoding, errors = 'backslashreplace') + if not output: logging.debug("No contacts in address book (empty string)") return [] - lines = resultstring.splitlines() + + lines = output.splitlines() res = [] logging.debug("Apply %s on %d results" % (self.regex, len(lines))) for l in lines: diff --git a/alot/commands/globals.py b/alot/commands/globals.py index e30192c6..310a59db 100644 --- a/alot/commands/globals.py +++ b/alot/commands/globals.py @@ -250,7 +250,6 @@ class ExternalCommand(Command): logging.info('calling external command: %s', self.cmdlist) ret = '' - # TODO: these can probably be refactored in terms of helper.call_cmd if self.in_thread: try: if self.shell: diff --git a/alot/helper.py b/alot/helper.py index 4bdb9731..8a7261e5 100644 --- a/alot/helper.py +++ b/alot/helper.py @@ -9,15 +9,12 @@ import mimetypes import os import re import shlex -import subprocess import email from email.mime.audio import MIMEAudio from email.mime.base import MIMEBase from email.mime.image import MIMEImage from email.mime.text import MIMEText -import asyncio -import urwid import magic @@ -130,44 +127,6 @@ def shorten_author_string(authors_string, maxlength): return authorsstring -def call_cmd(cmdlist, stdin=None): - """ - get a shell commands output, error message and return value and immediately - return. - - .. warning:: - - This returns with the first screen content for interactive commands. - - :param cmdlist: shellcommand to call, already splitted into a list accepted - by :meth:`subprocess.Popen` - :type cmdlist: list of str - :param stdin: string to pipe to the process - :type stdin: str, bytes, or None - :return: triple of stdout, stderr, return value of the shell command - :rtype: str, str, int - """ - termenc = urwid.util.detected_encoding - try: - - logging.debug("Calling %s" % cmdlist) - proc = subprocess.Popen( - cmdlist, - encoding = termenc, errors = 'backslashreplace', - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=subprocess.PIPE if stdin is not None else None) - except OSError as e: - out = '' - err = e.strerror - ret = e.errno - else: - out, err = proc.communicate(stdin) - ret = proc.returncode - - return out, err, ret - - def guess_mimetype(blob): """ uses file magic to determine the mime-type of the given data blob. -- cgit v1.2.3