helpers.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import argparse
  2. from datetime import datetime
  3. import grp
  4. import logging
  5. import pwd
  6. import re
  7. def format_time(t):
  8. """Format datetime suitable for fixed length list output
  9. """
  10. if (datetime.now() - t).days < 365:
  11. return t.strftime('%b %d %H:%M')
  12. else:
  13. return t.strftime('%b %d %Y')
  14. def format_file_mode(mod):
  15. """Format file mode bits for list output
  16. """
  17. def x(v):
  18. return ''.join(v & m and s or '-'
  19. for m, s in ((4, 'r'), (2, 'w'), (1, 'x')))
  20. return '%s%s%s' % (x(mod / 64), x(mod / 8), x(mod))
  21. def format_file_size(v):
  22. """Format file size into a human friendly format
  23. """
  24. if v > 1024 * 1024 * 1024:
  25. return '%.2f GB' % (v / 1024. / 1024. / 1024.)
  26. elif v > 1024 * 1024:
  27. return '%.2f MB' % (v / 1024. / 1024.)
  28. elif v > 1024:
  29. return '%.2f kB' % (v / 1024.)
  30. else:
  31. return str(v)
  32. class IntegrityError(Exception):
  33. """
  34. """
  35. def memoize(function):
  36. cache = {}
  37. def decorated_function(*args):
  38. try:
  39. return cache[args]
  40. except KeyError:
  41. val = function(*args)
  42. cache[args] = val
  43. return val
  44. return decorated_function
  45. @memoize
  46. def uid2user(uid):
  47. try:
  48. return pwd.getpwuid(uid).pw_name
  49. except KeyError:
  50. return None
  51. @memoize
  52. def user2uid(user):
  53. try:
  54. return pwd.getpwnam(user).pw_uid
  55. except KeyError:
  56. return None
  57. @memoize
  58. def gid2group(gid):
  59. try:
  60. return grp.getgrgid(gid).gr_name
  61. except KeyError:
  62. return None
  63. @memoize
  64. def group2gid(group):
  65. try:
  66. return grp.getgrnam(group).gr_gid
  67. except KeyError:
  68. return None
  69. class LevelFilter(logging.Filter):
  70. """Filter that counts record levels
  71. """
  72. def __init__(self, *args, **kwargs):
  73. logging.Filter.__init__(self, *args, **kwargs)
  74. self.count = {}
  75. def filter(self, record):
  76. self.count.setdefault(record.levelname, 0)
  77. self.count[record.levelname] += 1
  78. return record
  79. class Location(object):
  80. loc_re = re.compile(r'^((?:(?P<user>[^@]+)@)?(?P<host>[^:]+):)?'
  81. r'(?P<path>[^:]*)(?:::(?P<archive>[^:]+))?$')
  82. def __init__(self, text):
  83. loc = self.loc_re.match(text)
  84. loc = loc and loc.groupdict()
  85. if not loc:
  86. raise ValueError
  87. self.user = loc['user']
  88. self.host = loc['host']
  89. self.path = loc['path']
  90. if not self.host and not self.path:
  91. raise ValueError
  92. self.archive = loc['archive']
  93. def __str__(self):
  94. text = ''
  95. if self.user:
  96. text += '%s@' % self.user
  97. if self.host:
  98. text += '%s::' % self.host
  99. if self.path:
  100. text += self.path
  101. if self.archive:
  102. text += ':%s' % self.archive
  103. return text
  104. def __repr__(self):
  105. return "Location('%s')" % self
  106. def location_validator(archive=None):
  107. def validator(text):
  108. try:
  109. loc = Location(text)
  110. except ValueError:
  111. raise argparse.ArgumentTypeError('Invalid location format: "%s"' % text)
  112. if archive is True and not loc.archive:
  113. raise argparse.ArgumentTypeError('"%s": No archive specified' % text)
  114. elif archive is False and loc.archive:
  115. raise argparse.ArgumentTypeError('"%s" No archive can be specified' % text)
  116. return loc
  117. return validator