utils.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from __future__ import unicode_literals
  2. from __future__ import absolute_import
  3. from __future__ import division
  4. import datetime
  5. import os
  6. import socket
  7. import subprocess
  8. from .errors import UserError
  9. def cached_property(f):
  10. """
  11. returns a cached property that is calculated by function f
  12. http://code.activestate.com/recipes/576563-cached-property/
  13. """
  14. def get(self):
  15. try:
  16. return self._property_cache[f]
  17. except AttributeError:
  18. self._property_cache = {}
  19. x = self._property_cache[f] = f(self)
  20. return x
  21. except KeyError:
  22. x = self._property_cache[f] = f(self)
  23. return x
  24. return property(get)
  25. def yesno(prompt, default=None):
  26. """
  27. Prompt the user for a yes or no.
  28. Can optionally specify a default value, which will only be
  29. used if they enter a blank line.
  30. Unrecognised input (anything other than "y", "n", "yes",
  31. "no" or "") will return None.
  32. """
  33. answer = raw_input(prompt).strip().lower()
  34. if answer == "y" or answer == "yes":
  35. return True
  36. elif answer == "n" or answer == "no":
  37. return False
  38. elif answer == "":
  39. return default
  40. else:
  41. return None
  42. # http://stackoverflow.com/a/5164027
  43. def prettydate(d):
  44. diff = datetime.datetime.utcnow() - d
  45. s = diff.seconds
  46. if diff.days > 7 or diff.days < 0:
  47. return d.strftime('%d %b %y')
  48. elif diff.days == 1:
  49. return '1 day ago'
  50. elif diff.days > 1:
  51. return '{0} days ago'.format(diff.days)
  52. elif s <= 1:
  53. return 'just now'
  54. elif s < 60:
  55. return '{0} seconds ago'.format(s)
  56. elif s < 120:
  57. return '1 minute ago'
  58. elif s < 3600:
  59. return '{0} minutes ago'.format(s/60)
  60. elif s < 7200:
  61. return '1 hour ago'
  62. else:
  63. return '{0} hours ago'.format(s/3600)
  64. def mkdir(path, permissions=0o700):
  65. if not os.path.exists(path):
  66. os.mkdir(path)
  67. os.chmod(path, permissions)
  68. return path
  69. def docker_url():
  70. return os.environ.get('DOCKER_HOST')
  71. def split_buffer(reader, separator):
  72. """
  73. Given a generator which yields strings and a separator string,
  74. joins all input, splits on the separator and yields each chunk.
  75. Unlike string.split(), each chunk includes the trailing
  76. separator, except for the last one if none was found on the end
  77. of the input.
  78. """
  79. buffered = str('')
  80. separator = str(separator)
  81. for data in reader:
  82. buffered += data
  83. while True:
  84. index = buffered.find(separator)
  85. if index == -1:
  86. break
  87. yield buffered[:index+1]
  88. buffered = buffered[index+1:]
  89. if len(buffered) > 0:
  90. yield buffered
  91. def call_silently(*args, **kwargs):
  92. """
  93. Like subprocess.call(), but redirects stdout and stderr to /dev/null.
  94. """
  95. with open(os.devnull, 'w') as shutup:
  96. return subprocess.call(*args, stdout=shutup, stderr=shutup, **kwargs)