export_util.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/env python
  2. # Copyright 2015-2016 Scott Bezek and the splitflap contributors
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import logging
  16. import os
  17. import re
  18. import subprocess
  19. import sys
  20. import tempfile
  21. import time
  22. from contextlib import contextmanager
  23. electronics_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  24. repo_root = os.path.dirname(electronics_root)
  25. sys.path.append(repo_root)
  26. from xvfbwrapper import Xvfb
  27. from util import file_util, rev_info
  28. logging.basicConfig(level=logging.DEBUG)
  29. logger = logging.getLogger(__name__)
  30. class PopenContext(subprocess.Popen):
  31. def __enter__(self):
  32. return self
  33. def __exit__(self, type, value, traceback):
  34. if self.stdout:
  35. self.stdout.close()
  36. if self.stderr:
  37. self.stderr.close()
  38. if self.stdin:
  39. self.stdin.close()
  40. if type:
  41. self.terminate()
  42. # Wait for the process to terminate, to avoid zombies.
  43. self.wait()
  44. def xdotool(command):
  45. return subprocess.check_output(['xdotool'] + command)
  46. def wait_for_window(name, window_regex, additional_commands=None, timeout=10):
  47. if additional_commands is not None:
  48. commands = additional_commands
  49. else:
  50. commands = []
  51. DELAY = 0.5
  52. logger.info('Waiting for %s window...', name)
  53. for i in range(int(timeout/DELAY)):
  54. try:
  55. xdotool(['search', '--name', window_regex] + commands)
  56. logger.info('Found %s window', name)
  57. return
  58. except subprocess.CalledProcessError:
  59. pass
  60. time.sleep(DELAY)
  61. raise RuntimeError('Timed out waiting for %s window' % name)
  62. @contextmanager
  63. def recorded_xvfb(video_filename, **xvfb_args):
  64. with Xvfb(**xvfb_args):
  65. with PopenContext([
  66. 'recordmydesktop',
  67. '--no-sound',
  68. '--no-frame',
  69. '--on-the-fly-encoding',
  70. '-o', video_filename], close_fds=True) as screencast_proc:
  71. yield
  72. screencast_proc.terminate()
  73. def get_versioned_contents(filename):
  74. with open(filename, 'r') as f:
  75. original_contents = f.read()
  76. date = rev_info.git_date()
  77. date_long = rev_info.git_date(short=False)
  78. rev = rev_info.git_short_rev()
  79. logger.info('Replacing placeholders with %s and %s' % (date, rev))
  80. return original_contents, original_contents \
  81. .replace('Date ""', 'Date "%s"' % date_long) \
  82. .replace('DATE: YYYY-MM-DD TIME TZ', 'DATE: %s' % date_long) \
  83. .replace('DATE: YYYY-MM-DD', 'DATE: %s' % date) \
  84. .replace('Rev ""', 'Rev "%s"' % rev) \
  85. .replace('COMMIT: deadbeef', 'COMMIT: %s' % rev)
  86. @contextmanager
  87. def versioned_file(filename):
  88. original_contents, versioned_contents = get_versioned_contents(filename)
  89. with open(filename, 'w') as temp_schematic:
  90. logger.debug('Writing to %s', filename)
  91. temp_schematic.write(versioned_contents)
  92. try:
  93. yield
  94. finally:
  95. with open(filename, 'w') as temp_schematic:
  96. logger.debug('Restoring %s', filename)
  97. temp_schematic.write(original_contents)
  98. @contextmanager
  99. def patch_config(filename, replacements):
  100. if not os.path.exists(filename):
  101. yield
  102. return
  103. with open(filename, 'r') as f:
  104. original_contents = f.read()
  105. new_contents = original_contents
  106. for (key, value) in replacements.items():
  107. pattern = '^' + re.escape(key) + '=(.*)$'
  108. new_contents = re.sub(pattern, key + '=' + value, new_contents, flags=re.MULTILINE)
  109. with open(filename, 'w') as f:
  110. logger.debug('Writing to %s', filename)
  111. f.write(new_contents)
  112. try:
  113. yield
  114. finally:
  115. with open(filename, 'w') as f:
  116. logger.debug('Restoring %s', filename)
  117. f.write(original_contents)