-
-
Notifications
You must be signed in to change notification settings - Fork 503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add '_cmd_cls' special keyword for passing a RunningCommand subclass #250
Conversation
Interesting. What kinds of things are you doing/anticipating that would be accomplished with a custom class? I'm not opposed to the idea, but I am curious |
My original use case was logging each command before it runs as well as its stdout, stderr and exit code (if not zero) after it runs, something like this: import sh
class LoggingRunningCommand(sh.RunningCommand):
def __init__(self, cmd, call_args, stdin, stdout, stderr):
print '$ {}'.format(' '.join(cmd))
try:
super(LoggingRunningCommand, self).__init__(cmd, call_args, stdin,
stdout, stderr)
except sh.ErrorReturnCode:
pass
self._log('STDOUT', self.stdout)
self._log('STDERR', self.stderr)
if self.exit_code:
print '*** ABORTED (exit_code={}) ***'.format(self.exit_code)
exit(self.exit_code)
@staticmethod
def _log(label, text):
if text.strip():
print '>>> START {label}\n{text}\n<<< END {label}\n'.format(**locals())
if __name__ == '__main__':
sh.ls(__file__, 'foo', _cmd_cls=LoggingRunningCommand) Output:
But I can imagine more complex things one could do, like storing in a list all commands/outputs/exit codes that are run within a session, to be used for auditing, replaying, etc. |
It's an interesting idea. I'll tell you my thought process... currently the existing By accepting this work, I would be adding something that isn't fully able to be used reliably (because of the incomplete/unstable base-class API), but I'm not yet convinced that the need is there to warrant building it out. So I don't want to add something that's incomplete, nor do I want to add complexity for something that is unlikely to be used often. I know this doesn't help your current situation. sh does have some decent logging happening, which can be activated by |
I see what you're saying and it's definitely an advanced feature, requiring one to dive into the As for logging, it's maybe useful for debugging purposes but not really suitable for end-user feedback. For one thing, if there is no error it doesn't print the stdout and/or stderr, and the command itself is truncated:
If there is an error, it prints out the full command, stdout and stderr but also prints the full traceback which I'd rather not show:
These choices make sense from logging point of view ( |
FWIW, to get reasonable logging I had to do the same thing, except I just monkey patched the |
be4e486
to
d0db089
Compare
Closing this with similar thoughts as my previous comment |
Sometimes it's necessary to customize how a command is run in a way that:
(a) it is not supported by any existing special keyword arguments and
(b) it doesn't make sense to add a new special keyword to
sh
for it because it is very specific to the particular use case.This PR introduces a new special keyword,
_cmd_cls
(feel free to pick a better name), that allows the client to pass a customRunningCommand
subclass. This opens up new possibilities that aren't currently possible (at least not without monkeypatchingsh.RunningCommand
).