commit
b374901642
@ -2,13 +2,13 @@
|
||||
|
||||
python3 --version
|
||||
py.test --version
|
||||
pep8 --version
|
||||
python3 -mpep8 --version
|
||||
|
||||
# Target directory for all build files
|
||||
BUILD=${1:-ci-build}
|
||||
mkdir -p $BUILD
|
||||
|
||||
pep8 --ignore E501 i3pystatus tests
|
||||
python3 -mpep8 --ignore E501 i3pystatus tests
|
||||
|
||||
# Check that the setup.py script works
|
||||
rm -rf ${BUILD}/test-install ${BUILD}/test-install-bin
|
||||
|
@ -5,6 +5,16 @@ from i3pystatus.core.modules import Module, IntervalModule
|
||||
from i3pystatus.core.settings import SettingsBase
|
||||
from i3pystatus.core.util import formatp
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
h = logging.FileHandler(".i3pystatus-" + str(os.getpid()), delay=True)
|
||||
|
||||
logger = logging.getLogger("i3pystatus")
|
||||
logger.addHandler(h)
|
||||
logger.setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
__all__ = [
|
||||
|
29
i3pystatus/core/command.py
Normal file
29
i3pystatus/core/command.py
Normal file
@ -0,0 +1,29 @@
|
||||
# from subprocess import CalledProcessError
|
||||
import subprocess
|
||||
|
||||
|
||||
def run_through_shell(command, enable_shell=False):
|
||||
"""
|
||||
Retrieves output of command
|
||||
Returns tuple success (boolean)/ stdout(string) / stderr (string)
|
||||
|
||||
Don't use this function with programs that outputs lots of data since the output is saved
|
||||
in one variable
|
||||
"""
|
||||
returncode = None
|
||||
try:
|
||||
proc = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=enable_shell)
|
||||
|
||||
out, stderr = proc.communicate()
|
||||
out = out.decode("UTF-8")
|
||||
stderr = stderr.decode("UTF-8")
|
||||
|
||||
returncode = proc.returncode
|
||||
|
||||
except OSError as e:
|
||||
out = e.strerror
|
||||
stderr = e.strerror
|
||||
except subprocess.CalledProcessError as e:
|
||||
out = e.output
|
||||
|
||||
return returncode, out, stderr
|
@ -1,6 +1,7 @@
|
||||
from i3pystatus.core.util import KeyConstraintDict
|
||||
from i3pystatus.core.exceptions import ConfigKeyError, ConfigMissingError
|
||||
import inspect
|
||||
import logging
|
||||
|
||||
|
||||
class SettingsBase:
|
||||
@ -18,7 +19,7 @@ class SettingsBase:
|
||||
"""
|
||||
|
||||
settings = (
|
||||
("enable_log", "Set to true to log error to .i3pystatus-<pid> file"),
|
||||
("log_level", "Set to true to log error to .i3pystatus-<pid> file"),
|
||||
)
|
||||
|
||||
"""settings should be tuple containing two types of elements:
|
||||
@ -31,7 +32,8 @@ class SettingsBase:
|
||||
required = tuple()
|
||||
"""required can list settings which are required"""
|
||||
|
||||
enable_log = False
|
||||
log_level = logging.NOTSET
|
||||
logger = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def get_argument_dict(args, kwargs):
|
||||
@ -71,6 +73,8 @@ class SettingsBase:
|
||||
self.__name__ = "{}.{}".format(
|
||||
self.__module__, self.__class__.__name__)
|
||||
|
||||
self.logger = logging.getLogger(self.__name__)
|
||||
self.logger.setLevel(self.log_level)
|
||||
self.init()
|
||||
|
||||
def init(self):
|
||||
|
@ -1,7 +1,5 @@
|
||||
import subprocess
|
||||
|
||||
from i3pystatus import SettingsBase, IntervalModule
|
||||
from i3pystatus.core.util import internet, require
|
||||
from i3pystatus.core.command import run_through_shell
|
||||
|
||||
|
||||
class Backend(SettingsBase):
|
||||
@ -69,7 +67,9 @@ class Mail(IntervalModule):
|
||||
|
||||
def on_leftclick(self):
|
||||
if self.email_client:
|
||||
subprocess.Popen(self.email_client.split())
|
||||
retcode, _, stderr = run_through_shell(self.email_client)
|
||||
if retcode != 0 and stderr:
|
||||
self.logger.error(stderr)
|
||||
|
||||
def on_rightclick(self):
|
||||
self.run()
|
||||
|
@ -1,5 +1,8 @@
|
||||
from i3pystatus import IntervalModule
|
||||
from subprocess import check_output, CalledProcessError
|
||||
from i3pystatus.core.command import run_through_shell
|
||||
import logging
|
||||
|
||||
# logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Shell(IntervalModule):
|
||||
@ -19,21 +22,17 @@ class Shell(IntervalModule):
|
||||
required = ("command",)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
out = check_output(self.command, shell=True)
|
||||
color = self.color
|
||||
except CalledProcessError as e:
|
||||
out = e.output
|
||||
color = self.error_color
|
||||
retvalue, out, stderr = run_through_shell(self.command, enable_shell=True)
|
||||
|
||||
out = out.decode("UTF-8").replace("\n", " ")
|
||||
try:
|
||||
if out[-1] == " ":
|
||||
out = out[:-1]
|
||||
except:
|
||||
out = ""
|
||||
if retvalue != 0:
|
||||
self.logger.error(stderr if stderr else "Unknown error")
|
||||
|
||||
if out:
|
||||
out.replace("\n", " ").strip()
|
||||
elif stderr:
|
||||
out = stderr
|
||||
|
||||
self.output = {
|
||||
"full_text": out,
|
||||
"color": color
|
||||
"full_text": out if out else "Command `%s` returned %d" % (self.command, retvalue),
|
||||
"color": self.color if retvalue == 0 else self.error_color
|
||||
}
|
||||
|
@ -11,7 +11,8 @@ class IntervalModuleMetaTest(unittest.TestCase):
|
||||
def test_no_settings(self):
|
||||
class NoSettings(IntervalModule):
|
||||
pass
|
||||
self.assertTrue('interval' in NoSettings.settings)
|
||||
for element in ('interval', ):
|
||||
self.assertIn(element, NoSettings.settings)
|
||||
|
||||
def test_no_interval_setting(self):
|
||||
class NoIntervalSetting(IntervalModule):
|
||||
@ -20,9 +21,9 @@ class IntervalModuleMetaTest(unittest.TestCase):
|
||||
(('option', 'desc'), 'interval'))
|
||||
|
||||
def test_settings_with_interval(self):
|
||||
class SettingsInteval(IntervalModule):
|
||||
class SettingsInterval(IntervalModule):
|
||||
settings = ('option', 'interval')
|
||||
self.assertEqual(SettingsInteval.settings, ('option', 'interval'))
|
||||
self.assertEqual(SettingsInterval.settings, ('option', 'interval'))
|
||||
|
||||
def test_settings_with_interval_desc(self):
|
||||
class SetttingsIntervalDesc(IntervalModule):
|
||||
|
24
tests/test_shell.py
Normal file
24
tests/test_shell.py
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import unittest
|
||||
import logging
|
||||
|
||||
from i3pystatus.shell import Shell
|
||||
from i3pystatus.core.command import run_through_shell
|
||||
|
||||
|
||||
class ShellModuleMetaTest(unittest.TestCase):
|
||||
|
||||
valid_output = "hello world"
|
||||
|
||||
def test_shell_correct_output(self):
|
||||
# ShellTest test
|
||||
# http://python.readthedocs.org/en/latest/library/unittest.html
|
||||
retcode, out, err = run_through_shell("echo '%s'" % (self.valid_output), enable_shell=True)
|
||||
self.assertTrue(retcode == 0)
|
||||
self.assertEqual(out.strip(), self.valid_output)
|
||||
|
||||
def test_program_failure(self):
|
||||
success, out, err = run_through_shell("thisshouldtriggeranerror")
|
||||
self.assertFalse(success)
|
Loading…
Reference in New Issue
Block a user