mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Resolve merge conflicts
This commit is contained in:
commit
345c91e35a
5 changed files with 151 additions and 52 deletions
|
|
@ -251,20 +251,14 @@ class CmdCopy(ObjManipCommand):
|
|||
copy an object and its properties
|
||||
|
||||
Usage:
|
||||
copy[/reset] <original obj> [= <new_name>][;alias;alias..]
|
||||
copy <original obj> [= <new_name>][;alias;alias..]
|
||||
[:<new_location>] [,<new_name2> ...]
|
||||
|
||||
switch:
|
||||
reset - make a 'clean' copy off the object, thus
|
||||
removing any changes that might have been made to the original
|
||||
since it was first created.
|
||||
|
||||
Create one or more copies of an object. If you don't supply any targets,
|
||||
one exact copy of the original object will be created with the name *_copy.
|
||||
"""
|
||||
|
||||
key = "copy"
|
||||
switch_options = ("reset",)
|
||||
locks = "cmd:perm(copy) or perm(Builder)"
|
||||
help_category = "Building"
|
||||
|
||||
|
|
|
|||
|
|
@ -588,15 +588,30 @@ def _matching_puzzles(puzzles, puzzlename_tags_dict, puzzle_ingredients):
|
|||
|
||||
|
||||
class CmdUsePuzzleParts(MuxCommand):
|
||||
"""
|
||||
Use an object, or a group of objects at once.
|
||||
|
||||
|
||||
Example:
|
||||
You look around you and see a pole, a long string, and a needle.
|
||||
|
||||
use pole, long string, needle
|
||||
|
||||
Genius! You built a fishing pole.
|
||||
|
||||
|
||||
Usage:
|
||||
use <obj1> [,obj2,...]
|
||||
"""
|
||||
|
||||
# Technical explanation
|
||||
"""
|
||||
Searches for all puzzles whose parts match the given set of objects. If there are matching
|
||||
puzzles, the result objects are spawned in their corresponding location if all parts have been
|
||||
passed in.
|
||||
|
||||
Usage:
|
||||
use <part1[,part2,...>]
|
||||
"""
|
||||
|
||||
|
||||
key = "use"
|
||||
aliases = "combine"
|
||||
locks = "cmd:pperm(use) or pperm(Player)"
|
||||
|
|
|
|||
|
|
@ -175,6 +175,16 @@ class TestLockfuncs(EvenniaTest):
|
|||
self.assertEqual(True, lockfuncs.objtag(None, self.obj2, "test2", "category1"))
|
||||
self.assertEqual(False, lockfuncs.objtag(None, self.obj2, "test2"))
|
||||
|
||||
def test_traverse_taglock(self):
|
||||
self.obj2.tags.add("test1", "category1")
|
||||
self.exit.locks.add("traverse:tag(test1,category1)")
|
||||
self.assertEqual(self.exit.access(self.obj2, "traverse"), True)
|
||||
|
||||
def test_traverse_taglock_fail(self):
|
||||
self.obj2.tags.add("test1") # missing the category
|
||||
self.exit.locks.add("traverse:tag(test1,category1)")
|
||||
self.assertEqual(self.exit.access(self.obj2, "traverse"), False)
|
||||
|
||||
def test_inside_holds(self):
|
||||
self.assertEqual(True, lockfuncs.inside(self.char1, self.room1))
|
||||
self.assertEqual(False, lockfuncs.inside(self.char1, self.room2))
|
||||
|
|
|
|||
|
|
@ -31,7 +31,14 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
# Attribute manager methods
|
||||
def get_attribute(
|
||||
self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None, **kwargs
|
||||
self,
|
||||
key=None,
|
||||
category=None,
|
||||
value=None,
|
||||
strvalue=None,
|
||||
obj=None,
|
||||
attrtype=None,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
Return Attribute objects by key, by category, by value, by
|
||||
|
|
@ -75,9 +82,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
# no reason to make strvalue/value mutually exclusive at this level
|
||||
query.append(("attribute__db_value", value))
|
||||
return Attribute.objects.filter(
|
||||
pk__in=self.model.db_attributes.through.objects.filter(**dict(query)).values_list(
|
||||
"attribute_id", flat=True
|
||||
)
|
||||
pk__in=self.model.db_attributes.through.objects.filter(
|
||||
**dict(query)
|
||||
).values_list("attribute_id", flat=True)
|
||||
)
|
||||
|
||||
def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None):
|
||||
|
|
@ -104,7 +111,13 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
)
|
||||
|
||||
def get_by_attribute(
|
||||
self, key=None, category=None, value=None, strvalue=None, attrtype=None, **kwargs
|
||||
self,
|
||||
key=None,
|
||||
category=None,
|
||||
value=None,
|
||||
strvalue=None,
|
||||
attrtype=None,
|
||||
**kwargs
|
||||
):
|
||||
"""
|
||||
Return objects having attributes with the given key, category,
|
||||
|
|
@ -132,7 +145,10 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
"""
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
query = [("db_attributes__db_attrtype", attrtype), ("db_attributes__db_model", dbmodel)]
|
||||
query = [
|
||||
("db_attributes__db_attrtype", attrtype),
|
||||
("db_attributes__db_model", dbmodel),
|
||||
]
|
||||
if key:
|
||||
query.append(("db_attributes__db_key", key))
|
||||
if category:
|
||||
|
|
@ -158,11 +174,15 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
obj (list): Objects having the matching Nicks.
|
||||
|
||||
"""
|
||||
return self.get_by_attribute(key=key, category=category, strvalue=nick, attrtype="nick")
|
||||
return self.get_by_attribute(
|
||||
key=key, category=category, strvalue=nick, attrtype="nick"
|
||||
)
|
||||
|
||||
# Tag manager methods
|
||||
|
||||
def get_tag(self, key=None, category=None, obj=None, tagtype=None, global_search=False):
|
||||
def get_tag(
|
||||
self, key=None, category=None, obj=None, tagtype=None, global_search=False
|
||||
):
|
||||
"""
|
||||
Return Tag objects by key, by category, by object (it is
|
||||
stored on) or with a combination of those criteria.
|
||||
|
|
@ -206,9 +226,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
if category:
|
||||
query.append(("tag__db_category", category))
|
||||
return Tag.objects.filter(
|
||||
pk__in=self.model.db_tags.through.objects.filter(**dict(query)).values_list(
|
||||
"tag_id", flat=True
|
||||
)
|
||||
pk__in=self.model.db_tags.through.objects.filter(
|
||||
**dict(query)
|
||||
).values_list("tag_id", flat=True)
|
||||
)
|
||||
|
||||
def get_permission(self, key=None, category=None, obj=None):
|
||||
|
|
@ -279,7 +299,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
if not _Tag:
|
||||
from evennia.typeclasses.models import Tag as _Tag
|
||||
|
||||
match = kwargs.get("match", "all").lower().strip()
|
||||
anymatch = "any" == kwargs.get("match", "all").lower().strip()
|
||||
|
||||
keys = make_iter(key) if key else []
|
||||
categories = make_iter(category) if category else []
|
||||
|
|
@ -290,7 +310,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
query = (
|
||||
self.filter(db_tags__db_tagtype__iexact=tagtype, db_tags__db_model__iexact=dbmodel)
|
||||
self.filter(
|
||||
db_tags__db_tagtype__iexact=tagtype, db_tags__db_model__iexact=dbmodel
|
||||
)
|
||||
.distinct()
|
||||
.order_by("id")
|
||||
)
|
||||
|
|
@ -309,28 +331,30 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
)
|
||||
clauses = Q()
|
||||
for ikey, key in enumerate(keys):
|
||||
# Keep each key and category together, grouped by AND
|
||||
clauses |= Q(db_key__iexact=key, db_category__iexact=categories[ikey])
|
||||
|
||||
# ANY mode; must match any one of the given tags/categories
|
||||
clauses |= Q(
|
||||
db_key__iexact=key, db_category__iexact=categories[ikey]
|
||||
)
|
||||
else:
|
||||
# only one or more categories given
|
||||
# import evennia;evennia.set_trace()
|
||||
clauses = Q()
|
||||
# ANY mode; must match any one of them
|
||||
for category in unique_categories:
|
||||
clauses |= Q(db_category__iexact=category)
|
||||
|
||||
tags = _Tag.objects.filter(clauses)
|
||||
query = query.filter(db_tags__in=tags).annotate(
|
||||
matches=Count("db_tags__pk", filter=Q(db_tags__in=tags), distinct=True)
|
||||
matches=Count("db_tags__pk", filter=Q(db_tags__in=tags),
|
||||
distinct=True)
|
||||
)
|
||||
|
||||
# Default ALL: Match all of the tags and optionally more
|
||||
if match == "all":
|
||||
n_req_tags = tags.count() if n_keys > 0 else n_unique_categories
|
||||
query = query.filter(matches__gte=n_req_tags)
|
||||
# ANY: Match any single tag, ordered by weight
|
||||
elif match == "any":
|
||||
if anymatch:
|
||||
# ANY: Match any single tag, ordered by weight
|
||||
query = query.order_by("-matches")
|
||||
else:
|
||||
# Default ALL: Match all of the tags and optionally more
|
||||
n_req_tags = n_keys if n_keys > 0 else n_unique_categories
|
||||
query = query.filter(matches__gte=n_req_tags)
|
||||
|
||||
return query
|
||||
|
||||
|
|
@ -388,7 +412,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
# try to get old tag
|
||||
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
tag = self.get_tag(key=key, category=category, tagtype=tagtype, global_search=True)
|
||||
tag = self.get_tag(
|
||||
key=key, category=category, tagtype=tagtype, global_search=True
|
||||
)
|
||||
if tag and data is not None:
|
||||
# get tag from list returned by get_tag
|
||||
tag = tag[0]
|
||||
|
|
@ -402,7 +428,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
from evennia.typeclasses.models import Tag as _Tag
|
||||
tag = _Tag.objects.create(
|
||||
db_key=key.strip().lower() if key is not None else None,
|
||||
db_category=category.strip().lower() if category and key is not None else None,
|
||||
db_category=category.strip().lower()
|
||||
if category and key is not None
|
||||
else None,
|
||||
db_data=data,
|
||||
db_model=dbmodel,
|
||||
db_tagtype=tagtype.strip().lower() if tagtype is not None else None,
|
||||
|
|
@ -511,7 +539,8 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
typeclass=F("db_typeclass_path"),
|
||||
# Calculate this class' percentage of total composition
|
||||
percent=ExpressionWrapper(
|
||||
((F("count") / float(self.count())) * 100.0), output_field=FloatField()
|
||||
((F("count") / float(self.count())) * 100.0),
|
||||
output_field=FloatField(),
|
||||
),
|
||||
)
|
||||
.values("typeclass", "count", "percent")
|
||||
|
|
@ -531,7 +560,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
stats = self.get_typeclass_totals().order_by("typeclass")
|
||||
return {x.get("typeclass"): x.get("count") for x in stats}
|
||||
|
||||
def typeclass_search(self, typeclass, include_children=False, include_parents=False):
|
||||
def typeclass_search(
|
||||
self, typeclass, include_children=False, include_parents=False
|
||||
):
|
||||
"""
|
||||
Searches through all objects returning those which has a
|
||||
certain typeclass. If location is set, limit search to objects
|
||||
|
|
@ -806,7 +837,8 @@ class TypeclassManager(TypedObjectManager):
|
|||
|
||||
"""
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
"%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
kwargs.update({"db_typeclass_path__in": paths})
|
||||
return super().get(**kwargs)
|
||||
|
|
@ -828,7 +860,8 @@ class TypeclassManager(TypedObjectManager):
|
|||
"""
|
||||
# query, including all subclasses
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
"%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
kwargs.update({"db_typeclass_path__in": paths})
|
||||
return super().filter(*args, **kwargs)
|
||||
|
|
@ -843,6 +876,7 @@ class TypeclassManager(TypedObjectManager):
|
|||
|
||||
"""
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
"%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
return super().all().filter(db_typeclass_path__in=paths)
|
||||
|
|
|
|||
|
|
@ -58,12 +58,16 @@ class TestTypedObjectManager(EvenniaTest):
|
|||
self.obj2.tags.add("tag4")
|
||||
self.obj2.tags.add("tag2c")
|
||||
self.assertEqual(self._manager("get_by_tag", "tag1"), [self.obj1])
|
||||
self.assertEqual(set(self._manager("get_by_tag", "tag2")), set([self.obj1, self.obj2]))
|
||||
self.assertEqual(
|
||||
set(self._manager("get_by_tag", "tag2")), set([self.obj1, self.obj2])
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", "tag2a"), [self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", "tag3 with spaces"), [self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag2b"]), [self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag1"]), [])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag4", "tag2c"]), [self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag2a", "tag4", "tag2c"]), [self.obj2]
|
||||
)
|
||||
|
||||
def test_get_by_tag_and_category(self):
|
||||
self.obj1.tags.add("tag5", "category1")
|
||||
|
|
@ -79,24 +83,66 @@ class TestTypedObjectManager(EvenniaTest):
|
|||
self.obj1.tags.add("tag8", "category6")
|
||||
self.obj2.tags.add("tag9", "category6")
|
||||
|
||||
self.assertEqual(self._manager("get_by_tag", "tag5", "category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", "tag5", "category1"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", "tag6", "category1"), [])
|
||||
self.assertEqual(self._manager("get_by_tag", "tag6", "category3"), [self.obj1, self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", "tag6", "category3"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag5", "tag6"], ["category1", "category3"]),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag5", "tag7"], "category1"), [self.obj1, self.obj2]
|
||||
self._manager("get_by_tag", ["tag5", "tag7"], "category1"),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", category="category2"), [self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category1", "category3"]), [self.obj1, self.obj2]
|
||||
self._manager("get_by_tag", category=["category1", "category3"]),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category1", "category2"]), [self.obj1, self.obj2]
|
||||
self._manager("get_by_tag", category=["category1", "category2"]),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category5", "category4"]), []
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category="category6"), [self.obj1, self.obj2]
|
||||
)
|
||||
|
||||
def test_get_tag_with_all(self):
|
||||
self.obj1.tags.add("tagA", "categoryA")
|
||||
self.assertEqual(
|
||||
self._manager(
|
||||
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="all"
|
||||
),
|
||||
[],
|
||||
)
|
||||
|
||||
def test_get_tag_with_any(self):
|
||||
self.obj1.tags.add("tagA", "categoryA")
|
||||
self.assertEqual(
|
||||
self._manager(
|
||||
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="any"
|
||||
),
|
||||
[self.obj1],
|
||||
)
|
||||
|
||||
def test_get_tag_withnomatch(self):
|
||||
self.obj1.tags.add("tagC", "categoryC")
|
||||
self.assertEqual(
|
||||
self._manager(
|
||||
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="any"
|
||||
),
|
||||
[],
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", category=["category5", "category4"]), [])
|
||||
self.assertEqual(self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", category="category6"), [self.obj1, self.obj2])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue