utils.py 3.8 KB

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