Run black reformatter on code
This commit is contained in:
parent
4582eb4085
commit
bd3e31bf3c
178 changed files with 4511 additions and 3385 deletions
|
|
@ -78,13 +78,13 @@ class AccountChangeForm(UserChangeForm):
|
|||
)
|
||||
|
||||
is_superuser = forms.BooleanField(
|
||||
label = "Superuser status",
|
||||
label="Superuser status",
|
||||
required=False,
|
||||
help_text="Superusers bypass all in-game locks and has all "
|
||||
"permissions without explicitly assigning them. Usually "
|
||||
"only one superuser (user #1) is needed and only a superuser "
|
||||
"can create another superuser.<BR>"
|
||||
"Only Superusers can change the user/group permissions below."
|
||||
"permissions without explicitly assigning them. Usually "
|
||||
"only one superuser (user #1) is needed and only a superuser "
|
||||
"can create another superuser.<BR>"
|
||||
"Only Superusers can change the user/group permissions below.",
|
||||
)
|
||||
|
||||
def clean_username(self):
|
||||
|
|
@ -165,11 +165,13 @@ class AccountAttributeInline(AttributeInline):
|
|||
model = AccountDB.db_attributes.through
|
||||
related_field = "accountdb"
|
||||
|
||||
|
||||
class ObjectPuppetInline(admin.StackedInline):
|
||||
"""
|
||||
Inline creation of puppet-Object in Account.
|
||||
|
||||
"""
|
||||
|
||||
from .objects import ObjectCreateForm
|
||||
|
||||
verbose_name = "Puppeted Object"
|
||||
|
|
@ -185,19 +187,26 @@ class ObjectPuppetInline(admin.StackedInline):
|
|||
"fields": (
|
||||
("db_key", "db_typeclass_path"),
|
||||
("db_location", "db_home", "db_destination"),
|
||||
"db_cmdset_storage",
|
||||
"db_lock_storage",
|
||||
"db_cmdset_storage",
|
||||
"db_lock_storage",
|
||||
),
|
||||
"description": "Object currently puppeted by the account (note that this "
|
||||
"will go away if account logs out or unpuppets)",
|
||||
"will go away if account logs out or unpuppets)",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
extra = 0
|
||||
readonly_fields = ("db_key", "db_typeclass_path", "db_destination",
|
||||
"db_location", "db_home", "db_account",
|
||||
"db_cmdset_storage", "db_lock_storage")
|
||||
readonly_fields = (
|
||||
"db_key",
|
||||
"db_typeclass_path",
|
||||
"db_destination",
|
||||
"db_location",
|
||||
"db_home",
|
||||
"db_account",
|
||||
"db_cmdset_storage",
|
||||
"db_lock_storage",
|
||||
)
|
||||
|
||||
# disable adding/deleting this inline - read-only!
|
||||
def has_add_permission(self, request, obj=None):
|
||||
|
|
@ -213,7 +222,15 @@ class AccountAdmin(BaseUserAdmin):
|
|||
This is the main creation screen for Users/accounts
|
||||
|
||||
"""
|
||||
list_display = ("id", "username", "is_staff", "is_superuser", "db_typeclass_path", "db_date_created")
|
||||
|
||||
list_display = (
|
||||
"id",
|
||||
"username",
|
||||
"is_staff",
|
||||
"is_superuser",
|
||||
"db_typeclass_path",
|
||||
"db_date_created",
|
||||
)
|
||||
list_display_links = ("id", "username")
|
||||
form = AccountChangeForm
|
||||
add_form = AccountCreationForm
|
||||
|
|
@ -277,6 +294,7 @@ class AccountAdmin(BaseUserAdmin):
|
|||
from evennia.utils import dbserialize
|
||||
|
||||
return str(dbserialize.pack_dbobj(obj))
|
||||
|
||||
serialized_string.help_text = (
|
||||
"Copy & paste this string into an Attribute's `value` field to store this account there."
|
||||
)
|
||||
|
|
@ -289,8 +307,8 @@ class AccountAdmin(BaseUserAdmin):
|
|||
return mark_safe(
|
||||
", ".join(
|
||||
'<a href="{url}">{name}</a>'.format(
|
||||
url=reverse("admin:objects_objectdb_change", args=[obj.id]),
|
||||
name=obj.db_key)
|
||||
url=reverse("admin:objects_objectdb_change", args=[obj.id]), name=obj.db_key
|
||||
)
|
||||
for obj in ObjectDB.objects.filter(db_account=obj)
|
||||
)
|
||||
)
|
||||
|
|
@ -316,9 +334,7 @@ class AccountAdmin(BaseUserAdmin):
|
|||
form = super().get_form(request, obj, **kwargs)
|
||||
disabled_fields = set()
|
||||
if not request.user.is_superuser:
|
||||
disabled_fields |= {
|
||||
'is_superuser', 'user_permissions', 'user_groups'
|
||||
}
|
||||
disabled_fields |= {"is_superuser", "user_permissions", "user_groups"}
|
||||
for field_name in disabled_fields:
|
||||
if field_name in form.base_fields:
|
||||
form.base_fields[field_name].disabled = True
|
||||
|
|
|
|||
|
|
@ -27,28 +27,30 @@ class AttributeForm(forms.ModelForm):
|
|||
"""
|
||||
|
||||
attr_key = forms.CharField(
|
||||
label="Attribute Name", required=False,
|
||||
help_text="The main identifier of the Attribute. For Nicks, this is the pattern-matching string."
|
||||
label="Attribute Name",
|
||||
required=False,
|
||||
help_text="The main identifier of the Attribute. For Nicks, this is the pattern-matching string.",
|
||||
)
|
||||
attr_category = forms.CharField(
|
||||
label="Category",
|
||||
help_text="Categorization. Unset (default) gives a category of `None`, which is "
|
||||
"is what is searched with e.g. `obj.db.attrname`. For 'nick'-type attributes, this is usually "
|
||||
"'inputline' or 'channel'.",
|
||||
required=False, max_length=128
|
||||
"is what is searched with e.g. `obj.db.attrname`. For 'nick'-type attributes, this is usually "
|
||||
"'inputline' or 'channel'.",
|
||||
required=False,
|
||||
max_length=128,
|
||||
)
|
||||
attr_value = PickledFormField(
|
||||
label="Value",
|
||||
help_text="Value to pickle/save. Db-objects are serialized as a list "
|
||||
"containing `__packed_dbobj__` (they can't easily be added from here). Nicks "
|
||||
"store their pattern-replacement here.",
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
attr_type = forms.ChoiceField(
|
||||
label="Type",
|
||||
choices=[(None, "-"), ("nick", "nick")],
|
||||
help_text="Unset for regular Attributes, 'nick' for Nick-replacement usage.",
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
attr_lockstring = forms.CharField(
|
||||
label="Locks",
|
||||
|
|
@ -62,10 +64,10 @@ class AttributeForm(forms.ModelForm):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
If we have an Attribute, then we'll prepopulate our instance with the fields we'd expect it
|
||||
to have based on the Attribute. attr_key, attr_category, attr_value, attr_type,
|
||||
and attr_lockstring all refer to the corresponding Attribute fields. The initial data of the form fields will
|
||||
similarly be populated.
|
||||
If we have an Attribute, then we'll prepopulate our instance with the fields we'd expect it
|
||||
to have based on the Attribute. attr_key, attr_category, attr_value, attr_type,
|
||||
and attr_lockstring all refer to the corresponding Attribute fields. The initial data of the form fields will
|
||||
similarly be populated.
|
||||
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,11 @@ class MsgTagInline(TagInline):
|
|||
Inline display for Msg-tags.
|
||||
|
||||
"""
|
||||
|
||||
model = Msg.db_tags.through
|
||||
related_field = "msg"
|
||||
|
||||
|
||||
class MsgForm(forms.ModelForm):
|
||||
"""
|
||||
Custom Msg form.
|
||||
|
|
@ -35,7 +37,7 @@ class MsgForm(forms.ModelForm):
|
|||
required=False,
|
||||
widget=forms.Textarea(attrs={"cols": "100", "rows": "2"}),
|
||||
help_text="Optional header for the message; it could be a title or "
|
||||
"metadata depending on msg-use."
|
||||
"metadata depending on msg-use.",
|
||||
)
|
||||
|
||||
db_lock_storage = forms.CharField(
|
||||
|
|
@ -48,7 +50,6 @@ class MsgForm(forms.ModelForm):
|
|||
)
|
||||
|
||||
|
||||
|
||||
@admin.register(Msg)
|
||||
class MsgAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
|
|
@ -67,11 +68,19 @@ class MsgAdmin(admin.ModelAdmin):
|
|||
)
|
||||
list_display_links = ("id", "db_date_created", "start_of_message")
|
||||
ordering = ["-db_date_created", "-id"]
|
||||
search_fields = ["=id", "^db_date_created", "^db_message",
|
||||
"^db_sender_accounts__db_key", "^db_sender_objects__db_key",
|
||||
"^db_sender_scripts__db_key", "^db_sender_external",
|
||||
"^db_receivers_accounts__db_key", "^db_receivers_objects__db_key",
|
||||
"^db_receivers_scripts__db_key", "^db_receiver_external"]
|
||||
search_fields = [
|
||||
"=id",
|
||||
"^db_date_created",
|
||||
"^db_message",
|
||||
"^db_sender_accounts__db_key",
|
||||
"^db_sender_objects__db_key",
|
||||
"^db_sender_scripts__db_key",
|
||||
"^db_sender_external",
|
||||
"^db_receivers_accounts__db_key",
|
||||
"^db_receivers_objects__db_key",
|
||||
"^db_receivers_scripts__db_key",
|
||||
"^db_receiver_external",
|
||||
]
|
||||
readonly_fields = ["db_date_created", "serialized_string"]
|
||||
save_as = True
|
||||
save_on_top = True
|
||||
|
|
@ -80,21 +89,36 @@ class MsgAdmin(admin.ModelAdmin):
|
|||
|
||||
raw_id_fields = (
|
||||
"db_sender_accounts",
|
||||
"db_sender_objects", "db_sender_scripts",
|
||||
"db_receivers_accounts", "db_receivers_objects",
|
||||
"db_receivers_scripts", "db_hide_from_accounts",
|
||||
"db_hide_from_objects")
|
||||
"db_sender_objects",
|
||||
"db_sender_scripts",
|
||||
"db_receivers_accounts",
|
||||
"db_receivers_objects",
|
||||
"db_receivers_scripts",
|
||||
"db_hide_from_accounts",
|
||||
"db_hide_from_objects",
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
{
|
||||
"fields": (
|
||||
("db_sender_accounts", "db_sender_objects", "db_sender_scripts", "db_sender_external"),
|
||||
("db_receivers_accounts", "db_receivers_objects", "db_receivers_scripts", "db_receiver_external"),
|
||||
(
|
||||
"db_sender_accounts",
|
||||
"db_sender_objects",
|
||||
"db_sender_scripts",
|
||||
"db_sender_external",
|
||||
),
|
||||
(
|
||||
"db_receivers_accounts",
|
||||
"db_receivers_objects",
|
||||
"db_receivers_scripts",
|
||||
"db_receiver_external",
|
||||
),
|
||||
("db_hide_from_accounts", "db_hide_from_objects"),
|
||||
"db_header",
|
||||
"db_message", "serialized_string"
|
||||
"db_message",
|
||||
"serialized_string",
|
||||
)
|
||||
},
|
||||
),
|
||||
|
|
@ -104,12 +128,14 @@ class MsgAdmin(admin.ModelAdmin):
|
|||
senders = [o for o in obj.senders if o]
|
||||
if senders:
|
||||
return senders[0]
|
||||
|
||||
sender.help_text = "If multiple, only the first is shown."
|
||||
|
||||
def receiver(self, obj):
|
||||
receivers = [o for o in obj.receivers if o]
|
||||
if receivers:
|
||||
return receivers[0]
|
||||
|
||||
receiver.help_text = "If multiple, only the first is shown."
|
||||
|
||||
def start_of_message(self, obj):
|
||||
|
|
@ -126,6 +152,7 @@ class MsgAdmin(admin.ModelAdmin):
|
|||
|
||||
"""
|
||||
from evennia.utils import dbserialize
|
||||
|
||||
return str(dbserialize.pack_dbobj(obj))
|
||||
|
||||
serialized_string.help_text = (
|
||||
|
|
@ -144,7 +171,6 @@ class MsgAdmin(admin.ModelAdmin):
|
|||
return super().get_form(request, obj, **kwargs)
|
||||
|
||||
|
||||
|
||||
class ChannelAttributeInline(AttributeInline):
|
||||
"""
|
||||
Inline display of Channel Attribute - experimental
|
||||
|
|
@ -170,6 +196,7 @@ class ChannelForm(forms.ModelForm):
|
|||
Form for accessing channels.
|
||||
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ChannelDB
|
||||
fields = "__all__"
|
||||
|
|
@ -193,8 +220,14 @@ class ChannelAdmin(admin.ModelAdmin):
|
|||
|
||||
inlines = [ChannelTagInline, ChannelAttributeInline]
|
||||
form = ChannelForm
|
||||
list_display = ("id", "db_key", "no_of_subscribers", "db_lock_storage", "db_typeclass_path",
|
||||
"db_date_created")
|
||||
list_display = (
|
||||
"id",
|
||||
"db_key",
|
||||
"no_of_subscribers",
|
||||
"db_lock_storage",
|
||||
"db_typeclass_path",
|
||||
"db_date_created",
|
||||
)
|
||||
list_display_links = ("id", "db_key")
|
||||
ordering = ["-db_date_created", "-id", "-db_key"]
|
||||
search_fields = ["id", "db_key", "db_tags__db_key"]
|
||||
|
|
@ -212,7 +245,7 @@ class ChannelAdmin(admin.ModelAdmin):
|
|||
"db_lock_storage",
|
||||
"db_account_subscriptions",
|
||||
"db_object_subscriptions",
|
||||
"serialized_string"
|
||||
"serialized_string",
|
||||
)
|
||||
},
|
||||
),
|
||||
|
|
@ -244,6 +277,7 @@ class ChannelAdmin(admin.ModelAdmin):
|
|||
|
||||
"""
|
||||
from evennia.utils import dbserialize
|
||||
|
||||
return str(dbserialize.pack_dbobj(obj))
|
||||
|
||||
serialized_string.help_text = (
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ class HelpEntryForm(forms.ModelForm):
|
|||
widget=forms.Textarea(attrs={"cols": "100", "rows": "2"}),
|
||||
help_text="Set lock to view:all() unless you want it to only show to certain users."
|
||||
"<BR>Use the `edit:` limit if wanting to limit who can edit from in-game. By default it's "
|
||||
"only limited to who can use the `sethelp` command (Builders).")
|
||||
"only limited to who can use the `sethelp` command (Builders).",
|
||||
)
|
||||
|
||||
|
||||
@admin.register(HelpEntry)
|
||||
|
|
|
|||
|
|
@ -63,9 +63,11 @@ class ObjectCreateForm(forms.ModelForm):
|
|||
f"<BR>If you are creating a Character you usually need <B>{settings.BASE_CHARACTER_TYPECLASS}</B> "
|
||||
"or a subclass of that. <BR>If your custom class is not found in the list, it may not be imported "
|
||||
"into Evennia yet.",
|
||||
choices=lambda: adminutils.get_and_load_typeclasses(parent=ObjectDB))
|
||||
choices=lambda: adminutils.get_and_load_typeclasses(parent=ObjectDB),
|
||||
)
|
||||
|
||||
db_lock_storage = forms.CharField( label="Locks",
|
||||
db_lock_storage = forms.CharField(
|
||||
label="Locks",
|
||||
required=False,
|
||||
widget=forms.Textarea(attrs={"cols": "100", "rows": "2"}),
|
||||
help_text="In-game lock definition string. If not given, defaults will be used. "
|
||||
|
|
@ -92,29 +94,32 @@ class ObjectCreateForm(forms.ModelForm):
|
|||
label="Location",
|
||||
required=False,
|
||||
widget=ForeignKeyRawIdWidget(
|
||||
ObjectDB._meta.get_field('db_location').remote_field, admin.site),
|
||||
ObjectDB._meta.get_field("db_location").remote_field, admin.site
|
||||
),
|
||||
help_text="The (current) in-game location.<BR>"
|
||||
"Usually a Room but can be<BR>"
|
||||
"empty for un-puppeted Characters."
|
||||
"Usually a Room but can be<BR>"
|
||||
"empty for un-puppeted Characters.",
|
||||
)
|
||||
db_home = forms.ModelChoiceField(
|
||||
ObjectDB.objects.all(),
|
||||
label="Home",
|
||||
required=False,
|
||||
widget=ForeignKeyRawIdWidget(
|
||||
ObjectDB._meta.get_field('db_location').remote_field, admin.site),
|
||||
ObjectDB._meta.get_field("db_location").remote_field, admin.site
|
||||
),
|
||||
help_text="Fallback in-game location.<BR>"
|
||||
"All objects should usually have<BR>"
|
||||
"a home location."
|
||||
)
|
||||
"All objects should usually have<BR>"
|
||||
"a home location.",
|
||||
)
|
||||
db_destination = forms.ModelChoiceField(
|
||||
ObjectDB.objects.all(),
|
||||
label="Destination",
|
||||
required=False,
|
||||
widget=ForeignKeyRawIdWidget(
|
||||
ObjectDB._meta.get_field('db_destination').remote_field, admin.site),
|
||||
help_text="Only used by Exits."
|
||||
)
|
||||
ObjectDB._meta.get_field("db_destination").remote_field, admin.site
|
||||
),
|
||||
help_text="Only used by Exits.",
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
|
|
@ -157,9 +162,10 @@ class ObjectEditForm(ObjectCreateForm):
|
|||
label="Puppeting Account",
|
||||
required=False,
|
||||
widget=ForeignKeyRawIdWidget(
|
||||
ObjectDB._meta.get_field('db_account').remote_field, admin.site),
|
||||
ObjectDB._meta.get_field("db_account").remote_field, admin.site
|
||||
),
|
||||
help_text="An Account puppeting this Object (if any).<BR>Note that when a user logs "
|
||||
"off/unpuppets, this<BR>field will be empty again. This is normal."
|
||||
"off/unpuppets, this<BR>field will be empty again. This is normal.",
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -171,10 +177,24 @@ class ObjectAdmin(admin.ModelAdmin):
|
|||
"""
|
||||
|
||||
inlines = [ObjectTagInline, ObjectAttributeInline]
|
||||
list_display = ("id", "db_key", "db_typeclass_path", "db_location", "db_destination", "db_account", "db_date_created")
|
||||
list_display = (
|
||||
"id",
|
||||
"db_key",
|
||||
"db_typeclass_path",
|
||||
"db_location",
|
||||
"db_destination",
|
||||
"db_account",
|
||||
"db_date_created",
|
||||
)
|
||||
list_display_links = ("id", "db_key")
|
||||
ordering = ["-db_date_created", "-id"]
|
||||
search_fields = ["=id", "^db_key", "db_typeclass_path", "^db_account__db_key", "^db_location__db_key"]
|
||||
search_fields = [
|
||||
"=id",
|
||||
"^db_key",
|
||||
"db_typeclass_path",
|
||||
"^db_account__db_key",
|
||||
"^db_location__db_key",
|
||||
]
|
||||
raw_id_fields = ("db_destination", "db_location", "db_home", "db_account")
|
||||
readonly_fields = ("serialized_string", "link_button")
|
||||
|
||||
|
|
@ -197,7 +217,7 @@ class ObjectAdmin(admin.ModelAdmin):
|
|||
("db_account", "link_button"),
|
||||
"db_cmdset_storage",
|
||||
"db_lock_storage",
|
||||
"serialized_string"
|
||||
"serialized_string",
|
||||
)
|
||||
},
|
||||
),
|
||||
|
|
@ -223,6 +243,7 @@ class ObjectAdmin(admin.ModelAdmin):
|
|||
|
||||
"""
|
||||
from evennia.utils import dbserialize
|
||||
|
||||
return str(dbserialize.pack_dbobj(obj))
|
||||
|
||||
serialized_string.help_text = (
|
||||
|
|
@ -268,7 +289,7 @@ class ObjectAdmin(admin.ModelAdmin):
|
|||
path(
|
||||
"account-object-link/<int:pk>",
|
||||
self.admin_site.admin_view(self.link_object_to_account),
|
||||
name="object-account-link"
|
||||
name="object-account-link",
|
||||
)
|
||||
]
|
||||
return custom_urls + urls
|
||||
|
|
@ -276,8 +297,9 @@ class ObjectAdmin(admin.ModelAdmin):
|
|||
def link_button(self, obj):
|
||||
return format_html(
|
||||
'<a class="button" href="{}">Link to Account</a> ',
|
||||
reverse("admin:object-account-link", args=[obj.pk])
|
||||
reverse("admin:object-account-link", args=[obj.pk]),
|
||||
)
|
||||
|
||||
link_button.short_description = "Create attrs/locks for puppeting"
|
||||
link_button.allow_tags = True
|
||||
|
||||
|
|
@ -305,21 +327,24 @@ class ObjectAdmin(admin.ModelAdmin):
|
|||
lock = obj.locks.get("puppet")
|
||||
lock += f" or pid({account.id})"
|
||||
obj.locks.add(lock)
|
||||
self.message_user(request,
|
||||
"Did the following (where possible): "
|
||||
f"Set Account.db._last_puppet = {obj}, "
|
||||
f"Added {obj} to Account.db._playable_characters list, "
|
||||
f"Added 'puppet:pid({account.id})' lock to {obj}.")
|
||||
self.message_user(
|
||||
request,
|
||||
"Did the following (where possible): "
|
||||
f"Set Account.db._last_puppet = {obj}, "
|
||||
f"Added {obj} to Account.db._playable_characters list, "
|
||||
f"Added 'puppet:pid({account.id})' lock to {obj}.",
|
||||
)
|
||||
else:
|
||||
self.message_user(request, "Account must be connected for this action "
|
||||
"(set Puppeting Account and save this page first).",
|
||||
level=messages.ERROR)
|
||||
self.message_user(
|
||||
request,
|
||||
"Account must be connected for this action "
|
||||
"(set Puppeting Account and save this page first).",
|
||||
level=messages.ERROR,
|
||||
)
|
||||
|
||||
# stay on the same page
|
||||
return HttpResponseRedirect(reverse("admin:objects_objectdb_change", args=[obj.pk]))
|
||||
|
||||
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
"""
|
||||
Model-save hook.
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ from . import utils as adminutils
|
|||
class ScriptForm(forms.ModelForm):
|
||||
|
||||
db_key = forms.CharField(
|
||||
label = "Name/Key",
|
||||
help_text="Script identifier, shown in listings etc."
|
||||
label="Name/Key", help_text="Script identifier, shown in listings etc."
|
||||
)
|
||||
|
||||
db_typeclass_path = forms.ChoiceField(
|
||||
|
|
@ -24,10 +23,12 @@ class ScriptForm(forms.ModelForm):
|
|||
help_text="This is the Python-path to the class implementing the actual script functionality. "
|
||||
"<BR>If your custom class is not found here, it may not be imported into Evennia yet.",
|
||||
choices=lambda: adminutils.get_and_load_typeclasses(
|
||||
parent=ScriptDB, excluded_parents=["evennia.prototypes.prototypes.DbPrototype"])
|
||||
parent=ScriptDB, excluded_parents=["evennia.prototypes.prototypes.DbPrototype"]
|
||||
),
|
||||
)
|
||||
|
||||
db_lock_storage = forms.CharField( label="Locks",
|
||||
db_lock_storage = forms.CharField(
|
||||
label="Locks",
|
||||
required=False,
|
||||
widget=forms.Textarea(attrs={"cols": "100", "rows": "2"}),
|
||||
help_text="In-game lock definition string. If not given, defaults will be used. "
|
||||
|
|
@ -38,18 +39,14 @@ class ScriptForm(forms.ModelForm):
|
|||
db_interval = forms.IntegerField(
|
||||
label="Repeat Interval",
|
||||
help_text="Optional timer component.<BR>How often to call the Script's<BR>`at_repeat` hook, in seconds."
|
||||
"<BR>Set to 0 to disable."
|
||||
"<BR>Set to 0 to disable.",
|
||||
)
|
||||
db_repeats = forms.IntegerField(
|
||||
help_text="Only repeat this many times."
|
||||
"<BR>Set to 0 to run indefinitely."
|
||||
)
|
||||
db_start_delay = forms.BooleanField(
|
||||
help_text="Wait <B>Interval</B> seconds before first call."
|
||||
help_text="Only repeat this many times." "<BR>Set to 0 to run indefinitely."
|
||||
)
|
||||
db_start_delay = forms.BooleanField(help_text="Wait <B>Interval</B> seconds before first call.")
|
||||
db_persistent = forms.BooleanField(
|
||||
label = "Survives reboot",
|
||||
help_text="If unset, a server reboot will remove the timer."
|
||||
label="Survives reboot", help_text="If unset, a server reboot will remove the timer."
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -68,6 +65,7 @@ class ScriptAttributeInline(AttributeInline):
|
|||
Inline attribute tags.
|
||||
|
||||
"""
|
||||
|
||||
model = ScriptDB.db_attributes.through
|
||||
related_field = "scriptdb"
|
||||
|
||||
|
|
@ -108,8 +106,8 @@ class ScriptAdmin(admin.ModelAdmin):
|
|||
("db_key", "db_typeclass_path"),
|
||||
("db_interval", "db_repeats", "db_start_delay", "db_persistent"),
|
||||
"db_obj",
|
||||
"db_lock_storage",
|
||||
"serialized_string"
|
||||
"db_lock_storage",
|
||||
"serialized_string",
|
||||
)
|
||||
},
|
||||
),
|
||||
|
|
@ -122,13 +120,13 @@ class ScriptAdmin(admin.ModelAdmin):
|
|||
|
||||
"""
|
||||
from evennia.utils import dbserialize
|
||||
|
||||
return str(dbserialize.pack_dbobj(obj))
|
||||
|
||||
serialized_string.help_text = (
|
||||
"Copy & paste this string into an Attribute's `value` field to store this script there."
|
||||
)
|
||||
|
||||
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
"""
|
||||
Overrides help texts.
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ class TagForm(forms.ModelForm):
|
|||
|
||||
"""
|
||||
|
||||
db_key = forms.CharField(
|
||||
label="Key/Name", required=True, help_text="The main key identifier"
|
||||
)
|
||||
db_key = forms.CharField(label="Key/Name", required=True, help_text="The main key identifier")
|
||||
db_category = forms.CharField(
|
||||
label="Category",
|
||||
help_text="Used for grouping tags. Unset (default) gives a category of None",
|
||||
|
|
@ -32,15 +30,22 @@ class TagForm(forms.ModelForm):
|
|||
label="Type",
|
||||
choices=[(None, "-"), ("alias", "alias"), ("permission", "permission")],
|
||||
help_text="Tags are used for different things. Unset for regular tags.",
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
db_model = forms.ChoiceField(
|
||||
label="Model" ,
|
||||
label="Model",
|
||||
required=False,
|
||||
help_text = "Each Tag can only 'attach' to one type of entity.",
|
||||
choices=([("objectdb", "objectdb"), ("accountdb", "accountdb"),
|
||||
("scriptdb", "scriptdb"), ("channeldb", "channeldb"),
|
||||
("helpentry", "helpentry"), ("msg", "msg")])
|
||||
help_text="Each Tag can only 'attach' to one type of entity.",
|
||||
choices=(
|
||||
[
|
||||
("objectdb", "objectdb"),
|
||||
("accountdb", "accountdb"),
|
||||
("scriptdb", "scriptdb"),
|
||||
("channeldb", "channeldb"),
|
||||
("helpentry", "helpentry"),
|
||||
("msg", "msg"),
|
||||
]
|
||||
),
|
||||
)
|
||||
db_data = forms.CharField(
|
||||
label="Data",
|
||||
|
|
@ -77,7 +82,7 @@ class InlineTagForm(forms.ModelForm):
|
|||
label="Type",
|
||||
choices=[(None, "-"), ("alias", "alias"), ("permission", "permission")],
|
||||
help_text="Tags are used for different things. Unset for regular tags.",
|
||||
required=False
|
||||
required=False,
|
||||
)
|
||||
tag_data = forms.CharField(
|
||||
label="Data",
|
||||
|
|
@ -91,10 +96,10 @@ class InlineTagForm(forms.ModelForm):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
If we have a tag, then we'll prepopulate our instance with the fields we'd expect it
|
||||
to have based on the tag. tag_key, tag_category, tag_type, and tag_data all refer to
|
||||
the corresponding tag fields. The initial data of the form fields will similarly be
|
||||
populated.
|
||||
If we have a tag, then we'll prepopulate our instance with the fields we'd expect it
|
||||
to have based on the tag. tag_key, tag_category, tag_type, and tag_data all refer to
|
||||
the corresponding tag fields. The initial data of the form fields will similarly be
|
||||
populated.
|
||||
"""
|
||||
super().__init__(*args, **kwargs)
|
||||
tagkey = None
|
||||
|
|
@ -142,6 +147,7 @@ class TagFormSet(forms.BaseInlineFormSet):
|
|||
Object, where the handler is an AliasHandler, PermissionsHandler, or TagHandler, based on the
|
||||
type of tag.
|
||||
"""
|
||||
|
||||
verbose_name = "Tag"
|
||||
verbose_name_plural = "Tags"
|
||||
|
||||
|
|
@ -222,13 +228,6 @@ class TagAdmin(admin.ModelAdmin):
|
|||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
{
|
||||
"fields": (
|
||||
("db_key", "db_category"),
|
||||
("db_tagtype", "db_model"),
|
||||
"db_data"
|
||||
)
|
||||
},
|
||||
{"fields": (("db_key", "db_category"), ("db_tagtype", "db_model"), "db_data")},
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,4 @@ if settings.EVENNIA_ADMIN:
|
|||
]
|
||||
else:
|
||||
# Just include the normal Django admin.
|
||||
urlpatterns += [
|
||||
path("", admin.site.urls)
|
||||
]
|
||||
urlpatterns += [path("", admin.site.urls)]
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ def get_and_load_typeclasses(parent=None, excluded_parents=None):
|
|||
# this is necessary in order to have typeclasses imported and accessible
|
||||
# in the inheritance tree.
|
||||
import evennia
|
||||
|
||||
evennia._init()
|
||||
|
||||
# this return a dict (path: class}
|
||||
|
|
@ -33,18 +34,27 @@ def get_and_load_typeclasses(parent=None, excluded_parents=None):
|
|||
|
||||
# filter out any excludes
|
||||
excluded_parents = excluded_parents or []
|
||||
tpaths = [path for path, tclass in tmap.items()
|
||||
if not any(inherits_from(tclass, excl) for excl in excluded_parents)]
|
||||
tpaths = [
|
||||
path
|
||||
for path, tclass in tmap.items()
|
||||
if not any(inherits_from(tclass, excl) for excl in excluded_parents)
|
||||
]
|
||||
|
||||
# sort so we get custom paths (not in evennia repo) first
|
||||
tpaths = sorted(tpaths, key=lambda k: (1 if k.startswith("evennia.") else 0, k))
|
||||
|
||||
# the base models are not typeclasses so we filter them out
|
||||
tpaths = [path for path in tpaths if path not in
|
||||
("evennia.objects.models.ObjectDB",
|
||||
"evennia.accounts.models.AccountDB",
|
||||
"evennia.scripts.models.ScriptDB",
|
||||
"evennia.comms.models.ChannelDB",)]
|
||||
tpaths = [
|
||||
path
|
||||
for path in tpaths
|
||||
if path
|
||||
not in (
|
||||
"evennia.objects.models.ObjectDB",
|
||||
"evennia.accounts.models.AccountDB",
|
||||
"evennia.scripts.models.ScriptDB",
|
||||
"evennia.comms.models.ChannelDB",
|
||||
)
|
||||
]
|
||||
|
||||
# return on form excepted by ChoiceField
|
||||
return [(path, path) for path in tpaths if path]
|
||||
|
|
@ -66,6 +76,7 @@ def get_and_load_cmdsets(parent=None, excluded_parents=None):
|
|||
"""
|
||||
# we must do this to have cmdsets imported and accessible in the inheritance tree.
|
||||
import evennia
|
||||
|
||||
evennia._init()
|
||||
|
||||
cmap = get_all_cmdsets(parent)
|
||||
|
|
|
|||
|
|
@ -112,9 +112,11 @@ class AccountDBFilterSet(BaseTypeclassFilterSet):
|
|||
|
||||
class Meta:
|
||||
model = AccountDB
|
||||
fields = [fi for fi in (SHARED_FIELDS + ["username", "db_is_connected", "db_is_bot"])
|
||||
if fi != 'db_key']
|
||||
|
||||
fields = [
|
||||
fi
|
||||
for fi in (SHARED_FIELDS + ["username", "db_is_connected", "db_is_bot"])
|
||||
if fi != "db_key"
|
||||
]
|
||||
|
||||
|
||||
class ScriptDBFilterSet(BaseTypeclassFilterSet):
|
||||
|
|
@ -140,8 +142,7 @@ class HelpFilterSet(FilterSet):
|
|||
Filter for help entries
|
||||
|
||||
"""
|
||||
|
||||
name = CharFilter(lookup_expr="iexact", method="filter_name", field_name="db_key")
|
||||
category = CharFilter(lookup_expr="iexact", method="filter_name", field_name="db_category")
|
||||
alias = AliasFilter(lookup_expr="iexact")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ class EvenniaAPIRoot(routers.APIRootView):
|
|||
Root of the Evennia API tree.
|
||||
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class APIRootRouter(routers.DefaultRouter):
|
||||
APIRootView = EvenniaAPIRoot
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class AttributeSerializer(serializers.ModelSerializer):
|
|||
Serialize Attribute views.
|
||||
|
||||
"""
|
||||
|
||||
value_display = serializers.SerializerMethodField(source="value")
|
||||
db_value = serializers.CharField(write_only=True, required=False)
|
||||
|
||||
|
|
@ -151,6 +152,7 @@ class TypeclassListSerializerMixin:
|
|||
Shortened serializer for list views.
|
||||
|
||||
"""
|
||||
|
||||
shared_fields = [
|
||||
"id",
|
||||
"db_key",
|
||||
|
|
@ -215,6 +217,7 @@ class ObjectListSerializer(TypeclassListSerializerMixin, serializers.ModelSerial
|
|||
Shortened representation for listings.]
|
||||
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = DefaultObject
|
||||
fields = [
|
||||
|
|
@ -261,10 +264,12 @@ class AccountListSerializer(TypeclassListSerializerMixin, serializers.ModelSeria
|
|||
A shortened form for listing.
|
||||
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = DefaultAccount
|
||||
fields = ["username"] + [
|
||||
fi for fi in TypeclassListSerializerMixin.shared_fields if fi != "db_key"]
|
||||
fi for fi in TypeclassListSerializerMixin.shared_fields if fi != "db_key"
|
||||
]
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
|
|
@ -273,6 +278,7 @@ class ScriptDBSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
|
|||
Serializing Account.
|
||||
|
||||
"""
|
||||
|
||||
attributes = serializers.SerializerMethodField()
|
||||
tags = serializers.SerializerMethodField()
|
||||
aliases = serializers.SerializerMethodField()
|
||||
|
|
@ -295,6 +301,7 @@ class ScriptListSerializer(TypeclassListSerializerMixin, serializers.ModelSerial
|
|||
Shortened form for listing.
|
||||
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = ScriptDB
|
||||
fields = [
|
||||
|
|
@ -312,25 +319,36 @@ class HelpSerializer(TypeclassSerializerMixin, serializers.ModelSerializer):
|
|||
Serializers Help entries (not a typeclass).
|
||||
|
||||
"""
|
||||
|
||||
tags = serializers.SerializerMethodField()
|
||||
aliases = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = HelpEntry
|
||||
fields = [
|
||||
"id", "db_key", "db_help_category", "db_entrytext", "db_date_created",
|
||||
"tags", "aliases"
|
||||
"id",
|
||||
"db_key",
|
||||
"db_help_category",
|
||||
"db_entrytext",
|
||||
"db_date_created",
|
||||
"tags",
|
||||
"aliases",
|
||||
]
|
||||
read_only_fields = ["id"]
|
||||
|
||||
|
||||
class HelpListSerializer(TypeclassListSerializerMixin, serializers.ModelSerializer):
|
||||
"""
|
||||
Shortened form for listings.
|
||||
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = HelpEntry
|
||||
fields = [
|
||||
"id", "db_key", "db_help_category", "db_date_created",
|
||||
"id",
|
||||
"db_key",
|
||||
"db_help_category",
|
||||
"db_date_created",
|
||||
]
|
||||
read_only_fields = ["id"]
|
||||
|
|
|
|||
|
|
@ -38,7 +38,16 @@ class TestEvenniaRESTApi(BaseEvenniaTest):
|
|||
def get_view_details(self, action):
|
||||
"""Helper function for generating list of named tuples"""
|
||||
View = namedtuple(
|
||||
"View", ["view_name", "obj", "list", "serializer", "list_serializer", "create_data", "retrieve_data"]
|
||||
"View",
|
||||
[
|
||||
"view_name",
|
||||
"obj",
|
||||
"list",
|
||||
"serializer",
|
||||
"list_serializer",
|
||||
"create_data",
|
||||
"retrieve_data",
|
||||
],
|
||||
)
|
||||
views = [
|
||||
View(
|
||||
|
|
|
|||
|
|
@ -40,18 +40,17 @@ urlpatterns = router.urls
|
|||
|
||||
urlpatterns += [
|
||||
# openapi schema
|
||||
path('openapi',
|
||||
get_schema_view(
|
||||
title="Evennia API",
|
||||
description="Evennia OpenAPI Schema",
|
||||
version="1.0"),
|
||||
name='openapi',
|
||||
path(
|
||||
"openapi",
|
||||
get_schema_view(title="Evennia API", description="Evennia OpenAPI Schema", version="1.0"),
|
||||
name="openapi",
|
||||
),
|
||||
# redoc auto-doc (based on openapi schema)
|
||||
path('redoc/',
|
||||
TemplateView.as_view(
|
||||
template_name="rest_framework/redoc.html" ,
|
||||
extra_context={'schema_url': 'api:openapi'}),
|
||||
name='redoc'
|
||||
)
|
||||
path(
|
||||
"redoc/",
|
||||
TemplateView.as_view(
|
||||
template_name="rest_framework/redoc.html", extra_context={"schema_url": "api:openapi"}
|
||||
),
|
||||
name="redoc",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -26,12 +26,13 @@ class GeneralViewSetMixin:
|
|||
Mixin for both typeclass- and non-typeclass entities.
|
||||
|
||||
"""
|
||||
|
||||
def get_serializer_class(self):
|
||||
"""
|
||||
Allow different serializers for certain actions.
|
||||
|
||||
"""
|
||||
if self.action == 'list':
|
||||
if self.action == "list":
|
||||
if hasattr(self, "list_serializer_class"):
|
||||
return self.list_serializer_class
|
||||
return self.serializer_class
|
||||
|
|
@ -93,6 +94,7 @@ class ObjectDBViewSet(TypeclassViewSetMixin, ModelViewSet):
|
|||
(rooms, exits, characters etc).
|
||||
|
||||
"""
|
||||
|
||||
# An example of a basic viewset for all ObjectDB instances. It declares the
|
||||
# serializer to use for both retrieving and changing/creating/deleting
|
||||
# instances. Serializers are similar to django forms, used for the
|
||||
|
|
@ -109,6 +111,7 @@ class CharacterViewSet(ObjectDBViewSet):
|
|||
Characters are a type of Object commonly used as player avatars in-game.
|
||||
|
||||
"""
|
||||
|
||||
queryset = DefaultCharacter.objects.typeclass_search(
|
||||
DefaultCharacter.path, include_children=True
|
||||
)
|
||||
|
|
@ -167,6 +170,7 @@ class HelpViewSet(GeneralViewSetMixin, ModelViewSet):
|
|||
Note that command auto-help and file-based help entries are not accessible this way.
|
||||
|
||||
"""
|
||||
|
||||
serializer_class = serializers.HelpSerializer
|
||||
queryset = HelpEntry.objects.all()
|
||||
filterset_class = filters.HelpFilterSet
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ class EvenniaAdminApp(apps.AdminConfig):
|
|||
This is imported in INSTALLED_APPS instead of django.contrib.admin.
|
||||
|
||||
"""
|
||||
default_site = 'evennia.web.utils.adminsite.EvenniaAdminSite'
|
||||
|
||||
default_site = "evennia.web.utils.adminsite.EvenniaAdminSite"
|
||||
|
||||
|
||||
class EvenniaAdminSite(admin.AdminSite):
|
||||
|
|
@ -26,10 +27,21 @@ class EvenniaAdminSite(admin.AdminSite):
|
|||
admin.register in the admin/ folder, this is what is being registered to.
|
||||
|
||||
"""
|
||||
|
||||
site_header = "Evennia web admin"
|
||||
|
||||
app_order = ["accounts", "objects", "scripts", "comms", "help",
|
||||
"typeclasses", "server", "sites", "flatpages", "auth"]
|
||||
app_order = [
|
||||
"accounts",
|
||||
"objects",
|
||||
"scripts",
|
||||
"comms",
|
||||
"help",
|
||||
"typeclasses",
|
||||
"server",
|
||||
"sites",
|
||||
"flatpages",
|
||||
"auth",
|
||||
]
|
||||
|
||||
def get_app_list(self, request):
|
||||
app_list = super().get_app_list(request)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,10 @@ class TestGeneralContext(TestCase):
|
|||
|
||||
@patch("evennia.web.utils.general_context.GAME_NAME", "test_name")
|
||||
@patch("evennia.web.utils.general_context.GAME_SLOGAN", "test_game_slogan")
|
||||
@patch("evennia.web.utils.general_context.WEBSOCKET_CLIENT_ENABLED",
|
||||
"websocket_client_enabled_testvalue")
|
||||
@patch(
|
||||
"evennia.web.utils.general_context.WEBSOCKET_CLIENT_ENABLED",
|
||||
"websocket_client_enabled_testvalue",
|
||||
)
|
||||
@patch("evennia.web.utils.general_context.WEBCLIENT_ENABLED", "webclient_enabled_testvalue")
|
||||
@patch("evennia.web.utils.general_context.WEBSOCKET_PORT", "websocket_client_port_testvalue")
|
||||
@patch("evennia.web.utils.general_context.WEBSOCKET_URL", "websocket_client_url_testvalue")
|
||||
|
|
@ -39,7 +41,7 @@ class TestGeneralContext(TestCase):
|
|||
"websocket_port": "websocket_client_port_testvalue",
|
||||
"websocket_url": "websocket_client_url_testvalue",
|
||||
"rest_api_enabled": True,
|
||||
"server_hostname": 'localhost',
|
||||
"server_hostname": "localhost",
|
||||
"ssh_enabled": False,
|
||||
"ssh_ports": False,
|
||||
"telnet_enabled": True,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,4 @@ from . import views
|
|||
|
||||
app_name = "webclient"
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.webclient, name="index")
|
||||
]
|
||||
urlpatterns = [path("", views.webclient, name="index")]
|
||||
|
|
|
|||
|
|
@ -52,8 +52,9 @@ class AccountForm(UserCreationForm):
|
|||
"""
|
||||
|
||||
# The model/typeclass this form creates
|
||||
model = class_from_module(settings.BASE_ACCOUNT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_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")
|
||||
|
|
@ -88,8 +89,9 @@ class ObjectForm(EvenniaForm, ModelForm):
|
|||
"""
|
||||
|
||||
# The model/typeclass this form creates
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_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",)
|
||||
|
|
@ -142,8 +144,9 @@ class CharacterForm(ObjectForm):
|
|||
"""
|
||||
|
||||
# Get the correct object model
|
||||
model = class_from_module(settings.BASE_CHARACTER_TYPECLASS,
|
||||
fallback=settings.FALLBACK_CHARACTER_TYPECLASS)
|
||||
model = class_from_module(
|
||||
settings.BASE_CHARACTER_TYPECLASS, fallback=settings.FALLBACK_CHARACTER_TYPECLASS
|
||||
)
|
||||
|
||||
# Allow entry of the 'key' field
|
||||
fields = ("db_key",)
|
||||
|
|
|
|||
|
|
@ -129,8 +129,9 @@ class ChannelDetailTest(EvenniaWebTest):
|
|||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
klass = class_from_module(self.channel_typeclass,
|
||||
fallback=settings.FALLBACK_CHANNEL_TYPECLASS)
|
||||
klass = class_from_module(
|
||||
self.channel_typeclass, fallback=settings.FALLBACK_CHANNEL_TYPECLASS
|
||||
)
|
||||
|
||||
# Create a channel
|
||||
klass.create("demo")
|
||||
|
|
@ -144,13 +145,10 @@ class HelpListTest(EvenniaWebTest):
|
|||
|
||||
|
||||
HELP_ENTRY_DICTS = [
|
||||
{
|
||||
"key": "unit test file entry",
|
||||
"category": "General",
|
||||
"text": "cache test file entry text"
|
||||
}
|
||||
{"key": "unit test file entry", "category": "General", "text": "cache test file entry text"}
|
||||
]
|
||||
|
||||
|
||||
class HelpDetailTest(EvenniaWebTest):
|
||||
url_name = "help-entry-detail"
|
||||
|
||||
|
|
@ -158,31 +156,30 @@ class HelpDetailTest(EvenniaWebTest):
|
|||
super().setUp()
|
||||
|
||||
# create a db help entry
|
||||
create_help_entry('unit test db entry', 'unit test db entry text', category="General")
|
||||
create_help_entry("unit test db entry", "unit test db entry text", category="General")
|
||||
|
||||
def get_kwargs(self):
|
||||
return {"category": slugify("general"),
|
||||
"topic": slugify('unit test db entry')}
|
||||
return {"category": slugify("general"), "topic": slugify("unit test db entry")}
|
||||
|
||||
def test_view(self):
|
||||
response = self.client.get(reverse(self.url_name, kwargs=self.get_kwargs()), follow=True)
|
||||
self.assertEqual(response.context["entry_text"], 'unit test db entry text')
|
||||
self.assertEqual(response.context["entry_text"], "unit test db entry text")
|
||||
|
||||
def test_object_cache(self):
|
||||
# clear file help entries, use local HELP_ENTRY_DICTS to recreate new entries
|
||||
global _FILE_HELP_ENTRIES
|
||||
if _FILE_HELP_ENTRIES is None:
|
||||
from evennia.help.filehelp import FILE_HELP_ENTRIES as _FILE_HELP_ENTRIES
|
||||
help_module = 'evennia.web.website.tests'
|
||||
help_module = "evennia.web.website.tests"
|
||||
self.file_help_store = _FILE_HELP_ENTRIES.__init__(help_file_modules=[help_module])
|
||||
|
||||
# request access to an entry
|
||||
response = self.client.get(reverse(self.url_name, kwargs=self.get_kwargs()), follow=True)
|
||||
self.assertEqual(response.context["entry_text"], 'unit test db entry text')
|
||||
self.assertEqual(response.context["entry_text"], "unit test db entry text")
|
||||
# request a second entry, verifing the cached object is not provided on a new topic request
|
||||
entry_two_args = {"category": slugify("general"), "topic": slugify('unit test file entry')}
|
||||
entry_two_args = {"category": slugify("general"), "topic": slugify("unit test file entry")}
|
||||
response = self.client.get(reverse(self.url_name, kwargs=entry_two_args), follow=True)
|
||||
self.assertEqual(response.context["entry_text"], 'cache test file entry text')
|
||||
self.assertEqual(response.context["entry_text"], "cache test file entry text")
|
||||
|
||||
|
||||
class HelpLockedDetailTest(EvenniaWebTest):
|
||||
|
|
@ -192,24 +189,27 @@ class HelpLockedDetailTest(EvenniaWebTest):
|
|||
super().setUp()
|
||||
|
||||
# create a db entry with a lock
|
||||
self.db_help_entry = create_help_entry('unit test locked topic', 'unit test locked entrytext',
|
||||
category="General", locks='read:perm(Developer)')
|
||||
self.db_help_entry = create_help_entry(
|
||||
"unit test locked topic",
|
||||
"unit test locked entrytext",
|
||||
category="General",
|
||||
locks="read:perm(Developer)",
|
||||
)
|
||||
|
||||
def get_kwargs(self):
|
||||
return {"category": slugify("general"),
|
||||
"topic": slugify('unit test locked topic')}
|
||||
return {"category": slugify("general"), "topic": slugify("unit test locked topic")}
|
||||
|
||||
def test_locked_entry(self):
|
||||
# request access to an entry for permission the account does not have
|
||||
response = self.client.get(reverse(self.url_name, kwargs=self.get_kwargs()), follow=True)
|
||||
self.assertEqual(response.context["entry_text"], 'Failed to find entry.')
|
||||
self.assertEqual(response.context["entry_text"], "Failed to find entry.")
|
||||
|
||||
def test_lock_with_perm(self):
|
||||
# log TestAccount in, grant permission required, read the entry
|
||||
self.login()
|
||||
self.account.permissions.add("Developer")
|
||||
response = self.client.get(reverse(self.url_name, kwargs=self.get_kwargs()), follow=True)
|
||||
self.assertEqual(response.context["entry_text"], 'unit test locked entrytext')
|
||||
self.assertEqual(response.context["entry_text"], "unit test locked entrytext")
|
||||
|
||||
|
||||
class CharacterCreateView(EvenniaWebTest):
|
||||
|
|
|
|||
|
|
@ -5,53 +5,51 @@ This redirects to website sub-pages.
|
|||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from .views import (
|
||||
index, errors, accounts, help as helpviews, channels, characters)
|
||||
from .views import index, errors, accounts, help as helpviews, channels, characters
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
# website front page
|
||||
path("", index.EvenniaIndexView.as_view(), name="index"),
|
||||
|
||||
# errors
|
||||
path(r"tbi/", errors.to_be_implemented, name="to_be_implemented"),
|
||||
|
||||
# User Authentication (makes login/logout url names available)
|
||||
path("auth/register", accounts.AccountCreateView.as_view(), name="register"),
|
||||
path("auth/", include("django.contrib.auth.urls")),
|
||||
|
||||
# Help Topics
|
||||
path("help/", helpviews.HelpListView.as_view(), name="help"),
|
||||
path(r"help/<str:category>/<str:topic>/",
|
||||
helpviews.HelpDetailView.as_view(),
|
||||
name="help-entry-detail"),
|
||||
|
||||
path(
|
||||
r"help/<str:category>/<str:topic>/",
|
||||
helpviews.HelpDetailView.as_view(),
|
||||
name="help-entry-detail",
|
||||
),
|
||||
# Channels
|
||||
path("channels/", channels.ChannelListView.as_view(), name="channels"),
|
||||
path("channels/<str:slug>/",
|
||||
channels.ChannelDetailView.as_view(),
|
||||
name="channel-detail"),
|
||||
|
||||
path("channels/<str:slug>/", channels.ChannelDetailView.as_view(), name="channel-detail"),
|
||||
# Character management
|
||||
path("characters/", characters.CharacterListView.as_view(), name="characters"),
|
||||
path("characters/create/",
|
||||
characters.CharacterCreateView.as_view(),
|
||||
name="character-create"),
|
||||
path("characters/manage/",
|
||||
characters.CharacterManageView.as_view(),
|
||||
name="character-manage"),
|
||||
path("characters/detail/<str:slug>/<int:pk>/",
|
||||
characters.CharacterDetailView.as_view(),
|
||||
name="character-detail"),
|
||||
path("characters/puppet/<str:slug>/<int:pk>/",
|
||||
characters.CharacterPuppetView.as_view(),
|
||||
name="character-puppet"),
|
||||
path("characters/update/<str:slug>/<int:pk>/",
|
||||
characters.CharacterUpdateView.as_view(),
|
||||
name="character-update"),
|
||||
path("characters/delete/<str:slug>/<int:pk>/",
|
||||
characters.CharacterDeleteView.as_view(),
|
||||
name="character-delete"),
|
||||
path("characters/create/", characters.CharacterCreateView.as_view(), name="character-create"),
|
||||
path("characters/manage/", characters.CharacterManageView.as_view(), name="character-manage"),
|
||||
path(
|
||||
"characters/detail/<str:slug>/<int:pk>/",
|
||||
characters.CharacterDetailView.as_view(),
|
||||
name="character-detail",
|
||||
),
|
||||
path(
|
||||
"characters/puppet/<str:slug>/<int:pk>/",
|
||||
characters.CharacterPuppetView.as_view(),
|
||||
name="character-puppet",
|
||||
),
|
||||
path(
|
||||
"characters/update/<str:slug>/<int:pk>/",
|
||||
characters.CharacterUpdateView.as_view(),
|
||||
name="character-update",
|
||||
),
|
||||
path(
|
||||
"characters/delete/<str:slug>/<int:pk>/",
|
||||
characters.CharacterDeleteView.as_view(),
|
||||
name="character-delete",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -59,15 +57,18 @@ urlpatterns = [
|
|||
# is not recommended and is usually unnecessary).
|
||||
if settings.SERVE_MEDIA:
|
||||
from django import views as django_views
|
||||
|
||||
urlpatterns.extend(
|
||||
[
|
||||
path("media/<str:path>",
|
||||
django_views.static.serve,
|
||||
{"document_root": settings.MEDIA_ROOT},
|
||||
path(
|
||||
"media/<str:path>",
|
||||
django_views.static.serve,
|
||||
{"document_root": settings.MEDIA_ROOT},
|
||||
),
|
||||
path("static/<str:path>",
|
||||
django_views.static.serve,
|
||||
{"document_root": settings.STATIC_ROOT},
|
||||
path(
|
||||
"static/<str:path>",
|
||||
django_views.static.serve,
|
||||
{"document_root": settings.STATIC_ROOT},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@ class AccountMixin(TypeclassMixin):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_ACCOUNT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_ACCOUNT_TYPECLASS)
|
||||
model = class_from_module(
|
||||
settings.BASE_ACCOUNT_TYPECLASS, fallback=settings.FALLBACK_ACCOUNT_TYPECLASS
|
||||
)
|
||||
form_class = forms.AccountForm
|
||||
|
||||
|
||||
|
|
@ -73,4 +74,3 @@ class AccountCreateView(AccountMixin, EvenniaCreateView):
|
|||
|
||||
# Redirect the user to the login page
|
||||
return HttpResponseRedirect(self.success_url)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,9 @@ class ChannelMixin(TypeclassMixin):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_CHANNEL_TYPECLASS,
|
||||
fallback=settings.FALLBACK_CHANNEL_TYPECLASS)
|
||||
model = class_from_module(
|
||||
settings.BASE_CHANNEL_TYPECLASS, fallback=settings.FALLBACK_CHANNEL_TYPECLASS
|
||||
)
|
||||
|
||||
# -- Evennia constructs --
|
||||
page_title = "Channels"
|
||||
|
|
@ -175,5 +176,3 @@ class ChannelDetailView(ChannelMixin, ObjectDetailView):
|
|||
)
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,9 @@ class CharacterMixin(TypeclassMixin):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_CHARACTER_TYPECLASS,
|
||||
fallback=settings.FALLBACK_CHARACTER_TYPECLASS)
|
||||
model = class_from_module(
|
||||
settings.BASE_CHARACTER_TYPECLASS, fallback=settings.FALLBACK_CHARACTER_TYPECLASS
|
||||
)
|
||||
form_class = forms.CharacterForm
|
||||
success_url = reverse_lazy("character-manage")
|
||||
|
||||
|
|
@ -199,6 +200,7 @@ class CharacterDeleteView(CharacterMixin, ObjectDeleteView):
|
|||
ObjectDeleteView) can delete a character they own.
|
||||
|
||||
"""
|
||||
|
||||
# using the character form fails there
|
||||
form_class = forms.EvenniaForm
|
||||
|
||||
|
|
@ -251,4 +253,3 @@ class CharacterCreateView(CharacterMixin, ObjectCreateView):
|
|||
# Call the Django "form failed" hook
|
||||
messages.error(self.request, "Your character could not be created.")
|
||||
return self.form_invalid(form)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ Error views.
|
|||
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
def to_be_implemented(request):
|
||||
"""
|
||||
A notice letting the user know that this particular feature hasn't been
|
||||
|
|
|
|||
|
|
@ -33,12 +33,12 @@ def get_help_category(help_entry, slugify_cat=True):
|
|||
Returns:
|
||||
help_category (str): The category for the help entry.
|
||||
"""
|
||||
help_category = getattr(help_entry, 'help_category', None)
|
||||
help_category = getattr(help_entry, "help_category", None)
|
||||
if not help_category:
|
||||
help_category = getattr(help_entry, 'db_help_category', DEFAULT_HELP_CATEGORY)
|
||||
help_category = getattr(help_entry, "db_help_category", DEFAULT_HELP_CATEGORY)
|
||||
# if one does not exist, create a category for ease of use with web views html templates
|
||||
if not hasattr(help_entry, 'web_help_category'):
|
||||
setattr(help_entry, 'web_help_category', slugify(help_category))
|
||||
if not hasattr(help_entry, "web_help_category"):
|
||||
setattr(help_entry, "web_help_category", slugify(help_category))
|
||||
help_category = help_category.lower()
|
||||
return slugify(help_category) if slugify_cat else help_category
|
||||
|
||||
|
|
@ -52,13 +52,13 @@ def get_help_topic(help_entry):
|
|||
Returns:
|
||||
help_topic (str): The topic of the help entry. Default is 'unknown_topic'.
|
||||
"""
|
||||
help_topic = getattr(help_entry, 'key', None)
|
||||
help_topic = getattr(help_entry, "key", None)
|
||||
# if object has no key, assume it is a db help entry.
|
||||
if not help_topic:
|
||||
help_topic = getattr(help_entry, 'db_key', 'unknown_topic')
|
||||
help_topic = getattr(help_entry, "db_key", "unknown_topic")
|
||||
# if one does not exist, create a key for ease of use with web views html templates
|
||||
if not hasattr(help_entry, 'web_help_key'):
|
||||
setattr(help_entry, 'web_help_key', slugify(help_topic))
|
||||
if not hasattr(help_entry, "web_help_key"):
|
||||
setattr(help_entry, "web_help_key", slugify(help_topic))
|
||||
return help_topic.lower()
|
||||
|
||||
|
||||
|
|
@ -79,9 +79,9 @@ def can_read_topic(cmd_or_topic, account):
|
|||
`can_list_topic` is also returning False.
|
||||
"""
|
||||
if inherits_from(cmd_or_topic, "evennia.commands.command.Command"):
|
||||
return cmd_or_topic.auto_help and cmd_or_topic.access(account, 'read', default=True)
|
||||
return cmd_or_topic.auto_help and cmd_or_topic.access(account, "read", default=True)
|
||||
else:
|
||||
return cmd_or_topic.access(account, 'read', default=True)
|
||||
return cmd_or_topic.access(account, "read", default=True)
|
||||
|
||||
|
||||
def collect_topics(account):
|
||||
|
|
@ -99,7 +99,7 @@ def collect_topics(account):
|
|||
# collect commands of account and all puppets
|
||||
# skip a command if an entry is recorded with the same topics, category and help entry
|
||||
cmd_help_topics = []
|
||||
if not str(account) == 'AnonymousUser':
|
||||
if not str(account) == "AnonymousUser":
|
||||
# create list of account and account's puppets
|
||||
puppets = account.db._playable_characters + [account]
|
||||
# add the account's and puppets' commands to cmd_help_topics list
|
||||
|
|
@ -112,7 +112,7 @@ def collect_topics(account):
|
|||
# also check the 'cmd:' lock here
|
||||
for cmd in cmdset:
|
||||
# skip the command if the puppet does not have access
|
||||
if not cmd.access(puppet, 'cmd'):
|
||||
if not cmd.access(puppet, "cmd"):
|
||||
continue
|
||||
# skip the command if the puppet does not have read access
|
||||
if not can_read_topic(cmd, puppet):
|
||||
|
|
@ -121,10 +121,11 @@ def collect_topics(account):
|
|||
entry_exists = False
|
||||
for verify_cmd in cmd_help_topics:
|
||||
if (
|
||||
verify_cmd.key and cmd.key and
|
||||
verify_cmd.help_category == cmd.help_category and
|
||||
verify_cmd.__doc__ == cmd.__doc__
|
||||
):
|
||||
verify_cmd.key
|
||||
and cmd.key
|
||||
and verify_cmd.help_category == cmd.help_category
|
||||
and verify_cmd.__doc__ == cmd.__doc__
|
||||
):
|
||||
entry_exists = True
|
||||
break
|
||||
if entry_exists:
|
||||
|
|
@ -148,15 +149,14 @@ def collect_topics(account):
|
|||
|
||||
# Collect commands into a dictionary, read access verified at puppet level
|
||||
cmd_help_topics = {
|
||||
cmd.auto_help_display_key
|
||||
if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
|
||||
cmd.auto_help_display_key if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
|
||||
for cmd in cmd_help_topics
|
||||
}
|
||||
|
||||
return cmd_help_topics, db_help_topics, file_help_topics
|
||||
|
||||
|
||||
class HelpMixin():
|
||||
class HelpMixin:
|
||||
"""
|
||||
This is a "mixin", a modifier of sorts.
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ class HelpDetailView(HelpMixin, DetailView):
|
|||
# Makes sure the page has a sensible title.
|
||||
obj = self.get_object()
|
||||
topic = get_help_topic(obj)
|
||||
return f'{topic} detail'
|
||||
return f"{topic} detail"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""
|
||||
|
|
@ -272,7 +272,7 @@ class HelpDetailView(HelpMixin, DetailView):
|
|||
context["topic_previous"] = None
|
||||
|
||||
# Get the help entry text
|
||||
text = 'Failed to find entry.'
|
||||
text = "Failed to find entry."
|
||||
if inherits_from(obj, "evennia.commands.command.Command"):
|
||||
text = obj.__doc__
|
||||
elif inherits_from(obj, "evennia.help.models.HelpEntry"):
|
||||
|
|
@ -297,8 +297,8 @@ class HelpDetailView(HelpMixin, DetailView):
|
|||
|
||||
"""
|
||||
|
||||
if hasattr(self, 'obj'):
|
||||
return getattr(self, 'obj', None)
|
||||
if hasattr(self, "obj"):
|
||||
return getattr(self, "obj", None)
|
||||
|
||||
# Get the queryset for the help entries the user can access
|
||||
if not queryset:
|
||||
|
|
@ -323,9 +323,7 @@ class HelpDetailView(HelpMixin, DetailView):
|
|||
|
||||
# Check if this object was requested in a valid manner
|
||||
if not obj:
|
||||
return HttpResponseBadRequest(
|
||||
f"No ({category}/{topic})s found matching the query."
|
||||
)
|
||||
return HttpResponseBadRequest(f"No ({category}/{topic})s found matching the query.")
|
||||
else:
|
||||
# cache the object if one was found
|
||||
self.obj = obj
|
||||
|
|
|
|||
|
|
@ -29,14 +29,17 @@ 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,
|
||||
fallback=settings.FALLBACK_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,
|
||||
fallback=settings.FALLBACK_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,
|
||||
fallback=settings.FALLBACK_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
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ from django.core.exceptions import PermissionDenied
|
|||
from django.contrib import messages
|
||||
from evennia.utils import class_from_module
|
||||
from django.utils.text import slugify
|
||||
from .mixins import (
|
||||
EvenniaCreateView, EvenniaDeleteView, EvenniaUpdateView, EvenniaDetailView)
|
||||
from .mixins import EvenniaCreateView, EvenniaDeleteView, EvenniaUpdateView, EvenniaDetailView
|
||||
|
||||
|
||||
class ObjectDetailView(EvenniaDetailView):
|
||||
|
|
@ -35,8 +34,9 @@ class ObjectDetailView(EvenniaDetailView):
|
|||
#
|
||||
# So when you extend it, this line should look simple, like:
|
||||
# model = Object
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_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"
|
||||
|
|
@ -139,8 +139,9 @@ class ObjectCreateView(LoginRequiredMixin, EvenniaCreateView):
|
|||
|
||||
"""
|
||||
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
model = class_from_module(
|
||||
settings.BASE_OBJECT_TYPECLASS, fallback=settings.FALLBACK_OBJECT_TYPECLASS
|
||||
)
|
||||
|
||||
|
||||
class ObjectDeleteView(LoginRequiredMixin, ObjectDetailView, EvenniaDeleteView):
|
||||
|
|
@ -155,8 +156,9 @@ class ObjectDeleteView(LoginRequiredMixin, ObjectDetailView, EvenniaDeleteView):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
model = class_from_module(
|
||||
settings.BASE_OBJECT_TYPECLASS, fallback=settings.FALLBACK_OBJECT_TYPECLASS
|
||||
)
|
||||
template_name = "website/object_confirm_delete.html"
|
||||
|
||||
# -- Evennia constructs --
|
||||
|
|
@ -178,8 +180,9 @@ class ObjectUpdateView(LoginRequiredMixin, ObjectDetailView, EvenniaUpdateView):
|
|||
"""
|
||||
|
||||
# -- Django constructs --
|
||||
model = class_from_module(settings.BASE_OBJECT_TYPECLASS,
|
||||
fallback=settings.FALLBACK_OBJECT_TYPECLASS)
|
||||
model = class_from_module(
|
||||
settings.BASE_OBJECT_TYPECLASS, fallback=settings.FALLBACK_OBJECT_TYPECLASS
|
||||
)
|
||||
|
||||
# -- Evennia constructs --
|
||||
access_type = "edit"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue