Merge branch 'master' of https://github.com/trhr/evennia into aws-s3-cdn
This commit is contained in:
commit
b4cdbbc710
5 changed files with 94 additions and 9 deletions
|
|
@ -6,6 +6,7 @@ All commands in Evennia inherit from the 'Command' class in this module.
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
import math
|
import math
|
||||||
|
import inspect
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
@ -74,6 +75,13 @@ def _init_command(cls, **kwargs):
|
||||||
cls.is_exit = False
|
cls.is_exit = False
|
||||||
if not hasattr(cls, "help_category"):
|
if not hasattr(cls, "help_category"):
|
||||||
cls.help_category = "general"
|
cls.help_category = "general"
|
||||||
|
# make sure to pick up the parent's docstring if the child class is
|
||||||
|
# missing one (important for auto-help)
|
||||||
|
if cls.__doc__ is None:
|
||||||
|
for parent_class in inspect.getmro(cls):
|
||||||
|
if parent_class.__doc__ is not None:
|
||||||
|
cls.__doc__ = parent_class.__doc__
|
||||||
|
break
|
||||||
cls.help_category = cls.help_category.lower()
|
cls.help_category = cls.help_category.lower()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ from evennia.utils.eveditor import EvEditor
|
||||||
from evennia.utils.evmore import EvMore
|
from evennia.utils.evmore import EvMore
|
||||||
from evennia.prototypes import spawner, prototypes as protlib, menus as olc_menus
|
from evennia.prototypes import spawner, prototypes as protlib, menus as olc_menus
|
||||||
from evennia.utils.ansi import raw
|
from evennia.utils.ansi import raw
|
||||||
|
from evennia.prototypes.menus import _format_diff_text_and_options
|
||||||
|
|
||||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
|
|
||||||
|
|
@ -1912,8 +1913,8 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
typeclass[/switch] <object> [= typeclass.path]
|
typeclass[/switch] <object> [= typeclass.path]
|
||||||
type ''
|
typeclass/prototype <object> = prototype_key
|
||||||
parent ''
|
|
||||||
typeclass/list/show [typeclass.path]
|
typeclass/list/show [typeclass.path]
|
||||||
swap - this is a shorthand for using /force/reset flags.
|
swap - this is a shorthand for using /force/reset flags.
|
||||||
update - this is a shorthand for using the /force/reload flag.
|
update - this is a shorthand for using the /force/reload flag.
|
||||||
|
|
@ -1930,9 +1931,12 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
|
||||||
list - show available typeclasses. Only typeclasses in modules actually
|
list - show available typeclasses. Only typeclasses in modules actually
|
||||||
imported or used from somewhere in the code will show up here
|
imported or used from somewhere in the code will show up here
|
||||||
(those typeclasses are still available if you know the path)
|
(those typeclasses are still available if you know the path)
|
||||||
|
prototype - clean and overwrite the object with the specified
|
||||||
|
prototype key - effectively making a whole new object.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
type button = examples.red_button.RedButton
|
type button = examples.red_button.RedButton
|
||||||
|
type/prototype button=a red button
|
||||||
|
|
||||||
If the typeclass_path is not given, the current object's typeclass is
|
If the typeclass_path is not given, the current object's typeclass is
|
||||||
assumed.
|
assumed.
|
||||||
|
|
@ -1954,7 +1958,7 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
key = "typeclass"
|
key = "typeclass"
|
||||||
aliases = ["type", "parent", "swap", "update"]
|
aliases = ["type", "parent", "swap", "update"]
|
||||||
switch_options = ("show", "examine", "update", "reset", "force", "list")
|
switch_options = ("show", "examine", "update", "reset", "force", "list", "prototype")
|
||||||
locks = "cmd:perm(typeclass) or perm(Builder)"
|
locks = "cmd:perm(typeclass) or perm(Builder)"
|
||||||
help_category = "Building"
|
help_category = "Building"
|
||||||
|
|
||||||
|
|
@ -2038,6 +2042,27 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
new_typeclass = self.rhs or obj.path
|
new_typeclass = self.rhs or obj.path
|
||||||
|
|
||||||
|
prototype = None
|
||||||
|
if "prototype" in self.switches:
|
||||||
|
key = self.rhs
|
||||||
|
prototype = protlib.search_prototype(key=key)
|
||||||
|
if len(prototype) > 1:
|
||||||
|
caller.msg(
|
||||||
|
"More than one match for {}:\n{}".format(
|
||||||
|
key, "\n".join(proto.get("prototype_key", "") for proto in prototype)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
elif prototype:
|
||||||
|
# one match
|
||||||
|
prototype = prototype[0]
|
||||||
|
else:
|
||||||
|
# no match
|
||||||
|
caller.msg("No prototype '{}' was found.".format(key))
|
||||||
|
return
|
||||||
|
new_typeclass = prototype["typeclass"]
|
||||||
|
self.switches.append("force")
|
||||||
|
|
||||||
if "show" in self.switches or "examine" in self.switches:
|
if "show" in self.switches or "examine" in self.switches:
|
||||||
string = "%s's current typeclass is %s." % (obj.name, obj.__class__)
|
string = "%s's current typeclass is %s." % (obj.name, obj.__class__)
|
||||||
caller.msg(string)
|
caller.msg(string)
|
||||||
|
|
@ -2070,11 +2095,38 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
|
||||||
hooks = "at_object_creation" if update else "all"
|
hooks = "at_object_creation" if update else "all"
|
||||||
old_typeclass_path = obj.typeclass_path
|
old_typeclass_path = obj.typeclass_path
|
||||||
|
|
||||||
|
# special prompt for the user in cases where we want
|
||||||
|
# to confirm changes.
|
||||||
|
if "prototype" in self.switches:
|
||||||
|
diff, _ = spawner.prototype_diff_from_object(prototype, obj)
|
||||||
|
txt, options = _format_diff_text_and_options(diff, objects=[obj])
|
||||||
|
prompt = "Applying prototype '%s' over '%s' will cause the follow changes:\n%s\n" % \
|
||||||
|
(
|
||||||
|
prototype["key"],
|
||||||
|
obj.name,
|
||||||
|
"\n".join(txt)
|
||||||
|
)
|
||||||
|
if not reset:
|
||||||
|
prompt += "\n|yWARNING:|n Use the /reset switch to apply the prototype over a blank state."
|
||||||
|
prompt += "\nAre you sure you want to apply these changes [yes]/no?"
|
||||||
|
answer = yield (prompt)
|
||||||
|
if answer and answer in ("no", "n"):
|
||||||
|
caller.msg(
|
||||||
|
"Canceled: No changes were applied."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
# we let this raise exception if needed
|
# we let this raise exception if needed
|
||||||
obj.swap_typeclass(
|
obj.swap_typeclass(
|
||||||
new_typeclass, clean_attributes=reset, clean_cmdsets=reset, run_start_hooks=hooks
|
new_typeclass, clean_attributes=reset, clean_cmdsets=reset, run_start_hooks=hooks
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "prototype" in self.switches:
|
||||||
|
modified = spawner.batch_update_objects_with_prototype(prototype, objects=[obj])
|
||||||
|
prototype_success = modified > 0
|
||||||
|
if not prototype_success:
|
||||||
|
caller.msg("Prototype %s failed to apply." % prototype["key"])
|
||||||
|
|
||||||
if is_same:
|
if is_same:
|
||||||
string = "%s updated its existing typeclass (%s).\n" % (obj.name, obj.path)
|
string = "%s updated its existing typeclass (%s).\n" % (obj.name, obj.path)
|
||||||
else:
|
else:
|
||||||
|
|
@ -2091,6 +2143,8 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
|
||||||
string += " All old attributes where deleted before the swap."
|
string += " All old attributes where deleted before the swap."
|
||||||
else:
|
else:
|
||||||
string += " Attributes set before swap were not removed."
|
string += " Attributes set before swap were not removed."
|
||||||
|
if "prototype" in self.switches and prototype_success:
|
||||||
|
string += " Prototype '%s' was successfully applied over the object type." % prototype["key"]
|
||||||
|
|
||||||
caller.msg(string)
|
caller.msg(string)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -991,6 +991,27 @@ class TestBuilding(CommandTest):
|
||||||
"All object creation hooks were run. All old attributes where deleted before the swap.",
|
"All object creation hooks were run. All old attributes where deleted before the swap.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from evennia.prototypes.prototypes import homogenize_prototype
|
||||||
|
test_prototype = [homogenize_prototype(
|
||||||
|
{"prototype_key": "testkey",
|
||||||
|
"prototype_tags": [],
|
||||||
|
"typeclass": "typeclasses.objects.Object",
|
||||||
|
"key":"replaced_obj",
|
||||||
|
"attrs": [("foo", "bar", None, ""),
|
||||||
|
("desc", "protdesc", None, "")]})]
|
||||||
|
with mock.patch("evennia.commands.default.building.protlib.search_prototype",
|
||||||
|
new=mock.MagicMock(return_value=test_prototype)) as mprot:
|
||||||
|
self.call(
|
||||||
|
building.CmdTypeclass(),
|
||||||
|
"/prototype Obj=testkey",
|
||||||
|
"replaced_obj changed typeclass from "
|
||||||
|
"evennia.objects.objects.DefaultObject to "
|
||||||
|
"typeclasses.objects.Object.\nAll object creation hooks were "
|
||||||
|
"run. Attributes set before swap were not removed. Prototype "
|
||||||
|
"'replaced_obj' was successfully applied over the object type."
|
||||||
|
)
|
||||||
|
assert self.obj1.db.desc == "protdesc"
|
||||||
|
|
||||||
def test_lock(self):
|
def test_lock(self):
|
||||||
self.call(building.CmdLock(), "", "Usage: ")
|
self.call(building.CmdLock(), "", "Usage: ")
|
||||||
self.call(building.CmdLock(), "Obj = test:all()", "Added lock 'test:all()' to Obj.")
|
self.call(building.CmdLock(), "Obj = test:all()", "Added lock 'test:all()' to Obj.")
|
||||||
|
|
|
||||||
|
|
@ -388,8 +388,7 @@ if WEBSERVER_ENABLED:
|
||||||
webclientstr = "webclient-websocket%s: %s" % (w_ifacestr, port)
|
webclientstr = "webclient-websocket%s: %s" % (w_ifacestr, port)
|
||||||
INFO_DICT["webclient"].append(webclientstr)
|
INFO_DICT["webclient"].append(webclientstr)
|
||||||
|
|
||||||
web_root = Website(web_root, logPath=settings.HTTP_LOG_FILE)
|
|
||||||
web_root.is_portal = True
|
|
||||||
|
|
||||||
if WEB_PLUGINS_MODULE:
|
if WEB_PLUGINS_MODULE:
|
||||||
try:
|
try:
|
||||||
|
|
@ -399,8 +398,8 @@ if WEBSERVER_ENABLED:
|
||||||
"WARNING: WEB_PLUGINS_MODULE is enabled but at_webproxy_root_creation() not found - "
|
"WARNING: WEB_PLUGINS_MODULE is enabled but at_webproxy_root_creation() not found - "
|
||||||
"copy 'evennia/game_template/server/conf/web_plugins.py to mygame/server/conf."
|
"copy 'evennia/game_template/server/conf/web_plugins.py to mygame/server/conf."
|
||||||
)
|
)
|
||||||
|
web_root = Website(web_root, logPath=settings.HTTP_LOG_FILE)
|
||||||
|
web_root.is_portal = True
|
||||||
proxy_service = internet.TCPServer(proxyport, web_root, interface=interface)
|
proxy_service = internet.TCPServer(proxyport, web_root, interface=interface)
|
||||||
proxy_service.setName("EvenniaWebProxy%s:%s" % (ifacestr, proxyport))
|
proxy_service.setName("EvenniaWebProxy%s:%s" % (ifacestr, proxyport))
|
||||||
PORTAL.services.addService(proxy_service)
|
PORTAL.services.addService(proxy_service)
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@ pytz
|
||||||
django-sekizai
|
django-sekizai
|
||||||
inflect
|
inflect
|
||||||
autobahn >= 17.9.3
|
autobahn >= 17.9.3
|
||||||
model_mommy
|
|
||||||
|
# try to resolve dependency issue in py3.7
|
||||||
|
attrs >= 19.2.0
|
||||||
|
|
||||||
# testing and development
|
# testing and development
|
||||||
|
model_mommy
|
||||||
mock >= 1.0.1
|
mock >= 1.0.1
|
||||||
anything
|
anything
|
||||||
black
|
black
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue