| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- # Copyright (c) 2024 PaddlePaddle Authors. 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.
- import asyncio
- import subprocess
- from ....utils.logging import info
- __all__ = ["run_cmd", "CompletedProcess"]
- def run_cmd(
- cmd,
- env=None,
- silent=True,
- cwd=None,
- timeout=None,
- echo=False,
- pipe_stdout=False,
- pipe_stderr=False,
- blocking=True,
- async_run=False,
- text=True,
- ):
- """Wrap around `subprocess.Popen` to execute a shell command."""
- # TODO: Limit argument length
- cfg = dict(env=env, cwd=cwd)
- async_run = async_run and not blocking
- if blocking:
- cfg["timeout"] = timeout
- if silent:
- cfg["stdout"] = (
- subprocess.DEVNULL if not async_run else asyncio.subprocess.DEVNULL
- )
- cfg["stderr"] = (
- subprocess.STDOUT if not async_run else asyncio.subprocess.STDOUT
- )
- if not async_run and (pipe_stdout or pipe_stderr):
- cfg["text"] = True
- if pipe_stdout:
- cfg["stdout"] = subprocess.PIPE if not async_run else asyncio.subprocess.PIPE
- if pipe_stderr:
- cfg["stderr"] = subprocess.PIPE if not async_run else asyncio.subprocess.PIPE
- if echo:
- info(str(cmd))
- if blocking:
- return subprocess.run(cmd, **cfg, check=False)
- else:
- if async_run:
- return asyncio.create_subprocess_exec(cmd[0], *cmd[1:], **cfg)
- else:
- if text:
- cfg.update(dict(bufsize=1, text=True))
- else:
- cfg.update(dict(bufsize=0, text=False))
- return subprocess.Popen(cmd, **cfg)
- class CompletedProcess(object):
- """CompletedProcess"""
- __slots__ = ["args", "returncode", "stdout", "stderr", "_add_attrs"]
- def __init__(self, args, returncode, stdout=None, stderr=None):
- super().__init__()
- self.args = args
- self.returncode = returncode
- self.stdout = stdout
- self.stderr = stderr
- self._add_attrs = dict()
- def __getattr__(self, name):
- try:
- val = self._add_attrs[name]
- return val
- except KeyError:
- raise AttributeError
- def __setattr__(self, name, val):
- try:
- super().__setattr__(name, val)
- except AttributeError:
- self._add_attrs[name] = val
- def __repr__(self):
- args = [f"args={repr(self.args)}", f"returncode={repr(self.returncode)}"]
- if self.stdout is not None:
- args.append(f"stdout={repr(self.stdout)}")
- if self.stderr is not None:
- args.append(f"stderr={repr(self.stderr)}")
- return f"{self.__class__.__name__}({', '.join(args)})"
|