From e34d32bd60122db86bd35f9df5a5849a8c7d478b Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 2 Apr 2017 22:11:54 +0200 Subject: [PATCH] Add ability to batch-add tags, permissions and aliases along with category in the object/player create functions as well as in the tag handler. This is useful for direct assignment of categories from prototypes. --- evennia/objects/objects.py | 6 +++--- evennia/players/players.py | 2 +- evennia/typeclasses/tags.py | 34 +++++++++++++++++++++++++++++++++- evennia/utils/create.py | 6 +++--- evennia/utils/spawner.py | 8 ++++++-- evennia/utils/utils.py | 4 ++++ 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index c2c95798b8..e527892b58 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -944,17 +944,17 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)): self.save(update_fields=updates) if cdict.get("permissions"): - self.permissions.add(cdict["permissions"]) + self.permissions.batch_add(cdict["permissions"]) if cdict.get("locks"): self.locks.add(cdict["locks"]) if cdict.get("aliases"): - self.aliases.add(cdict["aliases"]) + self.aliases.batch_add(cdict["aliases"]) if cdict.get("location"): cdict["location"].at_object_receive(self, None) self.at_after_move(None) if cdict.get("tags"): # this should be a list of tags - self.tags.add(cdict["tags"]) + self.tags.batch_add(cdict["tags"]) if cdict.get("attributes"): # this should be a dict of attrname:value keys, values = list(cdict["attributes"]), listvalues(cdict["attributes"]) diff --git a/evennia/players/players.py b/evennia/players/players.py index 970e9748ea..fa7fa9840e 100644 --- a/evennia/players/players.py +++ b/evennia/players/players.py @@ -624,7 +624,7 @@ class DefaultPlayer(with_metaclass(TypeclassBase, PlayerDB)): permissions = cdict["permissions"] del self._createdict - self.permissions.add(permissions) + self.permissions.batch_add(permissions) def at_access(self, result, accessing_obj, access_type, **kwargs): """ diff --git a/evennia/typeclasses/tags.py b/evennia/typeclasses/tags.py index e9bd24eed0..1f1896f8a9 100644 --- a/evennia/typeclasses/tags.py +++ b/evennia/typeclasses/tags.py @@ -10,6 +10,7 @@ respective handlers. """ from builtins import object +from collections import defaultdict from django.conf import settings from django.db import models @@ -239,7 +240,7 @@ class TagHandler(object): category (str, optional): Category of Tag. `None` is the default category. data (str, optional): Info text about the tag(s) added. This can not be used to store object-unique info but only - eventual info about the text itself. + eventual info about the tag itself. Notes: If the tag + category combination matches an already @@ -356,6 +357,37 @@ class TagHandler(object): else: return [to_str(tag.db_key) for tag in tags] + def batch_add(self, *tuples): + """ + Batch-add tags from a list of tuples. + + Args: + tuples (tuple or str): Any number of `tagstr` keys, `(keystr, category)` or + `(keystr, category, data)` tuples. + + Notes: + This will generate a mimimal number of self.add calls, + based on the number of categories involved (including + `None`) (data is not unique and may be overwritten by the content + of a latter tuple with the same category). + + """ + keys = defaultdict(list) + data = {} + for tup in tuples: + tup = make_iter(tup) + nlen = len(tup) + if nlen == 1: # just a key + keys[None].append(tup[0]) + elif nlen == 2: + keys[tup[1]].append(tup[0]) + else: + keys[tup[1]].append(tup[0]) + data[tup[1]] = tup[2] # overwrite previous + for category, key in keys.iteritems(): + self.add(tag=key, category=category, data=data.get(category, None)) + + def __str__(self): return ",".join(self.all()) diff --git a/evennia/utils/create.py b/evennia/utils/create.py index 7445fa20a5..9e2289a059 100644 --- a/evennia/utils/create.py +++ b/evennia/utils/create.py @@ -65,10 +65,10 @@ def create_object(typeclass=None, key=None, location=None, home=None, #dbref will be set. home (Object or str): Obj or #dbref to use as the object's home location. - permissions (str): A comma-separated string of permissions. + permissions (list): A list of permission strings or tuples (permstring, category). locks (str): one or more lockstrings, separated by semicolons. - aliases (list): A list of alternative keys. - tags (list): List of tag keys (using no category). + aliases (list): A list of alternative keys or tuples (aliasstring, category). + tags (list): List of tag keys or tuples (tagkey, category). destination (Object or str): Obj or #dbref to use as an Exit's target. report_to (Object): The object to return error messages to. diff --git a/evennia/utils/spawner.py b/evennia/utils/spawner.py index 28274e5531..c6e5e0dea3 100644 --- a/evennia/utils/spawner.py +++ b/evennia/utils/spawner.py @@ -182,9 +182,11 @@ def _batch_create_object(*objparams): def spawn(*prototypes, **kwargs): """ - Spawn a number of prototyped objects. Each argument should be a - prototype dictionary. + Spawn a number of prototyped objects. + Args: + prototypes (dict): Each argument should be a prototype + dictionary. Kwargs: prototype_modules (str or list): A python-path to a prototype module, or a list of such paths. These will be used to build @@ -196,6 +198,7 @@ def spawn(*prototypes, **kwargs): prototypes from prototype_modules. return_prototypes (bool): Only return a list of the prototype-parents (no object creation happens) + """ protparents = {} @@ -249,6 +252,7 @@ def spawn(*prototypes, **kwargs): alias_string = aliasval() if callable(aliasval) else aliasval tagval = prot.pop("tags", "") tags = tagval() if callable(tagval) else tagval + exval = prot.pop("exec", "") execs = make_iter(exval() if callable(exval) else exval) diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index 79add32052..5bc3a20fc9 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -1834,3 +1834,7 @@ def get_game_dir_path(): else: os.chdir(os.pardir) raise RuntimeError("server/conf/settings.py not found: Must start from inside game dir.") + + + +