utils.py 3.8 KB

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