setup_util.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import re
  2. import os
  3. import sys
  4. import subprocess
  5. import platform
  6. from threading import Thread
  7. from Queue import Queue, Empty
  8. class NonBlockingStreamReader:
  9. '''
  10. Enables calling readline in a non-blocking manner with a blocking stream,
  11. such as the ones returned from subprocess.Popen
  12. Originally written by Eyal Arubas, who granted permission to use this inside TFB
  13. See http://eyalarubas.com/python-subproc-nonblock.html
  14. '''
  15. def __init__(self, stream, eof_message = None):
  16. '''
  17. stream: the stream to read from.
  18. Usually a process' stdout or stderr.
  19. eof_message: A message to print to stdout as soon
  20. as the stream's end is reached. Useful if you
  21. want to track the exact moment a stream terminates
  22. '''
  23. self._s = stream
  24. self._q = Queue()
  25. self._eof_message = eof_message
  26. self._poisonpill = 'MAGIC_POISONPILL_STRING'
  27. def _populateQueue(stream, queue):
  28. while True:
  29. line = stream.readline()
  30. if line: # 'data\n' or '\n'
  31. queue.put(line)
  32. else: # '' e.g. EOF
  33. if self._eof_message:
  34. sys.stdout.write(self._eof_message + '\n')
  35. queue.put(self._poisonpill)
  36. return
  37. self._t = Thread(target = _populateQueue,
  38. args = (self._s, self._q))
  39. self._t.daemon = True
  40. self._t.start()
  41. def readline(self, timeout = None):
  42. try:
  43. line = self._q.get(block = timeout is not None,
  44. timeout = timeout)
  45. if line == self._poisonpill:
  46. raise EndOfStream
  47. return line
  48. except Empty:
  49. return None
  50. class EndOfStream(Exception): pass
  51. # Replaces all text found using the regular expression to_replace with the supplied replacement.
  52. def replace_text(file, to_replace, replacement):
  53. with open(file, "r") as conf:
  54. contents = conf.read()
  55. replaced_text = re.sub(to_replace, replacement, contents)
  56. with open(file, "w") as f:
  57. f.write(replaced_text)
  58. # Replaces the current process environment with the one found in
  59. # config file. Retains a few original vars (HOME,PATH, etc) by default.
  60. # Optionally allows specification of a command to be run before loading
  61. # the environment, to allow the framework to set environment variables
  62. # Note: This command *cannot* print to stdout!
  63. #
  64. # Note: This will not replace the sudo environment (e.g. subprocess.check_call("sudo <command>")).
  65. # If you must use sudo, consider sudo sh -c ". <config> && your_command"
  66. def replace_environ(config=None, root=None, print_result=False, command='true'):
  67. if platform.system().lower() == 'windows':
  68. pass
  69. else:
  70. # Clean up our current environment, preserving some important items
  71. mini_environ = {}
  72. for envname in ['HOME', 'PATH', 'LANG', 'USER', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'FWROOT', 'TRAVIS']:
  73. if envname in os.environ:
  74. mini_environ[envname] = os.environ[envname]
  75. for key in os.environ:
  76. if key.startswith(('TFB_', 'TRAVIS_')): # Any TFB_* and TRAVIS_* variables are preserved
  77. mini_environ[key] = os.environ[key]
  78. os.environ.clear()
  79. # Use FWROOT if explicitely provided
  80. if root is not None:
  81. mini_environ['FWROOT']=root
  82. # Run command, source config file, and store resulting environment
  83. setup_env = "%s && . %s && env" % (command, config)
  84. env = ""
  85. try:
  86. env = subprocess.check_output(setup_env, shell=True, env=mini_environ,
  87. executable='/bin/bash')
  88. except subprocess.CalledProcessError:
  89. # Ensure that an error here does not crash the toolset
  90. print "CRITICAL: Loading %s returned non-zero exit" % config
  91. for key,value in mini_environ.iteritems():
  92. os.environ[key]=value
  93. return
  94. for line in env.split('\n'):
  95. try:
  96. key, value = line.split('=', 1)
  97. # If we already have this TFB_ variable, do not overwrite
  98. if key.startswith('TFB_') and key in mini_environ:
  99. os.environ[key]=mini_environ[key]
  100. else:
  101. os.environ[key]=value
  102. except Exception:
  103. if not line: # Don't warn for empty line
  104. continue
  105. print "WARN: Line '%s' from '%s' is not an environment variable" % (line, config)
  106. continue
  107. if print_result:
  108. out = subprocess.check_output('env', shell=True, executable='/bin/bash')
  109. print "Environment after loading %s" %config
  110. print out
  111. # Queries the shell for the value of FWROOT
  112. def get_fwroot():
  113. if platform.system().lower() == 'windows':
  114. fwroot = "C:\FrameworkBenchmarks"
  115. return fwroot
  116. else:
  117. try:
  118. # Use printf to avoid getting a newline
  119. # Redirect to avoid stderr printing
  120. fwroot = subprocess.check_output('printf $FWROOT 2> /dev/null', shell=True, executable='/bin/bash')
  121. return fwroot
  122. except subprocess.CalledProcessError:
  123. # Make a last-guess effort ;-)
  124. return os.getcwd();
  125. # Turns absolute path into path relative to FWROOT
  126. # Assumes path is underneath FWROOT, not above
  127. #
  128. # Useful for clean presentation of paths
  129. # e.g. /foo/bar/benchmarks/go/install.sh
  130. # v.s. FWROOT/go/install.sh
  131. def path_relative_to_root(path):
  132. # Requires bash shell parameter expansion
  133. return subprocess.check_output("D=%s && printf \"${D#%s}\""%(path, get_fwroot()), shell=True, executable='/bin/bash')