term.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.utils.term
  4. ~~~~~~~~~~~~~~~~~
  5. Terminals and colors.
  6. """
  7. from __future__ import absolute_import
  8. import platform
  9. from .encoding import safe_str
  10. BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
  11. OP_SEQ = '\033[%dm'
  12. RESET_SEQ = '\033[0m'
  13. COLOR_SEQ = '\033[1;%dm'
  14. fg = lambda s: COLOR_SEQ % s
  15. SYSTEM = platform.system()
  16. IS_WINDOWS = SYSTEM == 'Windows'
  17. class colored(object):
  18. """Terminal colored text.
  19. Example::
  20. >>> c = colored(enabled=True)
  21. >>> print(str(c.red('the quick '), c.blue('brown ', c.bold('fox ')),
  22. ... c.magenta(c.underline('jumps over')),
  23. ... c.yellow(' the lazy '),
  24. ... c.green('dog ')))
  25. """
  26. def __init__(self, *s, **kwargs):
  27. self.s = s
  28. self.enabled = not IS_WINDOWS and kwargs.get('enabled', True)
  29. self.op = kwargs.get('op', '')
  30. self.names = {'black': self.black,
  31. 'red': self.red,
  32. 'green': self.green,
  33. 'yellow': self.yellow,
  34. 'blue': self.blue,
  35. 'magenta': self.magenta,
  36. 'cyan': self.cyan,
  37. 'white': self.white}
  38. def _add(self, a, b):
  39. return unicode(a) + unicode(b)
  40. def _fold_no_color(self, a, b):
  41. try:
  42. A = a.no_color()
  43. except AttributeError:
  44. A = unicode(a)
  45. try:
  46. B = b.no_color()
  47. except AttributeError:
  48. B = unicode(b)
  49. return safe_str(A) + safe_str(B)
  50. def no_color(self):
  51. if self.s:
  52. return reduce(self._fold_no_color, self.s)
  53. return ''
  54. def embed(self):
  55. prefix = ''
  56. if self.enabled:
  57. prefix = self.op
  58. return prefix + safe_str(reduce(self._add, self.s))
  59. def __unicode__(self):
  60. suffix = ''
  61. if self.enabled:
  62. suffix = RESET_SEQ
  63. return safe_str(self.embed() + suffix)
  64. def __str__(self):
  65. return safe_str(self.__unicode__())
  66. def node(self, s, op):
  67. return self.__class__(enabled=self.enabled, op=op, *s)
  68. def black(self, *s):
  69. return self.node(s, fg(30 + BLACK))
  70. def red(self, *s):
  71. return self.node(s, fg(30 + RED))
  72. def green(self, *s):
  73. return self.node(s, fg(30 + GREEN))
  74. def yellow(self, *s):
  75. return self.node(s, fg(30 + YELLOW))
  76. def blue(self, *s):
  77. return self.node(s, fg(30 + BLUE))
  78. def magenta(self, *s):
  79. return self.node(s, fg(30 + MAGENTA))
  80. def cyan(self, *s):
  81. return self.node(s, fg(30 + CYAN))
  82. def white(self, *s):
  83. return self.node(s, fg(30 + WHITE))
  84. def __repr__(self):
  85. return repr(self.no_color())
  86. def bold(self, *s):
  87. return self.node(s, OP_SEQ % 1)
  88. def underline(self, *s):
  89. return self.node(s, OP_SEQ % 4)
  90. def blink(self, *s):
  91. return self.node(s, OP_SEQ % 5)
  92. def reverse(self, *s):
  93. return self.node(s, OP_SEQ % 7)
  94. def bright(self, *s):
  95. return self.node(s, OP_SEQ % 8)
  96. def ired(self, *s):
  97. return self.node(s, fg(40 + RED))
  98. def igreen(self, *s):
  99. return self.node(s, fg(40 + GREEN))
  100. def iyellow(self, *s):
  101. return self.node(s, fg(40 + YELLOW))
  102. def iblue(self, *s):
  103. return self.node(s, fg(40 + BLUE))
  104. def imagenta(self, *s):
  105. return self.node(s, fg(40 + MAGENTA))
  106. def icyan(self, *s):
  107. return self.node(s, fg(40 + CYAN))
  108. def iwhite(self, *s):
  109. return self.node(s, fg(40 + WHITE))
  110. def reset(self, *s):
  111. return self.node(s or [''], RESET_SEQ)
  112. def __add__(self, other):
  113. return unicode(self) + unicode(other)