Merge "Update shell command tool"
This commit is contained in:
commit
770f3dab17
|
@ -19,35 +19,37 @@ import shlex
|
||||||
import typing # noqa
|
import typing # noqa
|
||||||
|
|
||||||
|
|
||||||
|
ShellCommandType = typing.Union['ShellCommand', str, typing.Iterable[str]]
|
||||||
|
|
||||||
|
|
||||||
class ShellCommand(tuple):
|
class ShellCommand(tuple):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return "ShellCommand([{!s}])".format(', '.join(self))
|
return f"ShellCommand({str(self)!r})"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return list_to_command_line(self)
|
return join_command(self)
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other: ShellCommandType) -> 'ShellCommand':
|
||||||
other = shell_command(other)
|
return shell_command(tuple(self) + shell_command(other))
|
||||||
return shell_command(tuple(self) + other)
|
|
||||||
|
|
||||||
|
|
||||||
ShellCommandType = typing.Union[ShellCommand, str, typing.Iterable]
|
|
||||||
|
|
||||||
|
|
||||||
def shell_command(command: ShellCommandType) -> ShellCommand:
|
def shell_command(command: ShellCommandType) -> ShellCommand:
|
||||||
if isinstance(command, ShellCommand):
|
if isinstance(command, ShellCommand):
|
||||||
return command
|
return command
|
||||||
elif isinstance(command, str):
|
elif isinstance(command, str):
|
||||||
return ShellCommand(shlex.split(command))
|
return ShellCommand(split_command(command))
|
||||||
else:
|
else:
|
||||||
return ShellCommand(str(a) for a in command)
|
return ShellCommand(str(a) for a in command)
|
||||||
|
|
||||||
|
|
||||||
def list_to_command_line(seq):
|
NEED_QUOTE_CHARS = {' ', '\t', '\n', '\r', "'", '"'}
|
||||||
result = []
|
|
||||||
for arg in seq:
|
|
||||||
bs_buf = []
|
def join_command(sequence: typing.Iterable[str]) -> str:
|
||||||
|
result: typing.List[str] = []
|
||||||
|
for arg in sequence:
|
||||||
|
bs_buf: typing.List[str] = []
|
||||||
|
|
||||||
# Add a space to separate this argument from the others
|
# Add a space to separate this argument from the others
|
||||||
if result:
|
if result:
|
||||||
|
@ -82,3 +84,7 @@ def list_to_command_line(seq):
|
||||||
result.append("'")
|
result.append("'")
|
||||||
|
|
||||||
return ''.join(result)
|
return ''.join(result)
|
||||||
|
|
||||||
|
|
||||||
|
def split_command(command: str) -> typing.Sequence[str]:
|
||||||
|
return shlex.split(command)
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
# Copyright (c) 2021 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
|
||||||
|
from tobiko.shell import sh
|
||||||
|
from tobiko.tests import unit
|
||||||
|
|
||||||
|
|
||||||
|
class ShellCommandTest(unit.TobikoUnitTest):
|
||||||
|
|
||||||
|
def test_from_str(self):
|
||||||
|
result = sh.shell_command('ls -lh *.py')
|
||||||
|
self.assertIsInstance(result, sh.ShellCommand)
|
||||||
|
self.assertEqual(('ls', '-lh', '*.py'), result)
|
||||||
|
self.assertEqual("ls -lh *.py", str(result))
|
||||||
|
|
||||||
|
def test_from_str_with_quotes(self):
|
||||||
|
result = sh.shell_command('ls -lh "with quotes"')
|
||||||
|
self.assertIsInstance(result, sh.ShellCommand)
|
||||||
|
self.assertEqual(('ls', '-lh', "with quotes"), result)
|
||||||
|
self.assertEqual("ls -lh 'with quotes'", str(result))
|
||||||
|
|
||||||
|
def test_from_sequence(self):
|
||||||
|
result = sh.shell_command(['ls', '-lh', '*.py'])
|
||||||
|
self.assertIsInstance(result, sh.ShellCommand)
|
||||||
|
self.assertEqual(('ls', '-lh', '*.py'), result)
|
||||||
|
self.assertEqual("ls -lh *.py", str(result))
|
||||||
|
|
||||||
|
def test_from_sequence_with_quotes(self):
|
||||||
|
result = sh.shell_command(['ls', '-lh', "with quotes"])
|
||||||
|
self.assertIsInstance(result, sh.ShellCommand)
|
||||||
|
self.assertEqual(('ls', '-lh', "with quotes"), result)
|
||||||
|
self.assertEqual("ls -lh 'with quotes'", str(result))
|
||||||
|
|
||||||
|
def test_from_shell_command(self):
|
||||||
|
other = sh.shell_command(['ls', '-lh', '*.py'])
|
||||||
|
result = sh.shell_command(other)
|
||||||
|
self.assertIs(other, result)
|
||||||
|
|
||||||
|
def test_add_str(self):
|
||||||
|
base = sh.shell_command('ssh pippo@clubhouse.mouse')
|
||||||
|
result = base + 'ls -lh *.py'
|
||||||
|
self.assertEqual(('ssh', 'pippo@clubhouse.mouse', 'ls', '-lh', '*.py'),
|
||||||
|
result)
|
||||||
|
self.assertEqual("ssh pippo@clubhouse.mouse ls -lh *.py",
|
||||||
|
str(result))
|
||||||
|
|
||||||
|
def test_add_str_with_quotes(self):
|
||||||
|
base = sh.shell_command('sh -c')
|
||||||
|
result = base + "'echo Hello!'"
|
||||||
|
self.assertIsInstance(result, sh.ShellCommand)
|
||||||
|
self.assertEqual(('sh', '-c', "echo Hello!"), result)
|
||||||
|
self.assertEqual("sh -c 'echo Hello!'", str(result))
|
||||||
|
|
||||||
|
def test_add_sequence(self):
|
||||||
|
base = sh.shell_command('ssh pippo@clubhouse.mouse')
|
||||||
|
result = base + ['ls', '-lh', '*.py']
|
||||||
|
self.assertEqual(('ssh', 'pippo@clubhouse.mouse', 'ls', '-lh', '*.py'),
|
||||||
|
result)
|
||||||
|
self.assertEqual("ssh pippo@clubhouse.mouse ls -lh *.py",
|
||||||
|
str(result))
|
||||||
|
|
||||||
|
def test_add_sequence_with_quotes(self):
|
||||||
|
base = sh.shell_command('sh -c')
|
||||||
|
result = base + ['echo Hello!']
|
||||||
|
self.assertIsInstance(result, sh.ShellCommand)
|
||||||
|
self.assertEqual(('sh', '-c', "echo Hello!"), result)
|
||||||
|
self.assertEqual("sh -c 'echo Hello!'", str(result))
|
||||||
|
|
||||||
|
def test_add_shell_command(self):
|
||||||
|
base = sh.shell_command('ssh pippo@clubhouse.mouse')
|
||||||
|
result = base + sh.shell_command(['ls', '-lh', '*.py'])
|
||||||
|
self.assertEqual(('ssh', 'pippo@clubhouse.mouse', 'ls', '-lh', '*.py'),
|
||||||
|
result)
|
||||||
|
self.assertEqual("ssh pippo@clubhouse.mouse ls -lh *.py",
|
||||||
|
str(result))
|
||||||
|
|
||||||
|
def test_add_shell_command_with_quotes(self):
|
||||||
|
base = sh.shell_command('sh -c')
|
||||||
|
result = base + sh.shell_command(['echo Hello!'])
|
||||||
|
self.assertIsInstance(result, sh.ShellCommand)
|
||||||
|
self.assertEqual(('sh', '-c', "echo Hello!"), result)
|
||||||
|
self.assertEqual("sh -c 'echo Hello!'", str(result))
|
Loading…
Reference in New Issue