mirror of
https://github.com/evennia/evennia.git
synced 2026-03-28 18:47:16 +01:00
Make Trait unit tests pass for base trait types
This commit is contained in:
parent
9033767a1e
commit
d720acef1d
3 changed files with 264 additions and 227 deletions
|
|
@ -310,15 +310,15 @@ class TestTraitNumeric(_TraitHandlerBase):
|
|||
extra_val1="xvalue1",
|
||||
extra_val2="xvalue2"
|
||||
)
|
||||
self.trait1 = self.traithandler.get("test1")
|
||||
self.trait = self.traithandler.get("test1")
|
||||
|
||||
def _get_actuals(self):
|
||||
"""Get trait actuals for comparisons"""
|
||||
return self.trait1.actual, self.trait2.actual
|
||||
return self.trait.actual, self.trait2.actual
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(
|
||||
self.trait1._data,
|
||||
self.trait._data,
|
||||
{"name": "Test1",
|
||||
"trait_type": "numeric",
|
||||
"base": 1,
|
||||
|
|
@ -328,12 +328,12 @@ class TestTraitNumeric(_TraitHandlerBase):
|
|||
)
|
||||
|
||||
def test_set_wrong_type(self):
|
||||
self.trait1.base = "foo"
|
||||
self.assertEqual(self.trait1.base, 1)
|
||||
self.trait.base = "foo"
|
||||
self.assertEqual(self.trait.base, 1)
|
||||
|
||||
def test_actual(self):
|
||||
self.trait1.base = 10
|
||||
self.assertEqual(self.trait1.actual, 10)
|
||||
self.trait.base = 10
|
||||
self.assertEqual(self.trait.actual, 10)
|
||||
|
||||
|
||||
class TestTraitStatic(_TraitHandlerBase):
|
||||
|
|
@ -351,10 +351,10 @@ class TestTraitStatic(_TraitHandlerBase):
|
|||
extra_val1="xvalue1",
|
||||
extra_val2="xvalue2"
|
||||
)
|
||||
self.trait1 = self.traithandler.get("test1")
|
||||
self.trait = self.traithandler.get("test1")
|
||||
|
||||
def _get_values(self):
|
||||
return self.trait1.base, self.trait1.mod, self.trait1.actual
|
||||
return self.trait.base, self.trait.mod, self.trait.actual
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(
|
||||
|
|
@ -371,16 +371,16 @@ class TestTraitStatic(_TraitHandlerBase):
|
|||
def test_actual(self):
|
||||
"""Actual is base + mod"""
|
||||
self.assertEqual(self._get_values(), (1, 2, 3))
|
||||
self.trait1.base += 4
|
||||
self.trait.base += 4
|
||||
self.assertEqual(self._get_values(), (5, 2, 7))
|
||||
self.trait1.mod -= 1
|
||||
self.trait.mod -= 1
|
||||
self.assertEqual(self._get_values(), (5, 1, 6))
|
||||
|
||||
def test_delete(self):
|
||||
"""Deleting resets to default."""
|
||||
del self.trait1.base
|
||||
del self.trait.base
|
||||
self.assertEqual(self._get_values(), (0, 2, 2))
|
||||
del self.trait1.mod
|
||||
del self.trait.mod
|
||||
self.assertEqual(self._get_values(), (0, 0, 0))
|
||||
|
||||
|
||||
|
|
@ -396,15 +396,17 @@ class TestTraitCounter(_TraitHandlerBase):
|
|||
trait_type='counter',
|
||||
base=1,
|
||||
mod=2,
|
||||
min=-10,
|
||||
min=0,
|
||||
max=10,
|
||||
extra_val1="xvalue1",
|
||||
extra_val2="xvalue2"
|
||||
)
|
||||
self.trait1 = self.traithandler.get("test1")
|
||||
self.trait = self.traithandler.get("test1")
|
||||
|
||||
def _get_values(self):
|
||||
return self.trait1.base, self.trait1.mod, self.trait1.actual
|
||||
"""Get (base, mod, actual, min, max)."""
|
||||
return (self.trait.base, self.trait.mod,
|
||||
self.trait.actual, self.trait.min, self.trait.max)
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(
|
||||
|
|
@ -413,7 +415,7 @@ class TestTraitCounter(_TraitHandlerBase):
|
|||
"trait_type": 'counter',
|
||||
"base": 1,
|
||||
"mod": 2,
|
||||
"min": -10,
|
||||
"min": 0,
|
||||
"max": 10,
|
||||
"extra_val1": "xvalue1",
|
||||
"extra_val2": "xvalue2"
|
||||
|
|
@ -422,104 +424,116 @@ class TestTraitCounter(_TraitHandlerBase):
|
|||
|
||||
def test_actual(self):
|
||||
"""Actual is current + mod, where current defaults to base"""
|
||||
self.assertEqual(self._get_values(), (1, 2, 3))
|
||||
self.trait1.base += 4
|
||||
self.assertEqual(self._get_values(), (5, 2, 7))
|
||||
self.trait1.mod -= 1
|
||||
self.assertEqual(self._get_values(), (5, 1, 6))
|
||||
self.assertEqual(self._get_values(), (1, 2, 3, 0, 10))
|
||||
self.trait.base += 4
|
||||
self.assertEqual(self._get_values(), (5, 2, 7, 0, 10))
|
||||
self.trait.mod -= 1
|
||||
self.assertEqual(self._get_values(), (5, 1, 6, 0, 10))
|
||||
|
||||
def test_boundaries__minmax(self):
|
||||
"""Test range"""
|
||||
# should not exceed min/max values
|
||||
self.trait1.base += 20
|
||||
self.assertEqual(self._get_values(), (10, 2, 10))
|
||||
self.trait1.base = 100
|
||||
self.assertEqual(self._get_values(), (10, 2, 10))
|
||||
self.trait1.base -= 40
|
||||
self.assertEqual(self._get_values(), (-10, 2, -8))
|
||||
self.trait1.base = -100
|
||||
self.assertEqual(self._get_values(), (-10, 2, -8))
|
||||
self.trait.base += 20
|
||||
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
|
||||
self.trait.base = 100
|
||||
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
|
||||
self.trait.base -= 40
|
||||
self.assertEqual(self._get_values(), (-2, 2, 0, 0, 10))
|
||||
self.trait.base = -100
|
||||
self.assertEqual(self._get_values(), (-2, 2, 0, 0, 10))
|
||||
|
||||
def test_boundaries__bigmod(self):
|
||||
"""add a big mod"""
|
||||
self.trait1.base = 5
|
||||
self.trait1.mod = 100
|
||||
self.assertEqual(self._get_values(), (5, 100, 10))
|
||||
self.trait1.mod = -100
|
||||
self.assertEqual(self._get_values(), (5, -100, -10))
|
||||
self.trait.base = 5
|
||||
self.trait.mod = 100
|
||||
self.assertEqual(self._get_values(), (5, 5, 10, 0, 10))
|
||||
self.trait.mod = -100
|
||||
self.assertEqual(self._get_values(), (5, -5, 0, 0, 10))
|
||||
|
||||
def test_boundaries__change_boundaries(self):
|
||||
"""Change boundaries after base/mod change"""
|
||||
self.trait1.base = 5
|
||||
self.trait1.mod = -100
|
||||
self.trait1.min = -20
|
||||
self.assertEqual(self._get_values(), (5, -100, -20))
|
||||
self.trait1.mod = 100
|
||||
self.trait1.max = 20
|
||||
self.assertEqual(self._get_values(), (5, 100, 20))
|
||||
|
||||
def test_boundaries__base_literal(self):
|
||||
"""Use the "base" literal makes the max become base+mod"""
|
||||
self.trait1.base = 5
|
||||
self.trait1.mod = 100
|
||||
self.trait1.max = "base"
|
||||
self.assertEqual(self._get_values(), (5, 100, 105))
|
||||
self.trait.base = 5
|
||||
self.trait.mod = -100
|
||||
self.trait.min = -20
|
||||
self.assertEqual(self._get_values(), (5, -5, 0, -20, 10))
|
||||
self.trait.mod -= 100
|
||||
self.assertEqual(self._get_values(), (5, -25, -20, -20, 10))
|
||||
self.trait.mod = 100
|
||||
self.trait.max = 20
|
||||
self.assertEqual(self._get_values(), (5, 5, 10, -20, 20))
|
||||
self.trait.mod = 100
|
||||
self.assertEqual(self._get_values(), (5, 15, 20, -20, 20))
|
||||
|
||||
def test_boundaries__disable(self):
|
||||
"""Disable and re-enable boundaries"""
|
||||
self.trait1.base = 5
|
||||
self.trait1.mod = 100
|
||||
del self.trait1.max
|
||||
self.assertEqual(self.trait1.max, None)
|
||||
del self.trait1.min
|
||||
self.assertEqual(self.trait1.min, None)
|
||||
self.trait1.base = 100
|
||||
self.assertEqual(self._get_values(), (100, 100, 200))
|
||||
self.trait1.base = -10
|
||||
self.assertEqual(self._get_values(), (-10, 100, 90))
|
||||
self.trait.base = 5
|
||||
self.trait.mod = 100
|
||||
self.assertEqual(self._get_values(), (5, 5, 10, 0, 10))
|
||||
del self.trait.max
|
||||
self.assertEqual(self.trait.max, None)
|
||||
del self.trait.min
|
||||
self.assertEqual(self.trait.min, None)
|
||||
self.trait.base = 100
|
||||
self.assertEqual(self._get_values(), (100, 5, 105, None, None))
|
||||
self.trait.base = -200
|
||||
self.assertEqual(self._get_values(), (-200, 5, -195, None, None))
|
||||
|
||||
# re-activate boundaries
|
||||
self.trait1.max = 15
|
||||
self.trait1.min = 10
|
||||
self.assertEqual(self._get_values(), (-10, 100, 15))
|
||||
self.trait.max = 15
|
||||
self.trait.min = 10 # his is blocked since base+mod is lower
|
||||
self.assertEqual(self._get_values(), (-200, 5, -195, -195, 15))
|
||||
|
||||
def test_boundaries__inverse(self):
|
||||
"""Set inverse boundaries - limited by base"""
|
||||
self.trait1.base = -10
|
||||
self.trait1.mod = 100
|
||||
self.trait1.min = 20 # will be set to base
|
||||
self.assertEqual(self.trait1.min, -10)
|
||||
self.trait1.max = -20
|
||||
self.assertEqual(self.trait1.max, -10)
|
||||
self.assertEqual(self._get_values(), (-10, 100, -10))
|
||||
self.trait.mod = 0
|
||||
self.assertEqual(self._get_values(), (1, 0, 1, 0, 10))
|
||||
self.trait.min = 20 # will be set to base
|
||||
self.assertEqual(self._get_values(), (1, 0, 1, 1, 10))
|
||||
self.trait.max = -20
|
||||
self.assertEqual(self._get_values(), (1, 0, 1, 1, 1))
|
||||
|
||||
def test_current(self):
|
||||
"""Modifying current value"""
|
||||
self.trait1.current = 5
|
||||
self.assertEqual(self._get_values(), (1, 2, 7))
|
||||
self.trait1.current = 10
|
||||
self.assertEqual(self._get_values(), (1, 2, 10))
|
||||
self.trait1.current = 12
|
||||
self.assertEqual(self._get_values(), (1, 2, 10))
|
||||
self.trait.current = 5
|
||||
self.assertEqual(self._get_values(), (1, 2, 7, 0, 10))
|
||||
self.trait.current = 10
|
||||
self.assertEqual(self._get_values(), (1, 2, 10, 0, 10))
|
||||
self.trait.current = 12
|
||||
self.assertEqual(self._get_values(), (1, 2, 10, 0, 10))
|
||||
self.trait.current = -1
|
||||
self.assertEqual(self._get_values(), (1, 2, 2, 0, 10))
|
||||
self.trait.current -= 10
|
||||
self.assertEqual(self._get_values(), (1, 2, 2, 0, 10))
|
||||
|
||||
def test_delete(self):
|
||||
"""Deleting resets to default."""
|
||||
del self.trait1.base
|
||||
self.assertEqual(self._get_values(), (0, 2, 2))
|
||||
del self.trait1.mod
|
||||
self.assertEqual(self._get_values(), (0, 0, 0))
|
||||
del self.trait1.min
|
||||
del self.trait1.max
|
||||
self.assertEqual(self.trait1.max, None)
|
||||
self.assertEqual(self.trait1.min, None)
|
||||
del self.trait.base
|
||||
self.assertEqual(self._get_values(), (0, 2, 2, 0, 10))
|
||||
del self.trait.mod
|
||||
self.assertEqual(self._get_values(), (0, 0, 0, 0, 10))
|
||||
del self.trait.min
|
||||
del self.trait.max
|
||||
self.assertEqual(self._get_values(), (0, 0, 0, None, None))
|
||||
|
||||
def test_percentage(self):
|
||||
"""Test percentage calculation"""
|
||||
self.assertEqual(self.trait1.percent(), "100.0%")
|
||||
self.trait1.current = 5
|
||||
self.assertEqual(self.trait1.percent(), "50.0%")
|
||||
self.trait1.current = 3
|
||||
self.assertEqual(self.trait1.percent(), "33.3%")
|
||||
self.trait.base = 8
|
||||
self.trait.mod = 2
|
||||
self.trait.min = 0
|
||||
self.trait.max = 10
|
||||
self.assertEqual(self.trait.percent(), "100.0%")
|
||||
self.trait.current = 3
|
||||
self.assertEqual(self.trait.percent(), "50.0%")
|
||||
self.trait.current = 1
|
||||
self.assertEqual(self.trait.percent(), "30.0%")
|
||||
# have to lower this since max cannot be lowered below base+mod
|
||||
self.trait.mod = 1
|
||||
self.trait.current = 2
|
||||
self.trait.max -= 1
|
||||
self.assertEqual(self.trait.percent(), "33.3%")
|
||||
# open boundary
|
||||
del self.trait.min
|
||||
self.assertEqual(self.trait.percent(), "100.0%")
|
||||
|
||||
|
||||
class TestTraitGauge(_TraitHandlerBase):
|
||||
|
|
@ -535,11 +549,12 @@ class TestTraitGauge(_TraitHandlerBase):
|
|||
extra_val1="xvalue1",
|
||||
extra_val2="xvalue2"
|
||||
)
|
||||
self.trait1 = self.traithandler.get("test1")
|
||||
self.trait = self.traithandler.get("test1")
|
||||
|
||||
def _get_values(self):
|
||||
return (self.trait1.base, self.trait1.mod, self.trait1.actual,
|
||||
self.trait1.min, self.trait1.max)
|
||||
"""Get (base, mod, actual, min, max)."""
|
||||
return (self.trait.base, self.trait.mod, self.trait.actual,
|
||||
self.trait.min, self.trait.max)
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(
|
||||
|
|
@ -557,119 +572,121 @@ class TestTraitGauge(_TraitHandlerBase):
|
|||
"""Actual is current, where current defaults to base + mod"""
|
||||
# current unset - follows base + mod
|
||||
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
|
||||
self.trait1.base += 4
|
||||
self.trait.base += 4
|
||||
self.assertEqual(self._get_values(), (12, 2, 14, 0, 14))
|
||||
self.trait1.mod -= 1
|
||||
self.trait.mod -= 1
|
||||
self.assertEqual(self._get_values(), (12, 1, 13, 0, 13))
|
||||
# set current, decouple from base + mod
|
||||
self.trait1.current = 5
|
||||
self.trait.current = 5
|
||||
self.assertEqual(self._get_values(), (12, 1, 5, 0, 13))
|
||||
self.trait1.mod += 1
|
||||
self.trait1.base -= 4
|
||||
self.trait.mod += 1
|
||||
self.trait.base -= 4
|
||||
self.assertEqual(self._get_values(), (8, 2, 5, 0, 10))
|
||||
self.trait1.min = -100
|
||||
self.trait1.base = -20
|
||||
self.trait.min = -100
|
||||
self.trait.base = -20
|
||||
self.assertEqual(self._get_values(), (-20, 2, -18, -100, -18))
|
||||
|
||||
def test_boundaries__minmax(self):
|
||||
"""Test range"""
|
||||
# current unset - tied to base + mod
|
||||
self.trait1.base += 20
|
||||
self.trait.base += 20
|
||||
self.assertEqual(self._get_values(), (28, 2, 30, 0, 30))
|
||||
# set current - decouple from base + mod
|
||||
self.trait1.current = 19
|
||||
self.trait.current = 19
|
||||
self.assertEqual(self._get_values(), (28, 2, 19, 0, 30))
|
||||
# test upper bound
|
||||
self.trait1.current = 100
|
||||
self.trait.current = 100
|
||||
self.assertEqual(self._get_values(), (28, 2, 30, 0, 30))
|
||||
# min defaults to 0
|
||||
self.trait1.current = -10
|
||||
self.trait.current = -10
|
||||
self.assertEqual(self._get_values(), (28, 2, 0, 0, 30))
|
||||
self.trait1.min = -20
|
||||
self.trait.min = -20
|
||||
self.assertEqual(self._get_values(), (28, 2, 0, -20, 30))
|
||||
self.trait1.current = -10
|
||||
self.trait.current = -10
|
||||
self.assertEqual(self._get_values(), (28, 2, -10, -20, 30))
|
||||
|
||||
def test_boundaries__bigmod(self):
|
||||
"""add a big mod"""
|
||||
self.trait1.base = 5
|
||||
self.trait1.mod = 100
|
||||
self.trait.base = 5
|
||||
self.trait.mod = 100
|
||||
self.assertEqual(self._get_values(), (5, 100, 105, 0, 105))
|
||||
# restricted by min
|
||||
self.trait1.mod = -100
|
||||
self.trait.mod = -100
|
||||
self.assertEqual(self._get_values(), (5, -5, 0, 0, 0))
|
||||
self.trait1.min = -200
|
||||
self.trait.min = -200
|
||||
self.assertEqual(self._get_values(), (5, -5, 0, -200, 0))
|
||||
|
||||
def test_boundaries__change_boundaries(self):
|
||||
"""Change boundaries after current change"""
|
||||
self.trait1.current = 20
|
||||
self.trait.current = 20
|
||||
self.assertEqual(self._get_values(), (8, 2, 10, 0, 10))
|
||||
self.trait1.mod = 102
|
||||
self.trait.mod = 102
|
||||
self.assertEqual(self._get_values(), (8, 102, 10, 0, 110))
|
||||
# raising min past current value will force it upwards
|
||||
self.trait1.min = 20
|
||||
self.trait.min = 20
|
||||
self.assertEqual(self._get_values(), (8, 102, 20, 20, 110))
|
||||
|
||||
def test_boundaries__disable(self):
|
||||
"""Disable and re-enable boundary"""
|
||||
self.trait1.base = 5
|
||||
self.trait1.min = 1
|
||||
self.trait.base = 5
|
||||
self.trait.min = 1
|
||||
self.assertEqual(self._get_values(), (5, 2, 7, 1, 7))
|
||||
del self.trait1.min
|
||||
del self.trait.min
|
||||
self.assertEqual(self._get_values(), (5, 2, 7, 0, 7))
|
||||
del self.trait1.base
|
||||
del self.trait1.mod
|
||||
del self.trait.base
|
||||
del self.trait.mod
|
||||
self.assertEqual(self._get_values(), (0, 0, 0, 0, 0))
|
||||
with self.assertRaises(traits.TraitException):
|
||||
del self.trait1.max
|
||||
del self.trait.max
|
||||
def test_boundaries__inverse(self):
|
||||
"""Try to set reversed boundaries"""
|
||||
self.trait1.mod = 0
|
||||
self.trait1.base = -10 # limited by min
|
||||
self.trait.mod = 0
|
||||
self.trait.base = -10 # limited by min
|
||||
self.assertEqual(self._get_values(), (0, 0, 0, 0, 0))
|
||||
self.trait1.min = -10
|
||||
self.trait.min = -10
|
||||
self.assertEqual(self._get_values(), (0, 0, 0, -10, 0))
|
||||
self.trait1.base = -10
|
||||
self.trait.base = -10
|
||||
self.assertEqual(self._get_values(), (-10, 0, -10, -10, -10))
|
||||
self.min = 0 # limited by base + mod
|
||||
self.assertEqual(self._get_values(), (-10, 0, -10, -10, -10))
|
||||
|
||||
def test_current(self):
|
||||
"""Modifying current value"""
|
||||
self.trait1.base = 10
|
||||
self.trait1.current = 5
|
||||
self.trait.base = 10
|
||||
self.trait.current = 5
|
||||
self.assertEqual(self._get_values(), (10, 2, 5, 0, 12))
|
||||
self.trait1.current = 10
|
||||
self.trait.current = 10
|
||||
self.assertEqual(self._get_values(), (10, 2, 10, 0, 12))
|
||||
self.trait1.current = 12
|
||||
self.trait.current = 12
|
||||
self.assertEqual(self._get_values(), (10, 2, 12, 0, 12))
|
||||
self.trait1.current = 0
|
||||
self.trait.current = 0
|
||||
self.assertEqual(self._get_values(), (10, 2, 0, 0, 12))
|
||||
self.trait1.current = -1
|
||||
self.trait.current = -1
|
||||
self.assertEqual(self._get_values(), (10, 2, 0, 0, 12))
|
||||
|
||||
def test_delete(self):
|
||||
"""Deleting resets to default."""
|
||||
del self.trait1.mod
|
||||
del self.trait.mod
|
||||
self.assertEqual(self._get_values(), (8, 0, 8, 0, 8))
|
||||
self.trait1.mod = 2
|
||||
del self.trait1.base
|
||||
self.trait.mod = 2
|
||||
del self.trait.base
|
||||
self.assertEqual(self._get_values(), (0, 2, 2, 0, 2))
|
||||
del self.trait1.min
|
||||
del self.trait.min
|
||||
self.assertEqual(self._get_values(), (0, 2, 2, 0, 2))
|
||||
self.trait1.min = -10
|
||||
self.trait.min = -10
|
||||
self.assertEqual(self._get_values(), (0, 2, 2, -10, 2))
|
||||
del self.trait1.min
|
||||
del self.trait.min
|
||||
self.assertEqual(self._get_values(), (0, 2, 2, 0, 2))
|
||||
|
||||
def test_percentage(self):
|
||||
"""Test percentage calculation"""
|
||||
self.assertEqual(self.trait1.percent(), "100.0%")
|
||||
self.trait1.current = 5
|
||||
self.assertEqual(self.trait1.percent(), "50.0%")
|
||||
self.trait1.current = 3
|
||||
self.assertEqual(self.trait1.percent(), "33.3%")
|
||||
self.assertEqual(self.trait.percent(), "100.0%")
|
||||
self.trait.current = 5
|
||||
self.assertEqual(self.trait.percent(), "50.0%")
|
||||
self.trait.current = 3
|
||||
self.assertEqual(self.trait.percent(), "30.0%")
|
||||
self.trait.mod -= 1
|
||||
self.assertEqual(self.trait.percent(), "33.3%")
|
||||
|
||||
|
||||
class TestNumericTraitOperators(TestCase):
|
||||
|
|
|
|||
|
|
@ -865,7 +865,8 @@ class NumericTrait(Trait):
|
|||
|
||||
class StaticTrait(NumericTrait):
|
||||
"""
|
||||
Static Trait. This has a modification value.
|
||||
Static Trait. This is a single value with a modifier,
|
||||
with no concept of a 'current' value.
|
||||
|
||||
actual = base + mod
|
||||
|
||||
|
|
@ -906,15 +907,15 @@ class CounterTrait(NumericTrait):
|
|||
This includes modifications and min/max limits as well as the notion of a
|
||||
current value. The value can also be reset to the base value.
|
||||
|
||||
min/unset base max/unset
|
||||
|-----------------------|----------X-------------------|
|
||||
actual
|
||||
= current
|
||||
+ mod
|
||||
min/unset base base+mod max/unset
|
||||
|--------------|--------|---------X--------X------------|
|
||||
current actual
|
||||
= current
|
||||
+ mod
|
||||
|
||||
- actual = current + mod, starts at base
|
||||
- actual = current + mod, starts at base + mod
|
||||
- if min or max is None, there is no upper/lower bound (default)
|
||||
- if max is set to "base", max will be set as base changes.
|
||||
- if max is set to "base", max will be equal ot base+mod
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -929,21 +930,12 @@ class CounterTrait(NumericTrait):
|
|||
}
|
||||
|
||||
# Helpers
|
||||
|
||||
def _mod_base(self):
|
||||
"""Calculate adding base and modifications"""
|
||||
return self._enforce_bounds(self.mod + self.base)
|
||||
|
||||
def _mod_current(self):
|
||||
"""Calculate the current value"""
|
||||
return self._enforce_bounds(self.mod + self.current)
|
||||
|
||||
def _enforce_bounds(self, value):
|
||||
def _enforce_boundaries(self, value):
|
||||
"""Ensures that incoming value falls within trait's range."""
|
||||
if self.min is not None and value <= self.min:
|
||||
return self.min
|
||||
if self._data["max"] == "base" and value >= self.mod + self.base:
|
||||
return self.mod + self.base
|
||||
return self.base + self.mod
|
||||
if self.max is not None and value >= self.max:
|
||||
return self.max
|
||||
return value
|
||||
|
|
@ -955,11 +947,31 @@ class CounterTrait(NumericTrait):
|
|||
return self._data["base"]
|
||||
|
||||
@base.setter
|
||||
def base(self, amount):
|
||||
if self._data.get("max", None) == "base":
|
||||
self._data["base"] = amount
|
||||
if type(amount) in (int, float):
|
||||
self._data["base"] = self._enforce_bounds(amount)
|
||||
def base(self, value):
|
||||
if value is None:
|
||||
self._data["base"] = self.data_keys['base']
|
||||
if type(value) in (int, float):
|
||||
if self.min is not None and value + self.mod < self.min:
|
||||
value = self.min - self.mod
|
||||
if self.max is not None and value + self.mod > self.max:
|
||||
value = self.max - self.mod
|
||||
self._data["base"] = value
|
||||
|
||||
@property
|
||||
def mod(self):
|
||||
return self._data["mod"]
|
||||
|
||||
@mod.setter
|
||||
def mod(self, value):
|
||||
if value is None:
|
||||
# unsetting the boundary to default
|
||||
self._data["mod"] = self.data_keys['mod']
|
||||
elif type(value) in (int, float):
|
||||
if self.min is not None and value + self.base < self.min:
|
||||
value = self.min - self.base
|
||||
if self.max is not None and value + self.base > self.max:
|
||||
value = self.max - self.base
|
||||
self._data["mod"] = value
|
||||
|
||||
@property
|
||||
def min(self):
|
||||
|
|
@ -968,56 +980,46 @@ class CounterTrait(NumericTrait):
|
|||
@min.setter
|
||||
def min(self, value):
|
||||
if value is None:
|
||||
# unsetting the boundary
|
||||
self._data["min"] = value
|
||||
elif type(value) in (int, float):
|
||||
if self.max is not None:
|
||||
value = min(self.max, value)
|
||||
self._data["min"] = value if value < self.base else self.base
|
||||
self._data["min"] = min(value, self.base + self.mod)
|
||||
|
||||
@property
|
||||
def max(self):
|
||||
if self._data["max"] == "base":
|
||||
return self._mod_base()
|
||||
return self._data["max"]
|
||||
|
||||
@max.setter
|
||||
def max(self, value):
|
||||
"""The maximum value of the trait.
|
||||
|
||||
Note:
|
||||
This property may be set to the string literal 'base'.
|
||||
When set this way, the property returns the value of the
|
||||
`mod`+`base` properties.
|
||||
"""
|
||||
if value == "base" or value is None:
|
||||
if value is None:
|
||||
# unsetting the boundary
|
||||
self._data["max"] = value
|
||||
elif type(value) in (int, float):
|
||||
if self.min is not None:
|
||||
value = max(self.min, value)
|
||||
self._data["max"] = value if value > self.base else self.base
|
||||
self._data["max"] = max(value, self.base + self.mod)
|
||||
|
||||
@property
|
||||
def current(self):
|
||||
"""The `current` value of the `Trait`."""
|
||||
return self._enforce_bounds(self._data.get("current", self.base))
|
||||
"""The `current` value of the `Trait`. This does not have .mod added."""
|
||||
return self._data.get("current", self.base)
|
||||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
if type(value) in (int, float):
|
||||
self._data["current"] = self._enforce_bounds(value)
|
||||
self._data["current"] = self._enforce_boundaries(value)
|
||||
|
||||
@current.deleter
|
||||
def current(self):
|
||||
"""reset back to base"""
|
||||
self._data["current"] = self.base
|
||||
|
||||
@property
|
||||
def actual(self):
|
||||
"The actual value of the Trait"
|
||||
return self._mod_current()
|
||||
|
||||
def reset_mod(self):
|
||||
"""Clears any mod value to 0."""
|
||||
self.mod = 0
|
||||
|
||||
def reset(self):
|
||||
"""Resets `current` property equal to `base` value."""
|
||||
self.current = self.base
|
||||
"The actual value of the Trait (current + mod)"
|
||||
return self._enforce_boundaries(self.current + self.mod)
|
||||
|
||||
def percent(self, formatting="{:3.1f}%"):
|
||||
"""
|
||||
|
|
@ -1032,7 +1034,11 @@ class CounterTrait(NumericTrait):
|
|||
float or str: Depending of if a `formatting` string
|
||||
is supplied or not.
|
||||
"""
|
||||
return percent(self.current, self.min, self.max, formatting=formatting)
|
||||
return percent(self.actual, self.min, self.max, formatting=formatting)
|
||||
|
||||
def reset(self):
|
||||
"""Resets `current` property equal to `base` value."""
|
||||
del self.current
|
||||
|
||||
|
||||
class GaugeTrait(CounterTrait):
|
||||
|
|
@ -1041,7 +1047,7 @@ class GaugeTrait(CounterTrait):
|
|||
|
||||
This emulates a gauge-meter that empties from a base+mod value.
|
||||
|
||||
min/0 max=base + mod
|
||||
min/0 max=base+mod
|
||||
|-----------------------X---------------------------|
|
||||
actual
|
||||
= current
|
||||
|
|
@ -1063,15 +1069,7 @@ class GaugeTrait(CounterTrait):
|
|||
"min": 0,
|
||||
}
|
||||
|
||||
def _mod_base(self):
|
||||
"""Calculate adding base and modifications"""
|
||||
return self._enforce_bounds(self.mod + self.base)
|
||||
|
||||
def _mod_current(self):
|
||||
"""Calculate the current value"""
|
||||
return self._enforce_bounds(self.current)
|
||||
|
||||
def _enforce_bounds(self, value):
|
||||
def _enforce_boundaries(self, value):
|
||||
"""Ensures that incoming value falls within trait's range."""
|
||||
if self.min is not None and value <= self.min:
|
||||
return self.min
|
||||
|
|
@ -1135,12 +1133,18 @@ class GaugeTrait(CounterTrait):
|
|||
@property
|
||||
def current(self):
|
||||
"""The `current` value of the gauge."""
|
||||
return self._enforce_bounds(self._data.get("current", self._mod_base()))
|
||||
return self._enforce_boundaries(
|
||||
self._data.get("current", self.base + self.mod))
|
||||
|
||||
@current.setter
|
||||
def current(self, value):
|
||||
if type(value) in (int, float):
|
||||
self._data["current"] = self._enforce_bounds(value)
|
||||
self._data["current"] = self._enforce_boundaries(value)
|
||||
|
||||
@current.deleter
|
||||
def current(self):
|
||||
"Resets current back to 'full'"
|
||||
self._data["current"] = self.base + self.mod
|
||||
|
||||
@property
|
||||
def actual(self):
|
||||
|
|
@ -1162,10 +1166,8 @@ class GaugeTrait(CounterTrait):
|
|||
"""
|
||||
return percent(self.current, self.min, self.max, formatting=formatting)
|
||||
|
||||
|
||||
def fill_gauge(self):
|
||||
def reset(self):
|
||||
"""
|
||||
Fills the gauge to its maximum allowed by base + mod
|
||||
|
||||
"""
|
||||
self.current = self.base + self.mod
|
||||
del self.current
|
||||
|
|
|
|||
|
|
@ -1687,15 +1687,17 @@ def format_table(table, extra_space=1):
|
|||
return ftable
|
||||
|
||||
|
||||
def percent(self, value, minval, maxval, formatting="{:3.1f}%"):
|
||||
def percent(value, minval, maxval, formatting="{:3.1f}%"):
|
||||
"""
|
||||
Get a value in an interval as a percentage of its position
|
||||
in that interval. This also understands negative numbers.
|
||||
|
||||
Args:
|
||||
value (number): This should be a value minval<=value<=maxval.
|
||||
minval (number): Smallest value in interval.
|
||||
maxval (number): Biggest value in interval.
|
||||
minval (number or None): Smallest value in interval. This could be None
|
||||
for an open interval (then return will always be 100%)
|
||||
maxval (number or None): Biggest value in interval. This could be None
|
||||
for an open interval (then return will always be 100%)
|
||||
formatted (str, optional): This is a string that should
|
||||
accept one formatting tag. This will receive the
|
||||
current value as a percentage. If None, the
|
||||
|
|
@ -1703,30 +1705,46 @@ def percent(self, value, minval, maxval, formatting="{:3.1f}%"):
|
|||
Returns:
|
||||
str or float: The formatted value or the raw percentage
|
||||
as a float.
|
||||
Raises:
|
||||
RuntimeError: If min/max does not make sense.
|
||||
Notes:
|
||||
We handle the case of minval==maxval because we may see this case and
|
||||
don't want to raise exceptions unnecessarily. In that case we return
|
||||
100%.
|
||||
We try to handle a weird interval gracefully.
|
||||
- If either maxval or minval is None (open interval),
|
||||
we (aribtrarily) assume 100%.
|
||||
- If minval > maxval, we return 0%.
|
||||
- If minval == maxval == value we are looking at a single value match
|
||||
and return 100%.
|
||||
- If minval == maxval != value we return 0%.
|
||||
- If value not in [minval..maxval], we set value to the closest
|
||||
boundary, so the result will be 0% or 100%, respectively.
|
||||
|
||||
"""
|
||||
if minval > maxval:
|
||||
raise RuntimeError("The minimum value must be <= the max value.")
|
||||
# constrain value to interval
|
||||
value = min(max(minval, value), maxval)
|
||||
|
||||
# these should both be >0
|
||||
dpart = value - minval
|
||||
dfull = maxval - minval
|
||||
try:
|
||||
result = (dpart / dfull) * 100.0
|
||||
except ZeroDivisionError:
|
||||
# this means minval == maxval
|
||||
result = None
|
||||
if None in (minval, maxval):
|
||||
# we have no boundaries, percent calculation makes no sense,
|
||||
# we set this to 100% since it
|
||||
result = 100.0
|
||||
if not isinstance(formatting, str):
|
||||
return result
|
||||
return formatting.format(result)
|
||||
elif minval > maxval:
|
||||
# interval has no width so we cannot
|
||||
# occupy any position within it.
|
||||
result = 0.0
|
||||
elif minval == maxval == value:
|
||||
# this is a single value that we match
|
||||
result = 100.0
|
||||
elif minval == maxval != value:
|
||||
# interval has no width so we cannot be in it.
|
||||
result = 0.0
|
||||
|
||||
if result is None:
|
||||
# constrain value to interval
|
||||
value = min(max(minval, value), maxval)
|
||||
|
||||
# these should both be >0
|
||||
dpart = value - minval
|
||||
dfull = maxval - minval
|
||||
result = (dpart / dfull) * 100.0
|
||||
|
||||
if isinstance(formatting, str):
|
||||
return formatting.format(result)
|
||||
return result
|
||||
|
||||
|
||||
import functools # noqa
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue