Make PEP8 cleanup of line spaces and character distances as well as indents
This commit is contained in:
parent
7ff783fea1
commit
b278337172
189 changed files with 2039 additions and 1583 deletions
|
|
@ -142,7 +142,7 @@ class ANSIParser(object):
|
|||
(r'|[C', ANSI_BACK_CYAN),
|
||||
(r'|[W', ANSI_BACK_WHITE), # light grey background
|
||||
(r'|[X', ANSI_BACK_BLACK) # pure black background
|
||||
]
|
||||
]
|
||||
|
||||
ansi_xterm256_bright_bg_map = [
|
||||
# "bright" ANSI backgrounds using xterm256 since ANSI
|
||||
|
|
@ -186,7 +186,7 @@ class ANSIParser(object):
|
|||
|
||||
# prepare regex matching
|
||||
brightbg_sub = re.compile(r"|".join([r"(?<!\|)%s" % re.escape(tup[0])
|
||||
for tup in ansi_xterm256_bright_bg_map]), re.DOTALL)
|
||||
for tup in ansi_xterm256_bright_bg_map]), re.DOTALL)
|
||||
xterm256_fg_sub = re.compile(r"|".join(xterm256_fg), re.DOTALL)
|
||||
xterm256_bg_sub = re.compile(r"|".join(xterm256_bg), re.DOTALL)
|
||||
xterm256_gfg_sub = re.compile(r"|".join(xterm256_gfg), re.DOTALL)
|
||||
|
|
@ -207,6 +207,7 @@ class ANSIParser(object):
|
|||
# escapes - these double-chars will be replaced with a single
|
||||
# instance of each
|
||||
ansi_escapes = re.compile(r"(%s)" % "|".join(ANSI_ESCAPES), re.DOTALL)
|
||||
|
||||
def sub_ansi(self, ansimatch):
|
||||
"""
|
||||
Replacer used by `re.sub` to replace ANSI
|
||||
|
|
@ -285,7 +286,7 @@ class ANSIParser(object):
|
|||
colval = 134 + ord(letter)
|
||||
|
||||
# ansi fallback logic expects r,g,b values in [0..5] range
|
||||
gray = (ord(letter)-97)/5.0
|
||||
gray = (ord(letter) - 97) / 5.0
|
||||
red, green, blue = gray, gray, gray
|
||||
|
||||
if use_xterm256:
|
||||
|
|
@ -532,6 +533,7 @@ def _spacing_preflight(func):
|
|||
functions used for padding ANSIStrings.
|
||||
|
||||
"""
|
||||
|
||||
def wrapped(self, width, fillchar=None):
|
||||
if fillchar is None:
|
||||
fillchar = " "
|
||||
|
|
@ -552,6 +554,7 @@ def _query_super(func_name):
|
|||
of ANSIString.
|
||||
|
||||
"""
|
||||
|
||||
def wrapped(self, *args, **kwargs):
|
||||
return getattr(self.clean(), func_name)(*args, **kwargs)
|
||||
return wrapped
|
||||
|
|
@ -562,6 +565,7 @@ 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)
|
||||
try:
|
||||
|
|
@ -588,6 +592,7 @@ def _transform(func_name):
|
|||
with the resulting string.
|
||||
|
||||
"""
|
||||
|
||||
def wrapped(self, *args, **kwargs):
|
||||
replacement_string = _query_super(func_name)(self, *args, **kwargs)
|
||||
to_string = []
|
||||
|
|
@ -1107,7 +1112,7 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
|||
if next < 0:
|
||||
break
|
||||
# Get character codes after the index as well.
|
||||
res.append(self[next+bylen:end])
|
||||
res.append(self[next + bylen:end])
|
||||
end = next
|
||||
maxsplit -= 1 # NB. if it's already < 0, it stays < 0
|
||||
|
||||
|
|
@ -1151,7 +1156,7 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
|||
ic += 1
|
||||
ir1 += 1
|
||||
rstripped = ""
|
||||
ic, ir2 = nlen-1, len(raw)-1
|
||||
ic, ir2 = nlen - 1, len(raw) - 1
|
||||
while nrstripped:
|
||||
if nlen - ic > nrstripped:
|
||||
break
|
||||
|
|
@ -1161,7 +1166,7 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
|||
ic -= 1
|
||||
ir2 -= 1
|
||||
rstripped = rstripped[::-1]
|
||||
return ANSIString(lstripped + raw[ir1:ir2+1] + rstripped)
|
||||
return ANSIString(lstripped + raw[ir1:ir2 + 1] + rstripped)
|
||||
|
||||
def lstrip(self, chars=None):
|
||||
"""
|
||||
|
|
@ -1214,7 +1219,7 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
|||
nlen = len(clean)
|
||||
nrstripped = nlen - len(clean.rstrip(chars))
|
||||
rstripped = ""
|
||||
ic, ir2 = nlen-1, len(raw)-1
|
||||
ic, ir2 = nlen - 1, len(raw) - 1
|
||||
while nrstripped:
|
||||
if nlen - ic > nrstripped:
|
||||
break
|
||||
|
|
@ -1224,7 +1229,7 @@ class ANSIString(with_metaclass(ANSIMeta, unicode)):
|
|||
ic -= 1
|
||||
ir2 -= 1
|
||||
rstripped = rstripped[::-1]
|
||||
return ANSIString(raw[:ir2+1] + rstripped)
|
||||
return ANSIString(raw[:ir2 + 1] + rstripped)
|
||||
|
||||
def join(self, iterable):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ class BatchCommandProcessor(object):
|
|||
This class implements a batch-command processor.
|
||||
|
||||
"""
|
||||
|
||||
def parse_file(self, pythonpath):
|
||||
"""
|
||||
This parses the lines of a batchfile according to the following
|
||||
|
|
@ -413,5 +414,6 @@ class BatchCodeProcessor(object):
|
|||
return err
|
||||
return None
|
||||
|
||||
|
||||
BATCHCMD = BatchCommandProcessor()
|
||||
BATCHCODE = BatchCodeProcessor()
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ def create_object(typeclass=None, key=None, location=None, home=None,
|
|||
new_object.save()
|
||||
return new_object
|
||||
|
||||
|
||||
# alias for create_object
|
||||
object = create_object
|
||||
|
||||
|
|
@ -179,14 +180,22 @@ def create_script(typeclass=None, key=None, obj=None, account=None, locks=None,
|
|||
|
||||
# validate input
|
||||
kwarg = {}
|
||||
if key: kwarg["db_key"] = key
|
||||
if account: kwarg["db_account"] = dbid_to_obj(account, _ScriptDB)
|
||||
if obj: kwarg["db_obj"] = dbid_to_obj(obj, _ScriptDB)
|
||||
if interval: kwarg["db_interval"] = interval
|
||||
if start_delay: kwarg["db_start_delay"] = start_delay
|
||||
if repeats: kwarg["db_repeats"] = repeats
|
||||
if persistent: kwarg["db_persistent"] = persistent
|
||||
if desc: kwarg["db_desc"] = desc
|
||||
if key:
|
||||
kwarg["db_key"] = key
|
||||
if account:
|
||||
kwarg["db_account"] = dbid_to_obj(account, _ScriptDB)
|
||||
if obj:
|
||||
kwarg["db_obj"] = dbid_to_obj(obj, _ScriptDB)
|
||||
if interval:
|
||||
kwarg["db_interval"] = interval
|
||||
if start_delay:
|
||||
kwarg["db_start_delay"] = start_delay
|
||||
if repeats:
|
||||
kwarg["db_repeats"] = repeats
|
||||
if persistent:
|
||||
kwarg["db_persistent"] = persistent
|
||||
if desc:
|
||||
kwarg["db_desc"] = desc
|
||||
|
||||
# create new instance
|
||||
new_script = typeclass(**kwarg)
|
||||
|
|
@ -201,6 +210,7 @@ def create_script(typeclass=None, key=None, obj=None, account=None, locks=None,
|
|||
new_script.save()
|
||||
return new_script
|
||||
|
||||
|
||||
# alias
|
||||
script = create_script
|
||||
|
||||
|
|
@ -250,6 +260,8 @@ def create_help_entry(key, entrytext, category="General", locks=None, aliases=No
|
|||
except Exception:
|
||||
logger.log_trace()
|
||||
return None
|
||||
|
||||
|
||||
# alias
|
||||
help_entry = create_help_entry
|
||||
|
||||
|
|
@ -301,6 +313,8 @@ def create_message(senderobj, message, channels=None, receivers=None, locks=None
|
|||
new_message.locks.add(locks)
|
||||
new_message.save()
|
||||
return new_message
|
||||
|
||||
|
||||
message = create_message
|
||||
|
||||
|
||||
|
|
@ -348,6 +362,7 @@ def create_channel(key, aliases=None, desc=None,
|
|||
new_channel.save()
|
||||
return new_channel
|
||||
|
||||
|
||||
channel = create_channel
|
||||
|
||||
|
||||
|
|
@ -357,11 +372,10 @@ channel = create_channel
|
|||
|
||||
|
||||
def create_account(key, email, password,
|
||||
typeclass=None,
|
||||
is_superuser=False,
|
||||
locks=None, permissions=None,
|
||||
report_to=None):
|
||||
|
||||
typeclass=None,
|
||||
is_superuser=False,
|
||||
locks=None, permissions=None,
|
||||
report_to=None):
|
||||
"""
|
||||
This creates a new account.
|
||||
|
||||
|
|
@ -416,8 +430,8 @@ def create_account(key, email, password,
|
|||
now = timezone.now()
|
||||
email = typeclass.objects.normalize_email(email)
|
||||
new_account = typeclass(username=key, email=email,
|
||||
is_staff=is_superuser, is_superuser=is_superuser,
|
||||
last_login=now, date_joined=now)
|
||||
is_staff=is_superuser, is_superuser=is_superuser,
|
||||
last_login=now, date_joined=now)
|
||||
new_account.set_password(password)
|
||||
new_account._createdict = dict(locks=locks, permissions=permissions, report_to=report_to)
|
||||
# saving will trigger the signal that calls the
|
||||
|
|
@ -426,5 +440,6 @@ def create_account(key, email, password,
|
|||
new_account.save()
|
||||
return new_account
|
||||
|
||||
|
||||
# alias
|
||||
account = create_account
|
||||
|
|
|
|||
|
|
@ -56,13 +56,22 @@ def _get_mysql_db_version():
|
|||
|
||||
# initialization and helpers
|
||||
|
||||
|
||||
_GA = object.__getattribute__
|
||||
_SA = object.__setattr__
|
||||
_FROM_MODEL_MAP = None
|
||||
_TO_MODEL_MAP = None
|
||||
_SESSION_HANDLER = None
|
||||
_IS_PACKED_DBOBJ = lambda o: type(o) == tuple and len(o) == 4 and o[0] == '__packed_dbobj__'
|
||||
_IS_PACKED_SESSION = lambda o: type(o) == tuple and len(o) == 3 and o[0] == '__packed_session__'
|
||||
|
||||
|
||||
def _IS_PACKED_DBOBJ(o):
|
||||
return isinstance(o, tuple) and len(o) == 4 and o[0] == '__packed_dbobj__'
|
||||
|
||||
|
||||
def _IS_PACKED_SESSION(o):
|
||||
return isinstance(o, tuple) and len(o) == 3 and o[0] == '__packed_session__'
|
||||
|
||||
|
||||
if uses_database("mysql") and _get_mysql_db_version() < '5.6.4':
|
||||
# mysql <5.6.4 don't support millisecond precision
|
||||
_DATESTRING = "%Y:%m:%d-%H:%M:%S:000000"
|
||||
|
|
@ -112,6 +121,7 @@ def _init_globals():
|
|||
|
||||
def _save(method):
|
||||
"""method decorator that saves data to Attribute"""
|
||||
|
||||
def save_wrapper(self, *args, **kwargs):
|
||||
self.__doc__ = method.__doc__
|
||||
ret = method(self, *args, **kwargs)
|
||||
|
|
@ -127,6 +137,7 @@ class _SaverMutable(object):
|
|||
obj.db.mylist[1][2] = "test" (allocation to a nested list)
|
||||
will not save the updated value to the database.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""store all properties for tracking the tree"""
|
||||
self._parent = kwargs.pop("_parent", None)
|
||||
|
|
@ -196,6 +207,7 @@ class _SaverList(_SaverMutable, MutableSequence):
|
|||
"""
|
||||
A list that saves itself to an Attribute when updated.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(_SaverList, self).__init__(*args, **kwargs)
|
||||
self._data = list()
|
||||
|
|
@ -223,6 +235,7 @@ class _SaverDict(_SaverMutable, MutableMapping):
|
|||
"""
|
||||
A dict that stores changes to an Attribute when updated
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(_SaverDict, self).__init__(*args, **kwargs)
|
||||
self._data = dict()
|
||||
|
|
@ -235,6 +248,7 @@ class _SaverSet(_SaverMutable, MutableSet):
|
|||
"""
|
||||
A set that saves to an Attribute when updated
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(_SaverSet, self).__init__(*args, **kwargs)
|
||||
self._data = set()
|
||||
|
|
@ -255,6 +269,7 @@ class _SaverOrderedDict(_SaverMutable, MutableMapping):
|
|||
"""
|
||||
An ordereddict that can be saved and operated on.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(_SaverOrderedDict, self).__init__(*args, **kwargs)
|
||||
self._data = OrderedDict()
|
||||
|
|
@ -267,6 +282,7 @@ class _SaverDeque(_SaverMutable):
|
|||
"""
|
||||
A deque that can be saved and operated on.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(_SaverDeque, self).__init__(*args, **kwargs)
|
||||
self._data = deque()
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ class CmdLineInput(CmdEditorBase):
|
|||
indent = "off"
|
||||
|
||||
self.caller.msg("|b%02i|||n (|g%s|n) %s" % (
|
||||
cline, indent, raw(line)))
|
||||
cline, indent, raw(line)))
|
||||
else:
|
||||
self.caller.msg("|b%02i|||n %s" % (cline, raw(self.args)))
|
||||
|
||||
|
|
@ -643,7 +643,7 @@ class CmdEditorGroup(CmdEditorBase):
|
|||
indent = editor._indent
|
||||
if indent >= 0:
|
||||
caller.msg("Decreased indentation: new indentation is {}.".format(
|
||||
indent))
|
||||
indent))
|
||||
else:
|
||||
caller.msg("|rManual indentation is OFF.|n Use := to turn it on.")
|
||||
else:
|
||||
|
|
@ -655,7 +655,7 @@ class CmdEditorGroup(CmdEditorBase):
|
|||
indent = editor._indent
|
||||
if indent >= 0:
|
||||
caller.msg("Increased indentation: new indentation is {}.".format(
|
||||
indent))
|
||||
indent))
|
||||
else:
|
||||
caller.msg("|rManual indentation is OFF.|n Use := to turn it on.")
|
||||
else:
|
||||
|
|
@ -780,7 +780,7 @@ class EvEditor(object):
|
|||
caller.attributes.add("_eveditor_buffer_temp", (self._buffer, self._undo_buffer))
|
||||
caller.attributes.add("_eveditor_unsaved", False)
|
||||
caller.attributes.add("_eveditor_indent", 0)
|
||||
except Exception, err:
|
||||
except Exception as err:
|
||||
caller.msg(_ERROR_PERSISTENT_SAVING.format(error=err))
|
||||
logger.log_trace(_TRACE_PERSISTENT_SAVING)
|
||||
persistent = False
|
||||
|
|
@ -929,7 +929,7 @@ class EvEditor(object):
|
|||
nchars = len(buf)
|
||||
|
||||
sep = self._sep
|
||||
header = "|n" + sep * 10 + "Line Editor [%s]" % self._key + sep * (_DEFAULT_WIDTH-20-len(self._key))
|
||||
header = "|n" + sep * 10 + "Line Editor [%s]" % self._key + sep * (_DEFAULT_WIDTH - 20 - len(self._key))
|
||||
footer = "|n" + sep * 10 +\
|
||||
"[l:%02i w:%03i c:%04i]" % (nlines, nwords, nchars) + sep * 12 + "(:h for help)" + sep * 28
|
||||
if linenums:
|
||||
|
|
@ -956,10 +956,10 @@ class EvEditor(object):
|
|||
|
||||
"""
|
||||
keywords = {
|
||||
"elif ": ["if "],
|
||||
"else:": ["if ", "try"],
|
||||
"except": ["try:"],
|
||||
"finally:": ["try:"],
|
||||
"elif ": ["if "],
|
||||
"else:": ["if ", "try"],
|
||||
"except": ["try:"],
|
||||
"finally:": ["try:"],
|
||||
}
|
||||
opening_tags = ("if ", "try:", "for ", "while ")
|
||||
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ def _to_ansi(obj, regexable=False):
|
|||
else:
|
||||
return ANSIString(to_unicode(obj), regexable=regexable)
|
||||
|
||||
|
||||
class EvForm(object):
|
||||
"""
|
||||
This object is instantiated with a text file and parses
|
||||
|
|
@ -174,6 +175,7 @@ class EvForm(object):
|
|||
EvCell or Tables.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, filename=None, cells=None, tables=None, form=None, **kwargs):
|
||||
"""
|
||||
Initiate the form
|
||||
|
|
@ -194,7 +196,7 @@ class EvForm(object):
|
|||
self.filename = filename
|
||||
self.input_form_dict = form
|
||||
|
||||
self.cells_mapping = dict((to_str(key, force_string=True), value) for key, value in cells.items()) if cells else {}
|
||||
self.cells_mapping = dict((to_str(key, force_string=True), value) for key, value in cells.items()) if cells else {}
|
||||
self.tables_mapping = dict((to_str(key, force_string=True), value) for key, value in tables.items()) if tables else {}
|
||||
|
||||
self.cellchar = "x"
|
||||
|
|
@ -232,7 +234,7 @@ class EvForm(object):
|
|||
table_coords = {}
|
||||
|
||||
# Locate the identifier tags and the horizontal end coords for all forms
|
||||
re_cellchar = re.compile(r"%s+([^%s%s]+)%s+" % (cellchar, INVALID_FORMCHARS, cellchar, cellchar))
|
||||
re_cellchar = re.compile(r"%s+([^%s%s]+)%s+" % (cellchar, INVALID_FORMCHARS, cellchar, cellchar))
|
||||
re_tablechar = re.compile(r"%s+([^%s%s|+])%s+" % (tablechar, INVALID_FORMCHARS, tablechar, tablechar))
|
||||
for iy, line in enumerate(_to_ansi(form, regexable=True)):
|
||||
# find cells
|
||||
|
|
@ -262,16 +264,16 @@ class EvForm(object):
|
|||
# scan up to find top of rectangle
|
||||
dy_up = 0
|
||||
if iy > 0:
|
||||
for i in range(1,iy):
|
||||
if all(form[iy-i][ix] == cellchar for ix in range(leftix, rightix)):
|
||||
for i in range(1, iy):
|
||||
if all(form[iy - i][ix] == cellchar for ix in range(leftix, rightix)):
|
||||
dy_up += 1
|
||||
else:
|
||||
break
|
||||
# find bottom edge of rectangle
|
||||
dy_down = 0
|
||||
if iy < nform-1:
|
||||
for i in range(1,nform-iy-1):
|
||||
if all(form[iy+i][ix] == cellchar for ix in range(leftix, rightix)):
|
||||
if iy < nform - 1:
|
||||
for i in range(1, nform - iy - 1):
|
||||
if all(form[iy + i][ix] == cellchar for ix in range(leftix, rightix)):
|
||||
dy_down += 1
|
||||
else:
|
||||
break
|
||||
|
|
@ -284,13 +286,13 @@ class EvForm(object):
|
|||
|
||||
# we have all the coordinates we need. Create EvCell.
|
||||
data = self.cells_mapping.get(key, "")
|
||||
#if key == "1":
|
||||
# if key == "1":
|
||||
|
||||
options = { "pad_left":0, "pad_right":0, "pad_top":0, "pad_bottom":0, "align":"l", "valign":"t", "enforce_size":True}
|
||||
options = {"pad_left": 0, "pad_right": 0, "pad_top": 0, "pad_bottom": 0, "align": "l", "valign": "t", "enforce_size": True}
|
||||
options.update(custom_options)
|
||||
#if key=="4":
|
||||
# if key=="4":
|
||||
|
||||
mapping[key] = (iyup, leftix, width, height, EvCell(data, width=width, height=height,**options))
|
||||
mapping[key] = (iyup, leftix, width, height, EvCell(data, width=width, height=height, **options))
|
||||
|
||||
# get rectangles and assign Tables
|
||||
for key, (iy, leftix, rightix) in table_coords.items():
|
||||
|
|
@ -298,16 +300,16 @@ class EvForm(object):
|
|||
# scan up to find top of rectangle
|
||||
dy_up = 0
|
||||
if iy > 0:
|
||||
for i in range(1,iy):
|
||||
if all(form[iy-i][ix] == tablechar for ix in range(leftix, rightix)):
|
||||
for i in range(1, iy):
|
||||
if all(form[iy - i][ix] == tablechar for ix in range(leftix, rightix)):
|
||||
dy_up += 1
|
||||
else:
|
||||
break
|
||||
# find bottom edge of rectangle
|
||||
dy_down = 0
|
||||
if iy < nform-1:
|
||||
for i in range(1,nform-iy-1):
|
||||
if all(form[iy+i][ix] == tablechar for ix in range(leftix, rightix)):
|
||||
if iy < nform - 1:
|
||||
for i in range(1, nform - iy - 1):
|
||||
if all(form[iy + i][ix] == tablechar for ix in range(leftix, rightix)):
|
||||
dy_down += 1
|
||||
else:
|
||||
break
|
||||
|
|
@ -321,8 +323,8 @@ class EvForm(object):
|
|||
# we have all the coordinates we need. Create Table.
|
||||
table = self.tables_mapping.get(key, None)
|
||||
|
||||
options = { "pad_left":0, "pad_right":0, "pad_top":0, "pad_bottom":0,
|
||||
"align":"l", "valign":"t", "enforce_size":True}
|
||||
options = {"pad_left": 0, "pad_right": 0, "pad_top": 0, "pad_bottom": 0,
|
||||
"align": "l", "valign": "t", "enforce_size": True}
|
||||
options.update(custom_options)
|
||||
|
||||
if table:
|
||||
|
|
@ -343,9 +345,9 @@ class EvForm(object):
|
|||
# rect is a list of <height> lines, each <width> wide
|
||||
rect = cell_or_table.get()
|
||||
for il, rectline in enumerate(rect):
|
||||
formline = form[iy0+il]
|
||||
formline = form[iy0 + il]
|
||||
# insert new content, replacing old
|
||||
form[iy0+il] = formline[:ix0] + rectline + formline[ix0+width:]
|
||||
form[iy0 + il] = formline[:ix0] + rectline + formline[ix0 + width:]
|
||||
return form
|
||||
|
||||
def map(self, cells=None, tables=None, **kwargs):
|
||||
|
|
@ -366,7 +368,7 @@ class EvForm(object):
|
|||
kwargs.pop("width", None)
|
||||
kwargs.pop("height", None)
|
||||
|
||||
new_cells = dict((to_str(key, force_string=True), value) for key, value in cells.items()) if cells else {}
|
||||
new_cells = dict((to_str(key, force_string=True), value) for key, value in cells.items()) if cells else {}
|
||||
new_tables = dict((to_str(key, force_string=True), value) for key, value in tables.items()) if tables else {}
|
||||
|
||||
self.cells_mapping.update(new_cells)
|
||||
|
|
@ -424,6 +426,7 @@ class EvForm(object):
|
|||
"prints the form"
|
||||
return unicode(ANSIString("\n").join([line for line in self.form]))
|
||||
|
||||
|
||||
def _test():
|
||||
"test evform. This is used by the unittest system."
|
||||
form = EvForm("evennia.utils.evform_test")
|
||||
|
|
@ -434,18 +437,18 @@ def _test():
|
|||
3: "A sturdy fellow",
|
||||
4: 12,
|
||||
5: 10,
|
||||
6: 5,
|
||||
6: 5,
|
||||
7: 18,
|
||||
8: 10,
|
||||
9: 3})
|
||||
9: 3})
|
||||
# create the EvTables
|
||||
tableA = EvTable("HP","MV","MP",
|
||||
table=[["**"], ["*****"], ["***"]],
|
||||
border="incols")
|
||||
tableA = EvTable("HP", "MV", "MP",
|
||||
table=[["**"], ["*****"], ["***"]],
|
||||
border="incols")
|
||||
tableB = EvTable("Skill", "Value", "Exp",
|
||||
table=[["Shooting", "Herbalism", "Smithing"],
|
||||
[12,14,9],["550/1200", "990/1400", "205/900"]],
|
||||
border="incols")
|
||||
table=[["Shooting", "Herbalism", "Smithing"],
|
||||
[12, 14, 9], ["550/1200", "990/1400", "205/900"]],
|
||||
border="incols")
|
||||
# add the tables to the proper ids in the form
|
||||
form.map(tables={"A": tableA,
|
||||
"B": tableB})
|
||||
|
|
|
|||
|
|
@ -28,5 +28,3 @@ FORM = """
|
|||
| | |
|
||||
-----------`-------------------------------------
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ class CmdEvMenuNode(Command):
|
|||
if not menu:
|
||||
# can't restore from a session
|
||||
err = "Menu object not found as %s.ndb._menutree!" % orig_caller
|
||||
orig_caller.msg(err) # don't give the session as a kwarg here, direct to original
|
||||
orig_caller.msg(err) # don't give the session as a kwarg here, direct to original
|
||||
raise EvMenuError(err)
|
||||
# we must do this after the caller with the menui has been correctly identified since it
|
||||
# can be either Account, Object or Session (in the latter case this info will be superfluous).
|
||||
|
|
@ -299,6 +299,7 @@ class EvMenu(object):
|
|||
a menufile.py instruction.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, caller, menudata, startnode="start",
|
||||
cmdset_mergetype="Replace", cmdset_priority=1,
|
||||
auto_quit=True, auto_look=True, auto_help=True,
|
||||
|
|
@ -419,8 +420,8 @@ class EvMenu(object):
|
|||
|
||||
# assign kwargs as initialization vars on ourselves.
|
||||
if set(("_startnode", "_menutree", "_session", "_persistent",
|
||||
"cmd_on_exit", "default", "nodetext", "helptext",
|
||||
"options", "cmdset_mergetype", "auto_quit")).intersection(set(kwargs.keys())):
|
||||
"cmd_on_exit", "default", "nodetext", "helptext",
|
||||
"options", "cmdset_mergetype", "auto_quit")).intersection(set(kwargs.keys())):
|
||||
raise RuntimeError("One or more of the EvMenu `**kwargs` is reserved by EvMenu for internal use.")
|
||||
for key, val in kwargs.iteritems():
|
||||
setattr(self, key, val)
|
||||
|
|
@ -686,7 +687,7 @@ class EvMenu(object):
|
|||
goto, execute = dic.get("goto", None), dic.get("exec", None)
|
||||
self.default = (goto, execute)
|
||||
else:
|
||||
keys = list(make_iter(dic.get("key", str(inum+1).strip())))
|
||||
keys = list(make_iter(dic.get("key", str(inum + 1).strip())))
|
||||
desc = dic.get("desc", dic.get("text", _ERR_NO_OPTION_DESC).strip())
|
||||
goto, execute = dic.get("goto", None), dic.get("exec", None)
|
||||
if keys:
|
||||
|
|
@ -810,14 +811,14 @@ class EvMenu(object):
|
|||
# add a default white color to key
|
||||
table.append(" |lc%s|lt|w%s|n|le: %s" % (raw_key, raw_key, desc))
|
||||
|
||||
ncols = (_MAX_TEXT_WIDTH // table_width_max) + 1 # number of ncols
|
||||
ncols = (_MAX_TEXT_WIDTH // table_width_max) + 1 # number of ncols
|
||||
|
||||
# get the amount of rows needed (start with 4 rows)
|
||||
nrows = 4
|
||||
while nrows * ncols < nlist:
|
||||
nrows += 1
|
||||
ncols = nlist // nrows # number of full columns
|
||||
nlastcol = nlist % nrows # number of elements in last column
|
||||
ncols = nlist // nrows # number of full columns
|
||||
nlastcol = nlist % nrows # number of elements in last column
|
||||
|
||||
# get the final column count
|
||||
ncols = ncols + 1 if nlastcol > 0 else ncols
|
||||
|
|
@ -826,7 +827,7 @@ class EvMenu(object):
|
|||
table.extend([" " for i in range(nrows - nlastcol)])
|
||||
|
||||
# build the actual table grid
|
||||
table = [table[icol * nrows : (icol * nrows) + nrows] for icol in range(0, ncols)]
|
||||
table = [table[icol * nrows: (icol * nrows) + nrows] for icol in range(0, ncols)]
|
||||
|
||||
# adjust the width of each column
|
||||
for icol in range(len(table)):
|
||||
|
|
@ -857,7 +858,6 @@ class EvMenu(object):
|
|||
return separator1 + "|n" + nodetext + "|n" + separator2 + "|n" + optionstext
|
||||
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Simple input shortcuts
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ _SCREEN_HEIGHT = settings.CLIENT_DEFAULT_HEIGHT
|
|||
# text
|
||||
|
||||
_DISPLAY = \
|
||||
"""{text}
|
||||
"""{text}
|
||||
(|wmore|n [{pageno}/{pagemax}] retur|wn|n|||wb|nack|||wt|nop|||we|nnd|||wq|nuit)"""
|
||||
|
||||
|
||||
|
|
@ -82,6 +82,7 @@ class CmdMore(Command):
|
|||
# return or n, next
|
||||
more.page_next()
|
||||
|
||||
|
||||
class CmdMoreLook(Command):
|
||||
"""
|
||||
Override look to display window and prevent OOCLook from firing
|
||||
|
|
@ -89,6 +90,7 @@ class CmdMoreLook(Command):
|
|||
key = "look"
|
||||
aliases = ["l"]
|
||||
auto_help = False
|
||||
|
||||
def func(self):
|
||||
"""
|
||||
Implement the command
|
||||
|
|
@ -118,8 +120,9 @@ class EvMore(object):
|
|||
"""
|
||||
The main pager object
|
||||
"""
|
||||
|
||||
def __init__(self, caller, text, always_page=False, session=None,
|
||||
justify_kwargs=None, exit_on_lastpage=False, **kwargs):
|
||||
justify_kwargs=None, exit_on_lastpage=False, **kwargs):
|
||||
"""
|
||||
Initialization of the text handler.
|
||||
|
||||
|
|
@ -159,8 +162,8 @@ class EvMore(object):
|
|||
self._session = session
|
||||
|
||||
# set up individual pages for different sessions
|
||||
height = max(4, session.protocol_flags.get("SCREENHEIGHT", {0:_SCREEN_HEIGHT})[0] - 4)
|
||||
width = session.protocol_flags.get("SCREENWIDTH", {0:_SCREEN_WIDTH})[0]
|
||||
height = max(4, session.protocol_flags.get("SCREENHEIGHT", {0: _SCREEN_HEIGHT})[0] - 4)
|
||||
width = session.protocol_flags.get("SCREENWIDTH", {0: _SCREEN_WIDTH})[0]
|
||||
|
||||
if justify_kwargs is False:
|
||||
# no justification. Simple division by line
|
||||
|
|
@ -183,7 +186,7 @@ class EvMore(object):
|
|||
# always limit number of chars to 10 000 per page
|
||||
height = min(10000 // max(1, width), height)
|
||||
|
||||
self._pages = ["\n".join(lines[i:i+height]) for i in range(0, len(lines), height)]
|
||||
self._pages = ["\n".join(lines[i:i + height]) for i in range(0, len(lines), height)]
|
||||
self._npages = len(self._pages)
|
||||
self._npos = 0
|
||||
|
||||
|
|
@ -246,7 +249,6 @@ class EvMore(object):
|
|||
if self.exit_on_lastpage and self._pos == self._pos >= self._npages - 1:
|
||||
self.page_quit()
|
||||
|
||||
|
||||
def page_back(self):
|
||||
"""
|
||||
Scroll the text back up, at the most to the top.
|
||||
|
|
@ -283,5 +285,4 @@ def msg(caller, text="", always_page=False, session=None, justify_kwargs=None, *
|
|||
|
||||
"""
|
||||
EvMore(caller, text, always_page=always_page, session=session,
|
||||
justify_kwargs=justify_kwargs, **kwargs)
|
||||
|
||||
justify_kwargs=justify_kwargs, **kwargs)
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@ class EvCell(object):
|
|||
and resize as needed.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, data, **kwargs):
|
||||
"""
|
||||
Args:
|
||||
|
|
@ -472,7 +473,7 @@ class EvCell(object):
|
|||
"""
|
||||
if m_len(text) > width:
|
||||
crop_string = self.crop_string
|
||||
return text[:width-m_len(crop_string)] + crop_string
|
||||
return text[:width - m_len(crop_string)] + crop_string
|
||||
return text
|
||||
|
||||
def _reformat(self):
|
||||
|
|
@ -661,7 +662,7 @@ class EvCell(object):
|
|||
left = self.border_left_char * self.border_left + ANSIString('|n')
|
||||
right = ANSIString('|n') + self.border_right_char * self.border_right
|
||||
|
||||
cwidth = self.width + self.pad_left + self.pad_right + max(0, self.border_left-1) + max(0, self.border_right-1)
|
||||
cwidth = self.width + self.pad_left + self.pad_right + max(0, self.border_left - 1) + max(0, self.border_right - 1)
|
||||
|
||||
vfill = self.corner_top_left_char if left else ""
|
||||
vfill += cwidth * self.border_top_char
|
||||
|
|
@ -849,7 +850,7 @@ class EvCell(object):
|
|||
return unicode(ANSIString("\n").join(self.formatted))
|
||||
|
||||
|
||||
## EvColumn class
|
||||
# EvColumn class
|
||||
|
||||
class EvColumn(object):
|
||||
"""
|
||||
|
|
@ -861,7 +862,8 @@ class EvColumn(object):
|
|||
incorporated into an EvTable (like EvCells)
|
||||
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Args:
|
||||
Text for each row in the column
|
||||
|
|
@ -918,7 +920,7 @@ class EvColumn(object):
|
|||
self.column.extend([EvCell(data, **self.options) for data in args])
|
||||
else:
|
||||
# insert cells before given index
|
||||
ypos = min(len(self.column)-1, max(0, int(ypos)))
|
||||
ypos = min(len(self.column) - 1, max(0, int(ypos)))
|
||||
new_cells = [EvCell(data, **self.options) for data in args]
|
||||
self.column = self.column[:ypos] + new_cells + self.column[ypos:]
|
||||
# self._balance(**kwargs)
|
||||
|
|
@ -1223,7 +1225,7 @@ class EvTable(object):
|
|||
"""
|
||||
Add borders to table. This is called from self._balance.
|
||||
"""
|
||||
nx, ny = self.ncols-1, self.nrows-1
|
||||
nx, ny = self.ncols - 1, self.nrows - 1
|
||||
options = self.options
|
||||
for ix, col in enumerate(self.worktable):
|
||||
for iy, cell in enumerate(col):
|
||||
|
|
@ -1254,7 +1256,7 @@ class EvTable(object):
|
|||
self.worktable[icol].reformat(**options)
|
||||
if nrow < nrowmax:
|
||||
# add more rows to too-short columns
|
||||
empty_rows = ["" for _ in range(nrowmax-nrow)]
|
||||
empty_rows = ["" for _ in range(nrowmax - nrow)]
|
||||
self.worktable[icol].add_rows(*empty_rows)
|
||||
self.ncols = ncols
|
||||
self.nrows = nrowmax
|
||||
|
|
@ -1441,7 +1443,7 @@ class EvTable(object):
|
|||
self.table.append(column)
|
||||
else:
|
||||
# insert column
|
||||
xpos = min(wtable-1, max(0, int(xpos)))
|
||||
xpos = min(wtable - 1, max(0, int(xpos)))
|
||||
self.table.insert(xpos, column)
|
||||
self.ncols += 1
|
||||
# self._balance()
|
||||
|
|
@ -1491,7 +1493,7 @@ class EvTable(object):
|
|||
col.add_rows(row[icol], **options)
|
||||
else:
|
||||
# insert row elsewhere
|
||||
ypos = min(htable-1, max(0, int(ypos)))
|
||||
ypos = min(htable - 1, max(0, int(ypos)))
|
||||
for icol, col in enumerate(self.table):
|
||||
col.add_rows(row[icol], ypos=ypos, **options)
|
||||
self.nrows += 1
|
||||
|
|
@ -1575,9 +1577,9 @@ def _test():
|
|||
print(unicode(table))
|
||||
return table
|
||||
|
||||
|
||||
def _test2():
|
||||
table = EvTable("|yHeading1|n", "|B|[GHeading2|n", "Heading3")
|
||||
for i in range(100):
|
||||
table.add_row("This is col 0, row %i" % i, "|gThis is col 1, row |w%i|n|g.|n" % i, "This is col 2, row %i" % i)
|
||||
return table
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ def server_epoch():
|
|||
global _SERVER_EPOCH
|
||||
if not _SERVER_EPOCH:
|
||||
_SERVER_EPOCH = ServerConfig.objects.conf("server_epoch", default=None) \
|
||||
or time.time() - runtime()
|
||||
or time.time() - runtime()
|
||||
return _SERVER_EPOCH
|
||||
|
||||
|
||||
|
|
@ -224,12 +224,12 @@ def schedule(callback, repeat=False, sec=None, min=None,
|
|||
repeats=-1 if repeat else 1)
|
||||
script.db.callback = callback
|
||||
script.db.gametime = {
|
||||
"sec": sec,
|
||||
"min": min,
|
||||
"hour": hour,
|
||||
"day": day,
|
||||
"month": month,
|
||||
"year": year,
|
||||
"sec": sec,
|
||||
"min": min,
|
||||
"hour": hour,
|
||||
"day": day,
|
||||
"month": month,
|
||||
"year": year,
|
||||
}
|
||||
return script
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ IDmapper extension to the default manager.
|
|||
"""
|
||||
from django.db.models.manager import Manager
|
||||
|
||||
|
||||
class SharedMemoryManager(Manager):
|
||||
# CL: this ensures our manager is used when accessing instances via
|
||||
# ForeignKey etc. (see docs)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ from __future__ import absolute_import, division
|
|||
from builtins import object
|
||||
from future.utils import listitems, listvalues, with_metaclass
|
||||
|
||||
import os, threading, gc, time
|
||||
import os
|
||||
import threading
|
||||
import gc
|
||||
import time
|
||||
from weakref import WeakValueDictionary
|
||||
from twisted.internet.reactor import callFromThread
|
||||
from django.core.exceptions import ObjectDoesNotExist, FieldError
|
||||
|
|
@ -22,7 +25,7 @@ from evennia.utils.utils import dbref, get_evennia_pids, to_str
|
|||
|
||||
from .manager import SharedMemoryManager
|
||||
|
||||
AUTO_FLUSH_MIN_INTERVAL = 60.0 * 5 # at least 5 mins between cache flushes
|
||||
AUTO_FLUSH_MIN_INTERVAL = 60.0 * 5 # at least 5 mins between cache flushes
|
||||
|
||||
_GA = object.__getattribute__
|
||||
_SA = object.__setattr__
|
||||
|
|
@ -39,9 +42,10 @@ PROC_MODIFIED_OBJS = WeakValueDictionary()
|
|||
# subprocess or not)
|
||||
_SELF_PID = os.getpid()
|
||||
_SERVER_PID, _PORTAL_PID = get_evennia_pids()
|
||||
_IS_SUBPROCESS = (_SERVER_PID and _PORTAL_PID) and not _SELF_PID in (_SERVER_PID, _PORTAL_PID)
|
||||
_IS_SUBPROCESS = (_SERVER_PID and _PORTAL_PID) and _SELF_PID not in (_SERVER_PID, _PORTAL_PID)
|
||||
_IS_MAIN_THREAD = threading.currentThread().getName() == "MainThread"
|
||||
|
||||
|
||||
class SharedMemoryModelBase(ModelBase):
|
||||
# CL: upstream had a __new__ method that skipped ModelBase's __new__ if
|
||||
# SharedMemoryModelBase was not in the model class's ancestors. It's not
|
||||
|
|
@ -69,7 +73,6 @@ class SharedMemoryModelBase(ModelBase):
|
|||
cls.cache_instance(cached_instance, new=True)
|
||||
return cached_instance
|
||||
|
||||
|
||||
def _prepare(cls):
|
||||
"""
|
||||
Prepare the cache, making sure that proxies of the same db base
|
||||
|
|
@ -102,7 +105,7 @@ class SharedMemoryModelBase(ModelBase):
|
|||
"""
|
||||
|
||||
attrs["typename"] = cls.__name__
|
||||
attrs["path"] = "%s.%s" % (attrs["__module__"], name)
|
||||
attrs["path"] = "%s.%s" % (attrs["__module__"], name)
|
||||
attrs["_is_deleted"] = False
|
||||
|
||||
# set up the typeclass handling only if a variable _is_typeclass is set on the class
|
||||
|
|
@ -113,14 +116,17 @@ class SharedMemoryModelBase(ModelBase):
|
|||
if _GA(cls, "_is_deleted"):
|
||||
raise ObjectDoesNotExist("Cannot access %s: Hosting object was already deleted." % fname)
|
||||
return _GA(cls, fieldname)
|
||||
|
||||
def _get_foreign(cls, fname):
|
||||
"Wrapper for returning foreignkey fields"
|
||||
if _GA(cls, "_is_deleted"):
|
||||
raise ObjectDoesNotExist("Cannot access %s: Hosting object was already deleted." % fname)
|
||||
return _GA(cls, fieldname)
|
||||
|
||||
def _set_nonedit(cls, fname, value):
|
||||
"Wrapper for blocking editing of field"
|
||||
raise FieldError("Field %s cannot be edited." % fname)
|
||||
|
||||
def _set(cls, fname, value):
|
||||
"Wrapper for setting database field"
|
||||
if _GA(cls, "_is_deleted"):
|
||||
|
|
@ -130,6 +136,7 @@ class SharedMemoryModelBase(ModelBase):
|
|||
# primary key assigned already (won't be set when first creating object)
|
||||
update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None
|
||||
_GA(cls, "save")(update_fields=update_fields)
|
||||
|
||||
def _set_foreign(cls, fname, value):
|
||||
"Setter only used on foreign key relations, allows setting with #dbref"
|
||||
if _GA(cls, "_is_deleted"):
|
||||
|
|
@ -153,9 +160,11 @@ class SharedMemoryModelBase(ModelBase):
|
|||
# primary key assigned already (won't be set when first creating object)
|
||||
update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None
|
||||
_GA(cls, "save")(update_fields=update_fields)
|
||||
|
||||
def _del_nonedit(cls, fname):
|
||||
"wrapper for not allowing deletion"
|
||||
raise FieldError("Field %s cannot be edited." % fname)
|
||||
|
||||
def _del(cls, fname):
|
||||
"Wrapper for clearing database field - sets it to None"
|
||||
_SA(cls, fname, None)
|
||||
|
|
@ -163,29 +172,31 @@ class SharedMemoryModelBase(ModelBase):
|
|||
_GA(cls, "save")(update_fields=update_fields)
|
||||
|
||||
# wrapper factories
|
||||
fget = lambda cls: _get(cls, fieldname)
|
||||
def fget(cls): return _get(cls, fieldname)
|
||||
if not editable:
|
||||
fset = lambda cls, val: _set_nonedit(cls, fieldname, val)
|
||||
def fset(cls, val): return _set_nonedit(cls, fieldname, val)
|
||||
elif foreignkey:
|
||||
fget = lambda cls: _get_foreign(cls, fieldname)
|
||||
fset = lambda cls, val: _set_foreign(cls, fieldname, val)
|
||||
def fget(cls): return _get_foreign(cls, fieldname)
|
||||
|
||||
def fset(cls, val): return _set_foreign(cls, fieldname, val)
|
||||
else:
|
||||
fset = lambda cls, val: _set(cls, fieldname, val)
|
||||
fdel = lambda cls: _del(cls, fieldname) if editable else _del_nonedit(cls,fieldname)
|
||||
def fset(cls, val): return _set(cls, fieldname, val)
|
||||
|
||||
def fdel(cls): return _del(cls, fieldname) if editable else _del_nonedit(cls, fieldname)
|
||||
# set docstrings for auto-doc
|
||||
fget.__doc__ = "A wrapper for getting database field `%s`." % fieldname
|
||||
fset.__doc__ = "A wrapper for setting (and saving) database field `%s`." % fieldname
|
||||
fdel.__doc__ = "A wrapper for deleting database field `%s`." % fieldname
|
||||
# assigning
|
||||
attrs[wrappername] = property(fget, fset, fdel)
|
||||
#type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel))#, doc))
|
||||
# type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel))#, doc))
|
||||
|
||||
# exclude some models that should not auto-create wrapper fields
|
||||
if cls.__name__ in ("ServerConfig", "TypeNick"):
|
||||
return
|
||||
# dynamically create the wrapper properties for all fields not already handled (manytomanyfields are always handlers)
|
||||
for fieldname, field in ((fname, field) for fname, field in listitems(attrs)
|
||||
if fname.startswith("db_") and type(field).__name__ != "ManyToManyField"):
|
||||
if fname.startswith("db_") and type(field).__name__ != "ManyToManyField"):
|
||||
foreignkey = type(field).__name__ == "ForeignKey"
|
||||
wrappername = "dbid" if fieldname == "id" else fieldname.replace("db_", "", 1)
|
||||
if wrappername not in attrs:
|
||||
|
|
@ -394,7 +405,7 @@ class SharedMemoryModel(with_metaclass(SharedMemoryModelBase, Model)):
|
|||
for fieldname in kwargs.get("update_fields"))
|
||||
else:
|
||||
# meta.fields are already field objects; get them all
|
||||
new =True
|
||||
new = True
|
||||
update_fields = self._meta.fields
|
||||
for field in update_fields:
|
||||
fieldname = field.name
|
||||
|
|
@ -454,7 +465,9 @@ def flush_cache(**kwargs):
|
|||
cls.flush_instance_cache()
|
||||
# run the python garbage collector
|
||||
return gc.collect()
|
||||
#request_finished.connect(flush_cache)
|
||||
|
||||
|
||||
# request_finished.connect(flush_cache)
|
||||
post_migrate.connect(flush_cache)
|
||||
|
||||
|
||||
|
|
@ -467,6 +480,8 @@ def flush_cached_instance(sender, instance, **kwargs):
|
|||
if not hasattr(instance, 'flush_cached_instance'):
|
||||
return
|
||||
sender.flush_cached_instance(instance, force=True)
|
||||
|
||||
|
||||
pre_delete.connect(flush_cached_instance)
|
||||
|
||||
|
||||
|
|
@ -478,10 +493,14 @@ def update_cached_instance(sender, instance, **kwargs):
|
|||
if not hasattr(instance, 'cache_instance'):
|
||||
return
|
||||
sender.cache_instance(instance)
|
||||
|
||||
|
||||
post_save.connect(update_cached_instance)
|
||||
|
||||
|
||||
LAST_FLUSH = None
|
||||
|
||||
|
||||
def conditional_flush(max_rmem, force=False):
|
||||
"""
|
||||
Flush the cache if the estimated memory usage exceeds `max_rmem`.
|
||||
|
|
@ -530,8 +549,8 @@ def conditional_flush(max_rmem, force=False):
|
|||
|
||||
if ((now - LAST_FLUSH) < AUTO_FLUSH_MIN_INTERVAL) and not force:
|
||||
# too soon after last flush.
|
||||
logger.log_warn("Warning: Idmapper flush called more than "\
|
||||
"once in %s min interval. Check memory usage." % (AUTO_FLUSH_MIN_INTERVAL/60.0))
|
||||
logger.log_warn("Warning: Idmapper flush called more than "
|
||||
"once in %s min interval. Check memory usage." % (AUTO_FLUSH_MIN_INTERVAL / 60.0))
|
||||
return
|
||||
|
||||
if os.name == "nt":
|
||||
|
|
@ -549,6 +568,7 @@ def conditional_flush(max_rmem, force=False):
|
|||
flush_cache()
|
||||
LAST_FLUSH = now
|
||||
|
||||
|
||||
def cache_size(mb=True):
|
||||
"""
|
||||
Calculate statistics about the cache.
|
||||
|
|
@ -564,8 +584,9 @@ def cache_size(mb=True):
|
|||
total_num, {objclass:total_num, ...}
|
||||
|
||||
"""
|
||||
numtotal = [0] # use mutable to keep reference through recursion
|
||||
numtotal = [0] # use mutable to keep reference through recursion
|
||||
classdict = {}
|
||||
|
||||
def get_recurse(submodels):
|
||||
for submodel in submodels:
|
||||
subclasses = submodel.__subclasses__()
|
||||
|
|
|
|||
|
|
@ -6,22 +6,27 @@ from django.test import TestCase
|
|||
from .models import SharedMemoryModel
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Category(SharedMemoryModel):
|
||||
name = models.CharField(max_length=32)
|
||||
|
||||
|
||||
class RegularCategory(models.Model):
|
||||
name = models.CharField(max_length=32)
|
||||
|
||||
|
||||
class Article(SharedMemoryModel):
|
||||
name = models.CharField(max_length=32)
|
||||
category = models.ForeignKey(Category)
|
||||
category2 = models.ForeignKey(RegularCategory)
|
||||
|
||||
|
||||
class RegularArticle(models.Model):
|
||||
name = models.CharField(max_length=32)
|
||||
category = models.ForeignKey(Category)
|
||||
category2 = models.ForeignKey(RegularCategory)
|
||||
|
||||
|
||||
class SharedMemorysTest(TestCase):
|
||||
# TODO: test for cross model relation (singleton to regular)
|
||||
|
||||
|
|
@ -58,7 +63,7 @@ class SharedMemorysTest(TestCase):
|
|||
|
||||
#article_list = Article.objects.all().select_related('category')
|
||||
#last_article = article_list[0]
|
||||
#for article in article_list[1:]:
|
||||
# for article in article_list[1:]:
|
||||
# self.assertEquals(article.category2 is last_article.category2, False)
|
||||
# last_article = article
|
||||
|
||||
|
|
@ -70,5 +75,3 @@ class SharedMemorysTest(TestCase):
|
|||
pk = article.pk
|
||||
article.delete()
|
||||
self.assertEquals(pk not in Article.__instance_cache__, True)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ def clr(*args, **kwargs):
|
|||
# found. This will be overloaded by any nomatch function defined in
|
||||
# the imported modules.
|
||||
_INLINE_FUNCS = {"nomatch": lambda *args, **kwargs: "<UKNOWN>",
|
||||
"stackfull": lambda *args, **kwargs: "\n (not parsed: inlinefunc stack size exceeded.)"}
|
||||
"stackfull": lambda *args, **kwargs: "\n (not parsed: inlinefunc stack size exceeded.)"}
|
||||
|
||||
|
||||
# load custom inline func modules.
|
||||
|
|
@ -172,7 +172,7 @@ for module in utils.make_iter(settings.INLINEFUNC_MODULES):
|
|||
if module == "server.conf.inlinefuncs":
|
||||
# a temporary warning since the default module changed name
|
||||
raise ImportError("Error: %s\nPossible reason: mygame/server/conf/inlinefunc.py should "
|
||||
"be renamed to mygame/server/conf/inlinefuncs.py (note the S at the end)." % err)
|
||||
"be renamed to mygame/server/conf/inlinefuncs.py (note the S at the end)." % err)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ except AttributeError:
|
|||
|
||||
# regex definitions
|
||||
|
||||
_RE_STARTTOKEN = re.compile(r"(?<!\\)\$(\w+)\(") # unescaped $funcname{ (start of function call)
|
||||
_RE_STARTTOKEN = re.compile(r"(?<!\\)\$(\w+)\(") # unescaped $funcname{ (start of function call)
|
||||
|
||||
_RE_TOKEN = re.compile(r"""
|
||||
(?<!\\)\'\'\'(?P<singlequote>.*?)(?<!\\)\'\'\'| # unescaped single-triples (escapes all inside them)
|
||||
|
|
@ -199,12 +199,13 @@ _RE_TOKEN = re.compile(r"""
|
|||
(?P<start>(?<!\\)\$\w+\()| # unescaped $funcname( (start of function call)
|
||||
(?P<escaped>\\'|\\"|\\\)|\\$\w+\()| # escaped tokens should re-appear in text
|
||||
(?P<rest>[\w\s.-\/#!%\^&\*;:=\-_`~\|\(}{\[\]]+|\"{1}|\'{1}) # everything else should also be included""",
|
||||
re.UNICODE + re.IGNORECASE + re.VERBOSE + re.DOTALL)
|
||||
re.UNICODE + re.IGNORECASE + re.VERBOSE + re.DOTALL)
|
||||
|
||||
|
||||
# Cache for function lookups.
|
||||
_PARSING_CACHE = utils.LimitedSizeOrderedDict(size_limit=1000)
|
||||
|
||||
|
||||
class ParseStack(list):
|
||||
"""
|
||||
Custom stack that always concatenates strings together when the
|
||||
|
|
@ -221,6 +222,7 @@ class ParseStack(list):
|
|||
string + string]
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ParseStack, self).__init__(*args, **kwargs)
|
||||
# always start stack with the empty string
|
||||
|
|
@ -247,6 +249,7 @@ class ParseStack(list):
|
|||
class InlinefuncError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def parse_inlinefunc(string, strip=False, **kwargs):
|
||||
"""
|
||||
Parse the incoming string.
|
||||
|
|
@ -347,7 +350,7 @@ def parse_inlinefunc(string, strip=False, **kwargs):
|
|||
args.append("")
|
||||
else:
|
||||
# all other args should merge into one string
|
||||
args[-1] += _run_stack(arg, depth=depth+1)
|
||||
args[-1] += _run_stack(arg, depth=depth + 1)
|
||||
# execute the inlinefunc at this point or strip it.
|
||||
kwargs["inlinefunc_stack_depth"] = depth
|
||||
retval = "" if strip else func(*args, **kwargs)
|
||||
|
|
@ -360,6 +363,7 @@ def parse_inlinefunc(string, strip=False, **kwargs):
|
|||
# Nick templating
|
||||
#
|
||||
|
||||
|
||||
"""
|
||||
This supports the use of replacement templates in nicks:
|
||||
|
||||
|
|
@ -451,5 +455,3 @@ def parse_nick_template(string, template_regex, outtemplate):
|
|||
if match:
|
||||
return outtemplate.format(**match.groupdict())
|
||||
return string
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ def log_trace(errmsg=None):
|
|||
log.msg('[EE] %s' % line)
|
||||
except Exception:
|
||||
log.msg('[EE] %s' % errmsg)
|
||||
|
||||
|
||||
log_tracemsg = log_trace
|
||||
|
||||
|
||||
|
|
@ -100,6 +102,8 @@ def log_err(errmsg):
|
|||
errmsg = str(e)
|
||||
for line in errmsg.splitlines():
|
||||
log.msg('[EE] %s' % line)
|
||||
|
||||
|
||||
# log.err('ERROR: %s' % (errmsg,))
|
||||
log_errmsg = log_err
|
||||
|
||||
|
|
@ -118,6 +122,8 @@ def log_warn(warnmsg):
|
|||
warnmsg = str(e)
|
||||
for line in warnmsg.splitlines():
|
||||
log.msg('[WW] %s' % line)
|
||||
|
||||
|
||||
# log.msg('WARNING: %s' % (warnmsg,))
|
||||
log_warnmsg = log_warn
|
||||
|
||||
|
|
@ -134,6 +140,8 @@ def log_info(infomsg):
|
|||
infomsg = str(e)
|
||||
for line in infomsg.splitlines():
|
||||
log.msg('[..] %s' % line)
|
||||
|
||||
|
||||
log_infomsg = log_info
|
||||
|
||||
|
||||
|
|
@ -150,6 +158,8 @@ def log_dep(depmsg):
|
|||
depmsg = str(e)
|
||||
for line in depmsg.splitlines():
|
||||
log.msg('[DP] %s' % line)
|
||||
|
||||
|
||||
log_depmsg = log_dep
|
||||
|
||||
|
||||
|
|
@ -207,6 +217,7 @@ class EvenniaLogFile(logfile.LogFile):
|
|||
"""
|
||||
return self._file.readlines(*args, **kwargs)
|
||||
|
||||
|
||||
_LOG_FILE_HANDLES = {} # holds open log handles
|
||||
|
||||
|
||||
|
|
@ -307,7 +318,7 @@ def tail_log_file(filename, offset, nlines, callback=None):
|
|||
lines_found = filehandle.readlines()
|
||||
block_count -= 1
|
||||
# return the right number of lines
|
||||
lines_found = lines_found[-nlines-offset:-offset if offset else None]
|
||||
lines_found = lines_found[-nlines - offset:-offset if offset else None]
|
||||
if callback:
|
||||
callback(lines_found)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ from ast import literal_eval
|
|||
from copy import deepcopy
|
||||
from base64 import b64encode, b64decode
|
||||
from zlib import compress, decompress
|
||||
#import six # this is actually a pypy component, not in default syslib
|
||||
# import six # this is actually a pypy component, not in default syslib
|
||||
import django
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
|
|
@ -54,12 +54,13 @@ except ImportError:
|
|||
|
||||
# python 3.x does not have cPickle module
|
||||
try:
|
||||
from cPickle import loads, dumps # cpython 2.x
|
||||
from cPickle import loads, dumps # cpython 2.x
|
||||
except ImportError:
|
||||
from pickle import loads, dumps # cpython 3.x, other interpreters
|
||||
from pickle import loads, dumps # cpython 3.x, other interpreters
|
||||
|
||||
DEFAULT_PROTOCOL = 2
|
||||
|
||||
|
||||
class PickledObject(str):
|
||||
"""
|
||||
A subclass of string so it can be told whether a string is a pickled
|
||||
|
|
@ -105,12 +106,12 @@ def dbsafe_encode(value, compress_object=False, pickle_protocol=DEFAULT_PROTOCOL
|
|||
value = dumps(deepcopy(value), protocol=pickle_protocol)
|
||||
if compress_object:
|
||||
value = compress(value)
|
||||
value = b64encode(value).decode() # decode bytes to str
|
||||
value = b64encode(value).decode() # decode bytes to str
|
||||
return PickledObject(value)
|
||||
|
||||
|
||||
def dbsafe_decode(value, compress_object=False):
|
||||
value = value.encode() # encode str to bytes
|
||||
value = value.encode() # encode str to bytes
|
||||
value = b64decode(value)
|
||||
if compress_object:
|
||||
value = decompress(value)
|
||||
|
|
@ -198,7 +199,7 @@ class PickledObjectField(models.Field):
|
|||
# If the field doesn't have a default, then we punt to models.Field.
|
||||
return super(PickledObjectField, self).get_default()
|
||||
|
||||
#def to_python(self, value):
|
||||
# def to_python(self, value):
|
||||
def from_db_value(self, value, *args):
|
||||
"""
|
||||
B64decode and unpickle the object, optionally decompressing it.
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ _re = re.compile("\033\[[0-9;]*m")
|
|||
|
||||
def _ansi(method):
|
||||
"""decorator for converting ansi in input"""
|
||||
|
||||
def wrapper(self, *args, **kwargs):
|
||||
def convert(inp):
|
||||
if isinstance(inp, basestring):
|
||||
|
|
@ -110,7 +111,6 @@ class PrettyTable(object):
|
|||
|
||||
@_ansi
|
||||
def __init__(self, field_names=None, **kwargs):
|
||||
|
||||
"""Return a new PrettyTable instance
|
||||
|
||||
Arguments:
|
||||
|
|
@ -223,15 +223,15 @@ class PrettyTable(object):
|
|||
# Uneven padding
|
||||
# Put more space on right if text is of odd length...
|
||||
if _str_block_width(text) % 2:
|
||||
return (excess//2)*" " + text + (excess//2 + 1)*" "
|
||||
return (excess // 2) * " " + text + (excess // 2 + 1) * " "
|
||||
# and more space on left if text is of even length
|
||||
else:
|
||||
return (excess//2 + 1)*" " + text + (excess//2)*" "
|
||||
return (excess // 2 + 1) * " " + text + (excess // 2) * " "
|
||||
# Why distribute extra space this way? To match the behaviour of
|
||||
# the inbuilt str.center() method.
|
||||
else:
|
||||
# Equal padding on either side
|
||||
return (excess//2)*" " + text + (excess//2)*" "
|
||||
return (excess // 2) * " " + text + (excess // 2) * " "
|
||||
|
||||
def __getattr__(self, name):
|
||||
|
||||
|
|
@ -252,7 +252,7 @@ class PrettyTable(object):
|
|||
new = PrettyTable()
|
||||
new.field_names = self.field_names
|
||||
for attr in self._options:
|
||||
setattr(new, "_"+attr, getattr(self, "_"+attr))
|
||||
setattr(new, "_" + attr, getattr(self, "_" + attr))
|
||||
setattr(new, "_align", getattr(self, "_align"))
|
||||
if isinstance(index, slice):
|
||||
for row in self._rows[index]:
|
||||
|
|
@ -823,7 +823,7 @@ class PrettyTable(object):
|
|||
self._validate_option(option, kwargs[option])
|
||||
options[option] = kwargs[option]
|
||||
else:
|
||||
options[option] = getattr(self, "_"+option)
|
||||
options[option] = getattr(self, "_" + option)
|
||||
return options
|
||||
|
||||
##############################
|
||||
|
|
@ -893,7 +893,6 @@ class PrettyTable(object):
|
|||
|
||||
@_ansi
|
||||
def add_row(self, row):
|
||||
|
||||
"""Add a row to the table
|
||||
|
||||
Arguments:
|
||||
|
|
@ -905,24 +904,22 @@ class PrettyTable(object):
|
|||
raise Exception("Row has incorrect number of values, (actual) %d!=%d (expected)"
|
||||
% (len(row), len(self._field_names)))
|
||||
if not self._field_names:
|
||||
self.field_names = [("Field %d" % (n+1)) for n in range(0, len(row))]
|
||||
self.field_names = [("Field %d" % (n + 1)) for n in range(0, len(row))]
|
||||
self._rows.append(list(row))
|
||||
|
||||
def del_row(self, row_index):
|
||||
|
||||
"""Delete a row to the table
|
||||
|
||||
Arguments:
|
||||
|
||||
row_index - The index of the row you want to delete. Indexing starts at 0."""
|
||||
|
||||
if row_index > len(self._rows)-1:
|
||||
if row_index > len(self._rows) - 1:
|
||||
raise Exception("Can't delete row at index %d, table only has %d rows!" % (row_index, len(self._rows)))
|
||||
del self._rows[row_index]
|
||||
|
||||
@_ansi
|
||||
def add_column(self, fieldname, column, align="l", valign="t"):
|
||||
|
||||
"""Add a column to the table.
|
||||
|
||||
Arguments:
|
||||
|
|
@ -940,20 +937,18 @@ class PrettyTable(object):
|
|||
self._align[fieldname] = align
|
||||
self._valign[fieldname] = valign
|
||||
for i in range(0, len(column)):
|
||||
if len(self._rows) < i+1:
|
||||
if len(self._rows) < i + 1:
|
||||
self._rows.append([])
|
||||
self._rows[i].append(column[i])
|
||||
else:
|
||||
raise Exception("Column length %d does not match number of rows %d!" % (len(column), len(self._rows)))
|
||||
|
||||
def clear_rows(self):
|
||||
|
||||
"""Delete all rows from the table but keep the current field names"""
|
||||
|
||||
self._rows = []
|
||||
|
||||
def clear(self):
|
||||
|
||||
"""Delete all rows and field names from the table, maintaining nothing but styling options"""
|
||||
|
||||
self._rows = []
|
||||
|
|
@ -1017,7 +1012,7 @@ class PrettyTable(object):
|
|||
if options["sortby"]:
|
||||
sortindex = self._field_names.index(options["sortby"])
|
||||
# Decorate
|
||||
rows = [[row[sortindex]]+row for row in rows]
|
||||
rows = [[row[sortindex]] + row for row in rows]
|
||||
# Sort
|
||||
rows.sort(reverse=options["reversesort"], key=options["sort_key"])
|
||||
# Undecorate
|
||||
|
|
@ -1035,7 +1030,6 @@ class PrettyTable(object):
|
|||
##############################
|
||||
|
||||
def get_string(self, **kwargs):
|
||||
|
||||
"""Return string representation of table in current state.
|
||||
|
||||
Arguments:
|
||||
|
|
@ -1106,12 +1100,12 @@ class PrettyTable(object):
|
|||
bits = [options["horizontal_char"]]
|
||||
# For tables with no data or fieldnames
|
||||
if not self._field_names:
|
||||
bits.append(options["junction_char"])
|
||||
return "".join(bits)
|
||||
bits.append(options["junction_char"])
|
||||
return "".join(bits)
|
||||
for field, width in zip(self._field_names, self._widths):
|
||||
if options["fields"] and field not in options["fields"]:
|
||||
continue
|
||||
bits.append((width+lpad+rpad)*options["horizontal_char"])
|
||||
bits.append((width + lpad + rpad) * options["horizontal_char"])
|
||||
if options['vrules'] == ALL:
|
||||
bits.append(options["junction_char"])
|
||||
else:
|
||||
|
|
@ -1232,8 +1226,8 @@ class PrettyTable(object):
|
|||
bits[y].append(options["vertical_char"])
|
||||
|
||||
if options["border"] and options["hrules"] == ALL:
|
||||
bits[row_height-1].append("\n")
|
||||
bits[row_height-1].append(self._hrule)
|
||||
bits[row_height - 1].append("\n")
|
||||
bits[row_height - 1].append(self._hrule)
|
||||
|
||||
for y in range(0, row_height):
|
||||
bits[y] = "".join(bits[y])
|
||||
|
|
@ -1245,7 +1239,6 @@ class PrettyTable(object):
|
|||
##############################
|
||||
|
||||
def get_html_string(self, **kwargs):
|
||||
|
||||
"""Return string representation of HTML formatted version of table in current state.
|
||||
|
||||
Arguments:
|
||||
|
|
@ -1515,7 +1508,7 @@ class TableHandler(HTMLParser):
|
|||
iterates over the row and make each field unique
|
||||
"""
|
||||
for i in range(0, len(fields)):
|
||||
for j in range(i+1, len(fields)):
|
||||
for j in range(i + 1, len(fields)):
|
||||
if fields[i] == fields[j]:
|
||||
fields[j] += "'"
|
||||
|
||||
|
|
@ -1566,5 +1559,6 @@ def main():
|
|||
x.add_row(["Perth", 5386, 1554769, 869.4])
|
||||
print(x)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ def search_script_attribute(key=None, category=None, value=None, strvalue=None):
|
|||
def search_channel_attribute(key=None, category=None, value=None, strvalue=None):
|
||||
return Channel.objects.get_by_attribute(key=key, category=category, value=value, strvalue=strvalue)
|
||||
|
||||
|
||||
# search for attribute objects
|
||||
search_attribute_object = ObjectDB.objects.get_attribute
|
||||
|
||||
|
|
@ -243,6 +244,8 @@ def search_object_by_tag(key=None, category=None):
|
|||
|
||||
"""
|
||||
return ObjectDB.objects.get_by_tag(key=key, category=category)
|
||||
|
||||
|
||||
search_tag = search_object_by_tag # this is the most common case
|
||||
|
||||
|
||||
|
|
@ -302,5 +305,6 @@ def search_channel_tag(key=None, category=None):
|
|||
"""
|
||||
return Channel.objects.get_by_tag(key=key, category=category)
|
||||
|
||||
|
||||
# search for tag objects (not the objects they are attached to
|
||||
search_tag_object = ObjectDB.objects.get_tag
|
||||
|
|
|
|||
|
|
@ -307,35 +307,35 @@ if __name__ == "__main__":
|
|||
# testing
|
||||
|
||||
protparents = {
|
||||
"NOBODY": {},
|
||||
# "INFINITE" : {
|
||||
# "prototype":"INFINITE"
|
||||
# },
|
||||
"GOBLIN": {
|
||||
"key": "goblin grunt",
|
||||
"health": lambda: randint(20, 30),
|
||||
"resists": ["cold", "poison"],
|
||||
"attacks": ["fists"],
|
||||
"weaknesses": ["fire", "light"]
|
||||
},
|
||||
"GOBLIN_WIZARD": {
|
||||
"prototype": "GOBLIN",
|
||||
"key": "goblin wizard",
|
||||
"spells": ["fire ball", "lighting bolt"]
|
||||
},
|
||||
"GOBLIN_ARCHER": {
|
||||
"prototype": "GOBLIN",
|
||||
"key": "goblin archer",
|
||||
"attacks": ["short bow"]
|
||||
},
|
||||
"ARCHWIZARD": {
|
||||
"attacks": ["archwizard staff"],
|
||||
},
|
||||
"GOBLIN_ARCHWIZARD": {
|
||||
"key": "goblin archwizard",
|
||||
"prototype": ("GOBLIN_WIZARD", "ARCHWIZARD")
|
||||
}
|
||||
"NOBODY": {},
|
||||
# "INFINITE" : {
|
||||
# "prototype":"INFINITE"
|
||||
# },
|
||||
"GOBLIN": {
|
||||
"key": "goblin grunt",
|
||||
"health": lambda: randint(20, 30),
|
||||
"resists": ["cold", "poison"],
|
||||
"attacks": ["fists"],
|
||||
"weaknesses": ["fire", "light"]
|
||||
},
|
||||
"GOBLIN_WIZARD": {
|
||||
"prototype": "GOBLIN",
|
||||
"key": "goblin wizard",
|
||||
"spells": ["fire ball", "lighting bolt"]
|
||||
},
|
||||
"GOBLIN_ARCHER": {
|
||||
"prototype": "GOBLIN",
|
||||
"key": "goblin archer",
|
||||
"attacks": ["short bow"]
|
||||
},
|
||||
"ARCHWIZARD": {
|
||||
"attacks": ["archwizard staff"],
|
||||
},
|
||||
"GOBLIN_ARCHWIZARD": {
|
||||
"key": "goblin archwizard",
|
||||
"prototype": ("GOBLIN_WIZARD", "ARCHWIZARD")
|
||||
}
|
||||
}
|
||||
# test
|
||||
print([o.key for o in spawn(protparents["GOBLIN"],
|
||||
protparents["GOBLIN_ARCHWIZARD"],
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ class EvenniaTest(TestCase):
|
|||
dummysession = ServerSession()
|
||||
dummysession.init_session("telnet", ("localhost", "testmode"), SESSIONS)
|
||||
dummysession.sessid = 1
|
||||
SESSIONS.portal_connect(dummysession.get_sync_data()) # note that this creates a new Session!
|
||||
session = SESSIONS.session_from_sessid(1) # the real session
|
||||
SESSIONS.portal_connect(dummysession.get_sync_data()) # note that this creates a new Session!
|
||||
session = SESSIONS.session_from_sessid(1) # the real session
|
||||
SESSIONS.login(session, self.account, testmode=True)
|
||||
self.session = session
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from evennia import utils
|
|||
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class ANSIStringTestCase(TestCase):
|
||||
def checker(self, ansi, raw, clean):
|
||||
"""
|
||||
|
|
@ -209,6 +210,7 @@ class TestListToString(TestCase):
|
|||
with addquote and endsep
|
||||
[1,2,3] -> '"1", "2" and "3"'
|
||||
"""
|
||||
|
||||
def test_list_to_string(self):
|
||||
self.assertEqual('1, 2, 3', utils.list_to_string([1, 2, 3], endsep=""))
|
||||
self.assertEqual('"1", "2", "3"', utils.list_to_string([1, 2, 3], endsep="", addquote=True))
|
||||
|
|
@ -221,6 +223,7 @@ class TestMLen(TestCase):
|
|||
Verifies that m_len behaves like len in all situations except those
|
||||
where MXP may be involved.
|
||||
"""
|
||||
|
||||
def test_non_mxp_string(self):
|
||||
self.assertEqual(utils.m_len('Test_string'), 11)
|
||||
|
||||
|
|
@ -325,15 +328,19 @@ class TestTextToHTMLparser(TestCase):
|
|||
'</span><a href="http://example.com/" target="_blank">'
|
||||
'http://example.com/</a><span class="red">')
|
||||
|
||||
|
||||
from evennia.utils import evmenu
|
||||
from mock import Mock
|
||||
|
||||
|
||||
class TestEvMenu(TestCase):
|
||||
"Run the EvMenu test."
|
||||
|
||||
def setUp(self):
|
||||
self.caller = Mock()
|
||||
self.caller.msg = Mock()
|
||||
self.menu = evmenu.EvMenu(self.caller, "evennia.utils.evmenu", startnode="test_start_node",
|
||||
persistent=True, cmdset_mergetype="Replace", testval="val", testval2="val2")
|
||||
persistent=True, cmdset_mergetype="Replace", testval="val", testval2="val2")
|
||||
|
||||
def test_kwargsave(self):
|
||||
self.assertTrue(hasattr(self.menu, "testval"))
|
||||
|
|
@ -345,6 +352,7 @@ from evennia.utils import inlinefuncs
|
|||
|
||||
class TestInlineFuncs(TestCase):
|
||||
"""Test the nested inlinefunc module"""
|
||||
|
||||
def test_nofunc(self):
|
||||
self.assertEqual(inlinefuncs.parse_inlinefunc(
|
||||
"as$382ewrw w we w werw,|44943}"),
|
||||
|
|
@ -375,6 +383,7 @@ class TestInlineFuncs(TestCase):
|
|||
'this should be $pad("""escaped,""" and """instead,""" cropped $crop(with a long,5) text., 80)'),
|
||||
"this should be escaped, and instead, cropped with text. ")
|
||||
|
||||
|
||||
from evennia.utils import evform
|
||||
|
||||
|
||||
|
|
@ -424,7 +433,8 @@ class TestEvForm(TestCase):
|
|||
def test_ansi_escape(self):
|
||||
# note that in a msg() call, the result would be the correct |-----,
|
||||
# in a print, ansi only gets called once, so ||----- is the result
|
||||
self.assertEqual(unicode(evform.EvForm(form={"FORM":"\n||-----"})), "||-----")
|
||||
self.assertEqual(unicode(evform.EvForm(form={"FORM": "\n||-----"})), "||-----")
|
||||
|
||||
|
||||
class TestTimeformat(TestCase):
|
||||
"""
|
||||
|
|
@ -472,11 +482,11 @@ class TestTimeformat(TestCase):
|
|||
self.assertEqual(utils.time_format(3725, 2), "1 hour, 2 minutes")
|
||||
self.assertEqual(utils.time_format(86350, 2), "23 hours, 59 minutes")
|
||||
self.assertEqual(utils.time_format(86800, 2),
|
||||
"1 day, 0 hours, 6 minutes")
|
||||
"1 day, 0 hours, 6 minutes")
|
||||
self.assertEqual(utils.time_format(130800, 2),
|
||||
"1 day, 12 hours, 20 minutes")
|
||||
"1 day, 12 hours, 20 minutes")
|
||||
self.assertEqual(utils.time_format(530800, 2),
|
||||
"6 days, 3 hours, 26 minutes")
|
||||
"6 days, 3 hours, 26 minutes")
|
||||
|
||||
def test_style_3(self):
|
||||
"""Test the style 3 of time_format."""
|
||||
|
|
@ -486,17 +496,17 @@ class TestTimeformat(TestCase):
|
|||
self.assertEqual(utils.time_format(300, 3), "5 minutes 0 seconds")
|
||||
self.assertEqual(utils.time_format(660, 3), "11 minutes 0 seconds")
|
||||
self.assertEqual(utils.time_format(3600, 3),
|
||||
"1 hour, 0 minutes")
|
||||
"1 hour, 0 minutes")
|
||||
self.assertEqual(utils.time_format(3725, 3),
|
||||
"1 hour, 2 minutes 5 seconds")
|
||||
"1 hour, 2 minutes 5 seconds")
|
||||
self.assertEqual(utils.time_format(86350, 3),
|
||||
"23 hours, 59 minutes 10 seconds")
|
||||
"23 hours, 59 minutes 10 seconds")
|
||||
self.assertEqual(utils.time_format(86800, 3),
|
||||
"1 day, 0 hours, 6 minutes 40 seconds")
|
||||
"1 day, 0 hours, 6 minutes 40 seconds")
|
||||
self.assertEqual(utils.time_format(130800, 3),
|
||||
"1 day, 12 hours, 20 minutes 0 seconds")
|
||||
"1 day, 12 hours, 20 minutes 0 seconds")
|
||||
self.assertEqual(utils.time_format(530800, 3),
|
||||
"6 days, 3 hours, 26 minutes 40 seconds")
|
||||
"6 days, 3 hours, 26 minutes 40 seconds")
|
||||
|
||||
def test_style_4(self):
|
||||
"""Test the style 4 of time_format."""
|
||||
|
|
|
|||
|
|
@ -30,48 +30,48 @@ class TextToHTMLparser(object):
|
|||
tabstop = 4
|
||||
# mapping html color name <-> ansi code.
|
||||
hilite = ANSI_HILITE
|
||||
unhilite = ANSI_UNHILITE # this will be stripped - there is no css equivalent.
|
||||
normal = ANSI_NORMAL # "
|
||||
unhilite = ANSI_UNHILITE # this will be stripped - there is no css equivalent.
|
||||
normal = ANSI_NORMAL # "
|
||||
underline = ANSI_UNDERLINE
|
||||
blink = ANSI_BLINK
|
||||
inverse = ANSI_INVERSE # this will produce an outline; no obvious css equivalent?
|
||||
colorcodes = [
|
||||
('color-000', unhilite + ANSI_BLACK), # pure black
|
||||
('color-001', unhilite + ANSI_RED),
|
||||
('color-002', unhilite + ANSI_GREEN),
|
||||
('color-003', unhilite + ANSI_YELLOW),
|
||||
('color-004', unhilite + ANSI_BLUE),
|
||||
('color-005', unhilite + ANSI_MAGENTA),
|
||||
('color-006', unhilite + ANSI_CYAN),
|
||||
('color-007', unhilite + ANSI_WHITE), # light grey
|
||||
('color-008', hilite + ANSI_BLACK), # dark grey
|
||||
('color-009', hilite + ANSI_RED),
|
||||
('color-010', hilite + ANSI_GREEN),
|
||||
('color-011', hilite + ANSI_YELLOW),
|
||||
('color-012', hilite + ANSI_BLUE),
|
||||
('color-013', hilite + ANSI_MAGENTA),
|
||||
('color-014', hilite + ANSI_CYAN),
|
||||
('color-015', hilite + ANSI_WHITE) # pure white
|
||||
] + [("color-%03i" % (i+16), XTERM256_FG % ("%i" % (i+16))) for i in xrange(240)]
|
||||
('color-000', unhilite + ANSI_BLACK), # pure black
|
||||
('color-001', unhilite + ANSI_RED),
|
||||
('color-002', unhilite + ANSI_GREEN),
|
||||
('color-003', unhilite + ANSI_YELLOW),
|
||||
('color-004', unhilite + ANSI_BLUE),
|
||||
('color-005', unhilite + ANSI_MAGENTA),
|
||||
('color-006', unhilite + ANSI_CYAN),
|
||||
('color-007', unhilite + ANSI_WHITE), # light grey
|
||||
('color-008', hilite + ANSI_BLACK), # dark grey
|
||||
('color-009', hilite + ANSI_RED),
|
||||
('color-010', hilite + ANSI_GREEN),
|
||||
('color-011', hilite + ANSI_YELLOW),
|
||||
('color-012', hilite + ANSI_BLUE),
|
||||
('color-013', hilite + ANSI_MAGENTA),
|
||||
('color-014', hilite + ANSI_CYAN),
|
||||
('color-015', hilite + ANSI_WHITE) # pure white
|
||||
] + [("color-%03i" % (i + 16), XTERM256_FG % ("%i" % (i + 16))) for i in xrange(240)]
|
||||
|
||||
colorback = [
|
||||
('bgcolor-000', ANSI_BACK_BLACK), # pure black
|
||||
('bgcolor-001', ANSI_BACK_RED),
|
||||
('bgcolor-002', ANSI_BACK_GREEN),
|
||||
('bgcolor-003', ANSI_BACK_YELLOW),
|
||||
('bgcolor-004', ANSI_BACK_BLUE),
|
||||
('bgcolor-005', ANSI_BACK_MAGENTA),
|
||||
('bgcolor-006', ANSI_BACK_CYAN),
|
||||
('bgcolor-007', ANSI_BACK_WHITE), # light grey
|
||||
('bgcolor-008', hilite + ANSI_BACK_BLACK), # dark grey
|
||||
('bgcolor-009', hilite + ANSI_BACK_RED),
|
||||
('bgcolor-010', hilite + ANSI_BACK_GREEN),
|
||||
('bgcolor-011', hilite + ANSI_BACK_YELLOW),
|
||||
('bgcolor-012', hilite + ANSI_BACK_BLUE),
|
||||
('bgcolor-013', hilite + ANSI_BACK_MAGENTA),
|
||||
('bgcolor-014', hilite + ANSI_BACK_CYAN),
|
||||
('bgcolor-015', hilite + ANSI_BACK_WHITE), # pure white
|
||||
] + [("bgcolor-%03i" % (i+16), XTERM256_BG % ("%i" % (i+16))) for i in range(240)]
|
||||
('bgcolor-000', ANSI_BACK_BLACK), # pure black
|
||||
('bgcolor-001', ANSI_BACK_RED),
|
||||
('bgcolor-002', ANSI_BACK_GREEN),
|
||||
('bgcolor-003', ANSI_BACK_YELLOW),
|
||||
('bgcolor-004', ANSI_BACK_BLUE),
|
||||
('bgcolor-005', ANSI_BACK_MAGENTA),
|
||||
('bgcolor-006', ANSI_BACK_CYAN),
|
||||
('bgcolor-007', ANSI_BACK_WHITE), # light grey
|
||||
('bgcolor-008', hilite + ANSI_BACK_BLACK), # dark grey
|
||||
('bgcolor-009', hilite + ANSI_BACK_RED),
|
||||
('bgcolor-010', hilite + ANSI_BACK_GREEN),
|
||||
('bgcolor-011', hilite + ANSI_BACK_YELLOW),
|
||||
('bgcolor-012', hilite + ANSI_BACK_BLUE),
|
||||
('bgcolor-013', hilite + ANSI_BACK_MAGENTA),
|
||||
('bgcolor-014', hilite + ANSI_BACK_CYAN),
|
||||
('bgcolor-015', hilite + ANSI_BACK_WHITE), # pure white
|
||||
] + [("bgcolor-%03i" % (i + 16), XTERM256_BG % ("%i" % (i + 16))) for i in range(240)]
|
||||
|
||||
# make sure to escape [
|
||||
#colorcodes = [(c, code.replace("[", r"\[")) for c, code in colorcodes]
|
||||
|
|
@ -80,8 +80,8 @@ class TextToHTMLparser(object):
|
|||
bg_colormap = dict((code, clr) for clr, code in colorback)
|
||||
|
||||
# create stop markers
|
||||
fgstop = "(?:\033\[1m|\033\[22m)*\033\[3[0-8].*?m|\033\[0m|$"
|
||||
bgstop = "(?:\033\[1m|\033\[22m)*\033\[4[0-8].*?m|\033\[0m|$"
|
||||
fgstop = "(?:\033\[1m|\033\[22m)*\033\[3[0-8].*?m|\033\[0m|$"
|
||||
bgstop = "(?:\033\[1m|\033\[22m)*\033\[4[0-8].*?m|\033\[0m|$"
|
||||
|
||||
# extract color markers, tagging the start marker and the text marked
|
||||
re_fgs = re.compile("((?:\033\[1m|\033\[22m)*\033\[3[0-8].*?m)(.*?)(?=" + fgstop + ")")
|
||||
|
|
@ -93,9 +93,9 @@ class TextToHTMLparser(object):
|
|||
re_uline = re.compile("(?:%s)(.*?)(?=%s|%s)" % (underline.replace("[", r"\["), fgstop, bgstop))
|
||||
re_blink = re.compile("(?:%s)(.*?)(?=%s|%s)" % (blink.replace("[", r"\["), fgstop, bgstop))
|
||||
re_inverse = re.compile("(?:%s)(.*?)(?=%s|%s)" % (inverse.replace("[", r"\["), fgstop, bgstop))
|
||||
re_string = re.compile(r'(?P<htmlchars>[<&>])|(?P<space> [ \t]+)|(?P<spacestart>^ )|(?P<lineend>\r\n|\r|\n)', re.S|re.M|re.I)
|
||||
re_string = re.compile(r'(?P<htmlchars>[<&>])|(?P<space> [ \t]+)|(?P<spacestart>^ )|(?P<lineend>\r\n|\r|\n)', re.S | re.M | re.I)
|
||||
re_url = re.compile(r'((?:ftp|www|https?)\W+(?:(?!\.(?:\s|$)|&\w+;)[^"\',;$*^\\(){}<>\[\]\s])+)(\.(?:\s|$)|&\w+;|)')
|
||||
re_mxplink = re.compile(r'\|lc(.*?)\|lt(.*?)\|le', re.DOTALL)
|
||||
re_mxplink = re.compile(r'\|lc(.*?)\|lt(.*?)\|le', re.DOTALL)
|
||||
|
||||
def _sub_fg(self, colormatch):
|
||||
code, text = colormatch.groups()
|
||||
|
|
@ -135,7 +135,7 @@ class TextToHTMLparser(object):
|
|||
|
||||
"""
|
||||
text = self.re_hilite.sub(r'<strong>\1</strong>', text)
|
||||
return self.re_unhilite.sub(r'\1', text) # strip unhilite - there is no equivalent in css.
|
||||
return self.re_unhilite.sub(r'\1', text) # strip unhilite - there is no equivalent in css.
|
||||
|
||||
def re_underline(self, text):
|
||||
"""
|
||||
|
|
@ -245,9 +245,9 @@ class TextToHTMLparser(object):
|
|||
|
||||
"""
|
||||
cmd, text = [grp.replace('\"', "\\"") for grp in match.groups()]
|
||||
val = r'''<a id="mxplink" href="#" ''' \
|
||||
'''onclick="Evennia.msg("text",["{cmd}"],{{}});''' \
|
||||
'''return false;">{text}</a>'''.format(cmd=cmd, text=text)
|
||||
val = r'''<a id="mxplink" href="#" ''' \
|
||||
'''onclick="Evennia.msg("text",["{cmd}"],{{}});''' \
|
||||
'''return false;">{text}</a>'''.format(cmd=cmd, text=text)
|
||||
return val
|
||||
|
||||
def sub_text(self, match):
|
||||
|
|
@ -306,6 +306,7 @@ class TextToHTMLparser(object):
|
|||
|
||||
return result
|
||||
|
||||
|
||||
HTML_PARSER = TextToHTMLparser()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ from twisted.protocols.policies import ProtocolWrapper, WrappingFactory
|
|||
from twisted.python import log
|
||||
from twisted.web.http import datetimeToString
|
||||
|
||||
|
||||
class WSException(Exception):
|
||||
"""
|
||||
Something stupid happened here.
|
||||
|
|
@ -54,6 +55,7 @@ class WSException(Exception):
|
|||
# RFC6455 - RFC 6455. The official WebSocket protocol standard. The protocol
|
||||
# number is 13, but otherwise it is identical to HyBi-07.
|
||||
|
||||
|
||||
HYBI00, HYBI07, HYBI10, RFC6455 = list(range(4))
|
||||
|
||||
# States of the state machine. Because there are no reliable byte counts for
|
||||
|
|
@ -87,6 +89,7 @@ decoders = {
|
|||
# Fake HTTP stuff, and a couple convenience methods for examining fake HTTP
|
||||
# headers.
|
||||
|
||||
|
||||
def http_headers(s):
|
||||
"""
|
||||
Create a dictionary of data from raw HTTP headers.
|
||||
|
|
@ -104,13 +107,15 @@ def http_headers(s):
|
|||
|
||||
return d
|
||||
|
||||
|
||||
def is_websocket(headers):
|
||||
"""
|
||||
Determine whether a given set of headers is asking for WebSockets.
|
||||
"""
|
||||
|
||||
return ("upgrade" in headers.get("Connection", "").lower()
|
||||
and headers.get("Upgrade").lower() == "websocket")
|
||||
return ("upgrade" in headers.get("Connection", "").lower() and
|
||||
headers.get("Upgrade").lower() == "websocket")
|
||||
|
||||
|
||||
def is_hybi00(headers):
|
||||
"""
|
||||
|
|
@ -124,6 +129,7 @@ def is_hybi00(headers):
|
|||
|
||||
# Authentication for WS.
|
||||
|
||||
|
||||
def complete_hybi00(headers, challenge):
|
||||
"""
|
||||
Generate the response for a HyBi-00 challenge.
|
||||
|
|
@ -139,6 +145,7 @@ def complete_hybi00(headers, challenge):
|
|||
|
||||
return md5(nonce).digest()
|
||||
|
||||
|
||||
def make_accept(key):
|
||||
"""
|
||||
Create an "accept" response for a given key.
|
||||
|
|
@ -154,6 +161,7 @@ def make_accept(key):
|
|||
# Separated out to make unit testing a lot easier.
|
||||
# Frames are bonghits in newer WS versions, so helpers are appreciated.
|
||||
|
||||
|
||||
def make_hybi00_frame(buf):
|
||||
"""
|
||||
Make a HyBi-00 frame from some data.
|
||||
|
|
@ -164,6 +172,7 @@ def make_hybi00_frame(buf):
|
|||
|
||||
return "\x00%s\xff" % buf
|
||||
|
||||
|
||||
def parse_hybi00_frames(buf):
|
||||
"""
|
||||
Parse HyBi-00 frames, returning unwrapped frames and any unmatched data.
|
||||
|
|
@ -192,6 +201,7 @@ def parse_hybi00_frames(buf):
|
|||
buf = buf[tail:]
|
||||
return frames, buf
|
||||
|
||||
|
||||
def mask(buf, key):
|
||||
"""
|
||||
Mask or unmask a buffer of bytes with a masking key.
|
||||
|
|
@ -206,6 +216,7 @@ def mask(buf, key):
|
|||
buf[i] = chr(ord(char) ^ key[i % 4])
|
||||
return "".join(buf)
|
||||
|
||||
|
||||
def make_hybi07_frame(buf, opcode=0x1):
|
||||
"""
|
||||
Make a HyBi-07 frame.
|
||||
|
|
@ -226,6 +237,7 @@ def make_hybi07_frame(buf, opcode=0x1):
|
|||
frame = "%s%s%s" % (header, length, buf)
|
||||
return frame
|
||||
|
||||
|
||||
def make_hybi07_frame_dwim(buf):
|
||||
"""
|
||||
Make a HyBi-07 frame with binary or text data according to the type of buf.
|
||||
|
|
@ -239,6 +251,7 @@ def make_hybi07_frame_dwim(buf):
|
|||
else:
|
||||
raise TypeError("In binary support mode, frame data must be either str or unicode")
|
||||
|
||||
|
||||
def parse_hybi07_frames(buf):
|
||||
"""
|
||||
Parse HyBi-07 frames in a highly compliant manner.
|
||||
|
|
@ -259,7 +272,7 @@ def parse_hybi07_frames(buf):
|
|||
# At least one of the reserved flags is set. Pork chop sandwiches!
|
||||
raise WSException("Reserved flag in HyBi-07 frame (%d)" % header)
|
||||
#frames.append(("", CLOSE))
|
||||
#return frames, buf
|
||||
# return frames, buf
|
||||
|
||||
# Get the opcode, and translate it to a local enum which we actually
|
||||
# care about.
|
||||
|
|
@ -329,6 +342,7 @@ def parse_hybi07_frames(buf):
|
|||
|
||||
return frames, buf[start:]
|
||||
|
||||
|
||||
class WebSocketProtocol(ProtocolWrapper):
|
||||
"""
|
||||
Protocol which wraps another protocol to provide a WebSockets transport
|
||||
|
|
@ -538,7 +552,7 @@ class WebSocketProtocol(ProtocolWrapper):
|
|||
log.msg("Can't support protocol version %s!" % version)
|
||||
return False
|
||||
|
||||
self.validationMade() # custom Evennia addition
|
||||
self.validationMade() # custom Evennia addition
|
||||
return True
|
||||
|
||||
def dataReceived(self, data):
|
||||
|
|
@ -639,6 +653,7 @@ class WebSocketProtocol(ProtocolWrapper):
|
|||
|
||||
self.loseConnection()
|
||||
|
||||
|
||||
class WebSocketFactory(WrappingFactory):
|
||||
"""
|
||||
Factory which wraps another factory to provide WebSockets transports for
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ _DA = object.__delattr__
|
|||
|
||||
_DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
||||
|
||||
|
||||
def is_iter(iterable):
|
||||
"""
|
||||
Checks if an object behaves iterably.
|
||||
|
|
@ -96,6 +97,8 @@ def wrap(text, width=_DEFAULT_WIDTH, indent=0):
|
|||
text = to_unicode(text)
|
||||
indent = " " * indent
|
||||
return to_str(textwrap.fill(text, width, initial_indent=indent, subsequent_indent=indent))
|
||||
|
||||
|
||||
# alias - fill
|
||||
fill = wrap
|
||||
|
||||
|
|
@ -437,27 +440,27 @@ def time_format(seconds, style=0):
|
|||
"""
|
||||
Only return the highest unit.
|
||||
"""
|
||||
if days >= 730: # Several years
|
||||
if days >= 730: # Several years
|
||||
return "{} years".format(days // 365)
|
||||
elif days >= 365: # One year
|
||||
elif days >= 365: # One year
|
||||
return "a year"
|
||||
elif days >= 62: # Several months
|
||||
elif days >= 62: # Several months
|
||||
return "{} months".format(days // 31)
|
||||
elif days >= 31: # One month
|
||||
elif days >= 31: # One month
|
||||
return "a month"
|
||||
elif days >= 2: # Several days
|
||||
elif days >= 2: # Several days
|
||||
return "{} days".format(days)
|
||||
elif days > 0:
|
||||
return "a day"
|
||||
elif hours >= 2: # Several hours
|
||||
elif hours >= 2: # Several hours
|
||||
return "{} hours".format(hours)
|
||||
elif hours > 0: # One hour
|
||||
elif hours > 0: # One hour
|
||||
return "an hour"
|
||||
elif minutes >= 2: # Several minutes
|
||||
elif minutes >= 2: # Several minutes
|
||||
return "{} minutes".format(minutes)
|
||||
elif minutes > 0: # One minute
|
||||
elif minutes > 0: # One minute
|
||||
return "a minute"
|
||||
elif seconds >= 2: # Several seconds
|
||||
elif seconds >= 2: # Several seconds
|
||||
return "{} seconds".format(seconds)
|
||||
elif seconds == 1:
|
||||
return "a second"
|
||||
|
|
@ -593,9 +596,9 @@ def dbref(inp, reqhash=True):
|
|||
"""
|
||||
if reqhash:
|
||||
num = (int(inp.lstrip('#')) if (isinstance(inp, basestring) and
|
||||
inp.startswith("#") and
|
||||
inp.lstrip('#').isdigit())
|
||||
else None)
|
||||
inp.startswith("#") and
|
||||
inp.lstrip('#').isdigit())
|
||||
else None)
|
||||
return num if num > 0 else None
|
||||
elif isinstance(inp, basestring):
|
||||
inp = inp.lstrip('#')
|
||||
|
|
@ -641,6 +644,7 @@ def dbref_to_obj(inp, objclass, raise_errors=True):
|
|||
raise
|
||||
return inp
|
||||
|
||||
|
||||
# legacy alias
|
||||
dbid_to_obj = dbref_to_obj
|
||||
|
||||
|
|
@ -788,7 +792,7 @@ def to_str(obj, encoding='utf-8', force_string=False):
|
|||
# if we get to this point we have not found any way to convert this string. Try to parse it manually,
|
||||
try:
|
||||
return latinify(obj, '?')
|
||||
except Exception, err:
|
||||
except Exception as err:
|
||||
raise Exception("%s, Error: Unicode could not encode unicode string '%s'(%s) to a bytestring. " % (err, obj, encoding))
|
||||
return obj
|
||||
|
||||
|
|
@ -921,6 +925,7 @@ def uses_database(name="sqlite3"):
|
|||
|
||||
_TASK_HANDLER = None
|
||||
|
||||
|
||||
def delay(timedelay, callback, *args, **kwargs):
|
||||
"""
|
||||
Delay the return of a value.
|
||||
|
|
@ -989,7 +994,7 @@ def clean_object_caches(obj):
|
|||
|
||||
# on-object property cache
|
||||
[_DA(obj, cname) for cname in viewkeys(obj.__dict__)
|
||||
if cname.startswith("_cached_db_")]
|
||||
if cname.startswith("_cached_db_")]
|
||||
try:
|
||||
hashid = _GA(obj, "hashid")
|
||||
_TYPECLASSMODELS._ATTRIBUTE_CACHE[hashid] = {}
|
||||
|
|
@ -1001,6 +1006,8 @@ def clean_object_caches(obj):
|
|||
_PPOOL = None
|
||||
_PCMD = None
|
||||
_PROC_ERR = "A process has ended with a probable error condition: process ended by signal 9."
|
||||
|
||||
|
||||
def run_async(to_execute, *args, **kwargs):
|
||||
"""
|
||||
Runs a function or executes a code snippet asynchronously.
|
||||
|
|
@ -1094,7 +1101,7 @@ def check_evennia_dependencies():
|
|||
errstring = errstring.strip()
|
||||
if errstring:
|
||||
mlen = max(len(line) for line in errstring.split("\n"))
|
||||
logger.log_err("%s\n%s\n%s" % ("-"*mlen, errstring, '-'*mlen))
|
||||
logger.log_err("%s\n%s\n%s" % ("-" * mlen, errstring, '-' * mlen))
|
||||
return not_error
|
||||
|
||||
|
||||
|
|
@ -1333,7 +1340,7 @@ def fuzzy_import_from_module(path, variable, default=None, defaultpaths=None):
|
|||
try:
|
||||
mod = import_module(modpath)
|
||||
except ImportError as ex:
|
||||
if not str(ex).startswith ("No module named %s" % modpath):
|
||||
if not str(ex).startswith("No module named %s" % modpath):
|
||||
# this means the module was found but it
|
||||
# triggers an ImportError on import.
|
||||
raise ex
|
||||
|
|
@ -1396,6 +1403,8 @@ def class_from_module(path, defaultpaths=None):
|
|||
err += "."
|
||||
raise ImportError(err)
|
||||
return cls
|
||||
|
||||
|
||||
# alias
|
||||
object_from_module = class_from_module
|
||||
|
||||
|
|
@ -1430,7 +1439,7 @@ def string_similarity(string1, string2):
|
|||
vec2 = [string2.count(v) for v in vocabulary]
|
||||
try:
|
||||
return float(sum(vec1[i] * vec2[i] for i in range(len(vocabulary)))) / \
|
||||
(math.sqrt(sum(v1**2 for v1 in vec1)) * math.sqrt(sum(v2**2 for v2 in vec2)))
|
||||
(math.sqrt(sum(v1**2 for v1 in vec1)) * math.sqrt(sum(v2**2 for v2 in vec2)))
|
||||
except ZeroDivisionError:
|
||||
# can happen if empty-string cmdnames appear for some reason.
|
||||
# This is a no-match.
|
||||
|
|
@ -1456,9 +1465,9 @@ def string_suggestions(string, vocabulary, cutoff=0.6, maxnum=3):
|
|||
|
||||
"""
|
||||
return [tup[1] for tup in sorted([(string_similarity(string, sugg), sugg)
|
||||
for sugg in vocabulary],
|
||||
key=lambda tup: tup[0], reverse=True)
|
||||
if tup[0] >= cutoff][:maxnum]
|
||||
for sugg in vocabulary],
|
||||
key=lambda tup: tup[0], reverse=True)
|
||||
if tup[0] >= cutoff][:maxnum]
|
||||
|
||||
|
||||
def string_partial_matching(alternatives, inp, ret_index=True):
|
||||
|
|
@ -1589,6 +1598,7 @@ def get_evennia_pids():
|
|||
return int(server_pid), int(portal_pid)
|
||||
return None, None
|
||||
|
||||
|
||||
from gc import get_referents
|
||||
from sys import getsizeof
|
||||
|
||||
|
|
@ -1622,12 +1632,13 @@ def deepsize(obj, max_depth=4):
|
|||
idr = id(ref)
|
||||
if idr not in dct:
|
||||
dct[idr] = (ref, getsizeof(ref, default=0))
|
||||
_recurse(ref, dct, depth+1)
|
||||
_recurse(ref, dct, depth + 1)
|
||||
sizedict = {}
|
||||
_recurse(obj, sizedict, 0)
|
||||
size = getsizeof(obj) + sum([p[1] for p in sizedict.values()])
|
||||
return size
|
||||
|
||||
|
||||
# lazy load handler
|
||||
_missing = object()
|
||||
|
||||
|
|
@ -1651,6 +1662,7 @@ class lazy_property(object):
|
|||
property "attributes" on the object.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, func, name=None, doc=None):
|
||||
"""Store all properties for now"""
|
||||
self.__name__ = name or func.__name__
|
||||
|
|
@ -1668,6 +1680,7 @@ class lazy_property(object):
|
|||
obj.__dict__[self.__name__] = value
|
||||
return value
|
||||
|
||||
|
||||
_STRIP_ANSI = None
|
||||
_RE_CONTROL_CHAR = re.compile('[%s]' % re.escape(''.join([unichr(c) for c in range(0, 32)]))) # + range(127,160)])))
|
||||
|
||||
|
|
@ -1707,7 +1720,7 @@ def calledby(callerdepth=1):
|
|||
stack = inspect.stack()
|
||||
# we must step one extra level back in stack since we don't want
|
||||
# to include the call of this function itself.
|
||||
callerdepth = min(max(2, callerdepth + 1), len(stack)-1)
|
||||
callerdepth = min(max(2, callerdepth + 1), len(stack) - 1)
|
||||
frame = inspect.stack()[callerdepth]
|
||||
path = os.path.sep.join(frame[1].rsplit(os.path.sep, 2)[-2:])
|
||||
return "[called by '%s': %s:%s %s]" % (frame[3], path, frame[2], frame[4])
|
||||
|
|
@ -1774,15 +1787,15 @@ def at_search_result(matches, caller, query="", quiet=False, **kwargs):
|
|||
matches = None
|
||||
elif len(matches) > 1:
|
||||
error = kwargs.get("multimatch_string") or \
|
||||
_("More than one match for '%s' (please narrow target):\n" % query)
|
||||
_("More than one match for '%s' (please narrow target):\n" % query)
|
||||
for num, result in enumerate(matches):
|
||||
# we need to consider Commands, where .aliases is a list
|
||||
aliases = result.aliases.all() if hasattr(result.aliases, "all") else result.aliases
|
||||
error += _MULTIMATCH_TEMPLATE.format(
|
||||
number=num + 1,
|
||||
name=result.get_display_name(caller) if hasattr(result, "get_display_name") else query,
|
||||
aliases=" [%s]" % ";".join(aliases) if aliases else "",
|
||||
info=result.get_extra_info(caller))
|
||||
number=num + 1,
|
||||
name=result.get_display_name(caller) if hasattr(result, "get_display_name") else query,
|
||||
aliases=" [%s]" % ";".join(aliases) if aliases else "",
|
||||
info=result.get_extra_info(caller))
|
||||
matches = None
|
||||
else:
|
||||
# exactly one match
|
||||
|
|
@ -1800,6 +1813,7 @@ class LimitedSizeOrderedDict(OrderedDict):
|
|||
grow out of bounds.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Limited-size ordered dict.
|
||||
|
|
@ -1814,7 +1828,7 @@ class LimitedSizeOrderedDict(OrderedDict):
|
|||
"""
|
||||
super(LimitedSizeOrderedDict, self).__init__()
|
||||
self.size_limit = kwargs.get("size_limit", None)
|
||||
self.filo = not kwargs.get("fifo", True) # FIFO inverse of FILO
|
||||
self.filo = not kwargs.get("fifo", True) # FIFO inverse of FILO
|
||||
self._check_size()
|
||||
|
||||
def _check_size(self):
|
||||
|
|
@ -1850,7 +1864,3 @@ def get_game_dir_path():
|
|||
else:
|
||||
os.chdir(os.pardir)
|
||||
raise RuntimeError("server/conf/settings.py not found: Must start from inside game dir.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue