[modules/shell] Update to new API

This commit is contained in:
tobi-wan-kenobi 2020-03-30 21:09:09 +02:00
parent 251a23d2f1
commit 422a9986b4
2 changed files with 37 additions and 47 deletions

View file

@ -3,7 +3,7 @@
""" Execute command in shell and print result """ Execute command in shell and print result
Few command examples: Few command examples:
'ping 1.1.1.1 -c 1 | grep -Po '(?<=time=)\d+(\.\d+)? ms'' 'ping -c 1 1.1.1.1 | grep -Po '(?<=time=)\d+(\.\d+)? ms''
'echo 'BTC=$(curl -s rate.sx/1BTC | grep -Po \'^\d+\')USD'' 'echo 'BTC=$(curl -s rate.sx/1BTC | grep -Po \'^\d+\')USD''
'curl -s https://wttr.in/London?format=%l+%t+%h+%w' 'curl -s https://wttr.in/London?format=%l+%t+%h+%w'
'pip3 freeze | wc -l' 'pip3 freeze | wc -l'
@ -27,66 +27,53 @@ import os
import subprocess import subprocess
import threading import threading
import bumblebee.engine import core.module
import bumblebee.input import core.widget
import bumblebee.output import core.input
import util.format
import util.cli
class Module(core.module.Module):
def __init__(self, config):
super().__init__(config, core.widget.Widget(self.get_output))
class Module(bumblebee.engine.Module): self.__command = self.parameter('command')
def __init__(self, engine, config): self.__async = util.format.asbool(self.parameter('async'))
widget = bumblebee.output.Widget(full_text=self.get_output)
super(Module, self).__init__(engine, config, widget)
if self.parameter('interval'): self.__output = ''
self.interval(self.parameter('interval')) if self.__async:
self.__output = 'please wait...'
self._command = self.parameter('command') self.__current_thread = None
self._async = bumblebee.util.asbool(self.parameter('async'))
if self._async:
self._output = 'Computing...'
self._current_thread = None
else:
self._output = ''
# LMB and RMB will update output regardless of timer # LMB and RMB will update output regardless of timer
engine.input.register_callback(self, button=bumblebee.input.RIGHT_MOUSE, cmd=self.update) core.input.register(self, button=core.input.LEFT_MOUSE, cmd=self.update)
engine.input.register_callback(self, button=bumblebee.input.LEFT_MOUSE, cmd=self.update) core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.update)
def get_output(self, _): def get_output(self, _):
return self._output return self.__output
def update(self, _): def update(self):
# if requested then run not async version and just execute command in this thread # if requested then run not async version and just execute command in this thread
if not self._async: if not self.__async:
self._output = self._get_command_output_or_error(self._command) self.__output = util.cli.execute(self.__command, ignore_errors=True)
return return
# if previous thread didn't end yet then don't do anything # if previous thread didn't end yet then don't do anything
if self._current_thread: if self.__current_thread:
return return
# spawn new thread to execute command and pass callback method to get output from it # spawn new thread to execute command and pass callback method to get output from it
self._current_thread = threading.Thread(target=self._run_command_in_thread, self.__current_thread = threading.Thread(
args=(self._command, self._output_function)) target=self.__run,
self._current_thread.start() args=(self.__command, self.__output_function)
)
self.__current_thread.start()
@staticmethod def __run(self, command, output_callback):
def _get_command_output_or_error(command): output_callback(util.cli.execute(command, ignore_errors=True))
try:
command_output = subprocess.check_output(command,
executable=os.environ.get('SHELL'),
shell=True,
stderr=subprocess.STDOUT)
return command_output.decode('utf-8').strip()
except subprocess.CalledProcessError as exception:
exception_output = exception.output.decode('utf-8').replace('\n', '')
return 'Status:{} output:{}'.format(exception.returncode, exception_output)
def _run_command_in_thread(self, command, output_callback): def __output_function(self, text):
output_callback(self._get_command_output_or_error(command)) self.__output = text
def _output_function(self, text):
self._output = text
# clear this thread data, so next update will spawn a new one # clear this thread data, so next update will spawn a new one
self._current_thread = None self._current_thread = None

View file

@ -9,12 +9,15 @@ def execute(cmd, wait=True, ignore_errors=False):
try: try:
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except FileNotFoundError as e: except FileNotFoundError as e:
raise RuntimeError('{} not found'.format(cmd)) raise RuntimeError('{} not found'.format(cmd))
if wait: if wait:
out, _ = proc.communicate() out, _ = proc.communicate()
if proc.returncode != 0 and not ignore_errors: if proc.returncode != 0:
raise RuntimeError('{} exited with {}'.format(cmd, proc.returncode)) err = '{} exited with code {}'.format(cmd, proc.returncode)
if ignore_errors:
return err
raise RuntimeError(err)
return out.decode('utf-8') return out.decode('utf-8')
return '' return ''