Skip to content

Commit

Permalink
Improved Percentage logic. Raised test coverage to 75% (#38)
Browse files Browse the repository at this point in the history
* Improving percentage logic. Coverage is now 73%

* Improving percentage logic. Coverage is now 75%
  • Loading branch information
turulomio authored Dec 16, 2023
1 parent 6aafc81 commit b525d05
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 40 deletions.
79 changes: 41 additions & 38 deletions pydicts/percentage.py
Original file line number Diff line number Diff line change
@@ -1,72 +1,62 @@
from logging import warning
from decimal import Decimal

## Class to manage percentages in spreadsheets
## Converts values to decimal (Value is a decimal)
class Percentage:
def __init__(self, numerator=None, denominator=None):
self.setValue(self.toDecimal(numerator),self.toDecimal(denominator))

def toDecimal(self, o):
if o==None:
return o
if o.__class__.__name__ in ["Currency", "Money"]:
return o.amount
elif o.__class__.__name__=="Decimal":
return o
elif o.__class__.__name__ in ["int", "float"]:
return Decimal(o)
elif o.__class__.__name__=="Percentage":
return o.value
else:
warning (o.__class__.__name__)
return None

self.setValue(numerator, denominator)

def __repr__(self):
return self.string()

def __neg__(self):
if self.value==None:
return self
if self.value is None:
return Percentage(None)
return Percentage(-self.value, 1)

def __lt__(self, other):
if self.value==None:
value1=Decimal('-Infinity')
else:
value1=self.value
if other.value==None:
value2=Decimal('-Infinity')
else:
value2=other.value
if value1<value2:
if self.value is None or other.value is None:
return False


if self.value<other.value:
return True
return False


def __eq__(self, b):

return self.value==b.value

def __add__(self,p):
if self.value is None or p.value is None:
return None

return self.__class__(self.value+p.value,1)

def __sub__(self, p):
if self.value is None or p.value is None:
return None

return self.__class__(self.value-p.value,1)

def __mul__(self, value):
if self.value==None or value==None:
r=None
else:
r=self.value*self.toDecimal(value)
return Percentage(r, 1)
try:
if value.__class__==Percentage:
return Percentage(self.value*value.value, 1)
except:
return Percentage(None)

def __truediv__(self, value):
def __truediv__(self, other):
try:
r=self.value/self.toDecimal(value)
r=self.value/other.value
except:
r=None
return Percentage(r, 1)

def setValue(self, numerator, denominator):
try:
self.value=Decimal(numerator/denominator)
self.value=Decimal(numerator)/Decimal(denominator)
except:
self.value=None

Expand All @@ -78,10 +68,18 @@ def value_100(self):

## @return percentage float value
def float_100(self):
if self.value is None:
return None
return float(self.value_100())

## @return percentage float value
def float(self):
if self.value is None:
return None
return float(self.value)

def string(self, rnd=2):
if self.value==None:
if self.value is None:
return "None %"
return "{} %".format(round(self.value_100(), rnd))

Expand All @@ -105,6 +103,11 @@ def isLTZero(self):
if self.isValid() and self.value<0:
return True
return False

def isLETZero(self):
if self.isValid() and self.value<=0:
return True
return False

## Calculates porcentage to pass from a to b
## @param a. Can be an object divisible and that can be substracted
Expand Down
86 changes: 84 additions & 2 deletions pydicts/tests/test_percentage.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,85 @@
from pydicts.percentage import Percentage
def test_percentage():
from decimal import Decimal
from pydicts.percentage import Percentage, percentage_between
from pytest import raises

def test_percentage_init():
assert Percentage(None).value== None
assert Percentage(12, 1).value == 12
assert Percentage(12, 0).value== None

def test_percentage_add():
a=Percentage(1, 2)
b=Percentage(1, 4)
assert a+b==Percentage(3, 4)
assert not a+b==Percentage(None)
assert Percentage(None)+Percentage(None)==None

def test_percentage_sub():
a=Percentage(1, 2)
b=Percentage(1, 4)
assert a-b==Percentage(1, 4)
assert not a+b==Percentage(None)
assert Percentage(None)-Percentage(None)==None

def test_percentage_neg():
a=Percentage(1, 2)
assert -(-a)==a
assert -Percentage(None)==Percentage(None)

def test_percentage_repr():
assert repr(Percentage(1, 2))=="50.00 %"
assert repr(Percentage(None))=="None %"

def test_percentage_mult():
assert Percentage(1, 2)*Percentage(1,2 )==Percentage(1, 4)
assert Percentage(1, 2)*Percentage(None,2 )==Percentage(None)
with raises(TypeError):
2*Percentage(1,2 )

def test_percentage_truediv():
assert Percentage(1, 2)/Percentage(1,2 )==Percentage(1, 1)
assert Percentage(1, 2)/Percentage(None,2 )==Percentage(None)


def test_percentage_value_100():
assert Percentage(1, 2).value_100()==Decimal(50)
assert Percentage(None).value_100()==None

def test_percentage_float_100():
assert Percentage(1, 2).float_100()==50
assert Percentage(None).float_100()==None

def test_percentage_float():
assert Percentage(1, 2).float()==0.5
assert Percentage(None).float()==None

def test_percentage_lt():
assert not Percentage(1, 2)<Percentage(1, 4)
assert Percentage(1, 4)<Percentage(1, 2)
assert not Percentage(None)<Percentage(1, 2)
assert not Percentage(1, 2)<Percentage(None)

def test_percentage_isGETZero():
assert Percentage(1, 2).isGETZero()==True
assert Percentage(-1, 2).isGETZero()==False
assert Percentage(None).isGETZero()==False

def test_percentage_isLETZero():
assert Percentage(1, 2).isLETZero()==False
assert Percentage(-1, 2).isLETZero()==True
assert Percentage(None).isLETZero()==False

def test_percentage_isGTZero():
assert Percentage(1, 2).isGTZero()==True
assert Percentage(-1, 2).isGTZero()==False
assert Percentage(None).isGTZero()==False

def test_percentage_isLTZero():
assert Percentage(1, 2).isLTZero()==False
assert Percentage(-1, 2).isLTZero()==True
assert Percentage(None).isLTZero()==False

def test_percentage_between():
assert percentage_between(1, 2)==Percentage(1,1 )
assert percentage_between(None,1 )==Percentage(None )

0 comments on commit b525d05

Please sign in to comment.