utils.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. from __future__ import absolute_import
  2. from __future__ import division
  3. from __future__ import unicode_literals
  4. import os
  5. import platform
  6. import ssl
  7. import subprocess
  8. import sys
  9. import docker
  10. import compose
  11. from ..const import IS_WINDOWS_PLATFORM
  12. # WindowsError is not defined on non-win32 platforms. Avoid runtime errors by
  13. # defining it as OSError (its parent class) if missing.
  14. try:
  15. WindowsError
  16. except NameError:
  17. WindowsError = OSError
  18. def yesno(prompt, default=None):
  19. """
  20. Prompt the user for a yes or no.
  21. Can optionally specify a default value, which will only be
  22. used if they enter a blank line.
  23. Unrecognised input (anything other than "y", "n", "yes",
  24. "no" or "") will return None.
  25. """
  26. answer = input(prompt).strip().lower()
  27. if answer == "y" or answer == "yes":
  28. return True
  29. elif answer == "n" or answer == "no":
  30. return False
  31. elif answer == "":
  32. return default
  33. else:
  34. return None
  35. def input(prompt):
  36. """
  37. Version of input (raw_input in Python 2) which forces a flush of sys.stdout
  38. to avoid problems where the prompt fails to appear due to line buffering
  39. """
  40. sys.stdout.write(prompt)
  41. sys.stdout.flush()
  42. return sys.stdin.readline().rstrip('\n')
  43. def call_silently(*args, **kwargs):
  44. """
  45. Like subprocess.call(), but redirects stdout and stderr to /dev/null.
  46. """
  47. with open(os.devnull, 'w') as shutup:
  48. try:
  49. return subprocess.call(*args, stdout=shutup, stderr=shutup, **kwargs)
  50. except WindowsError:
  51. # On Windows, subprocess.call() can still raise exceptions. Normalize
  52. # to POSIXy behaviour by returning a nonzero exit code.
  53. return 1
  54. def is_mac():
  55. return platform.system() == 'Darwin'
  56. def is_ubuntu():
  57. return platform.system() == 'Linux' and platform.linux_distribution()[0] == 'Ubuntu'
  58. def is_windows():
  59. return IS_WINDOWS_PLATFORM
  60. def get_version_info(scope):
  61. versioninfo = 'docker-compose version {}, build {}'.format(
  62. compose.__version__,
  63. get_build_version())
  64. if scope == 'compose':
  65. return versioninfo
  66. if scope == 'full':
  67. return (
  68. "{}\n"
  69. "docker-py version: {}\n"
  70. "{} version: {}\n"
  71. "OpenSSL version: {}"
  72. ).format(
  73. versioninfo,
  74. docker.version,
  75. platform.python_implementation(),
  76. platform.python_version(),
  77. ssl.OPENSSL_VERSION)
  78. raise ValueError("{} is not a valid version scope".format(scope))
  79. def get_build_version():
  80. filename = os.path.join(os.path.dirname(compose.__file__), 'GITSHA')
  81. if not os.path.exists(filename):
  82. return 'unknown'
  83. with open(filename) as fh:
  84. return fh.read().strip()
  85. def is_docker_for_mac_installed():
  86. return is_mac() and os.path.isdir('/Applications/Docker.app')
  87. def generate_user_agent():
  88. parts = [
  89. "docker-compose/{}".format(compose.__version__),
  90. "docker-py/{}".format(docker.__version__),
  91. ]
  92. try:
  93. p_system = platform.system()
  94. p_release = platform.release()
  95. except IOError:
  96. pass
  97. else:
  98. parts.append("{}/{}".format(p_system, p_release))
  99. return " ".join(parts)
  100. def unquote_path(s):
  101. if not s:
  102. return s
  103. if s[0] == '"' and s[-1] == '"':
  104. return s[1:-1]
  105. return s