tristate.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. # vim: set fileencoding=utf-8 :
  2. #
  3. # (C) 2011 Guido Guenther <agx@sigxcpu.org>
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, please see
  16. # <http://www.gnu.org/licenses/>
  17. """
  18. A switch with three states: on|off|auto
  19. """
  20. class Tristate(object):
  21. """Tri-state value: on, off or auto """
  22. ON = True # state is on == do it
  23. OFF = False # state is off == don't do it
  24. AUTO = -1 # autodetect == do if possible
  25. # We accept true as alias for on and false as alias for off
  26. _VALID_NAMES = [ 'on', 'off', 'true', 'false', 'auto' ]
  27. def __init__(self, val):
  28. if type(val) in [ type(t) for t in (True, 1) ]:
  29. if val > 0:
  30. self._state = self.ON
  31. elif val < 0:
  32. self._state = self.AUTO
  33. else:
  34. self._state = self.OFF
  35. elif type(val) in [ type(t) for t in ("", u"") ]:
  36. if val.lower() in [ 'on', 'true' ]:
  37. self._state = self.ON
  38. elif val.lower() in [ 'auto' ]:
  39. self._state = self.AUTO
  40. else:
  41. self._state = self.OFF
  42. elif type(val) is Tristate:
  43. self._state = val.state
  44. else:
  45. raise TypeError
  46. def __repr__(self):
  47. """
  48. >>> Tristate('on').__repr__()
  49. 'on'
  50. >>> Tristate(True).__repr__()
  51. 'on'
  52. >>> Tristate(False).__repr__()
  53. 'off'
  54. >>> Tristate('auto').__repr__()
  55. 'auto'
  56. """
  57. if self._state == self.ON:
  58. return 'on'
  59. elif self._state == self.AUTO:
  60. return 'auto'
  61. else:
  62. return 'off'
  63. def __nonzero__(self):
  64. """
  65. >>> Tristate('on').__nonzero__()
  66. True
  67. >>> Tristate('auto').__nonzero__()
  68. True
  69. >>> Tristate('off').__nonzero__()
  70. False
  71. """
  72. return self._state is not self.OFF
  73. @property
  74. def state(self):
  75. """Get current state"""
  76. return self._state
  77. def is_auto(self):
  78. return [False, True][self._state == self.AUTO]
  79. def is_on(self):
  80. return [False, True][self._state == self.ON]
  81. def is_off(self):
  82. return [False, True][self._state == self.OFF]
  83. def do(self, function, *args, **kwargs):
  84. """
  85. Run function if tristate is on or auto, only report a failure if
  86. tristate is on since failing is o.k. for autodetect.
  87. """
  88. if self.is_off():
  89. return True
  90. success = function(*args, **kwargs)
  91. if not success:
  92. return [True, False][self.is_on()]
  93. return True