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.

191 lines
3.6 KiB

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