10000 A support of 'cwd' parameter is added to OsOperations::exec_command (… · postgrespro/testgres@8edea09 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8edea09

Browse files
A support of 'cwd' parameter is added to OsOperations::exec_command (#272)
1 parent 9da8981 commit 8edea09

File tree

3 files changed

+99
-24
lines changed

3 files changed

+99
-24
lines changed

testgres/operations/local_ops.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,13 @@ def _process_output(encoding, temp_file_path):
6767
output = output.decode(encoding)
6868
return output, None # In Windows stderr writing in stdout
6969

70-
def _run_command__nt(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding, exec_env=None):
70+
def _run_command__nt(
71+
self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding,
72+
exec_env: typing.Optional[dict],
73+
cwd: typing.Optional[str],
74+
):
7175
assert exec_env is None or type(exec_env) == dict # noqa: E721
76+
assert cwd is None or type(cwd) == str # noqa: E721
7277

7378
# TODO: why don't we use the data from input?
7479

@@ -104,6 +109,7 @@ def _run_command__nt(self, cmd, shell, input, stdin, stdout, stderr, get_process
104109
stdin=stdin or subprocess.PIPE if input is not None else None,
105110
stdout=stdout,
106111
stderr=stderr,
112+
cwd=cwd,
107113
**extParams,
108114
)
109115
if get_process:
@@ -116,8 +122,13 @@ def _run_command__nt(self, cmd, shell, input, stdin, stdout, stderr, get_process
116122
output, error = self._process_output(encoding, temp_file_path)
117123
return process, output, error
118124

119-
def _run_command__generic(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding, exec_env=None):
125+
def _run_command__generic(
126+
self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding,
127+
exec_env: typing.Optional[dict],
128+
cwd: typing.Optional[str],
129+
):
120130
assert exec_env is None or type(exec_env) == dict # noqa: E721
131+
assert cwd is None or type(cwd) == str # noqa: E721
121132

122133
input_prepared = None
123134
if not get_process:
@@ -154,6 +165,7 @@ def _run_command__generic(self, cmd, shell, input, stdin, stdout, stderr, get_pr
154165
stdin=stdin or subprocess.PIPE if input is not None else None,
155166
stdout=stdout or subprocess.PIPE,
156167
stderr=stderr or subprocess.PIPE,
168+
cwd=cwd,
157169
**extParams
158170
)
159171
assert not (process is None)
@@ -173,26 +185,44 @@ def _run_command__generic(self, cmd, shell, input, stdin, stdout, stderr, get_pr
173185
error = error.decode(encoding)
174186
return process, output, error
175187

176-
def _run_command(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding, exec_env=None):
188+
def _run_command(
189+
self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding,
190+
exec_env: typing.Optional[dict],
191+
cwd: typing.Optional[str],
192+
):
177193
"""Execute a command and return the process and its output."""
194+
195+
assert exec_env is None or type(exec_env) == dict # noqa: E721
196+
assert cwd is None or type(cwd) == str # noqa: E721
197+
178198
if os.name == 'nt' and stdout is None: # Windows
179199
method = __class__._run_command__nt
180200
else: # Other OS
181201
method = __class__._run_command__generic
182202

183-
return method(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding, exec_env=exec_env)
203+
return method(self, cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding, exec_env, cwd)
184204

185-
def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False, encoding=None, shell=False,
186-
text=False, input=None, stdin=None, stdout=None, stderr=None, get_process=False, timeout=None,
187-
ignore_errors=False, exec_env=None):
205+
def exec_command(
206+
self, cmd, wait_exit=False, verbose=False, expect_error=False, encoding=None, shell=False,
207+
text=False, input=None, stdin=None, stdout=None, stderr=None, get_process=False, timeout=None,
208+
ignore_errors=False,
209+
exec_env: typing.Optional[dict] = None,
210+
cwd: typing.Optional[str] = None
211+
):
188212
"""
189213
Execute a command in a subprocess and handle the output based on the provided parameters.
190214
"""
191215
assert type(expect_error) == bool # noqa: E721
192216
assert type(ignore_errors) == bool # noqa: E721
193217
assert exec_env is None or type(exec_env) == dict # noqa: E721
218+
assert cwd is None or type(cwd) == str # noqa: E721
219+
220+
process, output, error = self._run_command(
221+
cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding,
222+
exec_env,
223+
cwd
224+
)
194225

195-
process, output, error = self._run_command(cmd, shell, input, stdin, stdout, stderr, get_process, timeout, encoding, exec_env=exec_env)
196226
if get_process:
197227
return process
198228

testgres/operations/remote_ops.py

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,13 @@ def __init__(self, conn_params: ConnectionParams):
6363
def __enter__(self):
6464
return self
6565

66-
def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False,
67-
encoding=None, shell=True, text=False, input=None, stdin=None, stdout=None,
68-
stderr=None, get_process=None, timeout=None, ignore_errors=False,
69-
exec_env=None):
66+
def exec_command(
67+
self, cmd, wait_exit=False, verbose=False, expect_error=False,
68+
encoding=None, shell=True, text=False, input=None, stdin=None, stdout=None,
69+
stderr=None, get_process=None, timeout=None, ignore_errors=False,
70+
exec_env: typing.Optional[dict] = None,
71+
cwd: typing.Optional[str] = None
72+
):
7073
"""
7174
Execute a command in the SSH session.
7275
Args:
@@ -75,28 +78,29 @@ def exec_command(self, cmd, wait_exit=False, verbose=False, expect_error=False,
7578
assert type(expect_error) == bool # noqa: E721
7679
assert type(ignore_errors) == bool # noqa: E721
7780
assert exec_env is None or type(exec_env) == dict # noqa: E721
81+
assert cwd is None or type(cwd) == str # noqa: E721
7882

7983
input_prepared = None
8084
if not get_process:
8185
input_prepared = Helpers.PrepareProcessInput(input, encoding) # throw
8286

8387
assert input_prepared is None or (type(input_prepared) == bytes) # noqa: E721
8488

85-
if type(cmd) == str: # noqa: E721
86-
cmd_s = cmd
87-
elif type(cmd) == list: # noqa: E721
88-
cmd_s = subprocess.list2cmdline(cmd)
89-
else:
90-
raise ValueError("Invalid 'cmd' argument type - {0}".format(type(cmd).__name__))
89+
cmds = []
9190

92-
assert type(cmd_s) == str # noqa: E721
91+
if cwd is not None:
92+
assert type(cwd) == str # noqa: E721
93+
cmds.append(__class__._build_cmdline(["cd", cwd]))
94+
95+
cmds.append(__class__._build_cmdline(cmd, exec_env))
9396

94-
cmd_items = __class__._make_exec_env_list(exec_env=exec_env)
95-
cmd_items.append(cmd_s)
97+
assert len(cmds) >= 1
9698

97-
env_cmd_s = ';'.join(cmd_items)
99+
cmdline = ";".join(cmds)
100+
assert type(cmdline) == str # noqa: E721
101+
assert cmdline != ""
98102

99-
ssh_cmd = ['ssh', self.ssh_dest] + self.ssh_args + [env_cmd_s]
103+
ssh_cmd = ['ssh', self.ssh_dest] + self.ssh_args + [cmdline]
100104

101105
process = subprocess.Popen(ssh_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
102106
assert not (process is None)
@@ -718,7 +722,31 @@ def _is_port_free__process_1(error: str) -> bool:
718722
return True
719723

720724
@staticmethod
721-
def _make_exec_env_list(exec_env: typing.Dict) -> typing.List[str]:
725+
def _build_cmdline(cmd, exec_env: typing.Dict = None) -> str:
726+
cmd_items = __class__._create_exec_env_list(exec_env)
727+
728+
assert type(cmd_items) == list # noqa: E721
729+
730+
cmd_items.append(__class__._ensure_cmdline(cmd))
731+
732+
cmdline = ';'.join(cmd_items)
733+
assert type(cmdline) == str # noqa: E721
734+
return cmdline
735+
736+
@staticmethod
737+
def _ensure_cmdline(cmd) -> typing.List[str]:
738+
if type(cmd) == str: # noqa: E721
739+
cmd_s = cmd
740+
elif type(cmd) == list: # noqa: E721
741+
cmd_s = subprocess.list2cmdline(cmd)
742+
else:
743+
raise ValueError("Invalid 'cmd' argument type - {0}".format(type(cmd).__name__))
744+
745+
assert type(cmd_s) == str # noqa: E721
746+
return cmd_s
747+
748+
@staticmethod
749+
def _create_exec_env_list(exec_env: typing.Dict) -> typing.List[str]:
722750
env: typing.Dict[str, str] = dict()
723751

724752
# ---------------------------------- SYSTEM ENV

tests/test_os_ops_common.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,23 @@ def test_exec_command_with_exec_env(self, os_ops: OsOperations):
118118
assert type(response) == bytes # noqa: E721
119119
assert response == b'\n'
120120

121+
def test_exec_command_with_cwd(self, os_ops: OsOperations):
122+
assert isinstance(os_ops, OsOperations)
123+
124+
RunConditions.skip_if_windows()
125+
126+
cmd = ["pwd"]
127+
128+
response = os_ops.exec_command(cmd, cwd="/tmp")
129+
assert response is not None
130+
assert type(response) == bytes # noqa: E721
131+
assert response == b'/tmp\n'
132+
133+
response = os_ops.exec_command(cmd)
134+
assert response is not None
135+
assert type(response) == bytes # noqa: E721
136+
assert response != b'/tmp\n'
137+
121138
def test_exec_command__test_unset(self, os_ops: OsOperations):
122139
assert isinstance(os_ops, OsOperations)
123140

0 commit comments

Comments
 (0)
0