shell.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. # Copyright (c) 2021 Project CHIP Authors
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import logging
  15. import os
  16. import subprocess
  17. import threading
  18. class LogPipe(threading.Thread):
  19. def __init__(self, level):
  20. """Setup the object with a logger and a loglevel
  21. and start the thread
  22. """
  23. threading.Thread.__init__(self)
  24. self.daemon = False
  25. self.level = level
  26. self.fd_read, self.fd_write = os.pipe()
  27. self.pipeReader = os.fdopen(self.fd_read, errors='replace')
  28. self.start()
  29. def fileno(self):
  30. """Return the write file descriptor of the pipe"""
  31. return self.fd_write
  32. def run(self):
  33. """Run the thread, logging everything."""
  34. for line in iter(self.pipeReader.readline, ''):
  35. logging.log(self.level, line.strip('\n'))
  36. self.pipeReader.close()
  37. def close(self):
  38. """Close the write end of the pipe."""
  39. os.close(self.fd_write)
  40. class ShellRunner:
  41. def __init__(self, root: str):
  42. self.dry_run = False
  43. self.root_dir = root
  44. def StartCommandExecution(self):
  45. pass
  46. def Run(self, cmd, title=None):
  47. outpipe = LogPipe(logging.INFO)
  48. errpipe = LogPipe(logging.WARN)
  49. if title:
  50. logging.info(title)
  51. with subprocess.Popen(cmd, cwd=self.root_dir,
  52. stdout=outpipe, stderr=errpipe) as s:
  53. outpipe.close()
  54. errpipe.close()
  55. code = s.wait()
  56. if code != 0:
  57. raise Exception('Command %r failed: %d' % (cmd, code))
  58. else:
  59. logging.info('Command %r completed', cmd)