mirror of
https://github.com/evennia/evennia.git
synced 2026-03-19 14:26:30 +01:00
Converted a large part of utils/ folder to google code docstrings as per #709.
This commit is contained in:
parent
fc4beed9ca
commit
eb2bd8d44c
17 changed files with 1107 additions and 406 deletions
|
|
@ -472,10 +472,10 @@ def _create_player(session, playername, password, permissions, typeclass=None):
|
|||
logger.log_trace()
|
||||
return False
|
||||
|
||||
# This needs to be called so the engine knows this player is
|
||||
# This needs to be set so the engine knows this player is
|
||||
# logging in for the first time. (so it knows to call the right
|
||||
# hooks during login later)
|
||||
utils.init_new_player(new_player)
|
||||
new_player.db.FIRST_LOGIN = True
|
||||
|
||||
# join the new player to the public channel
|
||||
pchannel = ChannelDB.objects.get_channel(settings.DEFAULT_CHANNELS[0]["key"])
|
||||
|
|
|
|||
|
|
@ -213,10 +213,10 @@ its and @/./+/-/_ only.") # this echoes the restrictions made by django's auth m
|
|||
logger.log_trace()
|
||||
return
|
||||
|
||||
# This needs to be called so the engine knows this player is
|
||||
# This needs to be set so the engine knows this player is
|
||||
# logging in for the first time. (so it knows to call the right
|
||||
# hooks during login later)
|
||||
utils.init_new_player(new_player)
|
||||
new_player.db.FIRST_LOGIN = True
|
||||
|
||||
# join the new player to the public channel
|
||||
pchanneldef = settings.CHANNEL_PUBLIC
|
||||
|
|
|
|||
|
|
@ -80,6 +80,13 @@ class ANSIParser(object):
|
|||
"""
|
||||
Replacer used by `re.sub` to replace ANSI
|
||||
markers with correct ANSI sequences
|
||||
|
||||
Args:
|
||||
ansimatch (re.matchobject): The match.
|
||||
|
||||
Returns:
|
||||
processed (str): The processed match string.
|
||||
|
||||
"""
|
||||
return self.ansi_map.get(ansimatch.group(), "")
|
||||
|
||||
|
|
@ -87,6 +94,13 @@ class ANSIParser(object):
|
|||
"""
|
||||
Replacer used by `re.sub` to replace ANSI
|
||||
bright background markers with Xterm256 replacement
|
||||
|
||||
Args:
|
||||
ansimatch (re.matchobject): The match.
|
||||
|
||||
Returns:
|
||||
processed (str): The processed match string.
|
||||
|
||||
"""
|
||||
return self.ansi_bright_bgs.get(ansimatch.group(), "")
|
||||
|
||||
|
|
@ -97,6 +111,14 @@ class ANSIParser(object):
|
|||
|
||||
It checks `self.do_xterm256` to determine if conversion
|
||||
to standard ANSI should be done or not.
|
||||
|
||||
Args:
|
||||
rgbmatch (re.matchobject): The match.
|
||||
convert (bool, optional): Convert 256-colors to 16.
|
||||
|
||||
Returns:
|
||||
processed (str): The processed match string.
|
||||
|
||||
"""
|
||||
if not rgbmatch:
|
||||
return ""
|
||||
|
|
@ -177,21 +199,43 @@ class ANSIParser(object):
|
|||
def strip_raw_codes(self, string):
|
||||
"""
|
||||
Strips raw ANSI codes from a string.
|
||||
|
||||
Args:
|
||||
string (str): The string to strip.
|
||||
|
||||
Returns:
|
||||
string (str): The processed string.
|
||||
|
||||
"""
|
||||
return self.ansi_regex.sub("", string)
|
||||
|
||||
def strip_mxp(self, string):
|
||||
"""
|
||||
Strips all MXP codes from a string.
|
||||
|
||||
Args:
|
||||
string (str): The string to strip.
|
||||
|
||||
Returns:
|
||||
string (str): The processed string.
|
||||
|
||||
"""
|
||||
return self.mxp_sub.sub(r'\2', string)
|
||||
|
||||
def parse_ansi(self, string, strip_ansi=False, xterm256=False, mxp=False):
|
||||
"""
|
||||
Parses a string, subbing color codes according to
|
||||
the stored mapping.
|
||||
Parses a string, subbing color codes according to the stored
|
||||
mapping.
|
||||
|
||||
strip_ansi flag instead removes all ANSI markup.
|
||||
Args:
|
||||
string (str): The string to parse.
|
||||
strip_ansi (boolean, optional): Strip all found ansi markup.
|
||||
xterm256 (boolean, optional): If actually using xterm256 or if
|
||||
these values should be converted to 16-color ANSI.
|
||||
mxp (boolean, optional): Parse MXP commands in string.
|
||||
|
||||
Returns:
|
||||
string (str): The parsed string.
|
||||
|
||||
"""
|
||||
if hasattr(string, '_raw_string'):
|
||||
|
|
@ -351,27 +395,57 @@ def parse_ansi(string, strip_ansi=False, parser=ANSI_PARSER, xterm256=False, mxp
|
|||
"""
|
||||
Parses a string, subbing color codes as needed.
|
||||
|
||||
Args:
|
||||
string (str): The string to parse.
|
||||
strip_ansi (bool, optional): Strip all ANSI sequences.
|
||||
parser (ansi.AnsiParser, optional): A parser instance to use.
|
||||
xterm256 (bool, optional): Support xterm256 or not.
|
||||
mxp (bool, optional): Support MXP markup or not.
|
||||
|
||||
Returns:
|
||||
string (str): The parsed string.
|
||||
|
||||
"""
|
||||
return parser.parse_ansi(string, strip_ansi=strip_ansi, xterm256=xterm256, mxp=mxp)
|
||||
|
||||
|
||||
def strip_ansi(string, parser=ANSI_PARSER):
|
||||
"""
|
||||
Strip all ansi from the string.
|
||||
Strip all ansi from the string. This handles the Evennia-specific
|
||||
markup.
|
||||
|
||||
Args:
|
||||
parser (ansi.AnsiParser, optional): The parser to use.
|
||||
|
||||
Returns:
|
||||
string (str): The stripped string.
|
||||
|
||||
"""
|
||||
return parser.parse_ansi(string, strip_ansi=True)
|
||||
|
||||
def strip_raw_ansi(string, parser=ANSI_PARSER):
|
||||
"""
|
||||
Remove raw ansi codes from string
|
||||
Remove raw ansi codes from string. This assumes pure
|
||||
ANSI-bytecodes in the string.
|
||||
|
||||
Args:
|
||||
string (str): The string to parse.
|
||||
parser (bool, optional): The parser to use.
|
||||
|
||||
Returns:
|
||||
string (str): the stripped string.
|
||||
"""
|
||||
return parser.strip_raw_codes(string)
|
||||
|
||||
|
||||
def raw(string):
|
||||
"""
|
||||
Escapes a string into a form which won't be colorized by the ansi parser.
|
||||
Escapes a string into a form which won't be colorized by the ansi
|
||||
parser.
|
||||
|
||||
Returns:
|
||||
string (str): The raw, escaped string.
|
||||
|
||||
"""
|
||||
return string.replace('{', '{{')
|
||||
|
||||
|
|
@ -385,8 +459,9 @@ def group(lst, n):
|
|||
|
||||
def _spacing_preflight(func):
|
||||
"""
|
||||
This wrapper function is used to do some preflight checks on functions used
|
||||
for padding ANSIStrings.
|
||||
This wrapper function is used to do some preflight checks on
|
||||
functions used for padding ANSIStrings.
|
||||
|
||||
"""
|
||||
def wrapped(self, width, fillchar=None):
|
||||
if fillchar is None:
|
||||
|
|
@ -404,8 +479,9 @@ def _spacing_preflight(func):
|
|||
|
||||
def _query_super(func_name):
|
||||
"""
|
||||
Have the string class handle this with the cleaned string instead of
|
||||
ANSIString.
|
||||
Have the string class handle this with the cleaned string instead
|
||||
of ANSIString.
|
||||
|
||||
"""
|
||||
def wrapped(self, *args, **kwargs):
|
||||
return getattr(self.clean(), func_name)(*args, **kwargs)
|
||||
|
|
@ -415,6 +491,7 @@ def _query_super(func_name):
|
|||
def _on_raw(func_name):
|
||||
"""
|
||||
Like query_super, but makes the operation run on the raw string.
|
||||
|
||||
"""
|
||||
def wrapped(self, *args, **kwargs):
|
||||
args = list(args)
|
||||
|
|
@ -439,6 +516,7 @@ def _transform(func_name):
|
|||
return a string the same length as the original. This function
|
||||
allows us to do the same, replacing all the non-coded characters
|
||||
with the resulting string.
|
||||
|
||||
"""
|
||||
def wrapped(self, *args, **kwargs):
|
||||
replacement_string = _query_super(func_name)(self, *args, **kwargs)
|
||||
|
|
@ -461,6 +539,7 @@ class ANSIMeta(type):
|
|||
"""
|
||||
Many functions on ANSIString are just light wrappers around the unicode
|
||||
base class. We apply them here, as part of the classes construction.
|
||||
|
||||
"""
|
||||
def __init__(cls, *args, **kwargs):
|
||||
for func_name in [
|
||||
|
|
@ -493,6 +572,7 @@ class ANSIString(unicode):
|
|||
|
||||
Please refer to the Metaclass, ANSIMeta, which is used to apply wrappers
|
||||
for several of the methods that need not be defined directly here.
|
||||
|
||||
"""
|
||||
__metaclass__ = ANSIMeta
|
||||
|
||||
|
|
@ -506,6 +586,7 @@ class ANSIString(unicode):
|
|||
Internally, ANSIString can also passes itself precached code/character
|
||||
indexes and clean strings to avoid doing extra work when combining
|
||||
ANSIStrings.
|
||||
|
||||
"""
|
||||
string = args[0]
|
||||
if not isinstance(string, basestring):
|
||||
|
|
@ -554,9 +635,11 @@ class ANSIString(unicode):
|
|||
|
||||
def __unicode__(self):
|
||||
"""
|
||||
Unfortunately, this is not called during print() statements due to a
|
||||
bug in the Python interpreter. You can always do unicode() or str()
|
||||
around the resulting ANSIString and print that.
|
||||
Unfortunately, this is not called during print() statements
|
||||
due to a bug in the Python interpreter. You can always do
|
||||
unicode() or str() around the resulting ANSIString and print
|
||||
that.
|
||||
|
||||
"""
|
||||
return self._raw_string
|
||||
|
||||
|
|
@ -564,6 +647,7 @@ class ANSIString(unicode):
|
|||
"""
|
||||
Let's make the repr the command that would actually be used to
|
||||
construct this object, for convenience and reference.
|
||||
|
||||
"""
|
||||
return "ANSIString(%s, decoded=True)" % repr(self._raw_string)
|
||||
|
||||
|
|
@ -592,6 +676,7 @@ class ANSIString(unicode):
|
|||
Finally, _code_indexes and _char_indexes are defined. These are lookup
|
||||
tables for which characters in the raw string are related to ANSI
|
||||
escapes, and which are for the readable text.
|
||||
|
||||
"""
|
||||
self.parser = kwargs.pop('parser', ANSI_PARSER)
|
||||
super(ANSIString, self).__init__()
|
||||
|
|
@ -603,6 +688,7 @@ class ANSIString(unicode):
|
|||
"""
|
||||
Takes a list of integers, and produces a new one incrementing all
|
||||
by a number.
|
||||
|
||||
"""
|
||||
return [i + offset for i in iterable]
|
||||
|
||||
|
|
@ -610,6 +696,7 @@ class ANSIString(unicode):
|
|||
def _adder(cls, first, second):
|
||||
"""
|
||||
Joins two ANSIStrings, preserving calculated info.
|
||||
|
||||
"""
|
||||
|
||||
raw_string = first._raw_string + second._raw_string
|
||||
|
|
@ -629,6 +716,7 @@ class ANSIString(unicode):
|
|||
We have to be careful when adding two strings not to reprocess things
|
||||
that don't need to be reprocessed, lest we end up with escapes being
|
||||
interpreted literally.
|
||||
|
||||
"""
|
||||
if not isinstance(other, basestring):
|
||||
return NotImplemented
|
||||
|
|
@ -639,6 +727,7 @@ class ANSIString(unicode):
|
|||
def __radd__(self, other):
|
||||
"""
|
||||
Likewise, if we're on the other end.
|
||||
|
||||
"""
|
||||
if not isinstance(other, basestring):
|
||||
return NotImplemented
|
||||
|
|
@ -650,6 +739,7 @@ class ANSIString(unicode):
|
|||
"""
|
||||
This function is deprecated, so we just make it call the proper
|
||||
function.
|
||||
|
||||
"""
|
||||
return self.__getitem__(slice(i, j))
|
||||
|
||||
|
|
@ -667,6 +757,7 @@ class ANSIString(unicode):
|
|||
indexes that need slicing in the raw string. We can check between
|
||||
those indexes to figure out what escape characters need to be
|
||||
replayed.
|
||||
|
||||
"""
|
||||
slice_indexes = self._char_indexes[slc]
|
||||
# If it's the end of the string, we need to append final color codes.
|
||||
|
|
@ -700,6 +791,7 @@ class ANSIString(unicode):
|
|||
this is a regexable ANSIString, it will get the data from the raw
|
||||
string instead, bypassing ANSIString's intelligent escape skipping,
|
||||
for reasons explained in the __new__ method's docstring.
|
||||
|
||||
"""
|
||||
if isinstance(item, slice):
|
||||
# Slices must be handled specially.
|
||||
|
|
@ -727,12 +819,14 @@ class ANSIString(unicode):
|
|||
def clean(self):
|
||||
"""
|
||||
Return a unicode object without the ANSI escapes.
|
||||
|
||||
"""
|
||||
return self._clean_string
|
||||
|
||||
def raw(self):
|
||||
"""
|
||||
Return a unicode object with the ANSI escapes.
|
||||
|
||||
"""
|
||||
return self._raw_string
|
||||
|
||||
|
|
@ -746,6 +840,7 @@ class ANSIString(unicode):
|
|||
|
||||
We use the same techniques we used in split() to make sure each are
|
||||
colored.
|
||||
|
||||
"""
|
||||
if hasattr(sep, '_clean_string'):
|
||||
sep = sep.clean()
|
||||
|
|
@ -776,6 +871,7 @@ class ANSIString(unicode):
|
|||
|
||||
It's possible that only one of these tables is actually needed, the
|
||||
other assumed to be what isn't in the first.
|
||||
|
||||
"""
|
||||
|
||||
code_indexes = []
|
||||
|
|
@ -792,6 +888,7 @@ class ANSIString(unicode):
|
|||
"""
|
||||
Get the code characters from the given slice end to the next
|
||||
character.
|
||||
|
||||
"""
|
||||
try:
|
||||
index = self._char_indexes[index - 1]
|
||||
|
|
@ -815,6 +912,7 @@ class ANSIString(unicode):
|
|||
|
||||
PyPy is distributed under the MIT licence.
|
||||
http://opensource.org/licenses/MIT
|
||||
|
||||
"""
|
||||
bylen = len(by)
|
||||
if bylen == 0:
|
||||
|
|
@ -837,6 +935,7 @@ class ANSIString(unicode):
|
|||
def __mul__(self, other):
|
||||
"""
|
||||
Multiplication method. Implemented for performance reasons.
|
||||
|
||||
"""
|
||||
if not isinstance(other, int):
|
||||
return NotImplemented
|
||||
|
|
@ -863,6 +962,7 @@ class ANSIString(unicode):
|
|||
|
||||
PyPy is distributed under the MIT licence.
|
||||
http://opensource.org/licenses/MIT
|
||||
|
||||
"""
|
||||
res = []
|
||||
end = len(self)
|
||||
|
|
@ -886,6 +986,7 @@ class ANSIString(unicode):
|
|||
def join(self, iterable):
|
||||
"""
|
||||
Joins together strings in an iterable.
|
||||
|
||||
"""
|
||||
result = ANSIString('')
|
||||
last_item = None
|
||||
|
|
@ -902,6 +1003,7 @@ class ANSIString(unicode):
|
|||
"""
|
||||
Generate a line of characters in a more efficient way than just adding
|
||||
ANSIStrings.
|
||||
|
||||
"""
|
||||
if not isinstance(char, ANSIString):
|
||||
line = char * amount
|
||||
|
|
@ -929,6 +1031,7 @@ class ANSIString(unicode):
|
|||
def center(self, width, fillchar, difference):
|
||||
"""
|
||||
Center some text with some spaces padding both sides.
|
||||
|
||||
"""
|
||||
remainder = difference % 2
|
||||
difference /= 2
|
||||
|
|
@ -940,6 +1043,7 @@ class ANSIString(unicode):
|
|||
def ljust(self, width, fillchar, difference):
|
||||
"""
|
||||
Left justify some text.
|
||||
|
||||
"""
|
||||
return self + self._filler(fillchar, difference)
|
||||
|
||||
|
|
@ -947,5 +1051,6 @@ class ANSIString(unicode):
|
|||
def rjust(self, width, fillchar, difference):
|
||||
"""
|
||||
Right justify some text.
|
||||
|
||||
"""
|
||||
return self._filler(fillchar, difference) + self
|
||||
|
|
|
|||
|
|
@ -192,13 +192,23 @@ RE_CODE_SPLIT = re.compile(r"(^\#CODE.*?$|^\#HEADER)$", re.MULTILINE)
|
|||
|
||||
def read_batchfile(pythonpath, file_ending='.py'):
|
||||
"""
|
||||
This reads the contents of a batch-file.
|
||||
Filename is considered to be a python path to a batch file
|
||||
relative the directory specified in `settings.py`.
|
||||
This reads the contents of a batch-file. Filename is considered
|
||||
to be a python path to a batch file relative the directory
|
||||
specified in `settings.py`.
|
||||
|
||||
file_ending specify which batchfile ending should be assumed (.ev
|
||||
or .py). The ending should not be included in the python path.
|
||||
|
||||
Args:
|
||||
pythonpath (str): A dot-python path to a file.
|
||||
file_ending (str): The file ending of this file (.ev or .py)
|
||||
|
||||
Returns:
|
||||
text (str): The text content of the batch file.
|
||||
|
||||
Raises:
|
||||
IOError: If problems reading file.
|
||||
|
||||
file_ending specify which batchfile ending should be
|
||||
assumed (.ev or .py). The ending should not be included
|
||||
in the python path.
|
||||
"""
|
||||
|
||||
# open the file
|
||||
|
|
@ -293,6 +303,7 @@ def tb_filename(tb):
|
|||
|
||||
|
||||
def tb_iter(tb):
|
||||
"Traceback iterator."
|
||||
while tb is not None:
|
||||
yield tb
|
||||
tb = tb.tb_next
|
||||
|
|
@ -309,13 +320,22 @@ class BatchCodeProcessor(object):
|
|||
This parses the lines of a batchfile according to the following
|
||||
rules:
|
||||
|
||||
1) Lines starting with #HEADER starts a header block (ends other blocks)
|
||||
2) Lines starting with #CODE begins a code block (ends other blocks)
|
||||
3) #CODE headers may be of the following form:
|
||||
#CODE (info) objname, objname2, ...
|
||||
4) Lines starting with #INSERT are on form #INSERT filename.
|
||||
5) All lines outside blocks are stripped.
|
||||
6) All excess whitespace beginning/ending a block is stripped.
|
||||
Args:
|
||||
pythonpath (str): The dot-python path to the file.
|
||||
debug (bool, optional): Insert delete-commands for
|
||||
deleting created objects.
|
||||
|
||||
Returns:
|
||||
codeblocks (list): A list of all #CODE blocks.
|
||||
|
||||
Notes:
|
||||
1. Lines starting with #HEADER starts a header block (ends other blocks)
|
||||
2. Lines starting with #CODE begins a code block (ends other blocks)
|
||||
3. #CODE headers may be of the following form:
|
||||
#CODE (info) objname, objname2, ...
|
||||
4. Lines starting with #INSERT are on form #INSERT filename.
|
||||
5. All lines outside blocks are stripped.
|
||||
6. All excess whitespace beginning/ending a block is stripped.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -373,9 +393,17 @@ class BatchCodeProcessor(object):
|
|||
|
||||
def code_exec(self, code, extra_environ=None, debug=False):
|
||||
"""
|
||||
Execute a single code block, including imports and appending global vars
|
||||
Execute a single code block, including imports and appending
|
||||
global vars.
|
||||
|
||||
Args:
|
||||
code (str): Code to run.
|
||||
extra_environ (dict): Environment variables to run with code.
|
||||
debug (bool, optional): Insert delete statements for objects.
|
||||
|
||||
Returns:
|
||||
err (str or None): An error code or None (ok).
|
||||
|
||||
extra_environ - dict with environment variables
|
||||
"""
|
||||
# define the execution environment
|
||||
environdict = {"settings_module": settings}
|
||||
|
|
|
|||
|
|
@ -59,24 +59,35 @@ def create_object(typeclass=None, key=None, location=None,
|
|||
|
||||
Create a new in-game object.
|
||||
|
||||
keywords:
|
||||
typeclass - class or python path to a typeclass
|
||||
key - name of the new object. If not set, a name of #dbref will be set.
|
||||
home - obj or #dbref to use as the object's home location
|
||||
permissions - a comma-separated string of permissions
|
||||
locks - one or more lockstrings, separated by semicolons
|
||||
aliases - a list of alternative keys
|
||||
tags - a list of tag keys (using no category)
|
||||
destination - obj or #dbref to use as an Exit's target
|
||||
Kwargs:
|
||||
typeclass (class or str): Class or python path to a typeclass.
|
||||
key (str): Name of the new object. If not set, a name of
|
||||
#dbref will be set.
|
||||
home (Object or str): Obj or #dbref to use as the object's
|
||||
home location.
|
||||
permissions (str): A comma-separated string of permissions.
|
||||
locks (str): one or more lockstrings, separated by semicolons.
|
||||
aliases (list): A list of alternative keys.
|
||||
tags (list): List of tag keys (using no category).
|
||||
destination (Object or str): Obj or #dbref to use as an Exit's
|
||||
target.
|
||||
report_to (Object): The object to return error messages to.
|
||||
nohome (bool): This allows the creation of objects without a
|
||||
default home location; only used when creating the default
|
||||
location itself or during unittests.
|
||||
|
||||
Returns:
|
||||
object (Object): A newly created object of the given typeclass.
|
||||
|
||||
Raises:
|
||||
ObjectDB.DoesNotExist: If trying to create an Object with
|
||||
`location` or `home` that can't be found.
|
||||
|
||||
nohome - this allows the creation of objects without a default home location;
|
||||
only used when creating the default location itself or during unittests
|
||||
"""
|
||||
global _ObjectDB
|
||||
if not _ObjectDB:
|
||||
from evennia.objects.models import ObjectDB as _ObjectDB
|
||||
|
||||
|
||||
typeclass = typeclass if typeclass else settings.BASE_OBJECT_TYPECLASS
|
||||
|
||||
if isinstance(typeclass, basestring):
|
||||
|
|
@ -120,32 +131,42 @@ object = create_object
|
|||
# Script creation
|
||||
#
|
||||
|
||||
def create_script(typeclass, key=None, obj=None, player=None, locks=None,
|
||||
def create_script(typeclass=None, key=None, obj=None, player=None, locks=None,
|
||||
interval=None, start_delay=None, repeats=None,
|
||||
persistent=None, autostart=True, report_to=None):
|
||||
"""
|
||||
Create a new script. All scripts are a combination
|
||||
of a database object that communicates with the
|
||||
database, and an typeclass that 'decorates' the
|
||||
database object into being different types of scripts.
|
||||
It's behaviour is similar to the game objects except
|
||||
scripts has a time component and are more limited in
|
||||
scope.
|
||||
Create a new script. All scripts are a combination of a database
|
||||
object that communicates with the database, and an typeclass that
|
||||
'decorates' the database object into being different types of
|
||||
scripts. It's behaviour is similar to the game objects except
|
||||
scripts has a time component and are more limited in scope.
|
||||
|
||||
Kwargs:
|
||||
typeclass (class or str): Class or python path to a typeclass.
|
||||
key (str): Name of the new object. If not set, a name of
|
||||
#dbref will be set.
|
||||
obj (Object): The entity on which this Script sits. If this
|
||||
is `None`, we are creating a "global" script.
|
||||
player (Player): The player on which this Script sits. It is
|
||||
exclusiv to `obj`.
|
||||
locks (str): one or more lockstrings, separated by semicolons.
|
||||
interval (int): The triggering interval for this Script, in
|
||||
seconds. If unset, the Script will not have a timing
|
||||
component.
|
||||
start_delay (bool): If `True`, will wait `interval` seconds
|
||||
before triggering the first time.
|
||||
repeats (int): The number of times to trigger before stopping.
|
||||
If unset, will repeat indefinitely.
|
||||
persistent (bool): If this Script survives a server shutdown
|
||||
or not (all Scripts will survive a reload).
|
||||
autostart (bool): If this Script will start immediately when
|
||||
created or if the `start` method must be called explicitly.
|
||||
report_to (Object): The object to return error messages to.
|
||||
|
||||
Argument 'typeclass' can be either an actual
|
||||
typeclass object or a python path to such an object.
|
||||
Only set key here if you want a unique name for this
|
||||
particular script (set it in config to give
|
||||
same key to all scripts of the same type). Set obj
|
||||
to tie this script to a particular object.
|
||||
|
||||
See evennia.scripts.manager for methods to manipulate existing
|
||||
scripts in the database.
|
||||
|
||||
report_to is an obtional object to receive error messages.
|
||||
If report_to is not set, an Exception with the
|
||||
error will be raised. If set, this method will
|
||||
return None upon errors.
|
||||
"""
|
||||
global _ScriptDB
|
||||
if not _ScriptDB:
|
||||
|
|
@ -194,10 +215,20 @@ script = create_script
|
|||
def create_help_entry(key, entrytext, category="General", locks=None):
|
||||
"""
|
||||
Create a static help entry in the help database. Note that Command
|
||||
help entries are dynamic and directly taken from the __doc__ entries
|
||||
of the command. The database-stored help entries are intended for more
|
||||
general help on the game, more extensive info, in-game setting information
|
||||
and so on.
|
||||
help entries are dynamic and directly taken from the __doc__
|
||||
entries of the command. The database-stored help entries are
|
||||
intended for more general help on the game, more extensive info,
|
||||
in-game setting information and so on.
|
||||
|
||||
Args:
|
||||
key (str): The name of the help entry.
|
||||
entrytext (str): The body of te help entry
|
||||
category (str, optional): The help category of the entry.
|
||||
locks (str, optional): A lockstring to restrict access.
|
||||
|
||||
Returns:
|
||||
help (HelpEntry): A newly created help entry.
|
||||
|
||||
"""
|
||||
global _HelpEntry
|
||||
if not _HelpEntry:
|
||||
|
|
@ -230,24 +261,28 @@ help_entry = create_help_entry
|
|||
def create_message(senderobj, message, channels=None,
|
||||
receivers=None, locks=None, header=None):
|
||||
"""
|
||||
Create a new communication message. Msgs are used for all
|
||||
player-to-player communication, both between individual players
|
||||
and over channels.
|
||||
senderobj - the player sending the message. This must be the actual object.
|
||||
message - text with the message. Eventual headers, titles etc
|
||||
should all be included in this text string. Formatting
|
||||
will be retained.
|
||||
channels - a channel or a list of channels to send to. The channels
|
||||
may be actual channel objects or their unique key strings.
|
||||
receivers - a player to send to, or a list of them. May be Player objects
|
||||
or playernames.
|
||||
locks - lock definition string
|
||||
header - mime-type or other optional information for the message
|
||||
Create a new communication Msg. Msgs represent a unit of
|
||||
database-persistent communication between entites.
|
||||
|
||||
Args:
|
||||
senderobj (Object or Player): The entity sending the Msg.
|
||||
message (str): Text with the message. Eventual headers, titles
|
||||
etc should all be included in this text string. Formatting
|
||||
will be retained.
|
||||
channels (Channel, key or list): A channel or a list of channels to
|
||||
send to. The channels may be actual channel objects or their
|
||||
unique key strings.
|
||||
receivers (Object, Player, str or list): A Player/Object to send
|
||||
to, or a list of them. May be Player objects or playernames.
|
||||
locks (str): Lock definition string.
|
||||
header (str): Mime-type or other optional information for the message
|
||||
|
||||
Notes:
|
||||
The Comm system is created very open-ended, so it's fully possible
|
||||
to let a message both go to several channels and to several
|
||||
receivers at the same time, it's up to the command definitions to
|
||||
limit this as desired.
|
||||
|
||||
The Comm system is created very open-ended, so it's fully possible
|
||||
to let a message both go to several channels and to several receivers
|
||||
at the same time, it's up to the command definitions to limit this as
|
||||
desired.
|
||||
"""
|
||||
global _Msg
|
||||
if not _Msg:
|
||||
|
|
@ -275,16 +310,27 @@ def create_channel(key, aliases=None, desc=None,
|
|||
locks=None, keep_log=True,
|
||||
typeclass=None):
|
||||
"""
|
||||
Create A communication Channel. A Channel serves as a central
|
||||
hub for distributing Msgs to groups of people without
|
||||
specifying the receivers explicitly. Instead players may
|
||||
'connect' to the channel and follow the flow of messages. By
|
||||
default the channel allows access to all old messages, but
|
||||
this can be turned off with the keep_log switch.
|
||||
Create A communication Channel. A Channel serves as a central hub
|
||||
for distributing Msgs to groups of people without specifying the
|
||||
receivers explicitly. Instead players may 'connect' to the channel
|
||||
and follow the flow of messages. By default the channel allows
|
||||
access to all old messages, but this can be turned off with the
|
||||
keep_log switch.
|
||||
|
||||
Args:
|
||||
key (str): This must be unique.
|
||||
|
||||
Kwargs:
|
||||
aliases (list): List of alternative (likely shorter) keynames.
|
||||
desc (str): A description of the channel, for use in listings.
|
||||
locks (str): Lockstring.
|
||||
keep_log (bool): Log channel throughput.
|
||||
typeclass (str or class): The typeclass of the Channel (not
|
||||
often used).
|
||||
|
||||
Returns:
|
||||
channel (Channel): A newly created channel.
|
||||
|
||||
key - this must be unique.
|
||||
aliases - list of alternative (likely shorter) keynames.
|
||||
locks - lock string definitions
|
||||
"""
|
||||
typeclass = typeclass if typeclass else settings.BASE_CHANNEL_TYPECLASS
|
||||
|
||||
|
|
@ -322,23 +368,28 @@ def create_player(key, email, password,
|
|||
"""
|
||||
This creates a new player.
|
||||
|
||||
key - the player's name. This should be unique.
|
||||
email - email on valid addr@addr.domain form.
|
||||
password - password in cleartext
|
||||
is_superuser - wether or not this player is to be a superuser
|
||||
locks - lockstring
|
||||
permission - list of permissions
|
||||
report_to - an object with a msg() method to report errors to. If
|
||||
not given, errors will be logged.
|
||||
Args:
|
||||
key (str): The player's name. This should be unique.
|
||||
email (str): Email on valid addr@addr.domain form. This is
|
||||
technically required but if set to `None`, an email of
|
||||
`dummy@dummy.com` will be used as a placeholder.
|
||||
password (str): Password in cleartext.
|
||||
|
||||
Will return the Player-typeclass or None/raise Exception if the
|
||||
Typeclass given failed to load.
|
||||
Kwargs:
|
||||
is_superuser (bool): Wether or not this player is to be a superuser
|
||||
locks (str): Lockstring.
|
||||
permission (list): List of permission strings.
|
||||
report_to (Object): An object with a msg() method to report
|
||||
errors to. If not given, errors will be logged.
|
||||
|
||||
Concerning is_superuser:
|
||||
Usually only the server admin should need to be superuser, all
|
||||
other access levels can be handled with more fine-grained
|
||||
permissions or groups. A superuser bypasses all lock checking
|
||||
operations and is thus not suitable for play-testing the game.
|
||||
Raises:
|
||||
ValueError: If `key` already exists in database.
|
||||
|
||||
Notes:
|
||||
Usually only the server admin should need to be superuser, all
|
||||
other access levels can be handled with more fine-grained
|
||||
permissions or groups. A superuser bypasses all lock checking
|
||||
operations and is thus not suitable for play-testing the game.
|
||||
|
||||
"""
|
||||
global _PlayerDB
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ try:
|
|||
from cPickle import dumps, loads
|
||||
except ImportError:
|
||||
from pickle import dumps, loads
|
||||
from django.db import transaction
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from evennia.server.models import ServerConfig
|
||||
|
|
@ -52,8 +51,14 @@ else:
|
|||
|
||||
def _TO_DATESTRING(obj):
|
||||
"""
|
||||
this will only be called with valid database objects. Returns datestring
|
||||
on correct form.
|
||||
Creates datestring hash.
|
||||
|
||||
Args:
|
||||
obj (Object): Database object.
|
||||
|
||||
Returns:
|
||||
datestring (str): A datestring hash.
|
||||
|
||||
"""
|
||||
try:
|
||||
return _GA(obj, "db_date_created").strftime(_DATESTRING)
|
||||
|
|
@ -209,8 +214,14 @@ class _SaverSet(_SaverMutable, MutableSet):
|
|||
def pack_dbobj(item):
|
||||
"""
|
||||
Check and convert django database objects to an internal representation.
|
||||
This either returns the original input item or a tuple
|
||||
("__packed_dbobj__", key, creation_time, id)
|
||||
|
||||
Args:
|
||||
item (any): A database entity to pack
|
||||
|
||||
Returns:
|
||||
packed (any or tuple): Either returns the original input item
|
||||
or the packing tuple `("__packed_dbobj__", key, creation_time, id)`.
|
||||
|
||||
"""
|
||||
_init_globals()
|
||||
obj = item
|
||||
|
|
@ -224,10 +235,18 @@ def pack_dbobj(item):
|
|||
|
||||
def unpack_dbobj(item):
|
||||
"""
|
||||
Check and convert internal representations back to Django database models.
|
||||
The fact that item is a packed dbobj should be checked before this call.
|
||||
This either returns the original input or converts the internal store back
|
||||
to a database representation (its typeclass is returned if applicable).
|
||||
Check and convert internal representations back to Django database
|
||||
models.
|
||||
|
||||
Args:
|
||||
item (packed_dbobj): The fact that item is a packed dbobj
|
||||
should be checked before this call.
|
||||
|
||||
Returns:
|
||||
unpacked (any): Either the original input or converts the
|
||||
internal store back to a database representation (its
|
||||
typeclass is returned if applicable).
|
||||
|
||||
"""
|
||||
_init_globals()
|
||||
try:
|
||||
|
|
@ -244,11 +263,18 @@ def unpack_dbobj(item):
|
|||
|
||||
def to_pickle(data):
|
||||
"""
|
||||
This prepares data on arbitrary form to be pickled. It handles any nested
|
||||
structure and returns data on a form that is safe to pickle (including
|
||||
having converted any database models to their internal representation).
|
||||
We also convert any Saver*-type objects back to their normal
|
||||
representations, they are not pickle-safe.
|
||||
This prepares data on arbitrary form to be pickled. It handles any
|
||||
nested structure and returns data on a form that is safe to pickle
|
||||
(including having converted any database models to their internal
|
||||
representation). We also convert any Saver*-type objects back to
|
||||
their normal representations, they are not pickle-safe.
|
||||
|
||||
Args:
|
||||
data (any): Data to pickle.
|
||||
|
||||
Returns:
|
||||
data (any): Pickled data.
|
||||
|
||||
"""
|
||||
def process_item(item):
|
||||
"Recursive processor and identification of data"
|
||||
|
|
@ -281,13 +307,18 @@ def from_pickle(data, db_obj=None):
|
|||
object was removed (or changed in-place) in the database, None will be
|
||||
returned.
|
||||
|
||||
db_obj - this is the model instance (normally an Attribute) that
|
||||
_Saver*-type iterables (_SaverList etc) will save to when they
|
||||
update. It must have a 'value' property that saves assigned data
|
||||
to the database. Skip if not serializing onto a given object.
|
||||
Args_
|
||||
data (any): Pickled data to unpickle.
|
||||
db_obj (Atribute, any): This is the model instance (normally
|
||||
an Attribute) that _Saver*-type iterables (_SaverList etc)
|
||||
will save to when they update. It must have a 'value' property
|
||||
that saves assigned data to the database. Skip if not
|
||||
serializing onto a given object. If db_obj is given, this
|
||||
function will convert lists, dicts and sets to their
|
||||
_SaverList, _SaverDict and _SaverSet counterparts.
|
||||
|
||||
If db_obj is given, this function will convert lists, dicts and sets
|
||||
to their _SaverList, _SaverDict and _SaverSet counterparts.
|
||||
Returns:
|
||||
data (any): Unpickled data.
|
||||
|
||||
"""
|
||||
def process_item(item):
|
||||
|
|
|
|||
|
|
@ -631,7 +631,9 @@ class EvEditor(object):
|
|||
|
||||
def get_buffer(self):
|
||||
"""
|
||||
Return the current buffer
|
||||
Return:
|
||||
buffer (str): The current buffer.
|
||||
|
||||
"""
|
||||
return self._buffer
|
||||
|
||||
|
|
@ -639,6 +641,10 @@ class EvEditor(object):
|
|||
"""
|
||||
This should be called when the buffer has been changed
|
||||
somehow. It will handle unsaved flag and undo updating.
|
||||
|
||||
Args:
|
||||
buf (str): The text to update the buffer with.
|
||||
|
||||
"""
|
||||
if is_iter(buf):
|
||||
buf = "\n".join(buf)
|
||||
|
|
@ -651,6 +657,7 @@ class EvEditor(object):
|
|||
def quit(self):
|
||||
"""
|
||||
Cleanly exit the editor.
|
||||
|
||||
"""
|
||||
try:
|
||||
self._quitfunc(self._caller)
|
||||
|
|
@ -663,6 +670,7 @@ class EvEditor(object):
|
|||
"""
|
||||
Saves the content of the buffer. The 'quitting' argument is a bool
|
||||
indicating whether or not the editor intends to exit after saving.
|
||||
|
||||
"""
|
||||
if self._unsaved:
|
||||
try:
|
||||
|
|
@ -680,6 +688,12 @@ class EvEditor(object):
|
|||
"""
|
||||
This updates the undo position.
|
||||
|
||||
Args:
|
||||
step (int, optional): The amount of steps
|
||||
to progress the undo position to. This
|
||||
may be a negative value for undo and
|
||||
a positive value for redo.
|
||||
|
||||
"""
|
||||
if step and step < 0:
|
||||
# undo
|
||||
|
|
@ -706,8 +720,15 @@ class EvEditor(object):
|
|||
"""
|
||||
This displays the line editor buffer, or selected parts of it.
|
||||
|
||||
If `buf` is set and is not the full buffer, `offset` should define
|
||||
the starting line number, to get the linenum display right.
|
||||
Args:
|
||||
buf (str, optional): The buffer or part of buffer to display.
|
||||
offset (int, optional): If `buf` is set and is not the full buffer,
|
||||
`offset` should define the actual starting line number, to
|
||||
get the linenum display right.
|
||||
linenums (bool, optional): Show line numbers in buffer.
|
||||
raw (bool, optional): Tell protocol to not parse
|
||||
formatting information.
|
||||
|
||||
"""
|
||||
if buf == None:
|
||||
buf = self._buffer
|
||||
|
|
@ -733,6 +754,7 @@ class EvEditor(object):
|
|||
def display_help(self):
|
||||
"""
|
||||
Shows the help entry for the editor.
|
||||
|
||||
"""
|
||||
string = self._sep * _DEFAULT_WIDTH + _HELP_TEXT + self._sep * _DEFAULT_WIDTH
|
||||
self._caller.msg(string)
|
||||
|
|
|
|||
|
|
@ -168,17 +168,17 @@ class EvForm(object):
|
|||
"""
|
||||
Initiate the form
|
||||
|
||||
keywords:
|
||||
filename - path to template file
|
||||
form - dictionary of {"CELLCHAR":char,
|
||||
"TABLECHAR":char,
|
||||
"FORM":templatestring}
|
||||
Kwargs:
|
||||
filename (str): Path to template file.
|
||||
cells (dict): A dictionary mapping of {id:text}
|
||||
tables (dict): A dictionary mapping of {id:EvTable}.
|
||||
form (dict): A dictionary of {"CELLCHAR":char,
|
||||
"TABLECHAR":char,
|
||||
"FORM":templatestring}
|
||||
if this is given, filename is not read.
|
||||
cells - a dictionary mapping of {id:text}
|
||||
tables - dictionary mapping of {id:EvTable}
|
||||
|
||||
other kwargs are fed as options to the EvCells and EvTables
|
||||
(see `evtable.EvCell` and `evtable.EvTable` for more info).
|
||||
Notes:
|
||||
Other kwargs are fed as options to the EvCells and EvTables
|
||||
(see `evtable.EvCell` and `evtable.EvTable` for more info).
|
||||
|
||||
"""
|
||||
self.filename = filename
|
||||
|
|
@ -204,8 +204,9 @@ class EvForm(object):
|
|||
|
||||
def _parse_rectangles(self, cellchar, tablechar, form, **kwargs):
|
||||
"""
|
||||
Parse a form for rectangular formfields identified by
|
||||
formchar enclosing an identifier.
|
||||
Parse a form for rectangular formfields identified by formchar
|
||||
enclosing an identifier.
|
||||
|
||||
"""
|
||||
|
||||
# update options given at creation with new input - this
|
||||
|
|
@ -337,6 +338,7 @@ class EvForm(object):
|
|||
def _populate_form(self, raw_form, mapping):
|
||||
"""
|
||||
Insert cell contents into form at given locations
|
||||
|
||||
"""
|
||||
form = copy.copy(raw_form)
|
||||
for key, (iy0, ix0, width, height, cell_or_table) in mapping.items():
|
||||
|
|
@ -352,11 +354,13 @@ class EvForm(object):
|
|||
"""
|
||||
Add mapping for form.
|
||||
|
||||
cells - a dictionary of {identifier:celltext}
|
||||
tables - a dictionary of {identifier:table}
|
||||
Args:
|
||||
cells (dict): A dictionary of {identifier:celltext}
|
||||
tables (dict): A dictionary of {identifier:table}
|
||||
|
||||
kwargs will be forwarded to tables/cells. See
|
||||
evtable.EvCell and evtable.EvTable for info.
|
||||
Notes:
|
||||
kwargs will be forwarded to tables/cells. See
|
||||
`evtable.EvCell` and `evtable.EvTable` for info.
|
||||
|
||||
"""
|
||||
# clean kwargs (these cannot be overridden)
|
||||
|
|
@ -373,7 +377,15 @@ class EvForm(object):
|
|||
|
||||
def reload(self, filename=None, form=None, **kwargs):
|
||||
"""
|
||||
Creates the form from a stored file name
|
||||
Creates the form from a stored file name.
|
||||
|
||||
Args:
|
||||
filename (str): The file to read from.
|
||||
form (dict): A mapping for the form.
|
||||
|
||||
Notes:
|
||||
Kwargs are passed through to Cel creation.
|
||||
|
||||
"""
|
||||
# clean kwargs (these cannot be overridden)
|
||||
kwargs.pop("enforce_size", None)
|
||||
|
|
|
|||
|
|
@ -65,21 +65,52 @@ def _format(seconds, *divisors) :
|
|||
# Access functions
|
||||
|
||||
def runtime(format=False):
|
||||
"Get the total runtime of the server since first start (minus downtimes)"
|
||||
"""
|
||||
Get the total runtime of the server since first start (minus
|
||||
downtimes)
|
||||
|
||||
Args:
|
||||
format (bool, optional): Format into a time representation.
|
||||
|
||||
Returns:
|
||||
time (float or tuple): The runtime or the same time split up
|
||||
into time units.
|
||||
|
||||
"""
|
||||
runtime = SERVER_RUNTIME + (time() - SERVER_RUNTIME_LAST_UPDATED)
|
||||
if format:
|
||||
return _format(runtime, 31536000, 2628000, 604800, 86400, 3600, 60)
|
||||
return runtime
|
||||
|
||||
def uptime(format=False):
|
||||
"Get the current uptime of the server since last reload"
|
||||
"""
|
||||
Get the current uptime of the server since last reload
|
||||
|
||||
Args:
|
||||
format (bool, optional): Format into time representation.
|
||||
|
||||
Returns:
|
||||
time (float or tuple): The uptime or the same time split up
|
||||
into time units.
|
||||
|
||||
"""
|
||||
uptime = time() - SERVER_START_TIME
|
||||
if format:
|
||||
return _format(uptime, 31536000, 2628000, 604800, 86400, 3600, 60)
|
||||
return uptime
|
||||
|
||||
def gametime(format=False):
|
||||
"Get the total gametime of the server since first start (minus downtimes)"
|
||||
"""
|
||||
Get the total gametime of the server since first start (minus downtimes)
|
||||
|
||||
Args:
|
||||
format (bool, optional): Format into time representation.
|
||||
|
||||
Returns:
|
||||
time (float or tuple): The gametime or the same time split up
|
||||
into time units.
|
||||
|
||||
"""
|
||||
gametime = runtime() * TIMEFACTOR
|
||||
if format:
|
||||
return _format(gametime, YEAR, MONTH, WEEK, DAY, HOUR, MIN)
|
||||
|
|
@ -94,9 +125,18 @@ def gametime_to_realtime(secs=0, mins=0, hrs=0, days=0,
|
|||
in-game, you will be able to find the number of real-world seconds this
|
||||
corresponds to (hint: Interval events deal with real life seconds).
|
||||
|
||||
Kwargs:
|
||||
times (int): The various components of the time.
|
||||
format (bool): Formatting the output.
|
||||
|
||||
Returns:
|
||||
time (float or tuple): The realtime difference or the same
|
||||
time split up into time units.
|
||||
|
||||
Example:
|
||||
gametime_to_realtime(days=2) -> number of seconds in real life from
|
||||
now after which 2 in-game days will have passed.
|
||||
gametime_to_realtime(days=2) -> number of seconds in real life from
|
||||
now after which 2 in-game days will have passed.
|
||||
|
||||
"""
|
||||
realtime = (secs + mins * MIN + hrs * HOUR + days * DAY + weeks * WEEK + \
|
||||
months * MONTH + yrs * YEAR) / TIMEFACTOR
|
||||
|
|
@ -109,12 +149,21 @@ def realtime_to_gametime(secs=0, mins=0, hrs=0, days=0,
|
|||
weeks=0, months=0, yrs=0, format=False):
|
||||
"""
|
||||
This method calculates how much in-game time a real-world time
|
||||
interval would correspond to. This is usually a lot less interesting
|
||||
than the other way around.
|
||||
interval would correspond to. This is usually a lot less
|
||||
interesting than the other way around.
|
||||
|
||||
Kwargs:
|
||||
times (int): The various components of the time.
|
||||
format (bool): Formatting the output.
|
||||
|
||||
Returns:
|
||||
time (float or tuple): The gametime difference or the same
|
||||
time split up into time units.
|
||||
|
||||
Example:
|
||||
realtime_to_gametime(days=2) -> number of game-world seconds
|
||||
corresponding to 2 real days.
|
||||
|
||||
"""
|
||||
gametime = TIMEFACTOR * (secs + mins * 60 + hrs * 3600 + days * 86400 +
|
||||
weeks * 604800 + months * 2628000 + yrs * 31536000)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ class SharedMemoryManager(Manager):
|
|||
# still use the singleton cache, but the active model isn't required
|
||||
# to be a SharedMemoryModel.
|
||||
def get(self, **kwargs):
|
||||
"""
|
||||
Data entity lookup.
|
||||
"""
|
||||
items = kwargs.keys()
|
||||
inst = None
|
||||
if len(items) == 1:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from django.db.models.signals import post_save
|
|||
from django.db.models.base import Model, ModelBase
|
||||
from django.db.models.signals import pre_delete, post_syncdb
|
||||
from evennia.utils import logger
|
||||
from evennia.utils.utils import dbref, get_evennia_pids, to_str,calledby
|
||||
from evennia.utils.utils import dbref, get_evennia_pids, to_str
|
||||
|
||||
from manager import SharedMemoryManager
|
||||
|
||||
|
|
@ -53,6 +53,7 @@ class SharedMemoryModelBase(ModelBase):
|
|||
or try to retrieve one from the class-wide cache by inferring the pk value from
|
||||
`args` and `kwargs`. If instance caching is enabled for this class, the cache is
|
||||
populated whenever possible (ie when it is possible to infer the pk value).
|
||||
|
||||
"""
|
||||
def new_instance():
|
||||
return super(SharedMemoryModelBase, cls).__call__(*args, **kwargs)
|
||||
|
|
@ -75,6 +76,7 @@ class SharedMemoryModelBase(ModelBase):
|
|||
"""
|
||||
Prepare the cache, making sure that proxies of the same db base
|
||||
share the same cache.
|
||||
|
||||
"""
|
||||
# the dbmodel is either the proxy base or ourselves
|
||||
dbmodel = cls._meta.proxy_for_model if cls._meta.proxy else cls
|
||||
|
|
@ -89,15 +91,17 @@ class SharedMemoryModelBase(ModelBase):
|
|||
"""
|
||||
Field shortcut creation:
|
||||
|
||||
Takes field names `db_*` and creates property wrappers named without the
|
||||
`db_` prefix. So db_key -> key
|
||||
Takes field names `db_*` and creates property wrappers named
|
||||
without the `db_` prefix. So db_key -> key
|
||||
|
||||
This wrapper happens on the class level, so there is no overhead when creating objects.
|
||||
If a class already has a wrapper of the given name, the automatic creation is skipped.
|
||||
This wrapper happens on the class level, so there is no
|
||||
overhead when creating objects. If a class already has a
|
||||
wrapper of the given name, the automatic creation is skipped.
|
||||
|
||||
Notes:
|
||||
Remember to document this auto-wrapping in the class header, this could seem very
|
||||
much like magic to the user otherwise.
|
||||
Remember to document this auto-wrapping in the class
|
||||
header, this could seem very much like magic to the user
|
||||
otherwise.
|
||||
"""
|
||||
|
||||
attrs["typename"] = cls.__name__
|
||||
|
|
@ -218,8 +222,10 @@ class SharedMemoryModel(Model):
|
|||
@classmethod
|
||||
def _get_cache_key(cls, args, kwargs):
|
||||
"""
|
||||
This method is used by the caching subsystem to infer the PK value from the constructor arguments.
|
||||
It is used to decide if an instance has to be built or is already in the cache.
|
||||
This method is used by the caching subsystem to infer the PK
|
||||
value from the constructor arguments. It is used to decide if
|
||||
an instance has to be built or is already in the cache.
|
||||
|
||||
"""
|
||||
result = None
|
||||
# Quick hack for my composites work for now.
|
||||
|
|
@ -248,9 +254,11 @@ class SharedMemoryModel(Model):
|
|||
@classmethod
|
||||
def get_cached_instance(cls, id):
|
||||
"""
|
||||
Method to retrieve a cached instance by pk value. Returns None when not found
|
||||
(which will always be the case when caching is disabled for this class). Please
|
||||
note that the lookup will be done even when instance caching is disabled.
|
||||
Method to retrieve a cached instance by pk value. Returns None
|
||||
when not found (which will always be the case when caching is
|
||||
disabled for this class). Please note that the lookup will be
|
||||
done even when instance caching is disabled.
|
||||
|
||||
"""
|
||||
return cls.__dbclass__.__instance_cache__.get(id)
|
||||
|
||||
|
|
@ -261,9 +269,9 @@ class SharedMemoryModel(Model):
|
|||
|
||||
Args:
|
||||
instance (Class instance): the instance to cache.
|
||||
new (bool, optional): this is the first time this
|
||||
instance is cached (i.e. this is not an update
|
||||
operation like after a db save).
|
||||
new (bool, optional): this is the first time this instance is
|
||||
cached (i.e. this is not an update operation like after a
|
||||
db save).
|
||||
|
||||
"""
|
||||
pk = instance._get_pk_val()
|
||||
|
|
@ -281,6 +289,7 @@ class SharedMemoryModel(Model):
|
|||
def get_all_cached_instances(cls):
|
||||
"""
|
||||
Return the objects so far cached by idmapper for this class.
|
||||
|
||||
"""
|
||||
return cls.__dbclass__.__instance_cache__.values()
|
||||
|
||||
|
|
@ -288,6 +297,7 @@ class SharedMemoryModel(Model):
|
|||
def _flush_cached_by_key(cls, key, force=True):
|
||||
"""
|
||||
Remove the cached reference.
|
||||
|
||||
"""
|
||||
try:
|
||||
if force or not cls._idmapper_recache_protection:
|
||||
|
|
@ -312,6 +322,7 @@ class SharedMemoryModel(Model):
|
|||
"""
|
||||
This will clean safe objects from the cache. Use `force`
|
||||
keyword to remove all objects, safe or not.
|
||||
|
||||
"""
|
||||
if force:
|
||||
cls.__dbclass__.__instance_cache__ = {}
|
||||
|
|
@ -326,6 +337,7 @@ class SharedMemoryModel(Model):
|
|||
"""
|
||||
Flush this instance from the instance cache. Use
|
||||
`force` to override recache_protection for the object.
|
||||
|
||||
"""
|
||||
pk = self._get_pk_val()
|
||||
if pk and (force or not self._idmapper_recache_protection):
|
||||
|
|
@ -334,12 +346,14 @@ class SharedMemoryModel(Model):
|
|||
def set_recache_protection(self, mode=True):
|
||||
"""
|
||||
Set if this instance should be allowed to be recached.
|
||||
|
||||
"""
|
||||
self._idmapper_recache_protection = bool(mode)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
"""
|
||||
Delete the object, clearing cache.
|
||||
|
||||
"""
|
||||
self.flush_from_cache()
|
||||
self._is_deleted = True
|
||||
|
|
@ -349,12 +363,11 @@ class SharedMemoryModel(Model):
|
|||
"""
|
||||
Central database save operation.
|
||||
|
||||
Arguments as per Django documentation
|
||||
|
||||
Calls:
|
||||
self.at_<fieldname>_postsave(new)
|
||||
# this is a wrapper set by oobhandler:
|
||||
self._oob_at_<fieldname>_postsave()
|
||||
Notes:
|
||||
Arguments as per Django documentation.
|
||||
Calls `self.at_<fieldname>_postsave(new)`
|
||||
(this is a wrapper set by oobhandler:
|
||||
self._oob_at_<fieldname>_postsave())
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -400,6 +413,7 @@ class SharedMemoryModel(Model):
|
|||
class WeakSharedMemoryModelBase(SharedMemoryModelBase):
|
||||
"""
|
||||
Uses a WeakValue dictionary for caching instead of a regular one.
|
||||
|
||||
"""
|
||||
def _prepare(cls):
|
||||
super(WeakSharedMemoryModelBase, cls)._prepare()
|
||||
|
|
@ -410,6 +424,7 @@ class WeakSharedMemoryModelBase(SharedMemoryModelBase):
|
|||
class WeakSharedMemoryModel(SharedMemoryModel):
|
||||
"""
|
||||
Uses a WeakValue dictionary for caching instead of a regular one
|
||||
|
||||
"""
|
||||
__metaclass__ = WeakSharedMemoryModelBase
|
||||
class Meta:
|
||||
|
|
@ -424,6 +439,7 @@ def flush_cache(**kwargs):
|
|||
is `True`.
|
||||
|
||||
Uses a signal so we make sure to catch cascades.
|
||||
|
||||
"""
|
||||
def class_hierarchy(clslist):
|
||||
"""Recursively yield a class hierarchy"""
|
||||
|
|
@ -448,6 +464,7 @@ post_syncdb.connect(flush_cache)
|
|||
def flush_cached_instance(sender, instance, **kwargs):
|
||||
"""
|
||||
Flush the idmapper cache only for a given instance.
|
||||
|
||||
"""
|
||||
# XXX: Is this the best way to make sure we can flush?
|
||||
if not hasattr(instance, 'flush_cached_instance'):
|
||||
|
|
@ -459,6 +476,7 @@ pre_delete.connect(flush_cached_instance)
|
|||
def update_cached_instance(sender, instance, **kwargs):
|
||||
"""
|
||||
Re-cache the given instance in the idmapper cache.
|
||||
|
||||
"""
|
||||
if not hasattr(instance, 'cache_instance'):
|
||||
return
|
||||
|
|
@ -481,6 +499,7 @@ def conditional_flush(max_rmem, force=False):
|
|||
cache is flushed.
|
||||
force (bool, optional): forces a flush, regardless of timeout.
|
||||
Defaults to `False`.
|
||||
|
||||
"""
|
||||
global LAST_FLUSH
|
||||
|
||||
|
|
@ -546,6 +565,7 @@ def cache_size(mb=True):
|
|||
|
||||
Returns:
|
||||
total_num, {objclass:total_num, ...}
|
||||
|
||||
"""
|
||||
numtotal = [0] # use mutable to keep reference through recursion
|
||||
classdict = {}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
"""
|
||||
Inlinefunc
|
||||
|
||||
This is a simple inline text language for use to custom-format text
|
||||
in Evennia. It is applied BEFORE ANSI/MUX parsing is applied.
|
||||
This is a simple inline text language for use to custom-format text in
|
||||
Evennia. It is applied BEFORE ANSI/MUX parsing is applied.
|
||||
|
||||
To activate Inlinefunc, settings.INLINEFUNC_ENABLED must be set.
|
||||
|
||||
|
|
@ -52,7 +52,10 @@ _DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
|||
# inline functions
|
||||
|
||||
def pad(text, *args, **kwargs):
|
||||
"Pad to width. pad(text, width=78, align='c', fillchar=' ')"
|
||||
"""
|
||||
Pad to width. pad(text, width=78, align='c', fillchar=' ')
|
||||
|
||||
"""
|
||||
width = _DEFAULT_WIDTH
|
||||
align = 'c'
|
||||
fillchar = ' '
|
||||
|
|
@ -67,8 +70,12 @@ def pad(text, *args, **kwargs):
|
|||
break
|
||||
return utils.pad(text, width=width, align=align, fillchar=fillchar)
|
||||
|
||||
|
||||
def crop(text, *args, **kwargs):
|
||||
"Crop to width. crop(text, width=78, suffix='[...]')"
|
||||
"""
|
||||
Crop to width. crop(text, width=78, suffix='[...]')
|
||||
|
||||
"""
|
||||
width = _DEFAULT_WIDTH
|
||||
suffix = "[...]"
|
||||
for iarg, arg in enumerate(args):
|
||||
|
|
@ -80,8 +87,12 @@ def crop(text, *args, **kwargs):
|
|||
break
|
||||
return utils.crop(text, width=width, suffix=suffix)
|
||||
|
||||
|
||||
def wrap(text, *args, **kwargs):
|
||||
"Wrap/Fill text to width. fill(text, width=78, indent=0)"
|
||||
"""
|
||||
Wrap/Fill text to width. fill(text, width=78, indent=0)
|
||||
|
||||
"""
|
||||
width = _DEFAULT_WIDTH
|
||||
indent = 0
|
||||
for iarg, arg in enumerate(args):
|
||||
|
|
@ -91,16 +102,24 @@ def wrap(text, *args, **kwargs):
|
|||
indent = int(arg) if arg.isdigit() else indent
|
||||
return utils.wrap(text, width=width, indent=indent)
|
||||
|
||||
|
||||
def time(text, *args, **kwargs):
|
||||
"Inserts current time"
|
||||
"""
|
||||
Inserts current time.
|
||||
|
||||
"""
|
||||
import time
|
||||
strformat = "%h %d, %H:%M"
|
||||
if args and args[0]:
|
||||
strformat = str(args[0])
|
||||
return time.strftime(strformat)
|
||||
|
||||
|
||||
def you(text, *args, **kwargs):
|
||||
"Inserts your name"
|
||||
"""
|
||||
Inserts your name.
|
||||
|
||||
"""
|
||||
name = "You"
|
||||
sess = kwargs.get("session")
|
||||
if sess and sess.puppet:
|
||||
|
|
@ -139,23 +158,40 @@ def _execute_inline_function(funcname, text, session):
|
|||
Get the enclosed text between {funcname(...) and {/funcname
|
||||
and execute the inline function to replace the whole block
|
||||
with the result.
|
||||
Note that this lookup is "dumb" - we just grab the first end
|
||||
tag we find. So to work correctly this function must be called
|
||||
"inside out" on a nested function tree, so each call only works
|
||||
on a "flat" tag.
|
||||
|
||||
Args:
|
||||
funcname (str): Inlinefunction identifier.
|
||||
text (str): Text to process.
|
||||
session (Session): Session object.
|
||||
|
||||
Notes:
|
||||
This lookup is "dumb" - we just grab the first end tag we find. So
|
||||
to work correctly this function must be called "inside out" on a
|
||||
nested function tree, so each call only works on a "flat" tag.
|
||||
|
||||
"""
|
||||
def subfunc(match):
|
||||
"replace the entire block with the result of the function call"
|
||||
"""
|
||||
replace the entire block with the result of the function call
|
||||
|
||||
"""
|
||||
args = [part.strip() for part in match.group(1).split(",")]
|
||||
intext = match.group(2)
|
||||
kwargs = {"session":session}
|
||||
return _INLINE_FUNCS[funcname][0](intext, *args, **kwargs)
|
||||
return _INLINE_FUNCS[funcname][1].sub(subfunc, text)
|
||||
|
||||
|
||||
def _execute_inline_single_function(funcname, text, session):
|
||||
"""
|
||||
Get the arguments of a single function call (no matching end tag)
|
||||
and execute it with an empty text input.
|
||||
|
||||
Args:
|
||||
funcname (str): Function identifier.
|
||||
text (str): String to process.
|
||||
session (Session): Session id.
|
||||
|
||||
"""
|
||||
def subfunc(match):
|
||||
"replace the single call with the result of the function call"
|
||||
|
|
@ -164,12 +200,20 @@ def _execute_inline_single_function(funcname, text, session):
|
|||
return _INLINE_FUNCS[funcname][0]("", *args, **kwargs)
|
||||
return _INLINE_FUNCS[funcname][2].sub(subfunc, text)
|
||||
|
||||
|
||||
def parse_inlinefunc(text, strip=False, session=None):
|
||||
"""
|
||||
Parse inline function-replacement.
|
||||
|
||||
strip - remove all supported inlinefuncs from text
|
||||
session - session calling for the parsing
|
||||
Args:
|
||||
text (str): Text to parse.
|
||||
strip (bool, optional): Remove all supported inlinefuncs from text.
|
||||
session (bool): Session calling for the parsing.
|
||||
|
||||
Returns:
|
||||
text (str): Parsed text with processed results of
|
||||
inlinefuncs.
|
||||
|
||||
"""
|
||||
|
||||
if strip:
|
||||
|
|
@ -204,6 +248,7 @@ def parse_inlinefunc(text, strip=False, session=None):
|
|||
|
||||
return "".join(outstack)
|
||||
|
||||
|
||||
def _test():
|
||||
# this should all be handled
|
||||
s = "This is a text with a{pad(78,c,-)text {pad(5)of{/pad {pad(30)nice{/pad size{/pad inside {pad(4,l)it{/pad."
|
||||
|
|
|
|||
|
|
@ -24,9 +24,13 @@ _TIMEZONE = None
|
|||
|
||||
def log_trace(errmsg=None):
|
||||
"""
|
||||
Log a traceback to the log. This should be called
|
||||
from within an exception. errmsg is optional and
|
||||
adds an extra line with added info.
|
||||
Log a traceback to the log. This should be called from within an
|
||||
exception.
|
||||
|
||||
Args:
|
||||
errmsg (str, optional): Adds an extra line with added info
|
||||
at the end of the traceback in the log.
|
||||
|
||||
"""
|
||||
tracestring = format_exc()
|
||||
try:
|
||||
|
|
@ -49,7 +53,9 @@ def log_err(errmsg):
|
|||
"""
|
||||
Prints/logs an error message to the server log.
|
||||
|
||||
errormsg: (string) The message to be logged.
|
||||
Args:
|
||||
errormsg (str): The message to be logged.
|
||||
|
||||
"""
|
||||
try:
|
||||
errmsg = str(errmsg)
|
||||
|
|
@ -65,7 +71,9 @@ def log_warn(warnmsg):
|
|||
"""
|
||||
Prints/logs any warnings that aren't critical but should be noted.
|
||||
|
||||
warnmsg: (string) The message to be logged.
|
||||
Args:
|
||||
warnmsg (str): The message to be logged.
|
||||
|
||||
"""
|
||||
try:
|
||||
warnmsg = str(warnmsg)
|
||||
|
|
@ -94,7 +102,10 @@ log_infomsg = log_info
|
|||
|
||||
def log_dep(depmsg):
|
||||
"""
|
||||
Prints a deprecation message
|
||||
Prints a deprecation message.
|
||||
|
||||
Args:
|
||||
depmsg (str): The deprecation message to log.
|
||||
"""
|
||||
try:
|
||||
depmsg = str(depmsg)
|
||||
|
|
@ -111,9 +122,13 @@ LOG_FILE_HANDLES = {} # holds open log handles
|
|||
|
||||
def log_file(msg, filename="game.log"):
|
||||
"""
|
||||
Arbitrary file logger using threads. Filename defaults to
|
||||
'game.log'. All logs will appear in the logs directory and log
|
||||
entries will start on new lines following datetime info.
|
||||
Arbitrary file logger using threads.
|
||||
|
||||
Args:
|
||||
filename (str, optional): Defaults to 'game.log'. All logs
|
||||
will appear in the logs directory and log entries will start
|
||||
on new lines following datetime info.
|
||||
|
||||
"""
|
||||
global LOG_FILE_HANDLES, _LOGDIR, _TIMEZONE
|
||||
|
||||
|
|
@ -131,6 +146,7 @@ def log_file(msg, filename="game.log"):
|
|||
# manually or log file won't be written to until the
|
||||
# write buffer is full.
|
||||
filehandle.flush()
|
||||
|
||||
def errback(failure):
|
||||
"Catching errors to normal log"
|
||||
log_trace()
|
||||
|
|
|
|||
|
|
@ -92,7 +92,10 @@ _handle_dbref = lambda inp: dbid_to_obj(inp, ObjectDB)
|
|||
|
||||
|
||||
def _validate_prototype(key, prototype, protparents, visited):
|
||||
"Run validation on a prototype, checking for inifinite regress"
|
||||
"""
|
||||
Run validation on a prototype, checking for inifinite regress.
|
||||
|
||||
"""
|
||||
assert isinstance(prototype, dict)
|
||||
if id(prototype) in visited:
|
||||
raise RuntimeError("%s has infinite nesting of prototypes." % key or prototype)
|
||||
|
|
@ -110,9 +113,10 @@ def _validate_prototype(key, prototype, protparents, visited):
|
|||
|
||||
def _get_prototype(dic, prot, protparents):
|
||||
"""
|
||||
Recursively traverse a prototype dictionary,
|
||||
including multiple inheritance. Use _validate_prototype
|
||||
before this, we don't check for infinite recursion here.
|
||||
Recursively traverse a prototype dictionary, including multiple
|
||||
inheritance. Use _validate_prototype before this, we don't check
|
||||
for infinite recursion here.
|
||||
|
||||
"""
|
||||
if "prototype" in dic:
|
||||
# move backwards through the inheritance
|
||||
|
|
@ -130,10 +134,11 @@ def _batch_create_object(*objparams):
|
|||
optimized for speed. It does NOT check and convert various input
|
||||
so make sure the spawned Typeclass works before using this!
|
||||
|
||||
Input:
|
||||
objsparams - each argument should be a tuple of arguments for the respective
|
||||
creation/add handlers in the following order:
|
||||
(create, permissions, locks, aliases, nattributes, attributes)
|
||||
Args:
|
||||
objsparams (any): Aach argument should be a tuple of arguments
|
||||
for the respective creation/add handlers in the following
|
||||
order: (create, permissions, locks, aliases, nattributes,
|
||||
attributes)
|
||||
Returns:
|
||||
objects (list): A list of created objects
|
||||
|
||||
|
|
@ -168,16 +173,17 @@ def spawn(*prototypes, **kwargs):
|
|||
Spawn a number of prototyped objects. Each argument should be a
|
||||
prototype dictionary.
|
||||
|
||||
keyword args:
|
||||
prototype_modules - a python-path to a
|
||||
prototype module, or a list of such paths. These will be used
|
||||
to build the global protparents dictionary accessible by the
|
||||
input prototypes. If not given, it will instead look for modules
|
||||
Kwargs:
|
||||
prototype_modules (str or list): A python-path to a prototype
|
||||
module, or a list of such paths. These will be used to build
|
||||
the global protparents dictionary accessible by the input
|
||||
prototypes. If not given, it will instead look for modules
|
||||
defined by settings.PROTOTYPE_MODULES.
|
||||
prototype_parents - a dictionary holding a custom prototype-parent dictionary. Will
|
||||
overload same-named prototypes from prototype_modules.
|
||||
return_prototypes - only return a list of the prototype-parents
|
||||
(no object creation happens)
|
||||
prototype_parents (dict): A dictionary holding a custom
|
||||
prototype-parent dictionary. Will overload same-named
|
||||
prototypes from prototype_modules.
|
||||
return_prototypes (bool): Only return a list of the
|
||||
prototype-parents (no object creation happens)
|
||||
"""
|
||||
|
||||
protparents = {}
|
||||
|
|
|
|||
|
|
@ -82,8 +82,16 @@ class TextToHTMLparser(object):
|
|||
|
||||
def re_color(self, text):
|
||||
"""
|
||||
Replace ansi colors with html color class names.
|
||||
Let the client choose how it will display colors, if it wishes to. """
|
||||
Replace ansi colors with html color class names. Let the
|
||||
client choose how it will display colors, if it wishes to.
|
||||
|
||||
Args:
|
||||
text (str): the string with color to replace.
|
||||
|
||||
Returns:
|
||||
text (str): Re-colored text.
|
||||
|
||||
"""
|
||||
for colorname, regex in self.re_fgs:
|
||||
text = regex.sub(r'''<span class="%s">\1</span>''' % colorname, text)
|
||||
for bgname, regex in self.re_bgs:
|
||||
|
|
@ -91,19 +99,56 @@ class TextToHTMLparser(object):
|
|||
return self.re_normal.sub("", text)
|
||||
|
||||
def re_bold(self, text):
|
||||
"Clean out superfluous hilights rather than set <strong>to make it match the look of telnet."
|
||||
"""
|
||||
Clean out superfluous hilights rather than set <strong>to make
|
||||
it match the look of telnet.
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
return self.re_hilite.sub(r'<strong>\1</strong>', text)
|
||||
|
||||
def re_underline(self, text):
|
||||
"Replace ansi underline with html underline class name."
|
||||
"""
|
||||
Replace ansi underline with html underline class name.
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
return self.re_uline.sub(r'<span class="underline">\1</span>', text)
|
||||
|
||||
def remove_bells(self, text):
|
||||
"Remove ansi specials"
|
||||
"""
|
||||
Remove ansi specials
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
return text.replace('\07', '')
|
||||
|
||||
def remove_backspaces(self, text):
|
||||
"Removes special escape sequences"
|
||||
"""
|
||||
Removes special escape sequences
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
backspace_or_eol = r'(.\010)|(\033\[K)'
|
||||
n = 1
|
||||
while n > 0:
|
||||
|
|
@ -111,11 +156,29 @@ class TextToHTMLparser(object):
|
|||
return text
|
||||
|
||||
def convert_linebreaks(self, text):
|
||||
"Extra method for cleaning linebreaks"
|
||||
"""
|
||||
Extra method for cleaning linebreaks
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
return text.replace(r'\n', r'<br>')
|
||||
|
||||
def convert_urls(self, text):
|
||||
"Replace urls (http://...) by valid HTML"
|
||||
"""
|
||||
Replace urls (http://...) by valid HTML.
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
regexp = r"((ftp|www|http)(\W+\S+[^).,:;?\]\}(\<span\>) \r\n$\"\']+))"
|
||||
# -> added target to output prevent the web browser from attempting to
|
||||
# change pages (and losing our webclient session).
|
||||
|
|
@ -123,14 +186,31 @@ class TextToHTMLparser(object):
|
|||
|
||||
def convert_links(self, text):
|
||||
"""
|
||||
Replaces links with HTML code
|
||||
Replaces links with HTML code.
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
html = "<a href='#' onclick='websocket.send(\"CMD\\1\"); return false;'>\\2</a>"
|
||||
repl = self.re_link.sub(html, text)
|
||||
return repl
|
||||
|
||||
def do_sub(self, m):
|
||||
"Helper method to be passed to re.sub."
|
||||
def do_sub(self, match):
|
||||
"""
|
||||
Helper method to be passed to re.sub,
|
||||
for handling all substitutions.
|
||||
|
||||
Args:
|
||||
match (re.Matchobject): Match for substitution.
|
||||
|
||||
Returns:
|
||||
text (str): Processed text.
|
||||
|
||||
"""
|
||||
c = m.groupdict()
|
||||
if c['htmlchars']:
|
||||
return cgi.escape(c['htmlchars'])
|
||||
|
|
@ -145,8 +225,15 @@ class TextToHTMLparser(object):
|
|||
|
||||
def parse(self, text, strip_ansi=False):
|
||||
"""
|
||||
Main access function, converts a text containing
|
||||
ANSI codes into html statements.
|
||||
Main access function, converts a text containing ANSI codes
|
||||
into html statements.
|
||||
|
||||
Args:
|
||||
text (str): Text to process.
|
||||
strip_ansi (bool, optional):
|
||||
|
||||
Returns:
|
||||
text (str): Parsed text.
|
||||
"""
|
||||
# parse everything to ansi first
|
||||
text = parse_ansi(text, strip_ansi=strip_ansi, xterm256=False, mxp=True)
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ def make_hybi07_frame_dwim(buf):
|
|||
"""
|
||||
Make a HyBi-07 frame with binary or text data according to the type of buf.
|
||||
"""
|
||||
|
||||
|
||||
# TODO: eliminate magic numbers.
|
||||
if isinstance(buf, str):
|
||||
return make_hybi07_frame(buf, opcode=0x2)
|
||||
|
|
@ -349,7 +349,7 @@ class WebSocketProtocol(ProtocolWrapper):
|
|||
def setBinaryMode(self, mode):
|
||||
"""
|
||||
If True, send str as binary and unicode as text.
|
||||
|
||||
|
||||
Defaults to false for backwards compatibility.
|
||||
"""
|
||||
self.do_binary_frames = bool(mode)
|
||||
|
|
|
|||
|
|
@ -40,22 +40,34 @@ _DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
|||
|
||||
def is_iter(iterable):
|
||||
"""
|
||||
Checks if an object behaves iterably. However,
|
||||
strings are not accepted as iterable (although
|
||||
they are actually iterable), since string iterations
|
||||
are usually not what we want to do with a string.
|
||||
"""
|
||||
# use a try..except here to avoid a property
|
||||
# lookup when using this from a typeclassed entity
|
||||
try:
|
||||
_GA(iterable, '__iter__')
|
||||
return True
|
||||
except AttributeError:
|
||||
return False
|
||||
Checks if an object behaves iterably.
|
||||
|
||||
Args:
|
||||
iterable (any): Entity to check for iterability.
|
||||
|
||||
Returns:
|
||||
is_iterable (bool): If `iterable` is iterable or not.
|
||||
|
||||
Notes:
|
||||
Strings are *not* accepted as iterable (although they are
|
||||
actually iterable), since string iterations are usually not
|
||||
what we want to do with a string.
|
||||
|
||||
"""
|
||||
return hasattr(iterable, '__iter__')
|
||||
|
||||
def make_iter(obj):
|
||||
"Makes sure that the object is always iterable."
|
||||
"""
|
||||
Makes sure that the object is always iterable.
|
||||
|
||||
Args:
|
||||
obj (any): Object to make iterable.
|
||||
|
||||
Returns:
|
||||
iterable (list or iterable): The same object
|
||||
passed-through or made iterable.
|
||||
|
||||
"""
|
||||
return not hasattr(obj, '__iter__') and [obj] or obj
|
||||
|
||||
|
||||
|
|
@ -63,10 +75,15 @@ def wrap(text, width=_DEFAULT_WIDTH, indent=0):
|
|||
"""
|
||||
Safely wrap text to a certain number of characters.
|
||||
|
||||
text: (str) The text to wrap.
|
||||
width: (int) The number of characters to wrap to.
|
||||
indent: (int) How much to indent new lines (the first line
|
||||
will not be indented)
|
||||
Args:
|
||||
text (str): The text to wrap.
|
||||
width (int, optional): The number of characters to wrap to.
|
||||
indent (int): How much to indent new lines (the first line
|
||||
will not be indented)
|
||||
|
||||
Returns:
|
||||
text (str): Properly wrapped text.
|
||||
|
||||
"""
|
||||
if not text:
|
||||
return ""
|
||||
|
|
@ -76,10 +93,21 @@ def wrap(text, width=_DEFAULT_WIDTH, indent=0):
|
|||
# alias - fill
|
||||
fill = wrap
|
||||
|
||||
|
||||
def pad(text, width=_DEFAULT_WIDTH, align="c", fillchar=" "):
|
||||
"""
|
||||
Pads to a given width, align is one of c,l,r
|
||||
and fillchar defaults to the space character.
|
||||
Pads to a given width.
|
||||
|
||||
Args:
|
||||
text (str): Text to pad.
|
||||
width (int, optional): The width to pad to, in characters.
|
||||
align (str, optional): This is one of 'c', 'l' or 'r' (center,
|
||||
left or right).
|
||||
fillchar (str, optional): The character to fill with.
|
||||
|
||||
Returns:
|
||||
text (str): The padded text.
|
||||
|
||||
"""
|
||||
align = align if align in ('c', 'l', 'r') else 'c'
|
||||
fillchar = fillchar[0] if fillchar else " "
|
||||
|
|
@ -90,12 +118,24 @@ def pad(text, width=_DEFAULT_WIDTH, align="c", fillchar=" "):
|
|||
else:
|
||||
return text.center(width, fillchar)
|
||||
|
||||
|
||||
def crop(text, width=_DEFAULT_WIDTH, suffix="[...]"):
|
||||
"""
|
||||
Crop text to a certain width, adding `suffix` to show that the line
|
||||
continues. Cropping will be done so that the suffix will also fit
|
||||
within the given width. If width is too small to fit both crop
|
||||
and suffix, crop without the suffix.
|
||||
Crop text to a certain width, throwing away text from too-long
|
||||
lines.
|
||||
|
||||
Args:
|
||||
text (str): Text to crop.
|
||||
width (int, optional): Width of line to crop, in characters.
|
||||
suffix (str, optional): This is appended to the end of cropped
|
||||
lines to show that the line actually continues. Cropping
|
||||
will be done so that the suffix will also fit within the
|
||||
given width. If width is too small to fit both crop and
|
||||
suffix, the suffix will be dropped.
|
||||
|
||||
Returns:
|
||||
text (str): The cropped text.
|
||||
|
||||
"""
|
||||
|
||||
utext = to_unicode(text)
|
||||
|
|
@ -110,11 +150,19 @@ def crop(text, width=_DEFAULT_WIDTH, suffix="[...]"):
|
|||
|
||||
def dedent(text):
|
||||
"""
|
||||
Safely clean all whitespace at the left
|
||||
of a paragraph. This is useful for preserving
|
||||
triple-quoted string indentation while still
|
||||
shifting it all to be next to the left edge of
|
||||
the display.
|
||||
Safely clean all whitespace at the left of a paragraph.
|
||||
|
||||
Args:
|
||||
text (str): The text to dedent.
|
||||
|
||||
Returns:
|
||||
text (str): Dedented string.
|
||||
|
||||
Notes:
|
||||
This is useful for preserving triple-quoted string indentation
|
||||
while still shifting it all to be next to the left edge of the
|
||||
display.
|
||||
|
||||
"""
|
||||
if not text:
|
||||
return ""
|
||||
|
|
@ -123,19 +171,31 @@ def dedent(text):
|
|||
|
||||
def list_to_string(inlist, endsep="and", addquote=False):
|
||||
"""
|
||||
This pretty-formats a list as string output, adding
|
||||
an optional alternative separator to the second to last entry.
|
||||
If `addquote` is `True`, the outgoing strings will be surrounded by quotes.
|
||||
This pretty-formats a list as string output, adding an optional
|
||||
alternative separator to the second to last entry. If `addquote`
|
||||
is `True`, the outgoing strings will be surrounded by quotes.
|
||||
|
||||
Args:
|
||||
inlist (list): The list to print.
|
||||
endsep (str, optional): If set, the last item separator will
|
||||
be replaced with this value.
|
||||
addquote (bool, optional): This will surround all outgoing
|
||||
values with double quotes.
|
||||
|
||||
Returns:
|
||||
liststr (str): The list represented as a string.
|
||||
|
||||
Examples:
|
||||
```
|
||||
no endsep:
|
||||
[1,2,3] -> '1, 2, 3'
|
||||
with endsep=='and':
|
||||
[1,2,3] -> '1, 2 and 3'
|
||||
with addquote and endsep
|
||||
[1,2,3] -> '"1", "2" and "3"'
|
||||
```
|
||||
|
||||
```python
|
||||
# no endsep:
|
||||
[1,2,3] -> '1, 2, 3'
|
||||
# with endsep=='and':
|
||||
[1,2,3] -> '1, 2 and 3'
|
||||
# with addquote and endsep
|
||||
[1,2,3] -> '"1", "2" and "3"'
|
||||
```
|
||||
|
||||
"""
|
||||
if not endsep:
|
||||
endsep = ","
|
||||
|
|
@ -155,10 +215,17 @@ def list_to_string(inlist, endsep="and", addquote=False):
|
|||
|
||||
def wildcard_to_regexp(instring):
|
||||
"""
|
||||
Converts a player-supplied string that may have wildcards in it to regular
|
||||
expressions. This is useful for name matching.
|
||||
Converts a player-supplied string that may have wildcards in it to
|
||||
regular expressions. This is useful for name matching.
|
||||
|
||||
Args:
|
||||
instring (string): A string that may potentially contain
|
||||
wildcards (`*` or `?`).
|
||||
|
||||
Returns:
|
||||
regex (str): A string where wildcards were replaced with
|
||||
regular expressions.
|
||||
|
||||
instring: (string) A string that may potentially contain wildcards (`*` or `?`).
|
||||
"""
|
||||
regexp_string = ""
|
||||
|
||||
|
|
@ -182,10 +249,13 @@ def time_format(seconds, style=0):
|
|||
"""
|
||||
Function to return a 'prettified' version of a value in seconds.
|
||||
|
||||
Style 0: 1d 08:30
|
||||
Style 1: 1d
|
||||
Style 2: 1 day, 8 hours, 30 minutes
|
||||
Style 3: 1 day, 8 hours, 30 minutes, 10 seconds
|
||||
Args:
|
||||
seconds (int): Number if seconds to format.
|
||||
style (int): One of the following styles:
|
||||
0. "1d 08:30"
|
||||
1. "1d"
|
||||
2. "1 day, 8 hours, 30 minutes"
|
||||
3. "1 day, 8 hours, 30 minutes, 10 seconds"
|
||||
"""
|
||||
if seconds < 0:
|
||||
seconds = 0
|
||||
|
|
@ -208,8 +278,8 @@ def time_format(seconds, style=0):
|
|||
retval = '%id %02i:%02i' % (days, hours, minutes,)
|
||||
else:
|
||||
retval = '%02i:%02i' % (hours, minutes,)
|
||||
|
||||
return retval
|
||||
|
||||
elif style is 1:
|
||||
"""
|
||||
Simple, abbreviated form that only shows the highest time amount.
|
||||
|
|
@ -275,8 +345,15 @@ def time_format(seconds, style=0):
|
|||
|
||||
def datetime_format(dtobj):
|
||||
"""
|
||||
Takes a datetime object instance (e.g. from Django's `DateTimeField`)
|
||||
and returns a string describing how long ago that date was.
|
||||
Pretty-prints the time since a given time.
|
||||
|
||||
Args:
|
||||
dtobj (datetime): An datetime object, e.g. from Django's
|
||||
`DateTimeField`.
|
||||
|
||||
Returns:
|
||||
deltatime (str): A string describing how long ago `dtobj`
|
||||
took place.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -302,16 +379,26 @@ def datetime_format(dtobj):
|
|||
def host_os_is(osname):
|
||||
"""
|
||||
Check to see if the host OS matches the query.
|
||||
Common osnames are
|
||||
posix
|
||||
nt
|
||||
|
||||
Args:
|
||||
osname (str): Common names are "posix" (linux/unix/mac) and
|
||||
"nt" (windows).
|
||||
|
||||
Args:
|
||||
is_os (bool): If the os matches or not.
|
||||
|
||||
"""
|
||||
if os.name == osname:
|
||||
return True
|
||||
return False
|
||||
return os.name == osname
|
||||
|
||||
|
||||
def get_evennia_version():
|
||||
"""
|
||||
Helper method for getting the current evennia version.
|
||||
|
||||
Returns:
|
||||
version (str): The version string.
|
||||
|
||||
"""
|
||||
import evennia
|
||||
return evennia.__version__
|
||||
|
||||
|
|
@ -345,11 +432,17 @@ def pypath_to_realpath(python_path, file_ending='.py'):
|
|||
|
||||
def dbref(dbref, reqhash=True):
|
||||
"""
|
||||
Converts/checks if input is a valid dbref. If `reqhash` is set,
|
||||
only input strings on the form '#N', where N is an integer is
|
||||
accepted. Otherwise strings '#N', 'N' and integers N are all
|
||||
accepted.
|
||||
Output is the integer part.
|
||||
Converts/checks if input is a valid dbref.
|
||||
|
||||
Args:
|
||||
dbref (int or str): A datbase ref on the form N or #N.
|
||||
reqhash (bool, optional): Require the #N form to accept
|
||||
input as a valid dbref.
|
||||
|
||||
Returns:
|
||||
dbref (int or None): The integer part of the dbref or `None`
|
||||
if input was not a valid dbref.
|
||||
|
||||
"""
|
||||
if reqhash:
|
||||
num = (int(dbref.lstrip('#')) if (isinstance(dbref, basestring) and
|
||||
|
|
@ -366,10 +459,22 @@ def dbref(dbref, reqhash=True):
|
|||
|
||||
def dbid_to_obj(inp, objclass, raise_errors=True):
|
||||
"""
|
||||
Convert a #dbid to a valid object of `objclass`. `objclass`
|
||||
should be a valid object class to filter against (`objclass.filter` ...)
|
||||
If not `raise_errors` is set, this will swallow errors of non-existing
|
||||
objects.
|
||||
Convert a #dbid to a valid object.
|
||||
|
||||
Args:
|
||||
inp (str or int): A valid dbref.
|
||||
objclass (class): A valid django model to filter against.
|
||||
raise_errors (bool, optional): Whether to raise errors
|
||||
or return `None` on errors.
|
||||
|
||||
Returns:
|
||||
obj (Object or None): An entity loaded from the dbref.
|
||||
|
||||
Raises:
|
||||
Exception: If `raise_errors` is `True` and
|
||||
`objclass.objects.get(id=dbref)` did not return a valid
|
||||
object.
|
||||
|
||||
"""
|
||||
dbid = dbref(inp)
|
||||
if not dbid:
|
||||
|
|
@ -389,13 +494,28 @@ def dbid_to_obj(inp, objclass, raise_errors=True):
|
|||
raise
|
||||
return inp
|
||||
|
||||
|
||||
def to_unicode(obj, encoding='utf-8', force_string=False):
|
||||
"""
|
||||
This decodes a suitable object to the unicode format. Note that
|
||||
one needs to encode it back to utf-8 before writing to disk or
|
||||
printing. Note that non-string objects are let through without
|
||||
conversion - this is important for e.g. Attributes. Use
|
||||
`force_string` to enforce conversion of objects to string.
|
||||
This decodes a suitable object to the unicode format.
|
||||
|
||||
Args:
|
||||
obj (any): Object to decode to unicode.
|
||||
encoding (str, optional): The encoding type to use for the
|
||||
dedoding.
|
||||
force_string (bool, optional): Always convert to string, no
|
||||
matter what type `obj` is initially.
|
||||
|
||||
Returns:
|
||||
result (unicode or any): Will return a unicode object if input
|
||||
was a string. If input was not a string, the original will be
|
||||
returned unchanged unless `force_string` is also set.
|
||||
|
||||
Notes:
|
||||
One needs to encode the obj back to utf-8 before writing to disk
|
||||
or printing. That non-string objects are let through without
|
||||
conversion is important for e.g. Attributes.
|
||||
|
||||
"""
|
||||
|
||||
if force_string and not isinstance(obj, basestring):
|
||||
|
|
@ -427,10 +547,20 @@ def to_unicode(obj, encoding='utf-8', force_string=False):
|
|||
def to_str(obj, encoding='utf-8', force_string=False):
|
||||
"""
|
||||
This encodes a unicode string back to byte-representation,
|
||||
for printing, writing to disk etc. Note that non-string
|
||||
objects are let through without modification - this is
|
||||
required e.g. for Attributes. Use `force_string` to force
|
||||
conversion of objects to strings.
|
||||
for printing, writing to disk etc.
|
||||
|
||||
Args:
|
||||
obj (any): Object to encode to bytecode.
|
||||
encoding (str, optional): The encoding type to use for the
|
||||
encoding.
|
||||
force_string (bool, optional): Always convert to string, no
|
||||
matter what type `obj` is initially.
|
||||
|
||||
Notes:
|
||||
Non-string objects are let through without modification - this
|
||||
is required e.g. for Attributes. Use `force_string` to force
|
||||
conversion of objects to strings.
|
||||
|
||||
"""
|
||||
|
||||
if force_string and not isinstance(obj, basestring):
|
||||
|
|
@ -460,8 +590,16 @@ def validate_email_address(emailaddress):
|
|||
"""
|
||||
Checks if an email address is syntactically correct.
|
||||
|
||||
(This snippet was adapted from
|
||||
http://commandline.org.uk/python/email-syntax-check.)
|
||||
Args:
|
||||
emailaddress (str): Email address to validate.
|
||||
|
||||
Returns:
|
||||
is_valid (bool): If this is a valid email or not.
|
||||
|
||||
Notes.
|
||||
(This snippet was adapted from
|
||||
http://commandline.org.uk/python/email-syntax-check.)
|
||||
|
||||
"""
|
||||
|
||||
emailaddress = r"%s" % emailaddress
|
||||
|
|
@ -498,11 +636,23 @@ def validate_email_address(emailaddress):
|
|||
|
||||
def inherits_from(obj, parent):
|
||||
"""
|
||||
Takes an object and tries to determine if it inherits at any distance
|
||||
from parent. What differs this function from e.g. `isinstance()`
|
||||
is that `obj` may be both an instance and a class, and parent
|
||||
may be an instance, a class, or the python path to a class (counting
|
||||
from the evennia root directory).
|
||||
Takes an object and tries to determine if it inherits at *any*
|
||||
distance from parent.
|
||||
|
||||
Args:
|
||||
obj (any): Object to analyze. This may be either an instance
|
||||
or a class.
|
||||
parent (any): Can be either instance, class or python path to class.
|
||||
|
||||
Returns:
|
||||
inherits_from (bool): If `parent` is a parent to `obj` or not.
|
||||
|
||||
Notes:
|
||||
What differs this function from e.g. `isinstance()` is that `obj`
|
||||
may be both an instance and a class, and parent may be an
|
||||
instance, a class, or the python path to a class (counting from
|
||||
the evennia root directory).
|
||||
|
||||
"""
|
||||
|
||||
if callable(obj):
|
||||
|
|
@ -524,9 +674,13 @@ def inherits_from(obj, parent):
|
|||
|
||||
def server_services():
|
||||
"""
|
||||
Lists all services active on the Server. Observe that
|
||||
since services are launched in memory, this function will
|
||||
only return any results if called from inside the game.
|
||||
Lists all services active on the Server. Observe that since
|
||||
services are launched in memory, this function will only return
|
||||
any results if called from inside the game.
|
||||
|
||||
Returns:
|
||||
services (dict): A dict of available services.
|
||||
|
||||
"""
|
||||
from evennia.server.sessionhandler import SESSIONS
|
||||
if hasattr(SESSIONS, "server") and hasattr(SESSIONS.server, "services"):
|
||||
|
|
@ -543,7 +697,13 @@ def uses_database(name="sqlite3"):
|
|||
Checks if the game is currently using a given database. This is a
|
||||
shortcut to having to use the full backend name.
|
||||
|
||||
name - one of 'sqlite3', 'mysql', 'postgresql_psycopg2' or 'oracle'
|
||||
Args:
|
||||
name (str): One of 'sqlite3', 'mysql', 'postgresql_psycopg2'
|
||||
or 'oracle'.
|
||||
|
||||
Returns:
|
||||
uses (bool): If the given database is used or not.
|
||||
|
||||
"""
|
||||
try:
|
||||
engine = settings.DATABASES["default"]["ENGINE"]
|
||||
|
|
@ -555,17 +715,21 @@ def uses_database(name="sqlite3"):
|
|||
def delay(delay=2, callback=None, retval=None):
|
||||
"""
|
||||
Delay the return of a value.
|
||||
Inputs:
|
||||
delay (int) - the delay in seconds
|
||||
callback (func() or func(retval)) - if given, will be called without
|
||||
arguments or with `retval` after delay seconds.
|
||||
retval (any) - this will be returned by this function after a delay,
|
||||
or as input to callback.
|
||||
|
||||
Args:
|
||||
delay (int): The delay in seconds
|
||||
callback (callable, optional): Will be called without arguments
|
||||
or with `retval` after delay seconds.
|
||||
retval (any, optional): Whis will be returned by this function
|
||||
after a delay, or as input to callback.
|
||||
|
||||
Returns:
|
||||
deferred that will fire with callback after `delay` seconds. Note that
|
||||
if `delay()` is used in the commandhandler callback chain, the callback
|
||||
chain can be defined directly in the command body and don't need to be
|
||||
specified here.
|
||||
deferred (deferred): Will fire fire with callback after
|
||||
`delay` seconds. Note that if `delay()` is used in the
|
||||
commandhandler callback chain, the callback chain can be
|
||||
defined directly in the command body and don't need to be
|
||||
specified here.
|
||||
|
||||
"""
|
||||
callb = callback or defer.Deferred().callback
|
||||
if retval is not None:
|
||||
|
|
@ -579,14 +743,18 @@ _OBJECTMODELS = None
|
|||
def clean_object_caches(obj):
|
||||
"""
|
||||
Clean all object caches on the given object.
|
||||
|
||||
Args:
|
||||
obj (Object instace): An object whose caches to clean.
|
||||
|
||||
Notes:
|
||||
This is only the contents cache these days.
|
||||
|
||||
"""
|
||||
global _TYPECLASSMODELS, _OBJECTMODELS
|
||||
if not _TYPECLASSMODELS:
|
||||
from evennia.typeclasses import models as _TYPECLASSMODELS
|
||||
#if not _OBJECTMODELS:
|
||||
# from evennia.objects import models as _OBJECTMODELS
|
||||
|
||||
#print "recaching:", obj
|
||||
if not obj:
|
||||
return
|
||||
# contents cache
|
||||
|
|
@ -612,45 +780,39 @@ def run_async(to_execute, *args, **kwargs):
|
|||
"""
|
||||
Runs a function or executes a code snippet asynchronously.
|
||||
|
||||
Inputs:
|
||||
to_execute (callable) - if this is a callable, it will
|
||||
be executed with *args and non-reserved *kwargs as
|
||||
arguments.
|
||||
The callable will be executed using ProcPool, or in
|
||||
a thread if ProcPool is not available.
|
||||
Args:
|
||||
to_execute (callable): If this is a callable, it will be
|
||||
executed with *args and non-reserved *kwargs as arguments.
|
||||
The callable will be executed using ProcPool, or in a thread
|
||||
if ProcPool is not available.
|
||||
|
||||
reserved kwargs:
|
||||
'at_return' -should point to a callable with one argument.
|
||||
It will be called with the return value from
|
||||
to_execute.
|
||||
'at_return_kwargs' - this dictionary which be used as keyword
|
||||
arguments to the at_return callback.
|
||||
'at_err' - this will be called with a Failure instance if
|
||||
there is an error in to_execute.
|
||||
'at_err_kwargs' - this dictionary will be used as keyword
|
||||
arguments to the at_err errback.
|
||||
Kwargs:
|
||||
at_return (callable): Should point to a callable with one
|
||||
argument. It will be called with the return value from
|
||||
to_execute.
|
||||
at_return_kwargs (dict): This dictionary will be used as
|
||||
keyword arguments to the at_return callback.
|
||||
at_err (callable): This will be called with a Failure instance
|
||||
if there is an error in to_execute.
|
||||
at_err_kwargs (dict): This dictionary will be used as keyword
|
||||
arguments to the at_err errback.
|
||||
|
||||
*args - these args will be used
|
||||
as arguments for that function. If to_execute is a string
|
||||
*args are not used.
|
||||
*kwargs - these kwargs will be used
|
||||
as keyword arguments in that function. If a string, they
|
||||
instead are used to define the executable environment
|
||||
that should be available to execute the code in to_execute.
|
||||
Notes:
|
||||
All other `*args` and `**kwargs` will be passed on to
|
||||
`to_execute`. Run_async will relay executed code to a thread
|
||||
or procpool.
|
||||
|
||||
run_async will relay executed code to a thread or procpool.
|
||||
Use this function with restrain and only for features/commands
|
||||
that you know has no influence on the cause-and-effect order of your
|
||||
game (commands given after the async function might be executed before
|
||||
it has finished). Accessing the same property from different threads
|
||||
can lead to unpredicted behaviour if you are not careful (this is called a
|
||||
"race condition").
|
||||
|
||||
Use this function with restrain and only for features/commands
|
||||
that you know has no influence on the cause-and-effect order of your
|
||||
game (commands given after the async function might be executed before
|
||||
it has finished). Accessing the same property from different threads
|
||||
can lead to unpredicted behaviour if you are not careful (this is called a
|
||||
"race condition").
|
||||
|
||||
Also note that some databases, notably sqlite3, don't support access from
|
||||
multiple threads simultaneously, so if you do heavy database access from
|
||||
your `to_execute` under sqlite3 you will probably run very slow or even get
|
||||
tracebacks.
|
||||
Also note that some databases, notably sqlite3, don't support access from
|
||||
multiple threads simultaneously, so if you do heavy database access from
|
||||
your `to_execute` under sqlite3 you will probably run very slow or even get
|
||||
tracebacks.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -676,9 +838,12 @@ def run_async(to_execute, *args, **kwargs):
|
|||
def check_evennia_dependencies():
|
||||
"""
|
||||
Checks the versions of Evennia's dependencies including making
|
||||
some checks for runtime libraries
|
||||
some checks for runtime libraries.
|
||||
|
||||
Returns:
|
||||
result (bool): `False` if a show-stopping version mismatch is
|
||||
found.
|
||||
|
||||
Returns False if a show-stopping version mismatch is found.
|
||||
"""
|
||||
|
||||
# check main dependencies
|
||||
|
|
@ -711,6 +876,14 @@ def check_evennia_dependencies():
|
|||
def has_parent(basepath, obj):
|
||||
"""
|
||||
Checks if `basepath` is somewhere in `obj`s parent tree.
|
||||
|
||||
Args:
|
||||
basepath (str): Python dotpath to compare against obj path.
|
||||
obj (any): Object whose path is to be checked.
|
||||
|
||||
Returns:
|
||||
has_parent (bool): If the check was successful or not.
|
||||
|
||||
"""
|
||||
try:
|
||||
return any(cls for cls in obj.__class__.mro()
|
||||
|
|
@ -726,15 +899,15 @@ def mod_import(module):
|
|||
A generic Python module loader.
|
||||
|
||||
Args:
|
||||
module - this can be either a Python path (dot-notation like
|
||||
`evennia.objects.models`), an absolute path
|
||||
(e.g. `/home/eve/evennia/evennia/objects.models.py`)
|
||||
or an already imported module object (e.g. `models`)
|
||||
module (str, module): This can be either a Python path
|
||||
(dot-notation like `evennia.objects.models`), an absolute path
|
||||
(e.g. `/home/eve/evennia/evennia/objects.models.py`) or an
|
||||
already imported module object (e.g. `models`)
|
||||
Returns:
|
||||
an imported module. If the input argument was already a model,
|
||||
this is returned as-is, otherwise the path is parsed and imported.
|
||||
Error:
|
||||
returns `None`. The error is also logged.
|
||||
module (module or None): An imported module. If the input argument was
|
||||
already a module, this is returned as-is, otherwise the path is
|
||||
parsed and imported. Returns `None` and logs error if import failed.
|
||||
|
||||
"""
|
||||
|
||||
def log_trace(errmsg=None):
|
||||
|
|
@ -800,8 +973,21 @@ def mod_import(module):
|
|||
|
||||
def all_from_module(module):
|
||||
"""
|
||||
Return all global-level variables from a module as a dict.
|
||||
Ignores modules and variable names starting with an underscore.
|
||||
Return all global-level variables from a module.
|
||||
|
||||
Args:
|
||||
module (str, module): This can be either a Python path
|
||||
(dot-notation like `evennia.objects.models`), an absolute path
|
||||
(e.g. `/home/eve/evennia/evennia/objects.models.py`) or an
|
||||
already imported module object (e.g. `models`)
|
||||
|
||||
Returns:
|
||||
variables (dict): A dict of {variablename: variable} for all
|
||||
variables in the given module.
|
||||
|
||||
Notes:
|
||||
Ignores modules and variable names starting with an underscore.
|
||||
|
||||
"""
|
||||
mod = mod_import(module)
|
||||
if not mod:
|
||||
|
|
@ -812,23 +998,24 @@ def all_from_module(module):
|
|||
|
||||
def variable_from_module(module, variable=None, default=None):
|
||||
"""
|
||||
Retrieve a variable or list of variables from a module. The variable(s)
|
||||
must be defined globally in the module. If no variable is given (or a
|
||||
list entry is `None`), all global variables are extracted from the module.
|
||||
|
||||
If `module` cannot be imported or a given `variable` not found, `default`
|
||||
is returned.
|
||||
Retrieve a variable or list of variables from a module. The
|
||||
variable(s) must be defined globally in the module. If no variable
|
||||
is given (or a list entry is `None`), all global variables are
|
||||
extracted from the module.
|
||||
|
||||
Args:
|
||||
module (string or module)- python path, absolute path or a module.
|
||||
variable (string or iterable) - single variable name or iterable of
|
||||
variable names to extract.
|
||||
default (string) - default value to use if a variable fails
|
||||
to be extracted. Ignored if `variable` is not given.
|
||||
module (string or module): Python path, absolute path or a module.
|
||||
variable (string or iterable, optional): Single variable name or iterable
|
||||
of variable names to extract. If not given, all variables in
|
||||
the module will be returned.
|
||||
default (string, optional): Default value to use if a variable fails to
|
||||
be extracted. Ignored if `variable` is not given.
|
||||
|
||||
Returns:
|
||||
a single value or a list of values depending on the type of
|
||||
`variable` argument. Errors in lists are replaced by the
|
||||
`default` argument.
|
||||
variables (value or list): A single value or a list of values
|
||||
depending on if `variable` is given or not. Errors in lists
|
||||
are replaced by the `default` argument.
|
||||
|
||||
"""
|
||||
|
||||
if not module:
|
||||
|
|
@ -856,8 +1043,20 @@ def string_from_module(module, variable=None, default=None):
|
|||
"""
|
||||
This is a wrapper for `variable_from_module` that requires return
|
||||
value to be a string to pass. It's primarily used by login screen.
|
||||
if `variable` is not set, returns a list of all string variables in
|
||||
`module`.
|
||||
|
||||
Args:
|
||||
module (string or module): Python path, absolute path or a module.
|
||||
variable (string or iterable, optional): Single variable name or iterable
|
||||
of variable names to extract. If not given, all variables in
|
||||
the module will be returned.
|
||||
default (string, optional): Default value to use if a variable fails to
|
||||
be extracted. Ignored if `variable` is not given.
|
||||
|
||||
Returns:
|
||||
variables (value or list): A single (string) value or a list of values
|
||||
depending on if `variable` is given or not. Errors in lists (such
|
||||
as the value not being a string) are replaced by the `default` argument.
|
||||
|
||||
"""
|
||||
val = variable_from_module(module, variable=variable, default=default)
|
||||
if val:
|
||||
|
|
@ -868,23 +1067,38 @@ def string_from_module(module, variable=None, default=None):
|
|||
return result if result else default
|
||||
return default
|
||||
|
||||
|
||||
def random_string_from_module(module):
|
||||
"""
|
||||
Returns a random global string from a module.
|
||||
|
||||
Args:
|
||||
module (string or module): Python path, absolute path or a module.
|
||||
|
||||
Returns:
|
||||
random (string): A random stribg variable from `module`.
|
||||
"""
|
||||
return random.choice(string_from_module(module))
|
||||
|
||||
|
||||
def fuzzy_import_from_module(path, variable, default=None, defaultpaths=None):
|
||||
"""
|
||||
Import a variable based on a fuzzy path. First the literal
|
||||
`path` will be tried, then all given `defaultpaths` will be
|
||||
prepended to see a match is found.
|
||||
|
||||
path - full or partial python path.
|
||||
variable - name of variable to import from module.
|
||||
defaultpaths - an iterable of python paths to attempt
|
||||
in order if importing directly from
|
||||
`path` doesn't work.
|
||||
Args:
|
||||
path (str): Full or partial python path.
|
||||
variable (str): Name of variable to import from module.
|
||||
default (string, optional): Default value to use if a variable fails to
|
||||
be extracted. Ignored if `variable` is not given.
|
||||
defaultpaths (iterable, options): Python paths to attempt in order if
|
||||
importing directly from `path` doesn't work.
|
||||
|
||||
Returns:
|
||||
value (any): The variable imported from the module, or `default`, if
|
||||
not found.
|
||||
|
||||
"""
|
||||
paths = [path] + make_iter(defaultpaths)
|
||||
for modpath in paths:
|
||||
|
|
@ -898,13 +1112,23 @@ def fuzzy_import_from_module(path, variable, default=None, defaultpaths=None):
|
|||
return getattr(mod, variable, default)
|
||||
return default
|
||||
|
||||
|
||||
def class_from_module(path, defaultpaths=None):
|
||||
"""
|
||||
Return a class from a module, given the module's path. This is
|
||||
primarily used to convert db_typeclass_path:s to classes.
|
||||
|
||||
if a list of `defaultpaths` is given, try subsequent runs by
|
||||
prepending those paths to the given `path`.
|
||||
Args:
|
||||
path (str): Full Python dot-path to module.
|
||||
defaultpaths (iterable, optional): If a direc import from `path` fails,
|
||||
try subsequent imports by prepending those paths to `path`.
|
||||
|
||||
Returns:
|
||||
class (Class): An uninstatiated class recovered from path.
|
||||
|
||||
Raises:
|
||||
ImportError: If all loading failed.
|
||||
|
||||
"""
|
||||
cls = None
|
||||
if defaultpaths:
|
||||
|
|
@ -949,14 +1173,10 @@ object_from_module = class_from_module
|
|||
|
||||
def init_new_player(player):
|
||||
"""
|
||||
Helper method to call all hooks, set flags etc on a newly created
|
||||
player (and potentially their character, if it exists already).
|
||||
Deprecated.
|
||||
"""
|
||||
# the FIRST_LOGIN flags are necessary for the system to call
|
||||
# the relevant first-login hooks.
|
||||
#if player.character:
|
||||
# player.character.db.FIRST_LOGIN = True
|
||||
player.db.FIRST_LOGIN = True
|
||||
from evennia.utils import logger
|
||||
logger.log_depmsg("evennia.utils.utils.init_new_player is DEPRECATED and should not be used.")
|
||||
|
||||
|
||||
def string_similarity(string1, string2):
|
||||
|
|
@ -967,8 +1187,14 @@ def string_similarity(string1, string2):
|
|||
The measure-vectors used is simply a "bag of words" type histogram
|
||||
(but for letters).
|
||||
|
||||
The function returns a value 0...1 rating how similar the two strings
|
||||
are. The strings can contain multiple words.
|
||||
Args:
|
||||
string1 (str): String to compare (may contain any number of words).
|
||||
string2 (str): Second string to compare (any number of words).
|
||||
|
||||
Returns:
|
||||
similarity (float): A value 0...1 rating how similar the two
|
||||
strings are.
|
||||
|
||||
"""
|
||||
vocabulary = set(list(string1 + string2))
|
||||
vec1 = [string1.count(v) for v in vocabulary]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue