You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
3.3 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. Provides the AccountingNone singleton
  4. AccountingNone is a null value that dissolves in basic arithmetic operations,
  5. as illustrated in the examples below. In comparisons, AccountingNone behaves
  6. the same as zero.
  7. >>> 1 + 1
  8. 2
  9. >>> 1 + AccountingNone
  10. 1
  11. >>> AccountingNone + 1
  12. 1
  13. >>> AccountingNone + None
  14. AccountingNone
  15. >>> +AccountingNone
  16. AccountingNone
  17. >>> -AccountingNone
  18. AccountingNone
  19. >>> -(AccountingNone)
  20. AccountingNone
  21. >>> AccountingNone - 1
  22. -1
  23. >>> 1 - AccountingNone
  24. 1
  25. >>> AccountingNone - None
  26. AccountingNone
  27. >>> AccountingNone / 2
  28. 0.0
  29. >>> 2 / AccountingNone
  30. Traceback (most recent call last):
  31. ...
  32. ZeroDivisionError
  33. >>> AccountingNone / AccountingNone
  34. AccountingNone
  35. >>> AccountingNone // 2
  36. 0.0
  37. >>> 2 // AccountingNone
  38. Traceback (most recent call last):
  39. ...
  40. ZeroDivisionError
  41. >>> AccountingNone // AccountingNone
  42. AccountingNone
  43. >>> AccountingNone * 2
  44. 0.0
  45. >>> 2 * AccountingNone
  46. 0.0
  47. >>> AccountingNone * AccountingNone
  48. AccountingNone
  49. >>> AccountingNone * None
  50. AccountingNone
  51. >>> None * AccountingNone
  52. AccountingNone
  53. >>> str(AccountingNone)
  54. ''
  55. >>> bool(AccountingNone)
  56. False
  57. >>> AccountingNone > 0
  58. False
  59. >>> AccountingNone < 0
  60. False
  61. >>> AccountingNone < 1
  62. True
  63. >>> AccountingNone > 1
  64. False
  65. >>> 0 < AccountingNone
  66. False
  67. >>> 0 > AccountingNone
  68. False
  69. >>> 1 < AccountingNone
  70. False
  71. >>> 1 > AccountingNone
  72. True
  73. >>> AccountingNone == 0
  74. True
  75. >>> AccountingNone == 0.0
  76. True
  77. >>> AccountingNone == None
  78. True
  79. """
  80. class AccountingNoneType(object):
  81. def __add__(self, other):
  82. if other is None:
  83. return AccountingNone
  84. return other
  85. __radd__ = __add__
  86. def __sub__(self, other):
  87. if other is None:
  88. return AccountingNone
  89. return -other
  90. def __rsub__(self, other):
  91. if other is None:
  92. return AccountingNone
  93. return other
  94. def __iadd__(self, other):
  95. if other is None:
  96. return AccountingNone
  97. return other
  98. def __isub__(self, other):
  99. if other is None:
  100. return AccountingNone
  101. return -other
  102. def __pos__(self):
  103. return self
  104. def __neg__(self):
  105. return self
  106. def __div__(self, other):
  107. if other is AccountingNone:
  108. return AccountingNone
  109. return 0.0
  110. def __rdiv__(self, other):
  111. raise ZeroDivisionError
  112. def __floordiv__(self, other):
  113. if other is AccountingNone:
  114. return AccountingNone
  115. return 0.0
  116. def __rfloordiv__(self, other):
  117. raise ZeroDivisionError
  118. def __truediv__(self, other):
  119. if other is AccountingNone:
  120. return AccountingNone
  121. return 0.0
  122. def __rtruediv__(self, other):
  123. raise ZeroDivisionError
  124. def __mul__(self, other):
  125. if other is None or other is AccountingNone:
  126. return AccountingNone
  127. return 0.0
  128. __rmul__ = __mul__
  129. def __repr__(self):
  130. return 'AccountingNone'
  131. def __str__(self):
  132. return ''
  133. def __nonzero__(self):
  134. return False
  135. def __bool__(self):
  136. return False
  137. def __eq__(self, other):
  138. return other == 0 or other is None or other is AccountingNone
  139. def __lt__(self, other):
  140. return 0 < other
  141. def __gt__(self, other):
  142. return 0 > other
  143. AccountingNone = AccountingNoneType()
  144. if __name__ == '__main__':
  145. import doctest
  146. doctest.testmod()