diff --git a/CHANGELOG.md b/CHANGELOG.md index a9400c92ba..303c23aef5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,6 +130,10 @@ Up requirements to Django 3.2+, Twisted 21+ to `.remove(key, category=None, return_exception=False, ...)` for consistency. - New `command cooldown` contrib for making it easier to manage commands using dynamic cooldowns between uses (owllex) +- Restructured `contrib/` folder, placing all contribs as separate packages under + subfolders. All imports will need to be updated. +- Made `MonitorHandler.add/remove` support `category` for monitoring Attributes + with a category (before only key was used, ignoring category entirely). ### Evennia 0.9.5 (2019-2020) diff --git a/evennia/scripts/monitorhandler.py b/evennia/scripts/monitorhandler.py index 1b799bfe3e..21c5969b8b 100644 --- a/evennia/scripts/monitorhandler.py +++ b/evennia/scripts/monitorhandler.py @@ -93,11 +93,25 @@ class MonitorHandler(object): # make sure to clean data from database ServerConfig.objects.conf(key=self.savekey, delete=True) + def _attr_category_fieldname(self, fieldname, category): + """ + Modify the saved fieldname to make sure to differentiate between Attributes + with different categories. + + """ + return f"{fieldname}[{category}]" if category else fieldname + def at_update(self, obj, fieldname): """ Called by the field/attribute as it saves. """ + # if this an Attribute with a category we should differentiate + fieldname = self._attr_category_fieldname( + fieldname, obj.db_category + if fieldname == "db_value" and hasattr(obj, "db_category") else None + ) + to_delete = [] if obj in self.monitors and fieldname in self.monitors[obj]: for idstring, (callback, persistent, kwargs) in self.monitors[obj][fieldname].items(): @@ -110,7 +124,8 @@ class MonitorHandler(object): for (obj, fieldname, idstring) in to_delete: del self.monitors[obj][fieldname][idstring] - def add(self, obj, fieldname, callback, idstring="", persistent=False, **kwargs): + def add(self, obj, fieldname, callback, idstring="", persistent=False, + category=None, **kwargs): """ Add monitoring to a given field or Attribute. A field must be specified with the full db_* name or it will be assumed @@ -126,6 +141,9 @@ class MonitorHandler(object): of the same field and object. persistent (bool, optional): If False, the monitor will survive a server reload but not a cold restart. This is default. + category (str, optional): This is only used if `fieldname` refers to + an Attribute (i.e. it does not start with `db_`). You must specify this + if you want to target an Attribute with a category. Keyword Args: session (Session): If this keyword is given, the monitorhandler will @@ -140,7 +158,7 @@ class MonitorHandler(object): obj = obj.attributes.get(fieldname, return_obj=True) if not obj: return - fieldname = "db_value" + fieldname = self._attr_category_fieldname("db_value", category) # we try to serialize this data to test it's valid. Otherwise we won't accept it. try: @@ -160,7 +178,7 @@ class MonitorHandler(object): else: self.monitors[obj][fieldname][idstring] = (callback, persistent, kwargs) - def remove(self, obj, fieldname, idstring=""): + def remove(self, obj, fieldname, idstring="", category=None): """ Remove a monitor. """ @@ -168,7 +186,7 @@ class MonitorHandler(object): obj = obj.attributes.get(fieldname, return_obj=True) if not obj: return - fieldname = "db_value" + fieldname = self._attr_category_fieldname("db_value", category) idstring_dict = self.monitors[obj][fieldname] if idstring in idstring_dict: