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.

187 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. >>> +AccountingNone
  19. AccountingNone
  20. >>> -AccountingNone
  21. AccountingNone
  22. >>> -(AccountingNone)
  23. AccountingNone
  24. >>> AccountingNone - 1
  25. -1
  26. >>> 1 - AccountingNone
  27. 1
  28. >>> abs(AccountingNone)
  29. AccountingNone
  30. >>> AccountingNone - None
  31. AccountingNone
  32. >>> AccountingNone / 2
  33. 0.0
  34. >>> 2 / AccountingNone
  35. Traceback (most recent call last):
  36. ...
  37. ZeroDivisionError
  38. >>> AccountingNone / AccountingNone
  39. AccountingNone
  40. >>> AccountingNone // 2
  41. 0.0
  42. >>> 2 // AccountingNone
  43. Traceback (most recent call last):
  44. ...
  45. ZeroDivisionError
  46. >>> AccountingNone // AccountingNone
  47. AccountingNone
  48. >>> AccountingNone * 2
  49. 0.0
  50. >>> 2 * AccountingNone
  51. 0.0
  52. >>> AccountingNone * AccountingNone
  53. AccountingNone
  54. >>> AccountingNone * None
  55. AccountingNone
  56. >>> None * AccountingNone
  57. AccountingNone
  58. >>> str(AccountingNone)
  59. ''
  60. >>> bool(AccountingNone)
  61. False
  62. >>> AccountingNone > 0
  63. False
  64. >>> AccountingNone < 0
  65. False
  66. >>> AccountingNone < 1
  67. True
  68. >>> AccountingNone > 1
  69. False
  70. >>> 0 < AccountingNone
  71. False
  72. >>> 0 > AccountingNone
  73. False
  74. >>> 1 < AccountingNone
  75. False
  76. >>> 1 > AccountingNone
  77. True
  78. >>> AccountingNone == 0
  79. True
  80. >>> AccountingNone == 0.0
  81. True
  82. >>> AccountingNone == None
  83. True
  84. """
  85. __all__ = ['AccountingNone']
  86. class AccountingNoneType(object):
  87. def __add__(self, other):
  88. if other is None:
  89. return AccountingNone
  90. return other
  91. __radd__ = __add__
  92. def __sub__(self, other):
  93. if other is None:
  94. return AccountingNone
  95. return -other
  96. def __rsub__(self, other):
  97. if other is None:
  98. return AccountingNone
  99. return other
  100. def __iadd__(self, other):
  101. if other is None:
  102. return AccountingNone
  103. return other
  104. def __isub__(self, other):
  105. if other is None:
  106. return AccountingNone
  107. return -other
  108. def __abs__(self):
  109. return self
  110. def __pos__(self):
  111. return self
  112. def __neg__(self):
  113. return self
  114. def __div__(self, other):
  115. if other is AccountingNone:
  116. return AccountingNone
  117. return 0.0
  118. def __rdiv__(self, other):
  119. raise ZeroDivisionError
  120. def __floordiv__(self, other):
  121. if other is AccountingNone:
  122. return AccountingNone
  123. return 0.0
  124. def __rfloordiv__(self, other):
  125. raise ZeroDivisionError
  126. def __truediv__(self, other):
  127. if other is AccountingNone:
  128. return AccountingNone
  129. return 0.0
  130. def __rtruediv__(self, other):
  131. raise ZeroDivisionError
  132. def __mul__(self, other):
  133. if other is None or other is AccountingNone:
  134. return AccountingNone
  135. return 0.0
  136. __rmul__ = __mul__
  137. def __repr__(self):
  138. return 'AccountingNone'
  139. def __str__(self):
  140. return ''
  141. def __nonzero__(self):
  142. return False
  143. def __bool__(self):
  144. return False
  145. def __eq__(self, other):
  146. return other == 0 or other is None or other is AccountingNone
  147. def __lt__(self, other):
  148. return 0 < other
  149. def __gt__(self, other):
  150. return 0 > other
  151. AccountingNone = AccountingNoneType()
  152. if __name__ == '__main__':
  153. import doctest
  154. doctest.testmod()