Remove tests from api doc

This commit is contained in:
Griatch 2020-07-10 18:04:55 +02:00
parent b1cae35e34
commit 2208a3030c
27 changed files with 298 additions and 320 deletions

View file

@ -12,7 +12,7 @@ SPHINXMULTIVERSION ?= sphinx-multiversion
SPHINXAPIDOC ?= sphinx-apidoc SPHINXAPIDOC ?= sphinx-apidoc
SPHINXAPIDOCOPTS = --tocfile evennia-api --module-first --force -d 6 --separate --templatedir=$(SOURCEDIR)/_templates/ SPHINXAPIDOCOPTS = --tocfile evennia-api --module-first --force -d 6 --separate --templatedir=$(SOURCEDIR)/_templates/
SPHINXAPIDOCENV = members,undoc-members,show-inheritance SPHINXAPIDOCENV = members,undoc-members,show-inheritance
SPHINXAPIDOCEXCLUDE = ../*/migrations/* ../evennia/game_template/* ../*/*/tests/* SPHINXAPIDOCEXCLUDE = ../*/migrations/* ../evennia/game_template/* ../evennia/*/tests/* ../evennia/*/tests.py
EVDIR ?= $(realpath ../evennia) EVDIR ?= $(realpath ../evennia)
EVGAMEDIR ?= $(realpath ../../gamedir) EVGAMEDIR ?= $(realpath ../../gamedir)

View file

@ -17,4 +17,3 @@ Modules
evennia.accounts.bots evennia.accounts.bots
evennia.accounts.manager evennia.accounts.manager
evennia.accounts.models evennia.accounts.models
evennia.accounts.tests

View file

@ -1,7 +0,0 @@
evennia.accounts.tests
=============================
.. automodule:: evennia.accounts.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -17,7 +17,6 @@ Modules
evennia.commands.cmdset evennia.commands.cmdset
evennia.commands.cmdsethandler evennia.commands.cmdsethandler
evennia.commands.command evennia.commands.command
evennia.commands.tests
Packages/folders Packages/folders
---------------- ----------------

View file

@ -1,7 +0,0 @@
evennia.commands.tests
=============================
.. automodule:: evennia.commands.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -17,4 +17,3 @@ Modules
evennia.comms.comms evennia.comms.comms
evennia.comms.managers evennia.comms.managers
evennia.comms.models evennia.comms.models
evennia.comms.tests

View file

@ -1,7 +0,0 @@
evennia.comms.tests
==========================
.. automodule:: evennia.comms.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -36,7 +36,6 @@ Modules
evennia.contrib.slow_exit evennia.contrib.slow_exit
evennia.contrib.talking_npc evennia.contrib.talking_npc
evennia.contrib.test_traits evennia.contrib.test_traits
evennia.contrib.tests
evennia.contrib.traits evennia.contrib.traits
evennia.contrib.tree_select evennia.contrib.tree_select
evennia.contrib.unixcommand evennia.contrib.unixcommand

View file

@ -1,7 +0,0 @@
evennia.contrib.tests
============================
.. automodule:: evennia.contrib.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -14,4 +14,3 @@ Modules
evennia.locks.lockfuncs evennia.locks.lockfuncs
evennia.locks.lockhandler evennia.locks.lockhandler
evennia.locks.tests

View file

@ -1,7 +0,0 @@
evennia.locks.tests
==========================
.. automodule:: evennia.locks.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -16,4 +16,3 @@ Modules
evennia.objects.manager evennia.objects.manager
evennia.objects.models evennia.objects.models
evennia.objects.objects evennia.objects.objects
evennia.objects.tests

View file

@ -1,7 +0,0 @@
evennia.objects.tests
============================
.. automodule:: evennia.objects.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -16,4 +16,3 @@ Modules
evennia.prototypes.protfuncs evennia.prototypes.protfuncs
evennia.prototypes.prototypes evennia.prototypes.prototypes
evennia.prototypes.spawner evennia.prototypes.spawner
evennia.prototypes.tests

View file

@ -1,7 +0,0 @@
evennia.prototypes.tests
===============================
.. automodule:: evennia.prototypes.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -19,5 +19,4 @@ Modules
evennia.scripts.scripthandler evennia.scripts.scripthandler
evennia.scripts.scripts evennia.scripts.scripts
evennia.scripts.taskhandler evennia.scripts.taskhandler
evennia.scripts.tests
evennia.scripts.tickerhandler evennia.scripts.tickerhandler

View file

@ -1,7 +0,0 @@
evennia.scripts.tests
============================
.. automodule:: evennia.scripts.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -17,4 +17,3 @@ Modules
evennia.typeclasses.managers evennia.typeclasses.managers
evennia.typeclasses.models evennia.typeclasses.models
evennia.typeclasses.tags evennia.typeclasses.tags
evennia.typeclasses.tests

View file

@ -1,7 +0,0 @@
evennia.typeclasses.tests
================================
.. automodule:: evennia.typeclasses.tests
:members:
:undoc-members:
:show-inheritance:

View file

@ -255,11 +255,28 @@ def autodoc_post_process_docstring(app, what, name, obj, options, lines):
return "::\n\n {}".format( return "::\n\n {}".format(
"\n ".join(lne for lne in code.split("\n"))) "\n ".join(lne for lne in code.split("\n")))
underline_map = {
1: "-",
2: "=",
3: '^',
4: '"',
}
def _sub_header(match):
# add underline to convert a markdown #header to ReST
groupdict = match.groupdict()
hashes, title = groupdict["hashes"], groupdict["title"]
title = title.strip()
lvl = min(max(1, len(hashes)), 4)
return f"{title}\n" + (underline_map[lvl] * len(title))
doc = "\n".join(lines) doc = "\n".join(lines)
doc = re.sub(r"```python\s*\n+(.*?)```", _sub_codeblock, doc, doc = re.sub(r"```python\s*\n+(.*?)```", _sub_codeblock, doc,
flags=re.MULTILINE + re.DOTALL) flags=re.MULTILINE + re.DOTALL)
doc = re.sub(r"```", "", doc, flags=re.MULTILINE) doc = re.sub(r"```", "", doc, flags=re.MULTILINE)
doc = re.sub(r"`{1}", "**", doc, flags=re.MULTILINE) doc = re.sub(r"`{1}", "**", doc, flags=re.MULTILINE)
doc = re.sub(r"^(?P<hashes>#{1,2})\s*?(?P<title>.*?)$", _sub_header, doc, flags=re.MULTILINE)
newlines = doc.split("\n") newlines = doc.split("\n")
# we must modify lines in-place # we must modify lines in-place
lines[:] = newlines[:] lines[:] = newlines[:]

View file

@ -4,12 +4,12 @@ sessions of users connecting to the server.
There are two similar but separate stores of sessions: There are two similar but separate stores of sessions:
- ServerSessionHandler - this stores generic game sessions - ServerSessionHandler - this stores generic game sessions
for the game. These sessions has no knowledge about for the game. These sessions has no knowledge about
how they are connected to the world. how they are connected to the world.
- PortalSessionHandler - this stores sessions created by - PortalSessionHandler - this stores sessions created by
twisted protocols. These are dumb connectors that twisted protocols. These are dumb connectors that
handle network communication but holds no game info. handle network communication but holds no game info.
""" """
import time import time
@ -156,21 +156,20 @@ class SessionHandler(dict):
Args: Args:
session (Session): The relevant session instance. session (Session): The relevant session instance.
kwargs (dict) Each keyword represents a kwargs (dict) Each keyword represents a send-instruction, with the keyword itself being the name
send-instruction, with the keyword itself being the name
of the instruction (like "text"). Suitable values for each of the instruction (like "text"). Suitable values for each
keyword are: keyword are:
- arg -> [[arg], {}] - arg -> [[arg], {}]
- [args] -> [[args], {}] - [args] -> [[args], {}]
- {kwargs} -> [[], {kwargs}] - {kwargs} -> [[], {kwargs}]
- [args, {kwargs}] -> [[arg], {kwargs}] - [args, {kwargs}] -> [[arg], {kwargs}]
- [[args], {kwargs}] -> [[args], {kwargs}] - [[args], {kwargs}] -> [[args], {kwargs}]
Returns: Returns:
kwargs (dict): A cleaned dictionary of cmdname:[[args],{kwargs}] pairs, kwargs (dict): A cleaned dictionary of cmdname:[[args],{kwargs}] pairs,
where the keys, args and kwargs have all been converted to where the keys, args and kwargs have all been converted to
send-safe entities (strings or numbers), and inlinefuncs have been send-safe entities (strings or numbers), and inlinefuncs have been
applied. applied.
""" """
options = kwargs.pop("options", None) or {} options = kwargs.pop("options", None) or {}
@ -809,9 +808,9 @@ class ServerSessionHandler(SessionHandler):
def call_inputfuncs(self, session, **kwargs): def call_inputfuncs(self, session, **kwargs):
""" """
Split incoming data into its inputfunc counterparts. Split incoming data into its inputfunc counterparts. This should be
This should be called by the serversession.data_in called by the `serversession.data_in` as
as sessionhandler.call_inputfunc(self, **kwargs). `sessionhandler.call_inputfunc(self, **kwargs)`.
We also intercept OOB communication here. We also intercept OOB communication here.
@ -819,8 +818,8 @@ class ServerSessionHandler(SessionHandler):
sessions (Session): Session. sessions (Session): Session.
Keyword args: Keyword args:
kwargs (any): Incoming data from protocol on any (tuple): Incoming data from protocol, each
the form `{"commandname": ((args), {kwargs}),...}` on the form `commandname=((args), {kwargs})`.
""" """

View file

@ -1,21 +1,23 @@
""" """
This module brings Django Signals into Evennia. These are events that This module brings Django Signals into Evennia. These are events that can be
can be subscribed to by importing a given Signal and using the subscribed to by importing a given Signal and using the following code.
following code.
```python
THIS_SIGNAL.connect(callback, sender_object) THIS_SIGNAL.connect(callback, sender_object)
```
When other code calls THIS_SIGNAL.send(sender, **kwargs), the callback When other code calls `THIS_SIGNAL.send(sender, **kwargs)`, the callback will
will be triggered. be triggered.
Callbacks must be in the following format: Callbacks must be on the following format:
```python
def my_callback(sender, **kwargs): def my_callback(sender, **kwargs):
... # ...
```
This is used on top of hooks to make certain features easier to This is used on top of hooks to make certain features easier to add to contribs
add to contribs without necessitating a full takeover of hooks without necessitating a full takeover of hooks that may be in high demand.
that may be in high demand.
""" """
from django.dispatch import Signal from django.dispatch import Signal

View file

@ -578,36 +578,38 @@ class IAttributeBackend:
def do_batch_finish(self, attr_objs): def do_batch_finish(self, attr_objs):
""" """
Called only by batch_add. Used for handling database operations and/or caching complications. Called only by batch_add. Used for handling database operations and/or
caching complications.
Args: Args:
attr_objs (list of IAttribute): The Attributes created/updated thus far. attr_objs (list of IAttribute): The Attributes created/updated thus far.
""" """
raise NotImplementedError() raise NotImplementedError()
def batch_add(self, *args, **kwargs): def batch_add(self, *args, **kwargs):
""" """
Batch-version of `add()`. This is more efficient than Batch-version of `.add()`. This is more efficient than repeat-calling
repeat-calling add when having many Attributes to add. `.add` when having many Attributes to add.
Args: Args:
indata (list): List of tuples of varying length representing the *args (tuple): Tuples of varying length representing the
Attribute to add to this object. Supported tuples are Attribute to add to this object. Supported tuples are
- `(key, value)`
- `(key, value, category)` - (key, value)
- `(key, value, category, lockstring)` - (key, value, category)
- `(key, value, category, lockstring, default_access)` - (key, value, category, lockstring)
- (key, value, category, lockstring, default_access)
Raises: Raises:
RuntimeError: If trying to pass a non-iterable as argument. RuntimeError: If trying to pass a non-iterable as argument.
Notes: Notes:
The indata tuple order matters, so if you want a lockstring The indata tuple order matters, so if you want a lockstring but no
but no category, set the category to `None`. This method category, set the category to `None`. This method does not have the
does not have the ability to check editing permissions like ability to check editing permissions and is mainly used internally.
normal .add does, and is mainly used internally. It does not It does not use the normal `self.add` but applies the Attributes
use the normal self.add but apply the Attributes directly directly to the database.
to the database.
""" """
new_attrobjs = [] new_attrobjs = []
@ -1092,12 +1094,13 @@ class AttributeHandler:
repeat-calling add when having many Attributes to add. repeat-calling add when having many Attributes to add.
Args: Args:
indata (list): List of tuples of varying length representing the *args (tuple): Tuples of varying length representing the
Attribute to add to this object. Supported tuples are Attribute to add to this object. Supported tuples are
- `(key, value)`
- `(key, value, category)` - (key, value)
- `(key, value, category, lockstring)` - (key, value, category)
- `(key, value, category, lockstring, default_access)` - (key, value, category, lockstring)
- (key, value, category, lockstring, default_access)
Keyword args: Keyword args:
strattr (bool): If `True`, value must be a string. This strattr (bool): If `True`, value must be a string. This
@ -1306,12 +1309,12 @@ def initialize_nick_templates(in_template, out_template):
Returns: Returns:
regex (regex): Regex to match against strings regex (regex): Regex to match against strings
template (str): Template with markers {arg1}, {arg2}, etc for template (str): Template with markers ``{arg1}, {arg2}``, etc for
replacement using the standard .format method. replacement using the standard .format method.
Raises: Raises:
NickTemplateInvalid: If the in/out template does not have a matching NickTemplateInvalid: If the in/out template does not have a matching
number of $args. number of `$args`.
""" """

View file

@ -34,14 +34,12 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None, **kwargs self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None, **kwargs
): ):
""" """
Return Attribute objects by key, by category, by value, by Return Attribute objects by key, by category, by value, by strvalue, by
strvalue, by object (it is stored on) or with a combination of object (it is stored on) or with a combination of those criteria.
those criteria.
Attrs: Args:
key (str, optional): The attribute's key to search for key (str, optional): The attribute's key to search for
category (str, optional): The category of the attribute(s) category (str, optional): The category of the attribute(s) to search for.
to search for.
value (str, optional): The attribute value to search for. value (str, optional): The attribute value to search for.
Note that this is not a very efficient operation since it Note that this is not a very efficient operation since it
will query for a pickled entity. Mutually exclusive to will query for a pickled entity. Mutually exclusive to
@ -55,10 +53,10 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
attrype (str, optional): An attribute-type to search for. attrype (str, optional): An attribute-type to search for.
By default this is either `None` (normal Attributes) or By default this is either `None` (normal Attributes) or
`"nick"`. `"nick"`.
kwargs (any): Currently unused. Reserved for future use. **kwargs (any): Currently unused. Reserved for future use.
Returns: Returns:
attributes (list): The matching Attributes. list: The matching Attributes.
""" """
dbmodel = self.model.__dbclass__.__name__.lower() dbmodel = self.model.__dbclass__.__name__.lower()
@ -84,7 +82,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
""" """
Get a nick, in parallel to `get_attribute`. Get a nick, in parallel to `get_attribute`.
Attrs: Args:
key (str, optional): The nicks's key to search for key (str, optional): The nicks's key to search for
category (str, optional): The category of the nicks(s) to search for. category (str, optional): The category of the nicks(s) to search for.
value (str, optional): The attribute value to search for. Note that this value (str, optional): The attribute value to search for. Note that this
@ -170,13 +168,13 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
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.
Attrs: Args:
key (str, optional): The Tag's key to search for key (str, optional): The Tag's key to search for
category (str, optional): The Tag of the attribute(s) category (str, optional): The Tag of the attribute(s)
to search for. to search for.
obj (Object, optional): On which object the Tag to obj (Object, optional): On which object the Tag to
search for is. search for is.
tagtype (str, optional): One of None (normal tags), tagtype (str, optional): One of `None` (normal tags),
"alias" or "permission" "alias" or "permission"
global_search (bool, optional): Include all possible tags, global_search (bool, optional): Include all possible tags,
not just tags on this object not just tags on this object

View file

@ -578,7 +578,7 @@ class TypedObject(SharedMemoryModel):
superuser lock bypass (be careful with this one). superuser lock bypass (be careful with this one).
Keyword args: Keyword args:
kwargs (any): Ignored, but is there to make the api kwar (any): Ignored, but is there to make the api
consistent with the object-typeclass method access, which consistent with the object-typeclass method access, which
use it to feed to its hook methods. use it to feed to its hook methods.
@ -667,14 +667,19 @@ class TypedObject(SharedMemoryModel):
def __db_get(self): def __db_get(self):
""" """
Attribute handler wrapper. Allows for the syntax Attribute handler wrapper. Allows for the syntax
```python
obj.db.attrname = value obj.db.attrname = value
and # and
value = obj.db.attrname value = obj.db.attrname
and # and
del obj.db.attrname del obj.db.attrname
and # and
all_attr = obj.db.all() (unless there is an attribute all_attr = obj.db.all()
named 'all', in which case that will be returned instead). # (unless there is an attribute
# named 'all', in which case that will be returned instead).
```
""" """
try: try:
return self._db_holder return self._db_holder
@ -844,26 +849,32 @@ class TypedObject(SharedMemoryModel):
Returns the URI path for a View that allows users to view details for Returns the URI path for a View that allows users to view details for
this object. this object.
ex. Oscar (Character) = '/characters/oscar/1/'
For this to work, the developer must have defined a named view somewhere
in urls.py that follows the format 'modelname-action', so in this case
a named view of 'character-detail' would be referenced by this method.
ex.
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/$',
CharDetailView.as_view(), name='character-detail')
If no View has been created and defined in urls.py, returns an
HTML anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can view this object is the developer's
responsibility.
Returns: Returns:
path (str): URI path to object detail page, if defined. path (str): URI path to object detail page, if defined.
Examples:
```python
Oscar (Character) = '/characters/oscar/1/'
```
For this to work, the developer must have defined a named view somewhere
in urls.py that follows the format 'modelname-action', so in this case
a named view of 'character-detail' would be referenced by this method.
```python
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/$',
CharDetailView.as_view(), name='character-detail')
```
If no View has been created and defined in urls.py, returns an
HTML anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can view this object is the
developer's responsibility.
""" """
try: try:
return reverse( return reverse(
@ -878,25 +889,31 @@ class TypedObject(SharedMemoryModel):
Returns the URI path for a View that allows users to puppet a specific Returns the URI path for a View that allows users to puppet a specific
object. object.
ex. Oscar (Character) = '/characters/oscar/1/puppet/'
For this to work, the developer must have defined a named view somewhere
in urls.py that follows the format 'modelname-action', so in this case
a named view of 'character-puppet' would be referenced by this method.
ex.
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/puppet/$',
CharPuppetView.as_view(), name='character-puppet')
If no View has been created and defined in urls.py, returns an
HTML anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can view this object is the developer's
responsibility.
Returns: Returns:
path (str): URI path to object puppet page, if defined. str: URI path to object puppet page, if defined.
Examples:
```python
Oscar (Character) = '/characters/oscar/1/puppet/'
```
For this to work, the developer must have defined a named view somewhere
in urls.py that follows the format 'modelname-action', so in this case
a named view of 'character-puppet' would be referenced by this method.
```python
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/puppet/$',
CharPuppetView.as_view(), name='character-puppet')
```
If no View has been created and defined in urls.py, returns an
HTML anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can view this object is the developer's
responsibility.
""" """
try: try:
@ -912,25 +929,31 @@ class TypedObject(SharedMemoryModel):
Returns the URI path for a View that allows users to update this Returns the URI path for a View that allows users to update this
object. object.
ex. Oscar (Character) = '/characters/oscar/1/change/'
For this to work, the developer must have defined a named view somewhere
in urls.py that follows the format 'modelname-action', so in this case
a named view of 'character-update' would be referenced by this method.
ex.
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/change/$',
CharUpdateView.as_view(), name='character-update')
If no View has been created and defined in urls.py, returns an
HTML anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can modify objects is the developer's
responsibility.
Returns: Returns:
path (str): URI path to object update page, if defined. str: URI path to object update page, if defined.
Examples:
```python
Oscar (Character) = '/characters/oscar/1/change/'
```
For this to work, the developer must have defined a named view somewhere
in urls.py that follows the format 'modelname-action', so in this case
a named view of 'character-update' would be referenced by this method.
```python
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/change/$',
CharUpdateView.as_view(), name='character-update')
```
If no View has been created and defined in urls.py, returns an
HTML anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can modify objects is the developer's
responsibility.
""" """
try: try:
@ -945,26 +968,33 @@ class TypedObject(SharedMemoryModel):
""" """
Returns the URI path for a View that allows users to delete this object. Returns the URI path for a View that allows users to delete this object.
ex. Oscar (Character) = '/characters/oscar/1/delete/'
For this to work, the developer must have defined a named view somewhere
in urls.py that follows the format 'modelname-action', so in this case
a named view of 'character-detail' would be referenced by this method.
ex.
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/delete/$',
CharDeleteView.as_view(), name='character-delete')
If no View has been created and defined in urls.py, returns an
HTML anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can delete this object is the developer's
responsibility.
Returns: Returns:
path (str): URI path to object deletion page, if defined. path (str): URI path to object deletion page, if defined.
Examples:
```python
Oscar (Character) = '/characters/oscar/1/delete/'
```
For this to work, the developer must have defined a named view
somewhere in urls.py that follows the format 'modelname-action', so
in this case a named view of 'character-detail' would be referenced
by this method.
```python
url(r'characters/(?P<slug>[\w\d\-]+)/(?P<pk>[0-9]+)/delete/$',
CharDeleteView.as_view(), name='character-delete')
```
If no View has been created and defined in urls.py, returns an HTML
anchor.
This method is naive and simply returns a path. Securing access to
the actual view and limiting who can delete this object is the
developer's responsibility.
""" """
try: try:
return reverse( return reverse(

View file

@ -5,9 +5,12 @@ Use the codes defined in ANSIPARSER in your text
to apply colour to text according to the ANSI standard. to apply colour to text according to the ANSI standard.
Examples: Examples:
This is |rRed text|n and this is normal again.
Mostly you should not need to call parse_ansi() explicitly; ```python
"This is |rRed text|n and this is normal again."
```
Mostly you should not need to call `parse_ansi()` explicitly;
it is run by Evennia just before returning data to/from the it is run by Evennia just before returning data to/from the
user. Depreciated example forms are available by extending user. Depreciated example forms are available by extending
the ansi mapping. the ansi mapping.
@ -982,13 +985,11 @@ class ANSIString(str, metaclass=ANSIMeta):
sep (str): The separator to split the string on. sep (str): The separator to split the string on.
reverse (boolean): Whether to split the string on the last reverse (boolean): Whether to split the string on the last
occurrence of the separator rather than the first. occurrence of the separator rather than the first.
Returns: Returns:
result (tuple): ANSIString: The part of the string before the separator
prefix (ANSIString): The part of the string before the ANSIString: The separator itself
separator ANSIString: The part of the string after the separator.
sep (ANSIString): The separator itself
postfix (ANSIString): The part of the string after the
separator.
""" """
if hasattr(sep, "_clean_string"): if hasattr(sep, "_clean_string"):
@ -1288,18 +1289,21 @@ class ANSIString(str, metaclass=ANSIMeta):
one. one.
NOTE: This should always be used for joining strings when ANSIStrings NOTE: This should always be used for joining strings when ANSIStrings
are involved. Otherwise color information will be discarded by are involved. Otherwise color information will be discarded by python,
python, due to details in the C implementation of strings. due to details in the C implementation of strings.
Args: Args:
iterable (list of strings): A list of strings to join together iterable (list of strings): A list of strings to join together
Returns: Returns:
result (ANSIString): A single string with all of the iterable's ANSIString: A single string with all of the iterable's
contents concatenated, with this string between each. For contents concatenated, with this string between each.
example:
ANSIString(', ').join(['up', 'right', 'left', 'down']) Examples:
...Would return: ::
ANSIString('up, right, left, down')
>>> ANSIString(', ').join(['up', 'right', 'left', 'down'])
ANSIString('up, right, left, down')
""" """
result = ANSIString("") result = ANSIString("")

View file

@ -1,23 +1,21 @@
""" """
This module contains the core methods for the Batch-command- and This module contains the core methods for the Batch-command- and
Batch-code-processors respectively. In short, these are two different Batch-code-processors respectively. In short, these are two different ways to
ways to build a game world using a normal text-editor without having build a game world using a normal text-editor without having to do so 'on the
to do so 'on the fly' in-game. They also serve as an automatic backup fly' in-game. They also serve as an automatic backup so you can quickly
so you can quickly recreate a world also after a server reset. The recreate a world also after a server reset. The functions in this module is
functions in this module is meant to form the backbone of a system meant to form the backbone of a system called and accessed through game
called and accessed through game commands. commands.
The Batch-command processor is the simplest. It simply runs a list of The Batch-command processor is the simplest. It simply runs a list of in-game
in-game commands in sequence by reading them from a text file. The commands in sequence by reading them from a text file. The advantage of this is
advantage of this is that the builder only need to remember the normal that the builder only need to remember the normal in-game commands. They are
in-game commands. They are also executing with full permission checks also executing with full permission checks etc, making it relatively safe for
etc, making it relatively safe for builders to use. The drawback is builders to use. The drawback is that in-game there is really a
that in-game there is really a builder-character walking around builder-character walking around building things, and it can be important to
building things, and it can be important to create rooms and objects create rooms and objects in the right order, so the character can move between
in the right order, so the character can move between them. Also them. Also objects that affects players (such as mobs, dark rooms etc) will
objects that affects players (such as mobs, dark rooms etc) will affect the building character too, requiring extra care to turn off/on.
affect the building character too, requiring extra care to turn
off/on.
The Batch-code processor is a more advanced system that accepts full The Batch-code processor is a more advanced system that accepts full
Python code, executing in chunks. The advantage of this is much more Python code, executing in chunks. The advantage of this is much more
@ -31,7 +29,7 @@ etc. You also need to know Python and Evennia's API. Hence it's
recommended that the batch-code processor is limited only to recommended that the batch-code processor is limited only to
superusers or highly trusted staff. superusers or highly trusted staff.
Batch-command processor file syntax # Batch-command processor file syntax
The batch-command processor accepts 'batchcommand files' e.g The batch-command processor accepts 'batchcommand files' e.g
`batch.ev`, containing a sequence of valid Evennia commands in a `batch.ev`, containing a sequence of valid Evennia commands in a
@ -41,64 +39,64 @@ had been run at the game prompt.
Each Evennia command must be delimited by a line comment to mark its Each Evennia command must be delimited by a line comment to mark its
end. end.
``` ::
#INSERT path.batchcmdfile - this as the first entry on a line will
import and run a batch.ev file in this position, as if it was look
written in this file. # delimiting comment
``` create/drop box
# another required comment
One can also inject another batchcmdfile:
::
#INSERT path.batchcmdfile
This way entire game worlds can be created and planned offline; it is This way entire game worlds can be created and planned offline; it is
especially useful in order to create long room descriptions where a especially useful in order to create long room descriptions where a
real offline text editor is often much better than any online text real offline text editor is often much better than any online text
editor or prompt. editor or prompt.
Example of batch.ev file: ## Example of batch.ev file:
----------------------------
``` ::
# batch file
# all lines starting with # are comments; they also indicate
# that a command definition is over.
@create box # batch file
# all lines starting with # are comments; they also indicate
# that a command definition is over.
# this comment ends the @create command. create box
@set box/desc = A large box. # this comment ends the @create command.
Inside are some scattered piles of clothing. set box/desc = A large box.
Inside are some scattered piles of clothing.
It seems the bottom of the box is a bit loose. It seems the bottom of the box is a bit loose.
# Again, this comment indicates the @set command is over. Note how # Again, this comment indicates the @set command is over. Note how
# the description could be freely added. Excess whitespace on a line # the description could be freely added. Excess whitespace on a line
# is ignored. An empty line in the command definition is parsed as a \n # is ignored. An empty line in the command definition is parsed as a \n
# (so two empty lines becomes a new paragraph). # (so two empty lines becomes a new paragraph).
@teleport #221 teleport #221
# (Assuming #221 is a warehouse or something.) # (Assuming #221 is a warehouse or something.)
# (remember, this comment ends the @teleport command! Don'f forget it) # (remember, this comment ends the @teleport command! Don'f forget it)
# Example of importing another file at this point. # Example of importing another file at this point.
#IMPORT examples.batch #IMPORT examples.batch
@drop box drop box
# Done, the box is in the warehouse! (this last comment is not necessary to # Done, the box is in the warehouse! (this last comment is not necessary to
# close the @drop command since it's the end of the file) # close the drop command since it's the end of the file)
```
-------------------------
An example batch file is `contrib/examples/batch_example.ev`. An example batch file is `contrib/examples/batch_example.ev`.
# Batch-code processor file syntax
==========================================================================
Batch-code processor file syntax
The Batch-code processor accepts full python modules (e.g. `batch.py`) The Batch-code processor accepts full python modules (e.g. `batch.py`)
that looks identical to normal Python files. The difference from that looks identical to normal Python files. The difference from
@ -113,62 +111,61 @@ the code and re-run sections of it easily during development.
Code blocks are marked by commented tokens alone on a line: Code blocks are marked by commented tokens alone on a line:
#HEADER - This denotes code that should be pasted at the top of all - `#HEADER` - This denotes code that should be pasted at the top of all
other code. Multiple HEADER statements - regardless of where other code. Multiple HEADER statements - regardless of where
it exists in the file - is the same as one big block. it exists in the file - is the same as one big block.
Observe that changes to variables made in one block is not Observe that changes to variables made in one block is not
preserved between blocks! preserved between blocks!
#CODE - This designates a code block that will be executed like a - `#CODE` - This designates a code block that will be executed like a
stand-alone piece of code together with any HEADER(s) stand-alone piece of code together with any HEADER(s)
defined. It is mainly used as a way to mark stop points for defined. It is mainly used as a way to mark stop points for
the interactive mode of the batchprocessor. If no CODE block the interactive mode of the batchprocessor. If no CODE block
is defined in the module, the entire module (including HEADERS) is defined in the module, the entire module (including HEADERS)
is assumed to be a CODE block. is assumed to be a CODE block.
#INSERT path.filename - This imports another batch_code.py file and - `#INSERT path.filename` - This imports another batch_code.py file and
runs it in the given position. The inserted file will retain runs it in the given position. The inserted file will retain
its own HEADERs which will not be mixed with the headers of its own HEADERs which will not be mixed with the headers of
this file. this file.
Importing works as normal. The following variables are automatically Importing works as normal. The following variables are automatically
made available in the script namespace. made available in the script namespace.
- `caller` - The object executing the batchscript - `caller` - The object executing the batchscript
- `DEBUG` - This is a boolean marking if the batchprocessor is running - `DEBUG` - This is a boolean marking if the batchprocessor is running
in debug mode. It can be checked to e.g. delete created objects in debug mode. It can be checked to e.g. delete created objects
when running a CODE block multiple times during testing. when running a CODE block multiple times during testing.
(avoids creating a slew of same-named db objects) (avoids creating a slew of same-named db objects)
## Example batch.py file
Example batch.py file ::
-----------------------------------
``` #HEADER
#HEADER
from django.conf import settings from django.conf import settings
from evennia.utils import create from evennia.utils import create
from types import basetypes from types import basetypes
GOLD = 10 GOLD = 10
#CODE #CODE
obj = create.create_object(basetypes.Object) obj = create.create_object(basetypes.Object)
obj2 = create.create_object(basetypes.Object) obj2 = create.create_object(basetypes.Object)
obj.location = caller.location obj.location = caller.location
obj.db.gold = GOLD obj.db.gold = GOLD
caller.msg("The object was created!") caller.msg("The object was created!")
if DEBUG: if DEBUG:
obj.delete() obj.delete()
obj2.delete() obj2.delete()
#INSERT another_batch_file #INSERT another_batch_file
#CODE #CODE
script = create.create_script()
script = create.create_script()
```
""" """
import re import re
import codecs import codecs