Ran black on sources

This commit is contained in:
Griatch 2020-06-16 14:50:02 +02:00
parent a9aae82092
commit 6929bec4e6
11 changed files with 100 additions and 163 deletions

View file

@ -35,8 +35,8 @@ extensions = [
"sphinx.ext.githubpages", "sphinx.ext.githubpages",
] ]
source_suffix = ['.md', '.rst'] source_suffix = [".md", ".rst"]
master_doc = 'index' master_doc = "index"
# make sure sectionlabel references can be used as path/to/file:heading # make sure sectionlabel references can be used as path/to/file:heading
autosectionlabel_prefix_document = True autosectionlabel_prefix_document = True
@ -74,9 +74,9 @@ smv_tag_whitelist = r"^$"
# html_theme = 'scrolls' # html_theme = 'scrolls'
# html_theme = 'agogo' # html_theme = 'agogo'
# html_theme = "traditional" # html_theme = "traditional"
html_theme = 'nature' html_theme = "nature"
## html_theme = 'pyramid' ## html_theme = 'pyramid'
#html_theme = 'bizstyle' # html_theme = 'bizstyle'
# html_theme = 'epub' # html_theme = 'epub'
# Custom extras for sidebar # Custom extras for sidebar
@ -100,23 +100,23 @@ pygments_style = "sphinx"
# -- Options for LaTeX output ------------------------------------------------ # -- Options for LaTeX output ------------------------------------------------
# experimental, not working well atm # experimental, not working well atm
latex_engine = 'xelatex' latex_engine = "xelatex"
latex_show_urls = 'footnote' latex_show_urls = "footnote"
latex_elements = { latex_elements = {
'papersize': 'a4paper', "papersize": "a4paper",
'fncychap': r'\usepackage[Bjarne]{fncychap}', "fncychap": r"\usepackage[Bjarne]{fncychap}",
'fontpkg': r'\usepackage{times,amsmath,amsfonts,amssymb,amsthm}', "fontpkg": r"\usepackage{times,amsmath,amsfonts,amssymb,amsthm}",
'preamble': r''' "preamble": r"""
\usepackage[utf8]{fontenc} \usepackage[utf8]{fontenc}
\usepackage{amsmath,amsfonts,amssymb,amsthm} \usepackage{amsmath,amsfonts,amssymb,amsthm}
\usepackage[math-style=literal]{unicode-math} \usepackage[math-style=literal]{unicode-math}
\usepackage{newunicodechar} \usepackage{newunicodechar}
\usepackage{graphicx} \usepackage{graphicx}
''' """,
} }
latex_documents = [ latex_documents = [
(master_doc, 'main.tex', 'Sphinx format', 'Evennia', 'report'), (master_doc, "main.tex", "Sphinx format", "Evennia", "report"),
("toc", 'toc.tex', 'TOC', 'Evennia', 'report') ("toc", "toc.tex", "TOC", "Evennia", "report"),
] ]
@ -139,7 +139,7 @@ def url_resolver(url):
return _github_issue_choose return _github_issue_choose
elif url.startswith(githubstart): elif url.startswith(githubstart):
urlpath = url[len(githubstart):] urlpath = url[len(githubstart) :]
if not (urlpath.startswith("develop/") or urlpath.startswith("master")): if not (urlpath.startswith("develop/") or urlpath.startswith("master")):
urlpath = "master/" + urlpath urlpath = "master/" + urlpath
return _github_code_root + urlpath return _github_code_root + urlpath
@ -240,13 +240,15 @@ napoleon_use_rtype = True
# -- Main config setup ------------------------------------------ # -- Main config setup ------------------------------------------
# last setup steps for some plugins # last setup steps for some plugins
def setup(app): def setup(app):
app.connect("autodoc-skip-member", autodoc_skip_member) app.connect("autodoc-skip-member", autodoc_skip_member)
app.add_transform(AutoStructify) app.add_transform(AutoStructify)
# build toctree file # build toctree file
sys.path.insert(1, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'docs')) sys.path.insert(1, os.path.join(os.path.dirname(os.path.dirname(__file__)), "docs"))
from docs.pylib import create_toctree from docs.pylib import create_toctree
create_toctree.create_toctree() create_toctree.create_toctree()
print("Updated source/toc.md file") print("Updated source/toc.md file")

View file

@ -92,9 +92,7 @@ def help_search_with_index(query, candidate_entries, suggestion_maxnum=5):
# matches (objs), suggestions (strs) # matches (objs), suggestions (strs)
return ( return (
[mapping[match["ref"]] for match in matches], [mapping[match["ref"]] for match in matches],
[ [str(match["ref"]) for match in matches], # + f" (score {match['score']})") # good debug
str(match["ref"]) for match in matches
], # + f" (score {match['score']})") # good debug
) )
@ -140,10 +138,7 @@ class CmdHelp(Command):
if type(self).help_more: if type(self).help_more:
usemore = True usemore = True
if self.session and self.session.protocol_key in ( if self.session and self.session.protocol_key in ("websocket", "ajax/comet",):
"websocket",
"ajax/comet",
):
try: try:
options = self.account.db._saved_webclient_options options = self.account.db._saved_webclient_options
if options and options["helppopup"]: if options and options["helppopup"]:
@ -177,9 +172,7 @@ class CmdHelp(Command):
if title: if title:
string += "|CHelp for |w%s|n" % title string += "|CHelp for |w%s|n" % title
if aliases: if aliases:
string += " |C(aliases: %s|C)|n" % ( string += " |C(aliases: %s|C)|n" % ("|C,|n ".join("|w%s|n" % ali for ali in aliases))
"|C,|n ".join("|w%s|n" % ali for ali in aliases)
)
if help_text: if help_text:
string += "\n%s" % dedent(help_text.rstrip()) string += "\n%s" % dedent(help_text.rstrip())
if suggested: if suggested:
@ -206,22 +199,15 @@ class CmdHelp(Command):
category_str = f"-- {category.title()} " category_str = f"-- {category.title()} "
grid.append( grid.append(
ANSIString( ANSIString(
category_clr category_clr + category_str + "-" * (width - len(category_str)) + topic_clr
+ category_str
+ "-" * (width - len(category_str))
+ topic_clr
) )
) )
verbatim_elements.append(len(grid) - 1) verbatim_elements.append(len(grid) - 1)
entries = sorted( entries = sorted(set(hdict_cmds.get(category, []) + hdict_db.get(category, [])))
set(hdict_cmds.get(category, []) + hdict_db.get(category, []))
)
grid.extend(entries) grid.extend(entries)
gridrows = format_grid( gridrows = format_grid(grid, width, sep=" ", verbatim_elements=verbatim_elements)
grid, width, sep=" ", verbatim_elements=verbatim_elements
)
gridrows = ANSIString("\n").join(gridrows) gridrows = ANSIString("\n").join(gridrows)
return gridrows return gridrows
@ -293,9 +279,7 @@ class CmdHelp(Command):
# retrieve all available commands and database topics # retrieve all available commands and database topics
all_cmds = [cmd for cmd in cmdset if self.check_show_help(cmd, caller)] all_cmds = [cmd for cmd in cmdset if self.check_show_help(cmd, caller)]
all_topics = [ all_topics = [
topic topic for topic in HelpEntry.objects.all() if topic.access(caller, "view", default=True)
for topic in HelpEntry.objects.all()
if topic.access(caller, "view", default=True)
] ]
all_categories = list( all_categories = list(
set( set(
@ -320,11 +304,7 @@ class CmdHelp(Command):
return return
# Try to access a particular help entry or category # Try to access a particular help entry or category
entries = ( entries = [cmd for cmd in all_cmds if cmd] + list(HelpEntry.objects.all()) + all_categories
[cmd for cmd in all_cmds if cmd]
+ list(HelpEntry.objects.all())
+ all_categories
)
for match_query in [f"{query}~1", f"{query}*"]: for match_query in [f"{query}~1", f"{query}*"]:
# We first do an exact word-match followed by a start-by query # We first do an exact word-match followed by a start-by query
@ -459,9 +439,7 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
# check if we have an old entry with the same name # check if we have an old entry with the same name
try: try:
for querystr in topicstrlist: for querystr in topicstrlist:
old_entry = HelpEntry.objects.find_topicmatch( old_entry = HelpEntry.objects.find_topicmatch(querystr) # also search by alias
querystr
) # also search by alias
if old_entry: if old_entry:
old_entry = list(old_entry)[0] old_entry = list(old_entry)[0]
break break
@ -483,11 +461,7 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
helpentry = old_entry helpentry = old_entry
else: else:
helpentry = create.create_help_entry( helpentry = create.create_help_entry(
topicstr, topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases,
self.rhs,
category=category,
locks=lockstring,
aliases=aliases,
) )
self.caller.db._editing_help = helpentry self.caller.db._editing_help = helpentry
@ -504,9 +478,7 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
if "append" in switches or "merge" in switches or "extend" in switches: if "append" in switches or "merge" in switches or "extend" in switches:
# merge/append operations # merge/append operations
if not old_entry: if not old_entry:
self.msg( self.msg("Could not find topic '%s'. You must give an exact name." % topicstr)
"Could not find topic '%s'. You must give an exact name." % topicstr
)
return return
if not self.rhs: if not self.rhs:
self.msg("You must supply text to append/merge.") self.msg("You must supply text to append/merge.")
@ -553,9 +525,7 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases
) )
if new_entry: if new_entry:
self.msg( self.msg("Topic '%s'%s was successfully created." % (topicstr, aliastxt))
"Topic '%s'%s was successfully created." % (topicstr, aliastxt)
)
if "edit" in switches: if "edit" in switches:
# open the line editor to edit the helptext # open the line editor to edit the helptext
self.caller.db._editing_help = new_entry self.caller.db._editing_help = new_entry
@ -570,6 +540,5 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
return return
else: else:
self.msg( self.msg(
"Error when creating topic '%s'%s! Contact an admin." "Error when creating topic '%s'%s! Contact an admin." % (topicstr, aliastxt)
% (topicstr, aliastxt)
) )

View file

@ -265,16 +265,17 @@ class TestGeneral(CommandTest):
class TestHelp(CommandTest): class TestHelp(CommandTest):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
# we need to set up a logger here since lunr takes over the logger otherwise # we need to set up a logger here since lunr takes over the logger otherwise
import logging import logging
logging.basicConfig(level=logging.ERROR) logging.basicConfig(level=logging.ERROR)
def tearDown(self): def tearDown(self):
super().tearDown() super().tearDown()
import logging import logging
logging.disable(level=logging.ERROR) logging.disable(level=logging.ERROR)
def test_help(self): def test_help(self):

View file

@ -611,7 +611,6 @@ class CmdUsePuzzleParts(MuxCommand):
passed in. passed in.
""" """
key = "use" key = "use"
aliases = "combine" aliases = "combine"
locks = "cmd:pperm(use) or pperm(Player)" locks = "cmd:pperm(use) or pperm(Player)"

View file

@ -1,4 +1,3 @@
try: try:
from django.utils.unittest import TestCase from django.utils.unittest import TestCase
except ImportError: except ImportError:
@ -290,7 +289,7 @@ class TestWebSocket(EvenniaTest):
self.proto.sessionhandler = PORTAL_SESSIONS self.proto.sessionhandler = PORTAL_SESSIONS
self.proto.sessionhandler.portal = Mock() self.proto.sessionhandler.portal = Mock()
self.proto.transport = proto_helpers.StringTransport() self.proto.transport = proto_helpers.StringTransport()
#self.proto.transport = proto_helpers.FakeDatagramTransport() # self.proto.transport = proto_helpers.FakeDatagramTransport()
self.proto.transport.client = ["localhost"] self.proto.transport.client = ["localhost"]
self.proto.transport.setTcpKeepAlive = Mock() self.proto.transport.setTcpKeepAlive = Mock()
self.proto.state = MagicMock() self.proto.state = MagicMock()
@ -318,4 +317,4 @@ class TestWebSocket(EvenniaTest):
self.proto.sendLine = MagicMock() self.proto.sendLine = MagicMock()
msg = json.dumps(["logged_in", (), {}]) msg = json.dumps(["logged_in", (), {}])
self.proto.sessionhandler.data_out(self.proto, text=[["Excepting Alice"], {}]) self.proto.sessionhandler.data_out(self.proto, text=[["Excepting Alice"], {}])
self.proto.sendLine.assert_called_with(json.dumps(['text', ['Excepting Alice'], {}])) self.proto.sendLine.assert_called_with(json.dumps(["text", ["Excepting Alice"], {}]))

View file

@ -132,7 +132,7 @@ def _server_maintenance():
else: else:
# adjust the runtime not with 60s but with the actual elapsed time # adjust the runtime not with 60s but with the actual elapsed time
# in case this may varies slightly from 60s. # in case this may varies slightly from 60s.
_GAMETIME_MODULE.SERVER_RUNTIME += (now - _LAST_SERVER_TIME_SNAPSHOT) _GAMETIME_MODULE.SERVER_RUNTIME += now - _LAST_SERVER_TIME_SNAPSHOT
_LAST_SERVER_TIME_SNAPSHOT = now _LAST_SERVER_TIME_SNAPSHOT = now
# update game time and save it across reloads # update game time and save it across reloads

View file

@ -162,6 +162,7 @@ class Attribute(IAttribute, SharedMemoryModel):
""" """
This attribute is stored via Django. Most Attributes will be using this class. This attribute is stored via Django. Most Attributes will be using this class.
""" """
# #
# Attribute Database Model setup # Attribute Database Model setup
# #
@ -269,10 +270,12 @@ class Attribute(IAttribute, SharedMemoryModel):
value = property(__value_get, __value_set, __value_del) value = property(__value_get, __value_set, __value_del)
# #
# Handlers making use of the Attribute model # Handlers making use of the Attribute model
# #
class IAttributeBackend: class IAttributeBackend:
""" """
Abstract interface for the backends used by the Attribute Handler. Abstract interface for the backends used by the Attribute Handler.
@ -336,8 +339,10 @@ class IAttributeBackend:
if not _TYPECLASS_AGGRESSIVE_CACHE: if not _TYPECLASS_AGGRESSIVE_CACHE:
return return
attrs = self.query_all() attrs = self.query_all()
self._cache = {f"{to_str(attr.key).lower()}-{attr.category.lower() if attr.category else None}": attr self._cache = {
for attr in attrs} f"{to_str(attr.key).lower()}-{attr.category.lower() if attr.category else None}": attr
for attr in attrs
}
self._cache_complete = True self._cache_complete = True
def _get_cache_key(self, key, category): def _get_cache_key(self, key, category):
@ -623,7 +628,9 @@ class IAttributeBackend:
# update an existing attribute object # update an existing attribute object
self.do_batch_update_attribute(attr_obj, category, lockstring, new_value, strattr) self.do_batch_update_attribute(attr_obj, category, lockstring, new_value, strattr)
else: else:
new_attr = self.do_create_attribute(keystr, category, lockstring, new_value, strvalue=strattr) new_attr = self.do_create_attribute(
keystr, category, lockstring, new_value, strvalue=strattr
)
new_attrobjs.append(new_attr) new_attrobjs.append(new_attr)
if new_attrobjs: if new_attrobjs:
self.do_batch_finish(new_attrobjs) self.do_batch_finish(new_attrobjs)
@ -696,8 +703,13 @@ class IAttributeBackend:
attrs = self._cache.values() attrs = self._cache.values()
if accessing_obj: if accessing_obj:
self.do_batch_delete([attr for attr in attrs if attr.access(accessing_obj, self._attredit, self.do_batch_delete(
default=default_access)]) [
attr
for attr in attrs
if attr.access(accessing_obj, self._attredit, default=default_access)
]
)
else: else:
# have to cast the results to a list or we'll get a RuntimeError for removing from the dict we're iterating # have to cast the results to a list or we'll get a RuntimeError for removing from the dict we're iterating
self.do_batch_delete(list(attrs)) self.do_batch_delete(list(attrs))
@ -765,7 +777,9 @@ class InMemoryAttributeBackend(IAttributeBackend):
strvalue has no meaning for InMemory attributes. strvalue has no meaning for InMemory attributes.
""" """
new_attr = self._attrclass(pk=self._next_id(), key=key, category=category, lock_storage=lockstring, value=value) new_attr = self._attrclass(
pk=self._next_id(), key=key, category=category, lock_storage=lockstring, value=value
)
self._storage[(key, category)] = new_attr self._storage[(key, category)] = new_attr
self._category_storage[category].append(new_attr) self._category_storage[category].append(new_attr)
return new_attr return new_attr
@ -805,6 +819,7 @@ class ModelAttributeBackend(IAttributeBackend):
""" """
Uses Django models for storing Attributes. Uses Django models for storing Attributes.
""" """
_attrclass = Attribute _attrclass = Attribute
_m2m_fieldname = "db_attributes" _m2m_fieldname = "db_attributes"
@ -844,9 +859,7 @@ class ModelAttributeBackend(IAttributeBackend):
} }
return [ return [
conn.attribute conn.attribute
for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter( for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)
**query
)
] ]
def do_create_attribute(self, key, category, lockstring, value, strvalue): def do_create_attribute(self, key, category, lockstring, value, strvalue):
@ -855,7 +868,7 @@ class ModelAttributeBackend(IAttributeBackend):
"db_category": category, "db_category": category,
"db_model": self._model, "db_model": self._model,
"db_lock_storage": lockstring if lockstring else "", "db_lock_storage": lockstring if lockstring else "",
"db_attrtype": self._attrtype "db_attrtype": self._attrtype,
} }
if strvalue: if strvalue:
kwargs["db_value"] = None kwargs["db_value"] = None
@ -901,6 +914,7 @@ class AttributeHandler:
""" """
Handler for adding Attributes to the object. Handler for adding Attributes to the object.
""" """
_attrcreate = "attrcreate" _attrcreate = "attrcreate"
_attredit = "attredit" _attredit = "attredit"
_attrread = "attrread" _attrread = "attrread"

View file

@ -31,14 +31,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
# Attribute manager methods # Attribute manager methods
def get_attribute( def get_attribute(
self, self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None, **kwargs
key=None,
category=None,
value=None,
strvalue=None,
obj=None,
attrtype=None,
**kwargs
): ):
""" """
Return Attribute objects by key, by category, by value, by Return Attribute objects by key, by category, by value, by
@ -82,9 +75,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
# no reason to make strvalue/value mutually exclusive at this level # no reason to make strvalue/value mutually exclusive at this level
query.append(("attribute__db_value", value)) query.append(("attribute__db_value", value))
return Attribute.objects.filter( return Attribute.objects.filter(
pk__in=self.model.db_attributes.through.objects.filter( pk__in=self.model.db_attributes.through.objects.filter(**dict(query)).values_list(
**dict(query) "attribute_id", flat=True
).values_list("attribute_id", flat=True) )
) )
def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None): def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None):
@ -111,13 +104,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
) )
def get_by_attribute( def get_by_attribute(
self, self, key=None, category=None, value=None, strvalue=None, attrtype=None, **kwargs
key=None,
category=None,
value=None,
strvalue=None,
attrtype=None,
**kwargs
): ):
""" """
Return objects having attributes with the given key, category, Return objects having attributes with the given key, category,
@ -174,15 +161,11 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
obj (list): Objects having the matching Nicks. obj (list): Objects having the matching Nicks.
""" """
return self.get_by_attribute( return self.get_by_attribute(key=key, category=category, strvalue=nick, attrtype="nick")
key=key, category=category, strvalue=nick, attrtype="nick"
)
# Tag manager methods # Tag manager methods
def get_tag( def get_tag(self, key=None, category=None, obj=None, tagtype=None, global_search=False):
self, key=None, category=None, obj=None, tagtype=None, global_search=False
):
""" """
Return Tag objects by key, by category, by object (it is Return Tag objects by key, by category, by object (it is
stored on) or with a combination of those criteria. stored on) or with a combination of those criteria.
@ -226,9 +209,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
if category: if category:
query.append(("tag__db_category", category)) query.append(("tag__db_category", category))
return Tag.objects.filter( return Tag.objects.filter(
pk__in=self.model.db_tags.through.objects.filter( pk__in=self.model.db_tags.through.objects.filter(**dict(query)).values_list(
**dict(query) "tag_id", flat=True
).values_list("tag_id", flat=True) )
) )
def get_permission(self, key=None, category=None, obj=None): def get_permission(self, key=None, category=None, obj=None):
@ -310,9 +293,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
dbmodel = self.model.__dbclass__.__name__.lower() dbmodel = self.model.__dbclass__.__name__.lower()
query = ( query = (
self.filter( self.filter(db_tags__db_tagtype__iexact=tagtype, db_tags__db_model__iexact=dbmodel)
db_tags__db_tagtype__iexact=tagtype, db_tags__db_model__iexact=dbmodel
)
.distinct() .distinct()
.order_by("id") .order_by("id")
) )
@ -332,9 +313,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
clauses = Q() clauses = Q()
for ikey, key in enumerate(keys): for ikey, key in enumerate(keys):
# ANY mode; must match any one of the given tags/categories # ANY mode; must match any one of the given tags/categories
clauses |= Q( clauses |= Q(db_key__iexact=key, db_category__iexact=categories[ikey])
db_key__iexact=key, db_category__iexact=categories[ikey]
)
else: else:
# only one or more categories given # only one or more categories given
clauses = Q() clauses = Q()
@ -344,8 +323,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
tags = _Tag.objects.filter(clauses) tags = _Tag.objects.filter(clauses)
query = query.filter(db_tags__in=tags).annotate( query = query.filter(db_tags__in=tags).annotate(
matches=Count("db_tags__pk", filter=Q(db_tags__in=tags), matches=Count("db_tags__pk", filter=Q(db_tags__in=tags), distinct=True)
distinct=True)
) )
if anymatch: if anymatch:
@ -412,9 +390,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
# try to get old tag # try to get old tag
dbmodel = self.model.__dbclass__.__name__.lower() dbmodel = self.model.__dbclass__.__name__.lower()
tag = self.get_tag( tag = self.get_tag(key=key, category=category, tagtype=tagtype, global_search=True)
key=key, category=category, tagtype=tagtype, global_search=True
)
if tag and data is not None: if tag and data is not None:
# get tag from list returned by get_tag # get tag from list returned by get_tag
tag = tag[0] tag = tag[0]
@ -428,9 +404,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
from evennia.typeclasses.models import Tag as _Tag from evennia.typeclasses.models import Tag as _Tag
tag = _Tag.objects.create( tag = _Tag.objects.create(
db_key=key.strip().lower() if key is not None else None, db_key=key.strip().lower() if key is not None else None,
db_category=category.strip().lower() db_category=category.strip().lower() if category and key is not None else None,
if category and key is not None
else None,
db_data=data, db_data=data,
db_model=dbmodel, db_model=dbmodel,
db_tagtype=tagtype.strip().lower() if tagtype is not None else None, db_tagtype=tagtype.strip().lower() if tagtype is not None else None,
@ -539,8 +513,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
typeclass=F("db_typeclass_path"), typeclass=F("db_typeclass_path"),
# Calculate this class' percentage of total composition # Calculate this class' percentage of total composition
percent=ExpressionWrapper( percent=ExpressionWrapper(
((F("count") / float(self.count())) * 100.0), ((F("count") / float(self.count())) * 100.0), output_field=FloatField(),
output_field=FloatField(),
), ),
) )
.values("typeclass", "count", "percent") .values("typeclass", "count", "percent")
@ -560,9 +533,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
stats = self.get_typeclass_totals().order_by("typeclass") stats = self.get_typeclass_totals().order_by("typeclass")
return {x.get("typeclass"): x.get("count") for x in stats} return {x.get("typeclass"): x.get("count") for x in stats}
def typeclass_search( def typeclass_search(self, typeclass, include_children=False, include_parents=False):
self, typeclass, include_children=False, include_parents=False
):
""" """
Searches through all objects returning those which has a Searches through all objects returning those which has a
certain typeclass. If location is set, limit search to objects certain typeclass. If location is set, limit search to objects
@ -837,8 +808,7 @@ class TypeclassManager(TypedObjectManager):
""" """
paths = [self.model.path] + [ paths = [self.model.path] + [
"%s.%s" % (cls.__module__, cls.__name__) "%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
for cls in self._get_subclasses(self.model)
] ]
kwargs.update({"db_typeclass_path__in": paths}) kwargs.update({"db_typeclass_path__in": paths})
return super().get(**kwargs) return super().get(**kwargs)
@ -860,8 +830,7 @@ class TypeclassManager(TypedObjectManager):
""" """
# query, including all subclasses # query, including all subclasses
paths = [self.model.path] + [ paths = [self.model.path] + [
"%s.%s" % (cls.__module__, cls.__name__) "%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
for cls in self._get_subclasses(self.model)
] ]
kwargs.update({"db_typeclass_path__in": paths}) kwargs.update({"db_typeclass_path__in": paths})
return super().filter(*args, **kwargs) return super().filter(*args, **kwargs)
@ -876,7 +845,6 @@ class TypeclassManager(TypedObjectManager):
""" """
paths = [self.model.path] + [ paths = [self.model.path] + [
"%s.%s" % (cls.__module__, cls.__name__) "%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
for cls in self._get_subclasses(self.model)
] ]
return super().all().filter(db_typeclass_path__in=paths) return super().all().filter(db_typeclass_path__in=paths)

View file

@ -36,7 +36,12 @@ from django.urls import reverse
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
from django.utils.text import slugify from django.utils.text import slugify
from evennia.typeclasses.attributes import Attribute, AttributeHandler, ModelAttributeBackend, InMemoryAttributeBackend from evennia.typeclasses.attributes import (
Attribute,
AttributeHandler,
ModelAttributeBackend,
InMemoryAttributeBackend,
)
from evennia.typeclasses.attributes import DbHolder from evennia.typeclasses.attributes import DbHolder
from evennia.typeclasses.tags import Tag, TagHandler, AliasHandler, PermissionHandler from evennia.typeclasses.tags import Tag, TagHandler, AliasHandler, PermissionHandler
@ -122,6 +127,7 @@ class TypeclassBase(SharedMemoryModelBase):
signals.pre_delete.connect(remove_attributes_on_delete, sender=new_class) signals.pre_delete.connect(remove_attributes_on_delete, sender=new_class)
return new_class return new_class
# #
# Main TypedObject abstraction # Main TypedObject abstraction
# #

View file

@ -58,16 +58,12 @@ class TestTypedObjectManager(EvenniaTest):
self.obj2.tags.add("tag4") self.obj2.tags.add("tag4")
self.obj2.tags.add("tag2c") self.obj2.tags.add("tag2c")
self.assertEqual(self._manager("get_by_tag", "tag1"), [self.obj1]) self.assertEqual(self._manager("get_by_tag", "tag1"), [self.obj1])
self.assertEqual( self.assertEqual(set(self._manager("get_by_tag", "tag2")), set([self.obj1, self.obj2]))
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", "tag2a"), [self.obj2])
self.assertEqual(self._manager("get_by_tag", "tag3 with spaces"), [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", "tag2b"]), [self.obj2])
self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag1"]), []) self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag1"]), [])
self.assertEqual( self.assertEqual(self._manager("get_by_tag", ["tag2a", "tag4", "tag2c"]), [self.obj2])
self._manager("get_by_tag", ["tag2a", "tag4", "tag2c"]), [self.obj2]
)
def test_get_by_tag_and_category(self): def test_get_by_tag_and_category(self):
self.obj1.tags.add("tag5", "category1") self.obj1.tags.add("tag5", "category1")
@ -83,24 +79,17 @@ class TestTypedObjectManager(EvenniaTest):
self.obj1.tags.add("tag8", "category6") self.obj1.tags.add("tag8", "category6")
self.obj2.tags.add("tag9", "category6") self.obj2.tags.add("tag9", "category6")
self.assertEqual( self.assertEqual(self._manager("get_by_tag", "tag5", "category1"), [self.obj1, self.obj2])
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", "category1"), [])
self.assertEqual( self.assertEqual(self._manager("get_by_tag", "tag6", "category3"), [self.obj1, self.obj2])
self._manager("get_by_tag", "tag6", "category3"), [self.obj1, self.obj2]
)
self.assertEqual( self.assertEqual(
self._manager("get_by_tag", ["tag5", "tag6"], ["category1", "category3"]), self._manager("get_by_tag", ["tag5", "tag6"], ["category1", "category3"]),
[self.obj1, self.obj2], [self.obj1, self.obj2],
) )
self.assertEqual( self.assertEqual(
self._manager("get_by_tag", ["tag5", "tag7"], "category1"), self._manager("get_by_tag", ["tag5", "tag7"], "category1"), [self.obj1, self.obj2],
[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="category2"), [self.obj2])
self.assertEqual( self.assertEqual(
self._manager("get_by_tag", category=["category1", "category3"]), self._manager("get_by_tag", category=["category1", "category3"]),
@ -110,39 +99,27 @@ class TestTypedObjectManager(EvenniaTest):
self._manager("get_by_tag", category=["category1", "category2"]), self._manager("get_by_tag", category=["category1", "category2"]),
[self.obj1, self.obj2], [self.obj1, self.obj2],
) )
self.assertEqual( self.assertEqual(self._manager("get_by_tag", category=["category5", "category4"]), [])
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])
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): def test_get_tag_with_all(self):
self.obj1.tags.add("tagA", "categoryA") self.obj1.tags.add("tagA", "categoryA")
self.assertEqual( self.assertEqual(
self._manager( self._manager("get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="all"),
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="all"
),
[], [],
) )
def test_get_tag_with_any(self): def test_get_tag_with_any(self):
self.obj1.tags.add("tagA", "categoryA") self.obj1.tags.add("tagA", "categoryA")
self.assertEqual( self.assertEqual(
self._manager( self._manager("get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="any"),
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="any"
),
[self.obj1], [self.obj1],
) )
def test_get_tag_withnomatch(self): def test_get_tag_withnomatch(self):
self.obj1.tags.add("tagC", "categoryC") self.obj1.tags.add("tagC", "categoryC")
self.assertEqual( self.assertEqual(
self._manager( self._manager("get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="any"),
"get_by_tag", ["tagA", "tagB"], ["categoryA", "categoryB"], match="any"
),
[], [],
) )

View file

@ -158,11 +158,13 @@ class EvenniaTest(TestCase):
self.account2.delete() self.account2.delete()
super().tearDown() super().tearDown()
class LocalEvenniaTest(EvenniaTest): class LocalEvenniaTest(EvenniaTest):
""" """
This test class is intended for inheriting in mygame tests. This test class is intended for inheriting in mygame tests.
It helps ensure your tests are run with your own objects. It helps ensure your tests are run with your own objects.
""" """
account_typeclass = settings.BASE_ACCOUNT_TYPECLASS account_typeclass = settings.BASE_ACCOUNT_TYPECLASS
object_typeclass = settings.BASE_OBJECT_TYPECLASS object_typeclass = settings.BASE_OBJECT_TYPECLASS
character_typeclass = settings.BASE_CHARACTER_TYPECLASS character_typeclass = settings.BASE_CHARACTER_TYPECLASS