Almost completed refactoring of source docstrings for new doc system

This commit is contained in:
Griatch 2020-07-10 22:47:37 +02:00
parent 2208a3030c
commit 9fbfc8f8d0
18 changed files with 331 additions and 332 deletions

View file

@ -185,6 +185,8 @@ def create_toctree():
with open(_TOC_FILE, "w") as fil: with open(_TOC_FILE, "w") as fil:
fil.write("# Toc\n") fil.write("# Toc\n")
fil.write("- [API root](api/evennia-api.rst)")
for ref in sorted(toc_map.values()): for ref in sorted(toc_map.values()):
if ref == "toc": if ref == "toc":
@ -193,6 +195,7 @@ def create_toctree():
linkname = ref.replace("-", " ") linkname = ref.replace("-", " ")
fil.write(f"\n- [{linkname}]({ref})") fil.write(f"\n- [{linkname}]({ref})")
# we add a self-reference so the toc itself is also a part of a toctree # we add a self-reference so the toc itself is also a part of a toctree
fil.write("\n\n```toctree::\n :hidden:\n\n toc\n```") fil.write("\n\n```toctree::\n :hidden:\n\n toc\n```")

View file

@ -364,6 +364,10 @@ div.code-block-caption {
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
} }
.sig-paren {
margin-left: 1px;
}
.property { .property {
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
} }

View file

@ -3,7 +3,4 @@
{% block footer %} {% block footer %}
{{ super() }}
The value of next is {{ next }}.
{% endblock %} {% endblock %}

View file

@ -1,5 +1,5 @@
# Toc # Toc
- [API root](api/evennia-api.rst)
- [Coding/Coding Introduction](Coding/Coding-Introduction) - [Coding/Coding Introduction](Coding/Coding-Introduction)
- [Coding/Coding Overview](Coding/Coding-Overview) - [Coding/Coding Overview](Coding/Coding-Overview)
- [Coding/Continuous Integration](Coding/Continuous-Integration) - [Coding/Continuous Integration](Coding/Continuous-Integration)

View file

@ -250,21 +250,30 @@ class BatchCommandProcessor(object):
def parse_file(self, pythonpath): def parse_file(self, pythonpath):
""" """
This parses the lines of a batchfile according to the following This parses the lines of a batch-command-file.
rules:
1) # at the beginning of a line marks the end of the command before Args:
pythonpath (str): The dot-python path to the file.
Returns:
list: A list of all parsed commands with arguments, as strings.
Notes:
Parsing follows the following rules:
1. A `#` at the beginning of a line marks the end of the command before
it. It is also a comment and any number of # can exist on it. It is also a comment and any number of # can exist on
subsequent lines (but not inside comments). subsequent lines (but not inside comments).
2) #INSERT at the beginning of a line imports another 2. #INSERT at the beginning of a line imports another
batch-cmd file file and pastes it into the batch file as if batch-cmd file file and pastes it into the batch file as if
it was written there. it was written there.
3) Commands are placed alone at the beginning of a line and their 3. Commands are placed alone at the beginning of a line and their
arguments are considered to be everything following (on any arguments are considered to be everything following (on any
number of lines) until the next comment line beginning with #. number of lines) until the next comment line beginning with #.
4) Newlines are ignored in command definitions 4. Newlines are ignored in command definitions
5) A completely empty line in a command line definition is condered 5. A completely empty line in a command line definition is condered
a newline (so two empty lines is a paragraph). a newline (so two empty lines is a paragraph).
6) Excess spaces and indents inside arguments are stripped. 6. Excess spaces and indents inside arguments are stripped.
""" """
@ -313,21 +322,23 @@ class BatchCodeProcessor(object):
def parse_file(self, pythonpath): def parse_file(self, pythonpath):
""" """
This parses the lines of a batchfile according to the following This parses the lines of a batch-code file
rules:
Args: Args:
pythonpath (str): The dot-python path to the file. pythonpath (str): The dot-python path to the file.
Returns: Returns:
codeblocks (list): A list of all #CODE blocks, each with list: A list of all `#CODE` blocks, each with
prepended #HEADER data. If no #CODE blocks were found, prepended `#HEADER` block data. If no `#CODE`
this will be a list of one element. blocks were found, this will be a list of one element
containing all code in the file (so a normal Python file).
Notes: Notes:
Parsing is done according to the following rules:
1. Code before a #CODE/HEADER block are considered part of 1. Code before a #CODE/HEADER block are considered part of
the first code/header block or is the ONLY block if no the first code/header block or is the ONLY block if no
#CODE/HEADER blocks are defined. `#CODE/HEADER` blocks are defined.
2. Lines starting with #HEADER starts a header block (ends other blocks) 2. Lines starting with #HEADER starts a header block (ends other blocks)
3. Lines starting with #CODE begins a code block (ends other blocks) 3. Lines starting with #CODE begins a code block (ends other blocks)
4. Lines starting with #INSERT are on form #INSERT filename. Code from 4. Lines starting with #INSERT are on form #INSERT filename. Code from
@ -336,6 +347,7 @@ class BatchCodeProcessor(object):
5. Code after the last block is considered part of the last header/code 5. Code after the last block is considered part of the last header/code
block block
""" """
text = "".join(read_batchfile(pythonpath, file_ending=".py")) text = "".join(read_batchfile(pythonpath, file_ending=".py"))

View file

@ -1,25 +1,17 @@
""" """
This module gathers all the essential database-creation This module gathers all the essential database-creation functions for the game
functions for the game engine's various object types. engine's various object types.
Only objects created 'stand-alone' are in here, e.g. object Attributes Only objects created 'stand-alone' are in here. E.g. object Attributes are
are always created directly through their respective objects. always created through their respective objects handlers.
Each creation_* function also has an alias named for the entity being Each `creation_*` function also has an alias named for the entity being created,
created, such as create_object() and object(). This is for such as create_object() and object(). This is for consistency with the
consistency with the utils.search module and allows you to do the utils.search module and allows you to do the shorter `create.object()`.
shorter "create.object()".
The respective object managers hold more methods for manipulating and The respective object managers hold more methods for manipulating and searching
searching objects already existing in the database. objects already existing in the database.
Models covered:
Objects
Scripts
Help
Message
Channel
Accounts
""" """
from django.conf import settings from django.conf import settings
from django.db import IntegrityError from django.db import IntegrityError
@ -81,15 +73,14 @@ def create_object(
Keyword args: Keyword args:
typeclass (class or str): Class or python path to a typeclass. typeclass (class or str): Class or python path to a typeclass.
key (str): Name of the new object. If not set, a name of key (str): Name of the new object. If not set, a name of
#dbref will be set. `#dbref` will be set.
home (Object or str): Obj or #dbref to use as the object's home (Object or str): Obj or #dbref to use as the object's
home location. home location.
permissions (list): A list of permission strings or tuples (permstring, category). permissions (list): A list of permission strings or tuples (permstring, category).
locks (str): one or more lockstrings, separated by semicolons. locks (str): one or more lockstrings, separated by semicolons.
aliases (list): A list of alternative keys or tuples (aliasstring, category). aliases (list): A list of alternative keys or tuples (aliasstring, category).
tags (list): List of tag keys or tuples (tagkey, category) or (tagkey, category, data). tags (list): List of tag keys or tuples (tagkey, category) or (tagkey, category, data).
destination (Object or str): Obj or #dbref to use as an Exit's destination (Object or str): Obj or #dbref to use as an Exit's target.
target.
report_to (Object): The object to return error messages to. report_to (Object): The object to return error messages to.
nohome (bool): This allows the creation of objects without a nohome (bool): This allows the creation of objects without a
default home location; only used when creating the default default home location; only used when creating the default

View file

@ -591,7 +591,7 @@ def from_pickle(data, db_obj=None):
object was removed (or changed in-place) in the database, None will be object was removed (or changed in-place) in the database, None will be
returned. returned.
Args_ Args:
data (any): Pickled data to unpickle. data (any): Pickled data to unpickle.
db_obj (Atribute, any): This is the model instance (normally db_obj (Atribute, any): This is the model instance (normally
an Attribute) that _Saver*-type iterables (_SaverList etc) an Attribute) that _Saver*-type iterables (_SaverList etc)

View file

@ -1,45 +1,42 @@
""" """
EvEditor (Evennia Line Editor) EvEditor (Evennia Line Editor)
This implements an advanced line editor for editing longer texts This implements an advanced line editor for editing longer texts in-game. The
in-game. The editor mimics the command mechanisms of the "VI" editor editor mimics the command mechanisms of the "VI" editor (a famous line-by-line
(a famous line-by-line editor) as far as reasonable. editor) as far as reasonable.
Features of the editor: Features of the editor:
- undo/redo. - undo/redo.
- edit/replace on any line of the buffer. - edit/replace on any line of the buffer.
- search&replace text anywhere in buffer. - search&replace text anywhere in buffer.
- formatting of buffer, or selection, to certain width + indentations. - formatting of buffer, or selection, to certain width + indentations.
- allow to echo the input or not, depending on your client. - allow to echo the input or not, depending on your client.
- in-built help
To use the editor, just import EvEditor from this module To use the editor, just import EvEditor from this module and initialize it:
and initialize it:
from evennia.utils.eveditor import EvEditor ```python
from evennia.utils.eveditor import EvEditor
EvEditor(caller, loadfunc=None, savefunc=None, quitfunc=None, key="", persistent=True) # set up an editor to edit the caller's 'desc' Attribute
def _loadfunc(caller):
return caller.db.desc
- caller is the user of the editor, the one to see all feedback. def _savefunc(caller, buffer):
- loadfunc(caller) is called when the editor is first launched; the caller.db.desc = buffer.strip()
return from this function is loaded as the starting buffer in the return True
editor.
- safefunc(caller, buffer) is called with the current buffer when
saving in the editor. The function should return True/False depending
on if the saving was successful or not.
- quitfunc(caller) is called when the editor exits. If this is given,
no automatic quit messages will be given.
- key is an optional identifier for the editing session, to be
displayed in the editor.
- persistent means the editor state will be saved to the database making it
survive a server reload. Note that using this mode, the load- save-
and quit-funcs must all be possible to pickle - notable unusable
callables are class methods and functions defined inside other
functions. With persistent=False, no such restriction exists.
- code set to True activates features on the EvEditor to enter Python code.
In addition, the EvEditor can be used to enter Python source code, def _quitfunc(caller):
and offers basic handling of indentation. caller.msg("Custom quit message")
# start the editor
EvEditor(caller, loadfunc=None, savefunc=None, quitfunc=None, key="",
persistent=True, code=False)
```
The editor can also be used to format Python code and be made to
survive a reload. See the `EvEditor` class for more details.
""" """
import re import re
@ -227,16 +224,19 @@ class CmdEditorBase(Command):
def parse(self): def parse(self):
""" """
Handles pre-parsing Handles pre-parsing. Editor commands are on the form
::
Editor commands are on the form
:cmd [li] [w] [txt] :cmd [li] [w] [txt]
Where all arguments are optional. Where all arguments are optional.
li - line number (int), starting from 1. This could also
- `li` - line number (int), starting from 1. This could also
be a range given as <l>:<l>. be a range given as <l>:<l>.
w - word(s) (string), could be encased in quotes. - `w` - word(s) (string), could be encased in quotes.
txt - extra text (string), could be encased in quotes. - `txt` - extra text (string), could be encased in quotes.
""" """
editor = self.caller.ndb._eveditor editor = self.caller.ndb._eveditor

View file

@ -91,28 +91,28 @@ Use as follows:
This produces the following result: This produces the following result:
``` ::
.------------------------------------------------.
| | .------------------------------------------------.
| Name: Tom the Player: Griatch | | |
| Bouncer | | Name: Tom the Player: Griatch |
| | | Bouncer |
| |
>----------------------------------------------< >----------------------------------------------<
| | | |
| Desc: A sturdy STR: 12 DEX: 10 | | Desc: A sturdy STR: 12 DEX: 10 |
| fellow INT: 5 STA: 18 | | fellow INT: 5 STA: 18 |
| LUC: 10 MAG: 3 | | LUC: 10 MAG: 3 |
| | | |
>----------------------------------------------< >----------------------------------------------<
| | | | | |
| HP|MV|MP | Skill |Value |Exp | | HP|MV|MP | Skill |Value |Exp |
| ~~+~~+~~ | ~~~~~~~~~~~+~~~~~~~~~~~+~~~~~~~~~~~ | | ~~+~~+~~ | ~~~~~~~~~~~+~~~~~~~~~~~+~~~~~~~~~~~ |
| **|**|** | Shooting |12 |550/1200 | | **|**|** | Shooting |12 |550/1200 |
| |**|* | Herbalism |14 |990/1400 | | |**|* | Herbalism |14 |990/1400 |
| |* | | Smithing |9 |205/900 | | |* | | Smithing |9 |205/900 |
| | | | | |
------------------------------------------------ ------------------------------------------------
```
The marked forms have been replaced with EvCells of text and with The marked forms have been replaced with EvCells of text and with
EvTables. The form can be updated by simply re-applying `form.map()` EvTables. The form can be updated by simply re-applying `form.map()`
@ -127,6 +127,8 @@ small for it). If you try to fit a table into an area it cannot fit
into (when including its borders and at least one line of text), the into (when including its borders and at least one line of text), the
form will raise an error. form will raise an error.
----
""" """
import re import re
@ -190,12 +192,12 @@ class EvForm(object):
Keyword args: Keyword args:
filename (str): Path to template file. filename (str): Path to template file.
cells (dict): A dictionary mapping of {id:text} cells (dict): A dictionary mapping `{id: text}`
tables (dict): A dictionary mapping of {id:EvTable}. tables (dict): A dictionary mapping `{id: EvTable}`.
form (dict): A dictionary of {"FORMCHAR":char, form (dict): A dictionary
"TABLECHAR":char, `{"FORMCHAR":char, "TABLECHAR":char, "FORM":templatestring}`.
"FORM":templatestring} If this is given, filename is not read.
if this is given, filename is not read.
Notes: Notes:
Other kwargs are fed as options to the EvCells and EvTables Other kwargs are fed as options to the EvCells and EvTables
(see `evtable.EvCell` and `evtable.EvTable` for more info). (see `evtable.EvCell` and `evtable.EvTable` for more info).

View file

@ -54,7 +54,7 @@ command entered by the user on the *previous* node (the command
entered to get to this node). The node function code will only be entered to get to this node). The node function code will only be
executed once per node-visit and the system will accept nodes with executed once per node-visit and the system will accept nodes with
both one or two arguments interchangeably. It also accepts nodes both one or two arguments interchangeably. It also accepts nodes
that takes **kwargs. that takes `**kwargs`.
The menu tree itself is available on the caller as The menu tree itself is available on the caller as
`caller.ndb._menutree`. This makes it a convenient place to store `caller.ndb._menutree`. This makes it a convenient place to store
@ -65,13 +65,13 @@ The return values must be given in the above order, but each can be
returned as None as well. If the options are returned as None, the returned as None as well. If the options are returned as None, the
menu is immediately exited and the default "look" command is called. menu is immediately exited and the default "look" command is called.
text (str, tuple or None): Text shown at this node. If a tuple, the - `text` (str, tuple or None): Text shown at this node. If a tuple, the
second element in the tuple is a help text to display at this second element in the tuple is a help text to display at this
node when the user enters the menu help command there. node when the user enters the menu help command there.
options (tuple, dict or None): If `None`, this exits the menu. - `options` (tuple, dict or None): If `None`, this exits the menu.
If a single dict, this is a single-option node. If a tuple, If a single dict, this is a single-option node. If a tuple,
it should be a tuple of option dictionaries. Option dicts have it should be a tuple of option dictionaries. Option dicts have the following keys:
the following keys:
- `key` (str or tuple, optional): What to enter to choose this option. - `key` (str or tuple, optional): What to enter to choose this option.
If a tuple, it must be a tuple of strings, where the first string is the If a tuple, it must be a tuple of strings, where the first string is the
key which will be shown to the user and the others are aliases. key which will be shown to the user and the others are aliases.
@ -82,8 +82,8 @@ menu is immediately exited and the default "look" command is called.
- `desc` (str, optional): This describes what choosing the option will do. - `desc` (str, optional): This describes what choosing the option will do.
- `goto` (str, tuple or callable): If string, should be the name of node to go to - `goto` (str, tuple or callable): If string, should be the name of node to go to
when this option is selected. If a callable, it has the signature when this option is selected. If a callable, it has the signature
`callable(caller[,raw_input][,**kwargs]). If a tuple, the first element `callable(caller[,raw_input][,**kwargs])`. If a tuple, the first element
is the callable and the second is a dict with the **kwargs to pass to is the callable and the second is a dict with the `**kwargs` to pass to
the callable. Those kwargs will also be passed into the next node if possible. the callable. Those kwargs will also be passed into the next node if possible.
Such a callable should return either a str or a (str, dict), where the Such a callable should return either a str or a (str, dict), where the
string is the name of the next node to go to and the dict is the new, string is the name of the next node to go to and the dict is the new,
@ -96,7 +96,7 @@ menu is immediately exited and the default "look" command is called.
next node name and the optional dict acting as the kwargs-input for the next node. next node name and the optional dict acting as the kwargs-input for the next node.
If an exec callable returns the empty string (only), the current node is re-run. If an exec callable returns the empty string (only), the current node is re-run.
If key is not given, the option will automatically be identified by If `key` is not given, the option will automatically be identified by
its number 1..N. its number 1..N.
Example: Example:
@ -142,6 +142,8 @@ Example:
When starting this menu with `Menu(caller, "path.to.menu_module")`, When starting this menu with `Menu(caller, "path.to.menu_module")`,
the first node will look something like this: the first node will look something like this:
::
This is a node text This is a node text
______________________________________ ______________________________________
@ -158,9 +160,10 @@ The menu tree is exited either by using the in-menu quit command or by
reaching a node without any options. reaching a node without any options.
For a menu demo, import CmdTestMenu from this module and add it to For a menu demo, import `CmdTestMenu` from this module and add it to
your default cmdset. Run it with this module, like `testmenu your default cmdset. Run it with this module, like `testmenu evennia.utils.evmenu`.
evennia.utils.evmenu`.
----
""" """
@ -1155,7 +1158,7 @@ def list_node(option_generator, select=None, pagesize=10):
select (callable or str, optional): Node to redirect a selection to. Its `**kwargs` will select (callable or str, optional): Node to redirect a selection to. Its `**kwargs` will
contain the `available_choices` list and `selection` will hold one of the elements in contain the `available_choices` list and `selection` will hold one of the elements in
that list. If a callable, it will be called as that list. If a callable, it will be called as
select(caller, menuchoice, **kwargs) where menuchoice is the chosen option as a `select(caller, menuchoice, **kwargs)` where menuchoice is the chosen option as a
string and `available_choices` is a kwarg mapping the option keys to the choices string and `available_choices` is a kwarg mapping the option keys to the choices
offered by the option_generator. The callable whould return the name of the target node offered by the option_generator. The callable whould return the name of the target node
to goto after this selection (or None to repeat the list-node). Note that if this is not to goto after this selection (or None to repeat the list-node). Note that if this is not
@ -1163,15 +1166,19 @@ def list_node(option_generator, select=None, pagesize=10):
pagesize (int): How many options to show per page. pagesize (int): How many options to show per page.
Example: Example:
@list_node(['foo', 'bar'], select)
```python
list_node(['foo', 'bar'], select)
def node_index(caller): def node_index(caller):
text = "describing the list" text = "describing the list"
return text, [] return text, []
```
Notes: Notes:
All normal `goto` or `exec` callables returned from the decorated nodes will, if they accept All normal `goto` or `exec` callables returned from the decorated nodes
**kwargs, get a new kwarg 'available_choices' injected. These are the ordered list of named will, if they accept `**kwargs`, get a new kwarg 'available_choices'
options (descs) visible on the current node page. injected. These are the ordered list of named options (descs) visible
on the current node page.
""" """
@ -1392,60 +1399,51 @@ class _Prompt(object):
def get_input(caller, prompt, callback, session=None, *args, **kwargs): def get_input(caller, prompt, callback, session=None, *args, **kwargs):
""" """
This is a helper function for easily request input from This is a helper function for easily request input from the caller.
the caller.
Args: Args:
caller (Account or Object): The entity being asked caller (Account or Object): The entity being asked the question. This
the question. This should usually be an object should usually be an object controlled by a user.
controlled by a user. prompt (str): This text will be shown to the user, in order to let them
prompt (str): This text will be shown to the user, know their input is needed.
in order to let them know their input is needed.
callback (callable): A function that will be called callback (callable): A function that will be called
when the user enters a reply. It must take three when the user enters a reply. It must take three arguments: the
arguments: the `caller`, the `prompt` text and the `caller`, the `prompt` text and the `result` of the input given by
`result` of the input given by the user. If the the user. If the callback doesn't return anything or return False,
callback doesn't return anything or return False, the input prompt will be cleaned up and exited. If returning True,
the input prompt will be cleaned up and exited. If the prompt will remain and continue to accept input.
returning True, the prompt will remain and continue to
accept input.
session (Session, optional): This allows to specify the session (Session, optional): This allows to specify the
session to send the prompt to. It's usually only session to send the prompt to. It's usually only needed if `caller`
needed if `caller` is an Account in multisession modes is an Account in multisession modes greater than 2. The session is
greater than 2. The session is then updated by the then updated by the command and is available (for example in
command and is available (for example in callbacks) callbacks) through `caller.ndb.getinput._session`.
through `caller.ndb.getinput._session`. *args (any): Extra arguments to pass to `callback`. To utilise `*args`
*args, **kwargs (optional): Extra arguments will be (and `**kwargs`), a value for the `session` argument must also be
passed to the fall back function as a list 'args' provided.
and all keyword arguments as a dictionary 'kwargs'. **kwargs (any): Extra kwargs to pass to `callback`.
To utilise *args and **kwargs, a value for the
session argument must be provided (None by default)
and the callback function must take *args and
**kwargs as arguments.
Raises: Raises:
RuntimeError: If the given callback is not callable. RuntimeError: If the given callback is not callable.
Notes: Notes:
The result value sent to the callback is raw and not The result value sent to the callback is raw and not processed in any
processed in any way. This means that you will get way. This means that you will get the ending line return character from
the ending line return character from most types of most types of client inputs. So make sure to strip that before doing a
client inputs. So make sure to strip that before comparison.
doing a comparison.
When the prompt is running, a temporary object When the prompt is running, a temporary object `caller.ndb._getinput`
`caller.ndb._getinput` is stored; this will be removed is stored; this will be removed when the prompt finishes.
when the prompt finishes.
If you need the specific Session of the caller (which
may not be easy to get if caller is an account in higher
multisession modes), then it is available in the
callback through `caller.ndb._getinput._session`.
Chaining get_input functions will result in the caller If you need the specific Session of the caller (which may not be easy
stacking ever more instances of InputCmdSets. Whilst to get if caller is an account in higher multisession modes), then it
they will all be cleared on concluding the get_input is available in the callback through `caller.ndb._getinput._session`.
chain, EvMenu should be considered for anything beyond This is why the `session` is required as input.
a single question.
It's not recommended to 'chain' `get_input` into a sequence of
questions. This will result in the caller stacking ever more instances
of InputCmdSets. While they will all be cleared on concluding the
get_input chain, EvMenu should be considered for anything beyond a
single question.
""" """
if not callable(callback): if not callable(callback):

View file

@ -2,29 +2,35 @@
""" """
EvMore - pager mechanism EvMore - pager mechanism
This is a pager for displaying long texts and allows stepping up and This is a pager for displaying long texts and allows stepping up and down in
down in the text (the name comes from the traditional 'more' unix the text (the name comes from the traditional 'more' unix command).
command).
To use, simply pass the text through the EvMore object: To use, simply pass the text through the EvMore object:
from evennia.utils.evmore import EvMore ```python
from evennia.utils.evmore import EvMore
text = some_long_text_output() text = some_long_text_output()
EvMore(caller, text, always_page=False, session=None, justify_kwargs=None, **kwargs) EvMore(caller, text, always_page=False, session=None, justify_kwargs=None, **kwargs)
```
One can also use the convenience function msg from this module: One can also use the convenience function `msg` from this module to avoid
having to set up the `EvMenu` object manually:
```python
from evennia.utils import evmore from evennia.utils import evmore
text = some_long_text_output() text = some_long_text_output()
evmore.msg(caller, text, always_page=False, session=None, justify_kwargs=None, **kwargs) evmore.msg(caller, text, always_page=False, session=None, justify_kwargs=None, **kwargs)
```
Where always_page decides if the pager is used also if the text is not The `always_page` argument decides if the pager is used also if the text is not long
long enough to need to scroll, session is used to determine which session to relay to enough to need to scroll, `session` is used to determine which session to relay
and justify_kwargs are kwargs to pass to utils.utils.justify in order to change the formatting to and `justify_kwargs` are kwargs to pass to utils.utils.justify in order to
of the text. The remaining **kwargs will be passed on to the change the formatting of the text. The remaining `**kwargs` will be passed on to
caller.msg() construct every time the page is updated. the `caller.msg()` construct every time the page is updated.
----
""" """
from django.conf import settings from django.conf import settings
@ -32,7 +38,7 @@ from django.db.models.query import QuerySet
from evennia import Command, CmdSet from evennia import Command, CmdSet
from evennia.commands import cmdhandler from evennia.commands import cmdhandler
from evennia.utils.ansi import ANSIString from evennia.utils.ansi import ANSIString
from evennia.utils.utils import make_iter, inherits_from, justify from evennia.utils.utils import make_iter, inherits_from, justify, dedent
_CMD_NOMATCH = cmdhandler.CMD_NOMATCH _CMD_NOMATCH = cmdhandler.CMD_NOMATCH
_CMD_NOINPUT = cmdhandler.CMD_NOINPUT _CMD_NOINPUT = cmdhandler.CMD_NOINPUT
@ -146,14 +152,15 @@ class EvMore(object):
): ):
""" """
Initialization of the text handler. EvMore pager
Args: Args:
caller (Object or Account): Entity reading the text. caller (Object or Account): Entity reading the text.
text (str, EvTable or iterator): The text or data to put under paging. text (str, EvTable or iterator): The text or data to put under paging.
- If a string, paginage normally. If this text contains
one or more `\f` format symbol, automatic pagination and justification - If a string, paginate normally. If this text contains one or more `\\\\f` format
are force-disabled and page-breaks will only happen after each `\f`. symbols, automatic pagination and justification are force-disabled and page-breaks
will only happen after each `\\\\f`.
- If `EvTable`, the EvTable will be paginated with the same - If `EvTable`, the EvTable will be paginated with the same
setting on each page if it is too long. The table setting on each page if it is too long. The table
decorations will be considered in the size of the page. decorations will be considered in the size of the page.
@ -187,6 +194,8 @@ class EvMore(object):
kwargs (any, optional): These will be passed on to the `caller.msg` method. kwargs (any, optional): These will be passed on to the `caller.msg` method.
Examples: Examples:
```python
super_long_text = " ... " super_long_text = " ... "
EvMore(caller, super_long_text) EvMore(caller, super_long_text)
@ -199,6 +208,7 @@ class EvMore(object):
EvMore(caller, multi_page_table, use_evtable=True, EvMore(caller, multi_page_table, use_evtable=True,
evtable_args=("Header1", "Header2"), evtable_args=("Header1", "Header2"),
evtable_kwargs={"align": "r", "border": "tablecols"}) evtable_kwargs={"align": "r", "border": "tablecols"})
```
""" """
self._caller = caller self._caller = caller
@ -305,9 +315,13 @@ class EvMore(object):
def init_f_str(self, text): def init_f_str(self, text):
""" """
The input contains \f markers. We use \f to indicate the user wants to The input contains `\\f` markers. We use `\\f` to indicate the user wants to
enforce their line breaks on their own. If so, we do no automatic enforce their line breaks on their own. If so, we do no automatic
line-breaking/justification at all. line-breaking/justification at all.
Args:
text (str): The string to format with f-markers.
""" """
self._data = text.split("\f") self._data = text.split("\f")
self._npages = len(self._data) self._npages = len(self._data)
@ -443,39 +457,6 @@ def msg(
): ):
""" """
EvMore-supported version of msg, mimicking the normal msg method. EvMore-supported version of msg, mimicking the normal msg method.
Args:
caller (Object or Account): Entity reading the text.
text (str, EvTable or iterator): The text or data to put under paging.
- If a string, paginage normally. If this text contains
one or more `\f` format symbol, automatic pagination is disabled
and page-breaks will only happen after each `\f`.
- If `EvTable`, the EvTable will be paginated with the same
setting on each page if it is too long. The table
decorations will be considered in the size of the page.
- Otherwise `text` is converted to an iterator, where each step is
is expected to be a line in the final display, and each line
will be run through repr().
always_page (bool, optional): If `False`, the
pager will only kick in if `text` is too big
to fit the screen.
session (Session, optional): If given, this session will be used
to determine the screen width and will receive all output.
justify (bool, optional): If set, justify long lines in output. Disable for
fixed-format output, like tables.
justify_kwargs (dict, bool or None, optional): If given, this should
be valid keyword arguments to the utils.justify() function. If False,
no justification will be done.
exit_on_lastpage (bool, optional): Immediately exit pager when reaching the last page.
use_evtable (bool, optional): If True, each page will be rendered as an
EvTable. For this to work, `text` must be an iterable, where each element
is the table (list of list) to render on that page.
evtable_args (tuple, optional): The args to use for EvTable on each page.
evtable_kwargs (dict, optional): The kwargs to use for EvTable on each
page (except `table`, which is supplied by EvMore per-page).
kwargs (any, optional): These will be passed on
to the `caller.msg` method.
""" """
EvMore( EvMore(
caller, caller,
@ -487,3 +468,6 @@ def msg(
exit_on_lastpage=exit_on_lastpage, exit_on_lastpage=exit_on_lastpage,
**kwargs, **kwargs,
) )
msg.__doc__ += dedent(EvMore.__init__.__doc__)

View file

@ -1,7 +1,8 @@
""" """
This is an advanced ASCII table creator. It was inspired by This is an advanced ASCII table creator. It was inspired by Prettytable
[prettytable](https://code.google.com/p/prettytable/) but shares no (https://code.google.com/p/prettytable/) but shares no code and is considerably
code. more advanced, supporting auto-balancing of incomplete tables and ANSI colors among
other things.
Example usage: Example usage:
@ -17,19 +18,19 @@ Example usage:
Result: Result:
``` ::
+----------------------+----------+---+--------------------------+
| Heading1 | Heading2 | | | +----------------------+----------+---+--------------------------+
+~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~~+~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~+ | Heading1 | Heading2 | | |
| 1 | 4 | 7 | This is long data | +~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~~+~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~+
+----------------------+----------+---+--------------------------+ | 1 | 4 | 7 | This is long data |
| 2 | 5 | 8 | This is even longer data | +----------------------+----------+---+--------------------------+
+----------------------+----------+---+--------------------------+ | 2 | 5 | 8 | This is even longer data |
| 3 | 6 | 9 | | +----------------------+----------+---+--------------------------+
+----------------------+----------+---+--------------------------+ | 3 | 6 | 9 | |
| This is a single row | | | | +----------------------+----------+---+--------------------------+
+----------------------+----------+---+--------------------------+ | This is a single row | | | |
``` +----------------------+----------+---+--------------------------+
As seen, the table will automatically expand with empty cells to make As seen, the table will automatically expand with empty cells to make
the table symmetric. Tables can be restricted to a given width: the table symmetric. Tables can be restricted to a given width:
@ -42,25 +43,26 @@ the table symmetric. Tables can be restricted to a given width:
This yields the following result: This yields the following result:
``` ::
+-----------+------------+-----------+-----------+
| Heading1 | Heading2 | | | +-----------+------------+-----------+-----------+
+~~~~~~~~~~~+~~~~~~~~~~~~+~~~~~~~~~~~+~~~~~~~~~~~+ | Heading1 | Heading2 | | |
| 1 | 4 | 7 | This is | +~~~~~~~~~~~+~~~~~~~~~~~~+~~~~~~~~~~~+~~~~~~~~~~~+
| | | | long data | | 1 | 4 | 7 | This is |
+-----------+------------+-----------+-----------+ | | | | long data |
| | | | This is | +-----------+------------+-----------+-----------+
| 2 | 5 | 8 | even | | | | | This is |
| | | | longer | | 2 | 5 | 8 | even |
| | | | data | | | | | longer |
+-----------+------------+-----------+-----------+ | | | | data |
| 3 | 6 | 9 | | +-----------+------------+-----------+-----------+
+-----------+------------+-----------+-----------+ | 3 | 6 | 9 | |
| This is a | | | | +-----------+------------+-----------+-----------+
| single | | | | | This is a | | | |
| row | | | | | single | | | |
+-----------+------------+-----------+-----------+ | row | | | |
``` +-----------+------------+-----------+-----------+
Table-columns can be individually formatted. Note that if an Table-columns can be individually formatted. Note that if an
individual column is set with a specific width, table auto-balancing individual column is set with a specific width, table auto-balancing
@ -75,22 +77,22 @@ table.reformat_column(3, width=30, align="r")
print table print table
``` ```
``` ::
+-----------+-------+-----+-----------------------------+---------+
| Heading1 | Headi | | | | +-----------+-------+-----+-----------------------------+---------+
| | ng2 | | | | | Heading1 | Headi | | | |
+~~~~~~~~~~~+~~~~~~~+~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~+ | | ng2 | | | |
| 1 | 4 | 7 | This is long data | Test1 | +~~~~~~~~~~~+~~~~~~~+~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~+
+-----------+-------+-----+-----------------------------+---------+ | 1 | 4 | 7 | This is long data | Test1 |
| 2 | 5 | 8 | This is even longer data | Test3 | +-----------+-------+-----+-----------------------------+---------+
+-----------+-------+-----+-----------------------------+---------+ | 2 | 5 | 8 | This is even longer data | Test3 |
| 3 | 6 | 9 | | Test4 | +-----------+-------+-----+-----------------------------+---------+
+-----------+-------+-----+-----------------------------+---------+ | 3 | 6 | 9 | | Test4 |
| This is a | | | | | +-----------+-------+-----+-----------------------------+---------+
| single | | | | | | This is a | | | | |
| row | | | | | | single | | | | |
+-----------+-------+-----+-----------------------------+---------+ | row | | | | |
``` +-----------+-------+-----+-----------------------------+---------+
When adding new rows/columns their data can have its own alignments When adding new rows/columns their data can have its own alignments
(left/center/right, top/center/bottom). (left/center/right, top/center/bottom).
@ -99,15 +101,16 @@ If the height is restricted, cells will be restricted from expanding
vertically. This will lead to text contents being cropped. Each cell vertically. This will lead to text contents being cropped. Each cell
can only shrink to a minimum width and height of 1. can only shrink to a minimum width and height of 1.
`EvTable` is intended to be used with [ANSIString](evennia.utils.ansi#ansistring) `EvTable` is intended to be used with `ANSIString` for supporting ANSI-coloured
for supporting ANSI-coloured string types. string types.
When a cell is auto-wrapped across multiple lines, ANSI-reset When a cell is auto-wrapped across multiple lines, ANSI-reset sequences will be
sequences will be put at the end of each wrapped line. This means that put at the end of each wrapped line. This means that the colour of a wrapped
the colour of a wrapped cell will not "bleed", but it also means that cell will not "bleed", but it also means that eventual colour outside the table
eventual colour outside the table will not transfer "across" a table, will not transfer "across" a table, you need to re-set the color to have it
you need to re-set the color to have it appear on both sides of the appear on both sides of the table string.
table string.
----
""" """

View file

@ -3,21 +3,21 @@ Inline functions (nested form).
This parser accepts nested inlinefunctions on the form This parser accepts nested inlinefunctions on the form
``` ```python
$funcname(arg, arg, ...) $funcname(arg, arg, ...)
``` ```
embedded in any text where any arg can be another $funcname{} call. embedded in any text where any arg can be another ``$funcname()`` call.
This functionality is turned off by default - to activate, This functionality is turned off by default - to activate,
`settings.INLINEFUNC_ENABLED` must be set to `True`. `settings.INLINEFUNC_ENABLED` must be set to `True`.
Each token starts with "$funcname(" where there must be no space Each token starts with `$funcname(` where there must be no space
between the $funcname and (. It ends with a matched ending parentesis. between the `$funcname` and `"("`. The inlinefunc ends with a matched ending parentesis.
")". `")"`.
Inside the inlinefunc definition, one can use `\` to escape. This is Inside the inlinefunc definition, one can use `\` to escape. This is
mainly needed for escaping commas in flowing text (which would mainly needed for escaping commas in flowing text (which would
otherwise be interpreted as an argument separator), or to escape `}` otherwise be interpreted as an argument separator), or to escape `)`
when not intended to close the function block. Enclosing text in when not intended to close the function block. Enclosing text in
matched `\"\"\"` (triple quotes) or `'''` (triple single-quotes) will matched `\"\"\"` (triple quotes) or `'''` (triple single-quotes) will
also escape *everything* within without needing to escape individual also escape *everything* within without needing to escape individual
@ -44,6 +44,7 @@ the string is sent to a non-puppetable object. The inlinefunc should
never raise an exception. never raise an exception.
There are two reserved function names: There are two reserved function names:
- "nomatch": This is called if the user uses a functionname that is - "nomatch": This is called if the user uses a functionname that is
not registered. The nomatch function will get the name of the not registered. The nomatch function will get the name of the
not-found function as its first argument followed by the normal not-found function as its first argument followed by the normal
@ -54,9 +55,11 @@ There are two reserved function names:
the `stackfull` inlinefunc is appended to the end. By default this is an the `stackfull` inlinefunc is appended to the end. By default this is an
error message. error message.
Error handling: Syntax errors, notably failing to completely closing all inlinefunc
Syntax errors, notably not completely closing all inlinefunc blocks, will lead to the entire string remaining unparsed. Inlineparsing should
blocks, will lead to the entire string remaining unparsed. never traceback.
----
""" """

View file

@ -109,9 +109,9 @@ class BaseOption(object):
def save(self, **kwargs): def save(self, **kwargs):
""" """
Stores the current value using .handler.save_handler(self.key, value, **kwargs) Stores the current value using `.handler.save_handler(self.key, value, **kwargs)`
where kwargs are a combination of those passed into this function and the where `kwargs` are a combination of those passed into this function and
ones specified by the OptionHandler. the ones specified by the `OptionHandler`.
Keyword args: Keyword args:
any (any): Not used by default. These are passed in from self.set any (any): Not used by default. These are passed in from self.set

View file

@ -36,7 +36,7 @@ __all__ = (
"search_message", "search_message",
"search_channel", "search_channel",
"search_help_entry", "search_help_entry",
"search_object_tag", "search_tag",
"search_script_tag", "search_script_tag",
"search_account_tag", "search_account_tag",
"search_channel_tag", "search_channel_tag",

View file

@ -39,12 +39,14 @@ def unload_module(module):
should directly give the module pathname to unload. should directly give the module pathname to unload.
Example: Example:
```python
# (in a test method) # (in a test method)
unload_module(foo) unload_module(foo)
with mock.patch("foo.GLOBALTHING", "mockval"): with mock.patch("foo.GLOBALTHING", "mockval"):
import foo import foo
... # test code using foo.GLOBALTHING, now set to 'mockval' ... # test code using foo.GLOBALTHING, now set to 'mockval'
```
This allows for mocking constants global to the module, since This allows for mocking constants global to the module, since
otherwise those would not be mocked (since a module is only otherwise those would not be mocked (since a module is only

View file

@ -1197,7 +1197,7 @@ def check_evennia_dependencies():
def has_parent(basepath, obj): def has_parent(basepath, obj):
""" """
Checks if `basepath` is somewhere in `obj`s parent tree. Checks if `basepath` is somewhere in obj's parent tree.
Args: Args:
basepath (str): Python dotpath to compare against obj path. basepath (str): Python dotpath to compare against obj path.

View file

@ -41,8 +41,8 @@ def color(entry, option_key="Color", **kwargs):
def datetime(entry, option_key="Datetime", account=None, from_tz=None, **kwargs): def datetime(entry, option_key="Datetime", account=None, from_tz=None, **kwargs):
""" """
Process a datetime string in standard forms while accounting for the inputer's timezone. Always Process a datetime string in standard forms while accounting for the
returns a result in UTC. inputer's timezone. Always returns a result in UTC.
Args: Args:
entry (str): A date string from a user. entry (str): A date string from a user.
@ -50,7 +50,7 @@ def datetime(entry, option_key="Datetime", account=None, from_tz=None, **kwargs)
account (AccountDB): The Account performing this lookup. Unless `from_tz` is provided, account (AccountDB): The Account performing this lookup. Unless `from_tz` is provided,
the account's timezone option will be used. the account's timezone option will be used.
from_tz (pytz.timezone): An instance of a pytz timezone object from the from_tz (pytz.timezone): An instance of a pytz timezone object from the
user. If not provided, tries to use the timezone option of the `account'. user. If not provided, tries to use the timezone option of `account`.
If neither one is provided, defaults to UTC. If neither one is provided, defaults to UTC.
Returns: Returns:
datetime in UTC. datetime in UTC.