diff --git a/evennia/contrib/test_traits.py b/evennia/contrib/test_traits.py index 7e111568cf..068684fdfa 100644 --- a/evennia/contrib/test_traits.py +++ b/evennia/contrib/test_traits.py @@ -31,6 +31,7 @@ class _MockObj: assert category == self.category self.dbstore[key] = value + # we want to test the base traits too _TEST_TRAIT_CLASS_PATHS = [ "evennia.contrib.traits.Trait", @@ -39,8 +40,10 @@ _TEST_TRAIT_CLASS_PATHS = [ "evennia.contrib.traits.GaugeTrait", ] + class _TraitHandlerBase(TestCase): "Base for trait tests" + @patch("evennia.contrib.traits._TRAIT_CLASS_PATHS", new=_TEST_TRAIT_CLASS_PATHS) def setUp(self): self.obj = _MockObj() @@ -48,7 +51,7 @@ class _TraitHandlerBase(TestCase): self.obj.traits = self.traithandler def _get_dbstore(self, key): - return self.obj.dbstore['traits'][key] + return self.obj.dbstore["traits"][key] class TraitHandlerTest(_TraitHandlerBase): @@ -56,32 +59,18 @@ class TraitHandlerTest(_TraitHandlerBase): def setUp(self): super().setUp() + self.traithandler.add("test1", name="Test1", trait_type="trait") self.traithandler.add( - "test1", - name="Test1", - trait_type='trait' - ) - self.traithandler.add( - "test2", - name="Test2", - trait_type='trait', - value=["foo", {"1": [1, 2, 3]}, 4], + "test2", name="Test2", trait_type="trait", value=["foo", {"1": [1, 2, 3]}, 4], ) def test_add_trait(self): self.assertEqual( - self._get_dbstore("test1"), - {"name": "Test1", - "trait_type": 'trait', - "value": None, - } + self._get_dbstore("test1"), {"name": "Test1", "trait_type": "trait", "value": None,} ) self.assertEqual( self._get_dbstore("test2"), - {"name": "Test2", - "trait_type": 'trait', - "value": ["foo", {"1": [1, 2, 3]}, 4], - } + {"name": "Test2", "trait_type": "trait", "value": ["foo", {"1": [1, 2, 3]}, 4],}, ) self.assertEqual(len(self.traithandler), 2) @@ -109,21 +98,14 @@ class TraitHandlerTest(_TraitHandlerBase): def test_getting(self): "Test we are getting data from the dbstore" self.assertEqual( - self.traithandler.test1._data, - {"name": "Test1", "trait_type": "trait", - "value": None} - ) - self.assertEqual( - self.traithandler._cache, Something + self.traithandler.test1._data, {"name": "Test1", "trait_type": "trait", "value": None} ) + self.assertEqual(self.traithandler._cache, Something) self.assertEqual( self.traithandler.test2._data, - {"name": "Test2", "trait_type": "trait", - "value": ["foo", {"1": [1, 2, 3]}, 4]} - ) - self.assertEqual( - self.traithandler._cache, Something + {"name": "Test2", "trait_type": "trait", "value": ["foo", {"1": [1, 2, 3]}, 4]}, ) + self.assertEqual(self.traithandler._cache, Something) self.assertFalse(self.traithandler.get("foo")) self.assertFalse(self.traithandler.bar) @@ -151,20 +133,13 @@ class TraitHandlerTest(_TraitHandlerBase): self.assertEqual(trait.value, None) trait.value = 10 self.assertEqual(trait.value, 10) - self.assertEqual( - self.obj.attributes.get("traits", category="traits")['test1']['value'], - 10 - ) + self.assertEqual(self.obj.attributes.get("traits", category="traits")["test1"]["value"], 10) trait.value = 20 self.assertEqual(trait.value, 20) - self.assertEqual( - self.obj.attributes.get("traits", category="traits")['test1']['value'], - 20 - ) + self.assertEqual(self.obj.attributes.get("traits", category="traits")["test1"]["value"], 20) del trait.value self.assertEqual( - self.obj.attributes.get("traits", category="traits")['test1']['value'], - None + self.obj.attributes.get("traits", category="traits")["test1"]["value"], None ) @@ -188,44 +163,40 @@ class TestTrait(_TraitHandlerBase): def test_init(self): self.assertEqual( self.trait._data, - {"name": "Test1", - "trait_type": "trait", - "value": "value", - "extra_val1": "xvalue1", - "extra_val2": "xvalue2" - } + { + "name": "Test1", + "trait_type": "trait", + "value": "value", + "extra_val1": "xvalue1", + "extra_val2": "xvalue2", + }, ) def test_validate_input__valid(self): """Test valid validation input""" # all data supplied, and extras - dat = { - "name": "Test", - "trait_type": "trait", - "value": 10, - "extra_val": 1000 - } + dat = {"name": "Test", "trait_type": "trait", "value": 10, "extra_val": 1000} expected = copy(dat) # we must break link or return === dat always self.assertEqual(expected, traits.Trait.validate_input(traits.Trait, dat)) # don't supply value, should get default dat = { - "name": "Test", - "trait_type": "trait", - # missing value - "extra_val": 1000 + "name": "Test", + "trait_type": "trait", + # missing value + "extra_val": 1000, } expected = copy(dat) - expected["value"] = traits.Trait.default_keys['value'] + expected["value"] = traits.Trait.default_keys["value"] self.assertEqual(expected, traits.Trait.validate_input(traits.Trait, dat)) # make sure extra values are cleaned if trait accepts no extras dat = { - "name": "Test", - "trait_type": "trait", - "value": 10, - "extra_val1": 1000, - "extra_val2": "xvalue" + "name": "Test", + "trait_type": "trait", + "value": 10, + "extra_val1": 1000, + "extra_val2": "xvalue", } expected = copy(dat) expected.pop("extra_val1") @@ -236,24 +207,22 @@ class TestTrait(_TraitHandlerBase): def test_validate_input__fail(self): """Test failing validation""" dat = { - # missing name - "trait_type": "trait", - "value": 10, - "extra_val": 1000 + # missing name + "trait_type": "trait", + "value": 10, + "extra_val": 1000, } with self.assertRaises(traits.TraitException): traits.Trait.validate_input(traits.Trait, dat) # make value a required key - mock_default_keys = { - "value": traits.MandatoryTraitKey - } + mock_default_keys = {"value": traits.MandatoryTraitKey} with patch.object(traits.Trait, "default_keys", mock_default_keys): dat = { - "name": "Trait", - "trait_type": "trait", - # missing value, now mandatory - "extra_val": 1000 + "name": "Trait", + "trait_type": "trait", + # missing value, now mandatory + "extra_val": 1000, } with self.assertRaises(traits.TraitException): traits.Trait.validate_input(traits.Trait, dat) @@ -261,15 +230,15 @@ class TestTrait(_TraitHandlerBase): def test_trait_getset(self): """Get-set-del operations on trait""" self.assertEqual(self.trait.name, "Test1") - self.assertEqual(self.trait['name'], "Test1") + self.assertEqual(self.trait["name"], "Test1") self.assertEqual(self.trait.value, "value") - self.assertEqual(self.trait['value'], "value") - self.assertEqual(self.trait.extra_val1, "xvalue1" ) - self.assertEqual(self.trait['extra_val2'], "xvalue2") + self.assertEqual(self.trait["value"], "value") + self.assertEqual(self.trait.extra_val1, "xvalue1") + self.assertEqual(self.trait["extra_val2"], "xvalue2") self.trait.value = 20 - self.assertEqual(self.trait['value'], 20) - self.trait['value'] = 20 + self.assertEqual(self.trait["value"], 20) + self.trait["value"] = 20 self.assertEqual(self.trait.value, 20) self.trait.extra_val1 = 100 self.assertEqual(self.trait.extra_val1, 100) @@ -279,7 +248,7 @@ class TestTrait(_TraitHandlerBase): del self.trait.foo with self.assertRaises(KeyError): - self.trait['foo'] + self.trait["foo"] with self.assertRaises(AttributeError): self.trait.foo del self.trait.extra_val1 @@ -298,16 +267,17 @@ class TestTraitStatic(_TraitHandlerBase): """ Test for static Traits """ + def setUp(self): super().setUp() self.traithandler.add( "test1", name="Test1", - trait_type='static', + trait_type="static", base=1, mod=2, extra_val1="xvalue1", - extra_val2="xvalue2" + extra_val2="xvalue2", ) self.trait = self.traithandler.get("test1") @@ -317,13 +287,14 @@ class TestTraitStatic(_TraitHandlerBase): def test_init(self): self.assertEqual( self._get_dbstore("test1"), - {"name": "Test1", - "trait_type": 'static', - "base": 1, - "mod": 2, - "extra_val1": "xvalue1", - "extra_val2": "xvalue2" - } + { + "name": "Test1", + "trait_type": "static", + "base": 1, + "mod": 2, + "extra_val1": "xvalue1", + "extra_val2": "xvalue2", + }, ) def test_value(self): @@ -346,53 +317,44 @@ class TestTraitCounter(_TraitHandlerBase): """ Test for counter- Traits """ + def setUp(self): super().setUp() self.traithandler.add( "test1", name="Test1", - trait_type='counter', + trait_type="counter", base=1, mod=2, min=0, max=10, extra_val1="xvalue1", extra_val2="xvalue2", - descs={ - 0: "range0", - 2: "range1", - 5: "range2", - 7: "range3", - } + descs={0: "range0", 2: "range1", 5: "range2", 7: "range3",}, ) self.trait = self.traithandler.get("test1") def _get_values(self): """Get (base, mod, value, min, max).""" - return (self.trait.base, self.trait.mod, - self.trait.value, self.trait.min, self.trait.max) + return (self.trait.base, self.trait.mod, self.trait.value, self.trait.min, self.trait.max) def test_init(self): self.assertEqual( self._get_dbstore("test1"), - {"name": "Test1", - "trait_type": 'counter', - "base": 1, - "mod": 2, - "min": 0, - "max": 10, - "extra_val1": "xvalue1", - "extra_val2": "xvalue2", - "descs": { - 0: "range0", - 2: "range1", - 5: "range2", - 7: "range3", - }, - "rate": 0, - "ratetarget": None, - "last_update": None, - } + { + "name": "Test1", + "trait_type": "counter", + "base": 1, + "mod": 2, + "min": 0, + "max": 10, + "extra_val1": "xvalue1", + "extra_val2": "xvalue2", + "descs": {0: "range0", 2: "range1", 5: "range2", 7: "range3",}, + "rate": 0, + "ratetarget": None, + "last_update": None, + }, ) def test_value(self): @@ -453,7 +415,7 @@ class TestTraitCounter(_TraitHandlerBase): # re-activate boundaries self.trait.max = 15 - self.trait.min = 10 # his is blocked since base+mod is lower + 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): @@ -533,33 +495,34 @@ class TestTraitCounterTimed(_TraitHandlerBase): """ Test for trait with timer component """ + @patch("evennia.contrib.traits.time", new=MagicMock(return_value=1000)) def setUp(self): super().setUp() self.traithandler.add( "test1", name="Test1", - trait_type='counter', + trait_type="counter", base=1, mod=2, min=0, max=100, extra_val1="xvalue1", extra_val2="xvalue2", - descs={ - 0: "range0", - 2: "range1", - 5: "range2", - 7: "range3", - }, + descs={0: "range0", 2: "range1", 5: "range2", 7: "range3",}, rate=1, ratetarget=None, ) self.trait = self.traithandler.get("test1") def _get_timer_data(self): - return (self.trait.value, self.trait.current, self.trait.rate, - self.trait._data["last_update"], self.trait.ratetarget) + return ( + self.trait.value, + self.trait.current, + self.trait.rate, + self.trait._data["last_update"], + self.trait.ratetarget, + ) @patch("evennia.contrib.traits.time") def test_timer_rate(self, mock_time): @@ -608,52 +571,42 @@ class TestTraitCounterTimed(_TraitHandlerBase): class TestTraitGauge(_TraitHandlerBase): - def setUp(self): super().setUp() self.traithandler.add( "test1", name="Test1", - trait_type='gauge', + trait_type="gauge", base=8, # max = base + mod mod=2, extra_val1="xvalue1", extra_val2="xvalue2", - descs={ - 0: "range0", - 2: "range1", - 5: "range2", - 7: "range3", - } + descs={0: "range0", 2: "range1", 5: "range2", 7: "range3",}, ) self.trait = self.traithandler.get("test1") def _get_values(self): """Get (base, mod, value, min, max).""" - return (self.trait.base, self.trait.mod, self.trait.value, - self.trait.min, self.trait.max) + return (self.trait.base, self.trait.mod, self.trait.value, self.trait.min, self.trait.max) def test_init(self): self.assertEqual( self._get_dbstore("test1"), - {"name": "Test1", - "trait_type": 'gauge', - "base": 8, - "mod": 2, - "min": 0, - "extra_val1": "xvalue1", - "extra_val2": "xvalue2", - "descs": { - 0: "range0", - 2: "range1", - 5: "range2", - 7: "range3", - }, - "rate": 0, - "ratetarget": None, - "last_update": None, - } + { + "name": "Test1", + "trait_type": "gauge", + "base": 8, + "mod": 2, + "min": 0, + "extra_val1": "xvalue1", + "extra_val2": "xvalue2", + "descs": {0: "range0", 2: "range1", 5: "range2", 7: "range3",}, + "rate": 0, + "ratetarget": None, + "last_update": None, + }, ) + def test_value(self): """value is current, where current defaults to base + mod""" # current unset - follows base + mod @@ -724,6 +677,7 @@ class TestTraitGauge(_TraitHandlerBase): self.assertEqual(self._get_values(), (0, 0, 0, 0, 0)) with self.assertRaises(traits.TraitException): del self.trait.max + def test_boundaries__inverse(self): """Try to set reversed boundaries""" self.trait.mod = 0 @@ -798,32 +752,33 @@ class TestTraitGaugeTimed(_TraitHandlerBase): """ Test for trait with timer component """ + @patch("evennia.contrib.traits.time", new=MagicMock(return_value=1000)) def setUp(self): super().setUp() self.traithandler.add( "test1", name="Test1", - trait_type='gauge', + trait_type="gauge", base=98, mod=2, min=0, extra_val1="xvalue1", extra_val2="xvalue2", - descs={ - 0: "range0", - 2: "range1", - 5: "range2", - 7: "range3", - }, + descs={0: "range0", 2: "range1", 5: "range2", 7: "range3",}, rate=1, ratetarget=None, ) self.trait = self.traithandler.get("test1") def _get_timer_data(self): - return (self.trait.value, self.trait.current, self.trait.rate, - self.trait._data["last_update"], self.trait.ratetarget) + return ( + self.trait.value, + self.trait.current, + self.trait.rate, + self.trait._data["last_update"], + self.trait.ratetarget, + ) @patch("evennia.contrib.traits.time") def test_timer_rate(self, mock_time): @@ -875,18 +830,11 @@ class TestTraitGaugeTimed(_TraitHandlerBase): class TestNumericTraitOperators(TestCase): """Test case for numeric magic method implementations.""" + def setUp(self): # direct instantiation for testing only; use TraitHandler in production - self.st = traits.Trait({ - 'name': 'Strength', - 'trait_type': 'trait', - 'value': 8, - }) - self.at = traits.Trait({ - 'name': 'Attack', - 'trait_type': 'trait', - 'value': 4, - }) + self.st = traits.Trait({"name": "Strength", "trait_type": "trait", "value": 8,}) + self.at = traits.Trait({"name": "Attack", "trait_type": "trait", "value": 4,}) def tearDown(self): self.st, self.at = None, None diff --git a/evennia/contrib/traits.py b/evennia/contrib/traits.py index be362aed55..73393c8966 100644 --- a/evennia/contrib/traits.py +++ b/evennia/contrib/traits.py @@ -336,8 +336,7 @@ from django.conf import settings from functools import total_ordering from evennia.utils.dbserialize import _SaverDict from evennia.utils import logger -from evennia.utils.utils import ( - inherits_from, class_from_module, list_to_string, percent) +from evennia.utils.utils import inherits_from, class_from_module, list_to_string, percent # Available Trait classes. @@ -437,8 +436,7 @@ class TraitHandler: # no existing storage; initialize it, we then have to fetch it again # to retain the db connection obj.attributes.add(db_attribute_key, {}, category=db_attribute_category) - self.trait_data = obj.attributes.get( - db_attribute_key, category=db_attribute_category) + self.trait_data = obj.attributes.get(db_attribute_key, category=db_attribute_category) self._cache = {} def __len__(self): @@ -459,8 +457,7 @@ class TraitHandler: trait_cls = self._get_trait_class(trait_key=trait_key) valid_keys = list_to_string(list(trait_cls.default_keys.keys()), endsep="or") raise TraitException( - "Trait object not settable directly. " - f"Assign to {trait_key}.{valid_keys}." + "Trait object not settable directly. " f"Assign to {trait_key}.{valid_keys}." ) def __setitem__(self, trait_key, value): @@ -524,7 +521,9 @@ class TraitHandler: trait = self._cache[trait_key] = trait_cls(_GA(self, "trait_data")[trait_key]) return trait - def add(self, trait_key, name=None, trait_type=DEFAULT_TRAIT_TYPE, force=True, **trait_properties): + def add( + self, trait_key, name=None, trait_type=DEFAULT_TRAIT_TYPE, force=True, **trait_properties + ): """ Create a new Trait and add it to the handler. @@ -566,7 +565,6 @@ class TraitHandler: self.trait_data[trait_key] = trait_properties - def remove(self, trait_key): """ Remove a Trait from the handler's parent object. @@ -592,6 +590,7 @@ class TraitHandler: # Parent Trait class + @total_ordering class Trait: """Represents an object or Character trait. This simple base is just @@ -605,6 +604,7 @@ class Trait: value """ + # this is the name used to refer to this trait when adding # a new trait in the TraitHandler trait_type = "trait" @@ -661,6 +661,7 @@ class Trait: TraitException: If finding unset keys without a default. """ + def _raise_err(unset_required): """Helper method to format exception.""" raise TraitException( @@ -668,6 +669,7 @@ class Trait: cls.trait_type, list_to_string(list(unset_required), addquote=True) ) ) + inp = set(trait_data.keys()) # separate check for name/trait_type, those are always required. @@ -683,15 +685,13 @@ class Trait: if MandatoryTraitKey in unset_defaults.values(): # we have one or more unset keys that was mandatory - _raise_err([key for key, value in unset_defaults.items() - if value == MandatoryTraitKey]) + _raise_err([key for key, value in unset_defaults.items() if value == MandatoryTraitKey]) # apply the default values trait_data.update(unset_defaults) if not cls.allow_extra_properties: # don't allow any extra properties - remove the extra data - for key in (key for key in inp.difference(req) - if key not in ("name", "trait_type")): + for key in (key for key in inp.difference(req) if key not in ("name", "trait_type")): del trait_data[key] return trait_data @@ -722,10 +722,8 @@ class Trait: except KeyError: raise AttributeError( "{!r} {} ({}) has no property {!r}.".format( - self._data['name'], - type(self).__name__, - self.trait_type, - key) + self._data["name"], type(self).__name__, self.trait_type, key + ) ) def __setattr__(self, key, value): @@ -746,14 +744,13 @@ class Trait: return else: # this is some other value - if key in ("_data", ): + if key in ("_data",): _SA(self, key, value) return if _GA(self, "allow_extra_properties"): _GA(self, "_data")[key] = value return - raise AttributeError(f"Can't set attribute {key} on " - f"{self.trait_type} Trait.") + raise AttributeError(f"Can't set attribute {key} on " f"{self.trait_type} Trait.") def __delattr__(self, key): """ @@ -775,7 +772,8 @@ class Trait: if self.default_keys[key] == MandatoryTraitKey: raise TraitException( "Trait-Key {key} cannot be deleted: It's a mandatory property " - "with no default value to fall back to.") + "with no default value to fall back to." + ) # set to default self._data[key] = self.default_keys[key] elif key in self._data: @@ -797,7 +795,11 @@ class Trait: return "{}({{{}}})".format( type(self).__name__, ", ".join( - ["'{}': {!r}".format(k, self._data[k]) for k in self.default_keys if k in self._data] + [ + "'{}': {!r}".format(k, self._data[k]) + for k in self.default_keys + if k in self._data + ] ), ) @@ -916,6 +918,7 @@ class Trait: # Implementation of the respective Trait types + class StaticTrait(Trait): """ Static Trait. This is a single value with a modifier, @@ -924,12 +927,10 @@ class StaticTrait(Trait): value = base + mod """ + trait_type = "static" - default_keys = { - "base": 0, - "mod": 0 - } + default_keys = {"base": 0, "mod": 0} def __str__(self): status = "{value:11}".format(value=self.value) @@ -997,7 +998,7 @@ class CounterTrait(Trait): "max": None, "descs": None, "rate": 0, - "ratetarget": None + "ratetarget": None, } @staticmethod @@ -1005,18 +1006,21 @@ class CounterTrait(Trait): """Add extra validation for descs""" trait_data = Trait.validate_input(cls, trait_data) # validate descs - descs = trait_data['descs'] + descs = trait_data["descs"] if isinstance(descs, dict): - if any(not (isinstance(key, (int, float)) and isinstance(value, str)) - for key, value in descs.items()): + if any( + not (isinstance(key, (int, float)) and isinstance(value, str)) + for key, value in descs.items() + ): raise TraitException( f"Trait descs must be defined on the " - f"form {{number:str}} (instead found {descs}).") + f"form {{number:str}} (instead found {descs})." + ) # set up rate - if trait_data['rate'] != 0: - trait_data['last_update'] = time() + if trait_data["rate"] != 0: + trait_data["last_update"] = time() else: - trait_data['last_update'] = None + trait_data["last_update"] = None return trait_data # Helpers @@ -1024,8 +1028,8 @@ class CounterTrait(Trait): def _within_boundaries(self, value): """Check if given value is within boundaries""" return not ( - (self.min is not None and value <= self.min) or - (self.max is not None and value >= self.max) + (self.min is not None and value <= self.min) + or (self.max is not None and value >= self.max) ) def _enforce_boundaries(self, value): @@ -1040,32 +1044,31 @@ class CounterTrait(Trait): def _passed_ratetarget(self, value): """Check if we passed the ratetarget in either direction.""" - ratetarget = self._data['ratetarget'] - return (ratetarget is not None and ( - (self.rate < 0 and value <= ratetarget) or - (self.rate > 0 and value >= ratetarget))) + ratetarget = self._data["ratetarget"] + return ratetarget is not None and ( + (self.rate < 0 and value <= ratetarget) or (self.rate > 0 and value >= ratetarget) + ) def _stop_timer(self): """Stop rate-timer component.""" - if self.rate != 0 and self._data['last_update'] is not None: - self._data['last_update'] = None + if self.rate != 0 and self._data["last_update"] is not None: + self._data["last_update"] = None def _check_and_start_timer(self, value): """Start timer if we are not at a boundary.""" - if self.rate != 0 and self._data['last_update'] is None: - ratetarget = self._data['ratetarget'] + if self.rate != 0 and self._data["last_update"] is None: + ratetarget = self._data["ratetarget"] if self._within_boundaries(value) and not self._passed_ratetarget(value): # we are not at a boundary [anymore]. - self._data['last_update'] = time() + self._data["last_update"] = time() return value - def _update_current(self, current): """Update current value by scaling with rate and time passed.""" rate = self.rate - if rate != 0 and self._data['last_update'] is not None: + if rate != 0 and self._data["last_update"] is not None: now = time() - tdiff = now - self._data['last_update'] + tdiff = now - self._data["last_update"] current += rate * tdiff value = current + self.mod @@ -1073,15 +1076,15 @@ class CounterTrait(Trait): # even if .mod is included if self._passed_ratetarget(value): - current = self._data['ratetarget'] - self.mod + current = self._data["ratetarget"] - self.mod self._stop_timer() elif not self._within_boundaries(value): current = self._enforce_boundaries(value) - self.mod self._stop_timer() else: - self._data['last_update'] = now + self._data["last_update"] = now - self._data['current'] = current + self._data["current"] = current return current @@ -1094,7 +1097,7 @@ class CounterTrait(Trait): @base.setter def base(self, value): if value is None: - self._data["base"] = self.default_keys['base'] + self._data["base"] = self.default_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 @@ -1110,7 +1113,7 @@ class CounterTrait(Trait): def mod(self, value): if value is None: # unsetting the boundary to default - self._data["mod"] = self.default_keys['mod'] + self._data["mod"] = self.default_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 @@ -1168,11 +1171,11 @@ class CounterTrait(Trait): @property def ratetarget(self): - return self._data['ratetarget'] + return self._data["ratetarget"] @ratetarget.setter def ratetarget(self, value): - self._data['ratetarget'] = self._enforce_boundaries(value) + self._data["ratetarget"] = self._enforce_boundaries(value) self._check_and_start_timer(self.value) def percent(self, formatting="{:3.1f}%"): @@ -1268,24 +1271,24 @@ class GaugeTrait(CounterTrait): def _update_current(self, current): """Update current value by scaling with rate and time passed.""" rate = self.rate - if rate != 0 and self._data['last_update'] is not None: + if rate != 0 and self._data["last_update"] is not None: now = time() - tdiff = now - self._data['last_update'] + tdiff = now - self._data["last_update"] current += rate * tdiff value = current # we don't worry about .mod for gauges if self._passed_ratetarget(value): - current = self._data['ratetarget'] + current = self._data["ratetarget"] self._stop_timer() elif not self._within_boundaries(value): current = self._enforce_boundaries(value) self._stop_timer() else: - self._data['last_update'] = now + self._data["last_update"] = now - self._data['current'] = current + self._data["current"] = current return current @@ -1332,7 +1335,7 @@ class GaugeTrait(CounterTrait): def min(self, value): """Limit so min can never be greater than base+mod.""" if value is None: - self._data["min"] = self.default_keys['min'] + self._data["min"] = self.default_keys["min"] elif type(value) in (int, float): self._data["min"] = min(value, self.base + self.mod) @@ -1343,18 +1346,22 @@ class GaugeTrait(CounterTrait): @max.setter def max(self, value): - raise TraitException("The .max property is not settable " - "on GaugeTraits. Set .base instead.") + raise TraitException( + "The .max property is not settable " "on GaugeTraits. Set .base instead." + ) + @max.deleter def max(self): - raise TraitException("The .max property cannot be reset " - "on GaugeTraits. Reset .mod and .base instead.") + raise TraitException( + "The .max property cannot be reset " "on GaugeTraits. Reset .mod and .base instead." + ) @property def current(self): """The `current` value of the gauge.""" - return self._update_current(self._enforce_boundaries( - self._data.get("current", self.base + self.mod))) + return self._update_current( + self._enforce_boundaries(self._data.get("current", self.base + self.mod)) + ) @current.setter def current(self, value): diff --git a/evennia/utils/tests/test_utils.py b/evennia/utils/tests/test_utils.py index cbc49c1829..4cbfbe41dd 100644 --- a/evennia/utils/tests/test_utils.py +++ b/evennia/utils/tests/test_utils.py @@ -318,6 +318,7 @@ class TestPercent(TestCase): """ Test the utils.percentage function. """ + def test_ok_input(self): result = utils.percent(3, 0, 10) self.assertEqual(result, "30.0%") @@ -332,4 +333,3 @@ class TestPercent(TestCase): self.assertEqual(utils.percent(3, 1, 1), "0.0%") self.assertEqual(utils.percent(3, 0, 1), "100.0%") self.assertEqual(utils.percent(-3, 0, 1), "0.0%") -