Skip to content

Commit

Permalink
Provide a log_msg call_arg to change log message
Browse files Browse the repository at this point in the history
  • Loading branch information
novas0x2a committed Apr 14, 2016
1 parent d73e8ce commit c619a72
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 10 deletions.
28 changes: 18 additions & 10 deletions sh.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,17 @@ def friendly_truncate(s, max_len):
return s


def default_logger_str(cmd, call_args):
friendly_cmd = friendly_truncate(cmd, 20)
friendly_call_args = friendly_truncate(str(call_args), 20)

# we're setting up the logger string here, instead of __repr__ because
# we reserve __repr__ to behave as if it was evaluating the child
# process's output
return "<Command %r call_args %s>" % (friendly_cmd, friendly_call_args)



class RunningCommand(object):
""" this represents an executing Command object. it is returned as the
result of __call__() being executed on a Command instance. this creates a
Expand All @@ -420,17 +431,10 @@ def __init__(self, cmd, call_args, stdin, stdout, stderr):
else:
self.ran = " ".join(cmd)


friendly_cmd = friendly_truncate(self.ran, 20)
friendly_call_args = friendly_truncate(str(call_args), 20)

# we're setting up the logger string here, instead of __repr__ because
# we reserve __repr__ to behave as if it was evaluating the child
# process's output
logger_str = "<Command %r call_args %s>" % (friendly_cmd,
friendly_call_args)

log_msg_cmd = call_args.get('log_msg') or default_logger_str
logger_str = log_msg_cmd(self.ran, call_args)
self.log = Logger("command", logger_str)

self.call_args = call_args
self.cmd = cmd

Expand Down Expand Up @@ -745,6 +749,10 @@ class Command(object):
# a tuple (rows, columns) of the desired size of both the stdout and
# stdin ttys, if ttys are being used
"tty_size": (20, 80),

# a callable that produces a log message from an argument tuple of the
# command and the args
"log_msg": None
}

# these are arguments that cannot be called together, because they wouldn't
Expand Down
31 changes: 31 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from os.path import exists, join, realpath
import unittest
import tempfile
import fnmatch
import logging
import sys
import sh
import platform
Expand Down Expand Up @@ -1906,6 +1908,31 @@ def test_signal_exception_aliases(self):

self.assertEqual(sig, SignalException_SIGQUIT)

def test_change_log_message(self):
py = create_tmp_test("""
print("cool")
""")
def log_msg(cmd, call_args):
return 'Hi! I ran <COMMAND %s>' % (cmd,)

buf = StringIO()
handler = logging.StreamHandler(buf)
logger = logging.getLogger('sh')
try:
logger.addHandler(handler)
with sh.args(log_msg=log_msg):
python(py.name, "meow", "bark")
finally:
logger.removeHandler(handler)

loglines = buf.getvalue().split('\n')
self.assertTrue(loglines, 'Log handler captured no messages?')
self.assertTrue(
fnmatch.fnmatch(loglines[0],
'Hi! I ran <COMMAND *python* meow bark>: starting process'),

'Log line did not match: %r' % (loglines[0],))


class StreamBuffererTests(unittest.TestCase):
def test_unbuffered(self):
Expand Down Expand Up @@ -1936,6 +1963,10 @@ def test_chunk_buffered(self):


if __name__ == "__main__":
root = logging.getLogger()
root.setLevel(logging.DEBUG)
root.addHandler(logging.NullHandler())

# if we're running a specific test, we can let unittest framework figure out
# that test and run it itself. it will also handle setting the return code
# of the process if any tests error or fail
Expand Down

0 comments on commit c619a72

Please sign in to comment.