mirror of
https://github.com/evennia/evennia.git
synced 2026-03-18 13:56:30 +01:00
Make evennia lib importable without created gamedir
This commit is contained in:
parent
d2046c9e0d
commit
b5ddc52536
9 changed files with 62 additions and 32 deletions
|
|
@ -30,6 +30,7 @@
|
|||
- Make MuxCommand `lhs/rhslist` always be lists, also if empty (used to be the empty string)
|
||||
- Fix typo in UnixCommand contrib, where `help` was given as `--hel`.
|
||||
- Latin (la) i18n translation (jamalainm)
|
||||
- Made the `evennia` dir possible to use without gamedir for purpose of doc generation.
|
||||
|
||||
### Evennia 0.9.5 (2019-2020)
|
||||
|
||||
|
|
|
|||
|
|
@ -379,19 +379,6 @@ def _init():
|
|||
del SystemCmds
|
||||
del _EvContainer
|
||||
|
||||
# typeclases
|
||||
from .utils.utils import class_from_module
|
||||
|
||||
BASE_ACCOUNT_TYPECLASS = class_from_module(settings.BASE_ACCOUNT_TYPECLASS)
|
||||
BASE_OBJECT_TYPECLASS = class_from_module(settings.BASE_OBJECT_TYPECLASS)
|
||||
BASE_CHARACTER_TYPECLASS = class_from_module(settings.BASE_CHARACTER_TYPECLASS)
|
||||
BASE_ROOM_TYPECLASS = class_from_module(settings.BASE_ROOM_TYPECLASS)
|
||||
BASE_EXIT_TYPECLASS = class_from_module(settings.BASE_EXIT_TYPECLASS)
|
||||
BASE_CHANNEL_TYPECLASS = class_from_module(settings.BASE_CHANNEL_TYPECLASS)
|
||||
BASE_SCRIPT_TYPECLASS = class_from_module(settings.BASE_SCRIPT_TYPECLASS)
|
||||
BASE_GUEST_TYPECLASS = class_from_module(settings.BASE_GUEST_TYPECLASS)
|
||||
del class_from_module
|
||||
|
||||
# delayed starts - important so as to not back-access evennia before it has
|
||||
# finished initializing
|
||||
GLOBAL_SCRIPTS.start()
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ from evennia.utils import create, logger, utils, evtable
|
|||
from evennia.utils.utils import make_iter, class_from_module
|
||||
|
||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||
CHANNEL_DEFAULT_TYPECLASS = class_from_module(settings.BASE_CHANNEL_TYPECLASS)
|
||||
CHANNEL_DEFAULT_TYPECLASS = class_from_module(
|
||||
settings.BASE_CHANNEL_TYPECLASS, fallback=settings.FALLBACK_CHANNEL_TYPECLASS)
|
||||
|
||||
|
||||
# limit symbol import for API
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ from evennia.utils.utils import get_evennia_version, mod_import, make_iter, clas
|
|||
from evennia.server.portal.portalsessionhandler import PORTAL_SESSIONS
|
||||
from evennia.utils import logger
|
||||
from evennia.server.webserver import EvenniaReverseProxyResource
|
||||
from django.db import connection
|
||||
|
||||
|
||||
# we don't need a connection to the database so close it right away
|
||||
|
|
@ -434,4 +433,6 @@ if WEBSERVER_ENABLED:
|
|||
|
||||
for plugin_module in PORTAL_SERVICES_PLUGIN_MODULES:
|
||||
# external plugin services to start
|
||||
plugin_module.start_plugin_services(PORTAL)
|
||||
if plugin_module:
|
||||
plugin_module.start_plugin_services(PORTAL)
|
||||
|
||||
|
|
|
|||
|
|
@ -511,6 +511,18 @@ START_LOCATION = "#2"
|
|||
# out of sync between the processes. Keep on unless you face such
|
||||
# issues.
|
||||
TYPECLASS_AGGRESSIVE_CACHE = True
|
||||
# These are fallbacks for BASE typeclasses failing to load. Usually needed only
|
||||
# during doc building. The system expects these to *always* load correctly, so
|
||||
# only modify if you are making fundamental changes to how objects/accounts
|
||||
# work and know what you are doing
|
||||
FALLBACK_ACCOUNT_TYPECLASS = "evennia.accounts.accounts.DefaultAccount"
|
||||
FALLBACK_OBJECT_TYPECLASS = "evennia.objects.objects.DefaultObject"
|
||||
FALLBACK_CHARACTER_TYPECLASS = "evennia.objects.objects.DefaultCharacter"
|
||||
FALLBACK_ROOM_TYPECLASS = "evennia.objects.objects.DefaultRoom"
|
||||
FALLBACK_EXIT_TYPECLASS = "evennia.objects.objects.DefaultExit"
|
||||
FALLBACK_CHANNEL_TYPECLASS = "evennia.comms.comms.DefaultChannel"
|
||||
FALLBACK_SCRIPT_TYPECLASS = "evennia.scripts.scripts.DefaultScript"
|
||||
|
||||
|
||||
######################################################################
|
||||
# Options and validators
|
||||
|
|
|
|||
|
|
@ -1319,6 +1319,9 @@ def variable_from_module(module, variable=None, default=None):
|
|||
|
||||
mod = mod_import(module)
|
||||
|
||||
if not mod:
|
||||
return default
|
||||
|
||||
if variable:
|
||||
result = []
|
||||
for var in make_iter(variable):
|
||||
|
|
@ -1410,7 +1413,7 @@ def fuzzy_import_from_module(path, variable, default=None, defaultpaths=None):
|
|||
return default
|
||||
|
||||
|
||||
def class_from_module(path, defaultpaths=None):
|
||||
def class_from_module(path, defaultpaths=None, fallback=None):
|
||||
"""
|
||||
Return a class from a module, given the class' full python path. This is
|
||||
primarily used to convert db_typeclass_path:s to classes.
|
||||
|
|
@ -1419,6 +1422,10 @@ def class_from_module(path, defaultpaths=None):
|
|||
path (str): Full Python dot-path to module.
|
||||
defaultpaths (iterable, optional): If a direct import from `path` fails,
|
||||
try subsequent imports by prepending those paths to `path`.
|
||||
fallback (str): If all other attempts fail, use this path as a fallback.
|
||||
This is intended as a last-resport. In the example of Evennia
|
||||
loading, this would be a path to a default parent class in the
|
||||
evennia repo itself.
|
||||
|
||||
Returns:
|
||||
class (Class): An uninstatiated class recovered from path.
|
||||
|
|
@ -1472,7 +1479,13 @@ def class_from_module(path, defaultpaths=None):
|
|||
err += "\nPaths searched:\n %s" % "\n ".join(paths)
|
||||
else:
|
||||
err += "."
|
||||
raise ImportError(err)
|
||||
logger.log_err(err)
|
||||
if fallback:
|
||||
logger.log_warn(f"Falling back to {fallback}.")
|
||||
return class_from_module(fallback)
|
||||
else:
|
||||
# even fallback fails
|
||||
raise ImportError(err)
|
||||
return cls
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ class AccountForm(UserCreationForm):
|
|||
"""
|
||||
|
||||
# The model/typeclass this form creates
|
||||
model = class_from_module(settings.BASE_ACCOUNT_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_ACCOUNT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_ACCOUNT_TYPECLASS)
|
||||
|
||||
# The fields to display on the form, in the given order
|
||||
fields = ("username", "email")
|
||||
|
|
@ -87,7 +88,8 @@ class ObjectForm(EvenniaForm, ModelForm):
|
|||
"""
|
||||
|
||||
# The model/typeclass this form creates
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
|
||||
# The fields to display on the form, in the given order
|
||||
fields = ("db_key",)
|
||||
|
|
@ -140,7 +142,8 @@ class CharacterForm(ObjectForm):
|
|||
"""
|
||||
|
||||
# Get the correct object model
|
||||
model = class_from_module(settings.BASE_CHARACTER_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_CHARACTER_TYPECLASS,
|
||||
fallback=settings.FALLBACK_CHARACTER_TYPECLASS)
|
||||
|
||||
# Allow entry of the 'key' field
|
||||
fields = ("db_key",)
|
||||
|
|
|
|||
|
|
@ -125,7 +125,8 @@ class ChannelDetailTest(EvenniaWebTest):
|
|||
def setUp(self):
|
||||
super(ChannelDetailTest, self).setUp()
|
||||
|
||||
klass = class_from_module(self.channel_typeclass)
|
||||
klass = class_from_module(self.channel_typeclass,
|
||||
fallback=settings.FALLBACK_CHANNEL_TYPECLASS)
|
||||
|
||||
# Create a channel
|
||||
klass.create("demo")
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ from django.utils.text import slugify
|
|||
|
||||
_BASE_CHAR_TYPECLASS = settings.BASE_CHARACTER_TYPECLASS
|
||||
|
||||
# typeclass fallbacks
|
||||
|
||||
def _gamestats():
|
||||
# Some misc. configurable stuff.
|
||||
|
|
@ -48,11 +49,14 @@ def _gamestats():
|
|||
|
||||
nobjs = ObjectDB.objects.count()
|
||||
nobjs = nobjs or 1 # fix zero-div error with empty database
|
||||
Character = class_from_module(settings.BASE_CHARACTER_TYPECLASS)
|
||||
Character = class_from_module(settings.BASE_CHARACTER_TYPECLASS,
|
||||
fallback=settings.FALLBACK_CHARACTER_TYPECLASS)
|
||||
nchars = Character.objects.all_family().count()
|
||||
Room = class_from_module(settings.BASE_ROOM_TYPECLASS)
|
||||
Room = class_from_module(settings.BASE_ROOM_TYPECLASS,
|
||||
fallback=settings.FALLBACK_ROOM_TYPECLASS)
|
||||
nrooms = Room.objects.all_family().count()
|
||||
Exit = class_from_module(settings.BASE_EXIT_TYPECLASS)
|
||||
Exit = class_from_module(settings.BASE_EXIT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_EXIT_TYPECLASS)
|
||||
nexits = Exit.objects.all_family().count()
|
||||
nothers = nobjs - nchars - nrooms - nexits
|
||||
|
||||
|
|
@ -269,7 +273,8 @@ class ObjectDetailView(EvenniaDetailView):
|
|||
#
|
||||
# So when you extend it, this line should look simple, like:
|
||||
# model = Object
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
|
||||
# What HTML template you wish to use to display this page.
|
||||
template_name = "website/object_detail.html"
|
||||
|
|
@ -372,7 +377,8 @@ class ObjectCreateView(LoginRequiredMixin, EvenniaCreateView):
|
|||
|
||||
"""
|
||||
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
|
||||
|
||||
class ObjectDeleteView(LoginRequiredMixin, ObjectDetailView, EvenniaDeleteView):
|
||||
|
|
@ -387,7 +393,8 @@ class ObjectDeleteView(LoginRequiredMixin, ObjectDetailView, EvenniaDeleteView):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
template_name = "website/object_confirm_delete.html"
|
||||
|
||||
# -- Evennia constructs --
|
||||
|
|
@ -430,7 +437,8 @@ class ObjectUpdateView(LoginRequiredMixin, ObjectDetailView, EvenniaUpdateView):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
|
||||
# -- Evennia constructs --
|
||||
access_type = "edit"
|
||||
|
|
@ -513,7 +521,8 @@ class AccountMixin(TypeclassMixin):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_ACCOUNT_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_ACCOUNT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_ACCOUNT_TYPECLASS)
|
||||
form_class = website_forms.AccountForm
|
||||
|
||||
|
||||
|
|
@ -578,7 +587,8 @@ class CharacterMixin(TypeclassMixin):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_CHARACTER_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_CHARACTER_TYPECLASS,
|
||||
fallback=settings.FALLBACK_CHARACTER_TYPECLASS)
|
||||
form_class = website_forms.CharacterForm
|
||||
success_url = reverse_lazy("character-manage")
|
||||
|
||||
|
|
@ -817,7 +827,8 @@ class ChannelMixin(TypeclassMixin):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_CHANNEL_TYPECLASS)
|
||||
model = class_from_module(settings.BASE_CHANNEL_TYPECLASS,
|
||||
fallback=settings.FALLBACK_CHANNEL_TYPECLASS)
|
||||
|
||||
# -- Evennia constructs --
|
||||
page_title = "Channels"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue