helpers.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import argparse
  2. import grp
  3. import hashlib
  4. import logging
  5. import msgpack
  6. import pwd
  7. import re
  8. import zlib
  9. def pack(data):
  10. data = zlib.compress(msgpack.packb(data))
  11. id = hashlib.sha256(data).digest()
  12. tid = 0
  13. return id, msgpack.packb((1, tid, id, data))
  14. def unpack(data):
  15. version, tid, id, data = msgpack.unpackb(data)
  16. assert version == 1
  17. if hashlib.sha256(data).digest() != id:
  18. raise ValueError
  19. return msgpack.unpackb(zlib.decompress(data))
  20. def memoize(function):
  21. cache = {}
  22. def decorated_function(*args):
  23. try:
  24. return cache[args]
  25. except KeyError:
  26. val = function(*args)
  27. cache[args] = val
  28. return val
  29. return decorated_function
  30. @memoize
  31. def uid2user(uid):
  32. try:
  33. return pwd.getpwuid(uid).pw_name
  34. except KeyError:
  35. return None
  36. @memoize
  37. def user2uid(user):
  38. try:
  39. return pwd.getpwnam(user).pw_uid
  40. except KeyError:
  41. return None
  42. @memoize
  43. def gid2group(gid):
  44. try:
  45. return grp.getgrgid(gid).gr_name
  46. except KeyError:
  47. return None
  48. @memoize
  49. def group2gid(group):
  50. try:
  51. return grp.getgrnam(group).gr_gid
  52. except KeyError:
  53. return None
  54. class LevelFilter(logging.Filter):
  55. """Filter that counts record levels
  56. """
  57. def __init__(self, *args, **kwargs):
  58. logging.Filter.__init__(self, *args, **kwargs)
  59. self.count = {}
  60. def filter(self, record):
  61. self.count.setdefault(record.levelname, 0)
  62. self.count[record.levelname] += 1
  63. return record
  64. class Location(object):
  65. loc_re = re.compile(r'^((?:(?P<user>[^@]+)@)?(?P<host>[^:]+):)?'
  66. r'(?P<path>[^:]*)(?:::(?P<archive>[^:]+))?$')
  67. def __init__(self, text):
  68. loc = self.loc_re.match(text)
  69. loc = loc and loc.groupdict()
  70. if not loc:
  71. raise ValueError
  72. self.user = loc['user']
  73. self.host = loc['host']
  74. self.path = loc['path']
  75. if not self.host and not self.path:
  76. raise ValueError
  77. self.archive = loc['archive']
  78. def __str__(self):
  79. text = ''
  80. if self.user:
  81. text += '%s@' % self.user
  82. if self.host:
  83. text += '%s::' % self.host
  84. if self.path:
  85. text += self.path
  86. if self.archive:
  87. text += ':%s' % self.archive
  88. return text
  89. def __repr__(self):
  90. return "Location('%s')" % self
  91. def location_validator(archive=None):
  92. def validator(text):
  93. try:
  94. loc = Location(text)
  95. except ValueError:
  96. raise argparse.ArgumentTypeError('Invalid location format: "%s"' % text)
  97. if archive is True and not loc.archive:
  98. raise argparse.ArgumentTypeError('"%s": No archive specified' % text)
  99. elif archive is False and loc.archive:
  100. raise argparse.ArgumentTypeError('"%s" No archive can be specified' % text)
  101. return loc
  102. return validator
  103. def pretty_size(v):
  104. if v > 1024 * 1024 * 1024:
  105. return '%.2f GB' % (v / 1024. / 1024. / 1024.)
  106. elif v > 1024 * 1024:
  107. return '%.2f MB' % (v / 1024. / 1024.)
  108. elif v > 1024:
  109. return '%.2f kB' % (v / 1024.)
  110. else:
  111. return str(v)