Format code with black. Add makefile to run fmt/tests
This commit is contained in:
parent
d00bce9288
commit
c2c7fa311a
299 changed files with 19037 additions and 11611 deletions
|
|
@ -56,7 +56,7 @@ def is_iter(obj):
|
|||
what we want to do with a string.
|
||||
|
||||
"""
|
||||
if isinstance(obj, (str, bytes )):
|
||||
if isinstance(obj, (str, bytes)):
|
||||
return False
|
||||
|
||||
try:
|
||||
|
|
@ -120,11 +120,11 @@ def pad(text, width=None, align="c", fillchar=" "):
|
|||
|
||||
"""
|
||||
width = width if width else settings.CLIENT_DEFAULT_WIDTH
|
||||
align = align if align in ('c', 'l', 'r') else 'c'
|
||||
align = align if align in ("c", "l", "r") else "c"
|
||||
fillchar = fillchar[0] if fillchar else " "
|
||||
if align == 'l':
|
||||
if align == "l":
|
||||
return text.ljust(width, fillchar)
|
||||
elif align == 'r':
|
||||
elif align == "r":
|
||||
return text.rjust(width, fillchar)
|
||||
else:
|
||||
return text.center(width, fillchar)
|
||||
|
|
@ -154,7 +154,7 @@ def crop(text, width=None, suffix="[...]"):
|
|||
return text
|
||||
else:
|
||||
lsuffix = len(suffix)
|
||||
text = text[:width] if lsuffix >= width else "%s%s" % (text[:width - lsuffix], suffix)
|
||||
text = text[:width] if lsuffix >= width else "%s%s" % (text[: width - lsuffix], suffix)
|
||||
return to_str(text)
|
||||
|
||||
|
||||
|
|
@ -183,11 +183,12 @@ def dedent(text, baseline_index=None):
|
|||
if baseline_index is None:
|
||||
return textwrap.dedent(text)
|
||||
else:
|
||||
lines = text.split('\n')
|
||||
lines = text.split("\n")
|
||||
baseline = lines[baseline_index]
|
||||
spaceremove = len(baseline) - len(baseline.lstrip(' '))
|
||||
return "\n".join(line[min(spaceremove, len(line) - len(line.lstrip(' '))):]
|
||||
for line in lines)
|
||||
spaceremove = len(baseline) - len(baseline.lstrip(" "))
|
||||
return "\n".join(
|
||||
line[min(spaceremove, len(line) - len(line.lstrip(" "))) :] for line in lines
|
||||
)
|
||||
|
||||
|
||||
def justify(text, width=None, align="f", indent=0):
|
||||
|
|
@ -220,19 +221,20 @@ def justify(text, width=None, align="f", indent=0):
|
|||
line_rest = width - (wlen + ngaps)
|
||||
gap = " " # minimum gap between words
|
||||
if line_rest > 0:
|
||||
if align == 'l':
|
||||
if align == "l":
|
||||
if line[-1] == "\n\n":
|
||||
line[-1] = " " * (line_rest-1) + "\n" + " " * width + "\n" + " " * width
|
||||
line[-1] = " " * (line_rest - 1) + "\n" + " " * width + "\n" + " " * width
|
||||
else:
|
||||
line[-1] += " " * line_rest
|
||||
elif align == 'r':
|
||||
elif align == "r":
|
||||
line[0] = " " * line_rest + line[0]
|
||||
elif align == 'c':
|
||||
elif align == "c":
|
||||
pad = " " * (line_rest // 2)
|
||||
line[0] = pad + line[0]
|
||||
if line[-1] == "\n\n":
|
||||
line[-1] += pad + " " * (line_rest % 2 - 1) + \
|
||||
"\n" + " " * width + "\n" + " " * width
|
||||
line[-1] += (
|
||||
pad + " " * (line_rest % 2 - 1) + "\n" + " " * width + "\n" + " " * width
|
||||
)
|
||||
else:
|
||||
line[-1] = line[-1] + pad + " " * (line_rest % 2)
|
||||
else: # align 'f'
|
||||
|
|
@ -282,7 +284,7 @@ def justify(text, width=None, align="f", indent=0):
|
|||
return "\n".join([indentstring + line for line in lines])
|
||||
|
||||
|
||||
def columnize(string, columns=2, spacing=4, align='l', width=None):
|
||||
def columnize(string, columns=2, spacing=4, align="l", width=None):
|
||||
"""
|
||||
Break a string into a number of columns, using as little
|
||||
vertical space as possible.
|
||||
|
|
@ -324,7 +326,7 @@ def columnize(string, columns=2, spacing=4, align='l', width=None):
|
|||
cols = []
|
||||
istart = 0
|
||||
for irows in nrows:
|
||||
cols.append(onecol[istart:istart+irows])
|
||||
cols.append(onecol[istart : istart + irows])
|
||||
istart = istart + irows
|
||||
for col in cols:
|
||||
if len(col) < height:
|
||||
|
|
@ -374,8 +376,8 @@ def list_to_string(inlist, endsep="and", addquote=False):
|
|||
return ""
|
||||
if addquote:
|
||||
if len(inlist) == 1:
|
||||
return "\"%s\"" % inlist[0]
|
||||
return ", ".join("\"%s\"" % v for v in inlist[:-1]) + "%s %s" % (endsep, "\"%s\"" % inlist[-1])
|
||||
return '"%s"' % inlist[0]
|
||||
return ", ".join('"%s"' % v for v in inlist[:-1]) + "%s %s" % (endsep, '"%s"' % inlist[-1])
|
||||
else:
|
||||
if len(inlist) == 1:
|
||||
return str(inlist[0])
|
||||
|
|
@ -448,9 +450,9 @@ def time_format(seconds, style=0):
|
|||
Standard colon-style output.
|
||||
"""
|
||||
if days > 0:
|
||||
retval = '%id %02i:%02i' % (days, hours, minutes,)
|
||||
retval = "%id %02i:%02i" % (days, hours, minutes)
|
||||
else:
|
||||
retval = '%02i:%02i' % (hours, minutes,)
|
||||
retval = "%02i:%02i" % (hours, minutes)
|
||||
return retval
|
||||
|
||||
elif style == 1:
|
||||
|
|
@ -458,62 +460,62 @@ def time_format(seconds, style=0):
|
|||
Simple, abbreviated form that only shows the highest time amount.
|
||||
"""
|
||||
if days > 0:
|
||||
return '%id' % (days,)
|
||||
return "%id" % (days,)
|
||||
elif hours > 0:
|
||||
return '%ih' % (hours,)
|
||||
return "%ih" % (hours,)
|
||||
elif minutes > 0:
|
||||
return '%im' % (minutes,)
|
||||
return "%im" % (minutes,)
|
||||
else:
|
||||
return '%is' % (seconds,)
|
||||
return "%is" % (seconds,)
|
||||
elif style == 2:
|
||||
"""
|
||||
Full-detailed, long-winded format. We ignore seconds.
|
||||
"""
|
||||
days_str = hours_str = ''
|
||||
minutes_str = '0 minutes'
|
||||
days_str = hours_str = ""
|
||||
minutes_str = "0 minutes"
|
||||
|
||||
if days > 0:
|
||||
if days == 1:
|
||||
days_str = '%i day, ' % days
|
||||
days_str = "%i day, " % days
|
||||
else:
|
||||
days_str = '%i days, ' % days
|
||||
days_str = "%i days, " % days
|
||||
if days or hours > 0:
|
||||
if hours == 1:
|
||||
hours_str = '%i hour, ' % hours
|
||||
hours_str = "%i hour, " % hours
|
||||
else:
|
||||
hours_str = '%i hours, ' % hours
|
||||
hours_str = "%i hours, " % hours
|
||||
if hours or minutes > 0:
|
||||
if minutes == 1:
|
||||
minutes_str = '%i minute ' % minutes
|
||||
minutes_str = "%i minute " % minutes
|
||||
else:
|
||||
minutes_str = '%i minutes ' % minutes
|
||||
retval = '%s%s%s' % (days_str, hours_str, minutes_str)
|
||||
minutes_str = "%i minutes " % minutes
|
||||
retval = "%s%s%s" % (days_str, hours_str, minutes_str)
|
||||
elif style == 3:
|
||||
"""
|
||||
Full-detailed, long-winded format. Includes seconds.
|
||||
"""
|
||||
days_str = hours_str = minutes_str = seconds_str = ''
|
||||
days_str = hours_str = minutes_str = seconds_str = ""
|
||||
if days > 0:
|
||||
if days == 1:
|
||||
days_str = '%i day, ' % days
|
||||
days_str = "%i day, " % days
|
||||
else:
|
||||
days_str = '%i days, ' % days
|
||||
days_str = "%i days, " % days
|
||||
if days or hours > 0:
|
||||
if hours == 1:
|
||||
hours_str = '%i hour, ' % hours
|
||||
hours_str = "%i hour, " % hours
|
||||
else:
|
||||
hours_str = '%i hours, ' % hours
|
||||
hours_str = "%i hours, " % hours
|
||||
if hours or minutes > 0:
|
||||
if minutes == 1:
|
||||
minutes_str = '%i minute ' % minutes
|
||||
minutes_str = "%i minute " % minutes
|
||||
else:
|
||||
minutes_str = '%i minutes ' % minutes
|
||||
minutes_str = "%i minutes " % minutes
|
||||
if minutes or seconds > 0:
|
||||
if seconds == 1:
|
||||
seconds_str = '%i second ' % seconds
|
||||
seconds_str = "%i second " % seconds
|
||||
else:
|
||||
seconds_str = '%i seconds ' % seconds
|
||||
retval = '%s%s%s%s' % (days_str, hours_str, minutes_str, seconds_str)
|
||||
seconds_str = "%i seconds " % seconds
|
||||
retval = "%s%s%s%s" % (days_str, hours_str, minutes_str, seconds_str)
|
||||
elif style == 4:
|
||||
"""
|
||||
Only return the highest unit.
|
||||
|
|
@ -611,6 +613,7 @@ def get_evennia_version(mode="long"):
|
|||
|
||||
"""
|
||||
import evennia
|
||||
|
||||
vers = evennia.__version__
|
||||
if mode == "short":
|
||||
return vers.split()[0].strip()
|
||||
|
|
@ -621,7 +624,7 @@ def get_evennia_version(mode="long"):
|
|||
return vers
|
||||
|
||||
|
||||
def pypath_to_realpath(python_path, file_ending='.py', pypath_prefixes=None):
|
||||
def pypath_to_realpath(python_path, file_ending=".py", pypath_prefixes=None):
|
||||
"""
|
||||
Converts a dotted Python path to an absolute path under the
|
||||
Evennia library directory or under the current game directory.
|
||||
|
|
@ -645,26 +648,38 @@ def pypath_to_realpath(python_path, file_ending='.py', pypath_prefixes=None):
|
|||
prefixes.
|
||||
|
||||
"""
|
||||
path = python_path.strip().split('.')
|
||||
path = python_path.strip().split(".")
|
||||
plong = osjoin(*path) + file_ending
|
||||
pshort = osjoin(*path[1:]) + file_ending if len(path) > 1 else plong # in case we had evennia. or mygame.
|
||||
prefixlong = [osjoin(*ppath.strip().split('.'))
|
||||
for ppath in make_iter(pypath_prefixes)] \
|
||||
if pypath_prefixes else []
|
||||
prefixshort = [osjoin(*ppath.strip().split('.')[1:])
|
||||
for ppath in make_iter(pypath_prefixes) if len(ppath.strip().split('.')) > 1]\
|
||||
if pypath_prefixes else []
|
||||
paths = [plong] + \
|
||||
[osjoin(_EVENNIA_DIR, prefix, plong) for prefix in prefixlong] + \
|
||||
[osjoin(_GAME_DIR, prefix, plong) for prefix in prefixlong] + \
|
||||
[osjoin(_EVENNIA_DIR, prefix, plong) for prefix in prefixshort] + \
|
||||
[osjoin(_GAME_DIR, prefix, plong) for prefix in prefixshort] + \
|
||||
[osjoin(_EVENNIA_DIR, plong), osjoin(_GAME_DIR, plong)] + \
|
||||
[osjoin(_EVENNIA_DIR, prefix, pshort) for prefix in prefixshort] + \
|
||||
[osjoin(_GAME_DIR, prefix, pshort) for prefix in prefixshort] + \
|
||||
[osjoin(_EVENNIA_DIR, prefix, pshort) for prefix in prefixlong] + \
|
||||
[osjoin(_GAME_DIR, prefix, pshort) for prefix in prefixlong] + \
|
||||
[osjoin(_EVENNIA_DIR, pshort), osjoin(_GAME_DIR, pshort)]
|
||||
pshort = (
|
||||
osjoin(*path[1:]) + file_ending if len(path) > 1 else plong
|
||||
) # in case we had evennia. or mygame.
|
||||
prefixlong = (
|
||||
[osjoin(*ppath.strip().split(".")) for ppath in make_iter(pypath_prefixes)]
|
||||
if pypath_prefixes
|
||||
else []
|
||||
)
|
||||
prefixshort = (
|
||||
[
|
||||
osjoin(*ppath.strip().split(".")[1:])
|
||||
for ppath in make_iter(pypath_prefixes)
|
||||
if len(ppath.strip().split(".")) > 1
|
||||
]
|
||||
if pypath_prefixes
|
||||
else []
|
||||
)
|
||||
paths = (
|
||||
[plong]
|
||||
+ [osjoin(_EVENNIA_DIR, prefix, plong) for prefix in prefixlong]
|
||||
+ [osjoin(_GAME_DIR, prefix, plong) for prefix in prefixlong]
|
||||
+ [osjoin(_EVENNIA_DIR, prefix, plong) for prefix in prefixshort]
|
||||
+ [osjoin(_GAME_DIR, prefix, plong) for prefix in prefixshort]
|
||||
+ [osjoin(_EVENNIA_DIR, plong), osjoin(_GAME_DIR, plong)]
|
||||
+ [osjoin(_EVENNIA_DIR, prefix, pshort) for prefix in prefixshort]
|
||||
+ [osjoin(_GAME_DIR, prefix, pshort) for prefix in prefixshort]
|
||||
+ [osjoin(_EVENNIA_DIR, prefix, pshort) for prefix in prefixlong]
|
||||
+ [osjoin(_GAME_DIR, prefix, pshort) for prefix in prefixlong]
|
||||
+ [osjoin(_EVENNIA_DIR, pshort), osjoin(_GAME_DIR, pshort)]
|
||||
)
|
||||
# filter out non-existing paths
|
||||
return list(set(p for p in paths if os.path.isfile(p)))
|
||||
|
||||
|
|
@ -684,13 +699,14 @@ def dbref(inp, reqhash=True):
|
|||
|
||||
"""
|
||||
if reqhash:
|
||||
num = (int(inp.lstrip('#')) if (isinstance(inp, str) and
|
||||
inp.startswith("#") and
|
||||
inp.lstrip('#').isdigit())
|
||||
else None)
|
||||
num = (
|
||||
int(inp.lstrip("#"))
|
||||
if (isinstance(inp, str) and inp.startswith("#") and inp.lstrip("#").isdigit())
|
||||
else None
|
||||
)
|
||||
return num if isinstance(num, int) and num > 0 else None
|
||||
elif isinstance(inp, str):
|
||||
inp = inp.lstrip('#')
|
||||
inp = inp.lstrip("#")
|
||||
return int(inp) if inp.isdigit() and int(inp) > 0 else None
|
||||
else:
|
||||
return inp if isinstance(inp, int) else None
|
||||
|
|
@ -739,11 +755,17 @@ dbid_to_obj = dbref_to_obj
|
|||
|
||||
|
||||
# some direct translations for the latinify
|
||||
_UNICODE_MAP = {"EM DASH": "-", "FIGURE DASH": "-", "EN DASH": "-", "HORIZONTAL BAR": "-",
|
||||
"HORIZONTAL ELLIPSIS": "...", "RIGHT SINGLE QUOTATION MARK": "'"}
|
||||
_UNICODE_MAP = {
|
||||
"EM DASH": "-",
|
||||
"FIGURE DASH": "-",
|
||||
"EN DASH": "-",
|
||||
"HORIZONTAL BAR": "-",
|
||||
"HORIZONTAL ELLIPSIS": "...",
|
||||
"RIGHT SINGLE QUOTATION MARK": "'",
|
||||
}
|
||||
|
||||
|
||||
def latinify(string, default='?', pure_ascii=False):
|
||||
def latinify(string, default="?", pure_ascii=False):
|
||||
"""
|
||||
Convert a unicode string to "safe" ascii/latin-1 characters.
|
||||
This is used as a last resort when normal encoding does not work.
|
||||
|
|
@ -769,7 +791,7 @@ def latinify(string, default='?', pure_ascii=False):
|
|||
converted = []
|
||||
for unich in iter(string):
|
||||
try:
|
||||
ch = unich.decode('ascii')
|
||||
ch = unich.decode("ascii")
|
||||
except UnicodeDecodeError:
|
||||
# deduce a latin letter equivalent from the Unicode data
|
||||
# point name; e.g., since `name(u'á') == 'LATIN SMALL
|
||||
|
|
@ -786,12 +808,12 @@ def latinify(string, default='?', pure_ascii=False):
|
|||
ch = _UNICODE_MAP[what]
|
||||
else:
|
||||
what = what.split()
|
||||
if what[0] == 'LATIN' and what[2] == 'LETTER' and len(what[3]) == 1:
|
||||
ch = what[3].lower() if what[1] == 'SMALL' else what[3].upper()
|
||||
if what[0] == "LATIN" and what[2] == "LETTER" and len(what[3]) == 1:
|
||||
ch = what[3].lower() if what[1] == "SMALL" else what[3].upper()
|
||||
else:
|
||||
ch = default
|
||||
converted.append(chr(ord(ch)))
|
||||
return ''.join(converted)
|
||||
return "".join(converted)
|
||||
|
||||
|
||||
def to_bytes(text, session=None):
|
||||
|
|
@ -824,7 +846,7 @@ def to_bytes(text, session=None):
|
|||
except Exception:
|
||||
text = repr(text)
|
||||
|
||||
default_encoding = session.protocol_flags.get("ENCODING", 'utf-8') if session else 'utf-8'
|
||||
default_encoding = session.protocol_flags.get("ENCODING", "utf-8") if session else "utf-8"
|
||||
try:
|
||||
return text.encode(default_encoding)
|
||||
except (LookupError, UnicodeEncodeError):
|
||||
|
|
@ -863,7 +885,7 @@ def to_str(text, session=None):
|
|||
except Exception:
|
||||
return repr(text)
|
||||
|
||||
default_encoding = session.protocol_flags.get("ENCODING", 'utf-8') if session else 'utf-8'
|
||||
default_encoding = session.protocol_flags.get("ENCODING", "utf-8") if session else "utf-8"
|
||||
try:
|
||||
return text.decode(default_encoding)
|
||||
except (LookupError, UnicodeDecodeError):
|
||||
|
|
@ -894,9 +916,28 @@ def validate_email_address(emailaddress):
|
|||
|
||||
emailaddress = r"%s" % emailaddress
|
||||
|
||||
domains = ("aero", "asia", "biz", "cat", "com", "coop",
|
||||
"edu", "gov", "info", "int", "jobs", "mil", "mobi", "museum",
|
||||
"name", "net", "org", "pro", "tel", "travel")
|
||||
domains = (
|
||||
"aero",
|
||||
"asia",
|
||||
"biz",
|
||||
"cat",
|
||||
"com",
|
||||
"coop",
|
||||
"edu",
|
||||
"gov",
|
||||
"info",
|
||||
"int",
|
||||
"jobs",
|
||||
"mil",
|
||||
"mobi",
|
||||
"museum",
|
||||
"name",
|
||||
"net",
|
||||
"org",
|
||||
"pro",
|
||||
"tel",
|
||||
"travel",
|
||||
)
|
||||
|
||||
# Email address must be more than 7 characters in total.
|
||||
if len(emailaddress) < 7:
|
||||
|
|
@ -904,8 +945,8 @@ def validate_email_address(emailaddress):
|
|||
|
||||
# Split up email address into parts.
|
||||
try:
|
||||
localpart, domainname = emailaddress.rsplit('@', 1)
|
||||
host, toplevel = domainname.rsplit('.', 1)
|
||||
localpart, domainname = emailaddress.rsplit("@", 1)
|
||||
host, toplevel = domainname.rsplit(".", 1)
|
||||
except ValueError:
|
||||
return False # Address does not have enough parts.
|
||||
|
||||
|
|
@ -913,9 +954,9 @@ def validate_email_address(emailaddress):
|
|||
if len(toplevel) != 2 and toplevel not in domains:
|
||||
return False # Not a domain name.
|
||||
|
||||
for i in '-_.%+.':
|
||||
for i in "-_.%+.":
|
||||
localpart = localpart.replace(i, "")
|
||||
for i in '-_.':
|
||||
for i in "-_.":
|
||||
host = host.replace(i, "")
|
||||
|
||||
if localpart.isalnum() and host.isalnum():
|
||||
|
|
@ -973,6 +1014,7 @@ def server_services():
|
|||
|
||||
"""
|
||||
from evennia.server.sessionhandler import SESSIONS
|
||||
|
||||
if hasattr(SESSIONS, "server") and hasattr(SESSIONS.server, "services"):
|
||||
server = SESSIONS.server.services.namedServices
|
||||
else:
|
||||
|
|
@ -1120,28 +1162,34 @@ def check_evennia_dependencies():
|
|||
|
||||
# check main dependencies
|
||||
from evennia.server.evennia_launcher import check_main_evennia_dependencies
|
||||
|
||||
not_error = check_main_evennia_dependencies()
|
||||
|
||||
errstring = ""
|
||||
# South is no longer used ...
|
||||
if 'south' in settings.INSTALLED_APPS:
|
||||
errstring += "\n ERROR: 'south' found in settings.INSTALLED_APPS. " \
|
||||
"\n South is no longer used. If this was added manually, remove it."
|
||||
if "south" in settings.INSTALLED_APPS:
|
||||
errstring += (
|
||||
"\n ERROR: 'south' found in settings.INSTALLED_APPS. "
|
||||
"\n South is no longer used. If this was added manually, remove it."
|
||||
)
|
||||
not_error = False
|
||||
# IRC support
|
||||
if settings.IRC_ENABLED:
|
||||
try:
|
||||
import twisted.words
|
||||
|
||||
twisted.words # set to avoid debug info about not-used import
|
||||
except ImportError:
|
||||
errstring += "\n ERROR: IRC is enabled, but twisted.words is not installed. Please install it." \
|
||||
"\n Linux Debian/Ubuntu users should install package 'python-twisted-words', others" \
|
||||
"\n can get it from http://twistedmatrix.com/trac/wiki/TwistedWords."
|
||||
errstring += (
|
||||
"\n ERROR: IRC is enabled, but twisted.words is not installed. Please install it."
|
||||
"\n Linux Debian/Ubuntu users should install package 'python-twisted-words', others"
|
||||
"\n can get it from http://twistedmatrix.com/trac/wiki/TwistedWords."
|
||||
)
|
||||
not_error = False
|
||||
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
|
||||
|
||||
|
||||
|
|
@ -1158,8 +1206,11 @@ def has_parent(basepath, obj):
|
|||
|
||||
"""
|
||||
try:
|
||||
return any(cls for cls in obj.__class__.mro()
|
||||
if basepath == "%s.%s" % (cls.__module__, cls.__name__))
|
||||
return any(
|
||||
cls
|
||||
for cls in obj.__class__.mro()
|
||||
if basepath == "%s.%s" % (cls.__module__, cls.__name__)
|
||||
)
|
||||
except (TypeError, AttributeError):
|
||||
# this can occur if we tried to store a class object, not an
|
||||
# instance. Not sure if one should defend against this.
|
||||
|
|
@ -1181,7 +1232,7 @@ def mod_import_from_path(path):
|
|||
if not os.path.isabs(path):
|
||||
path = os.path.abspath(path)
|
||||
dirpath, filename = path.rsplit(os.path.sep, 1)
|
||||
modname = filename.rstrip('.py')
|
||||
modname = filename.rstrip(".py")
|
||||
|
||||
try:
|
||||
return importlib.machinery.SourceFileLoader(modname, path).load_module()
|
||||
|
|
@ -1212,7 +1263,7 @@ def mod_import(module):
|
|||
# if this is already a module, we are done
|
||||
return module
|
||||
|
||||
if module.endswith('.py') and os.path.exists(module):
|
||||
if module.endswith(".py") and os.path.exists(module):
|
||||
return mod_import_from_path(module)
|
||||
|
||||
try:
|
||||
|
|
@ -1306,8 +1357,9 @@ def variable_from_module(module, variable=None, default=None):
|
|||
result.append(mod.__dict__.get(var, default))
|
||||
else:
|
||||
# get all
|
||||
result = [val for key, val in mod.__dict__.items()
|
||||
if not (key.startswith("_") or ismodule(val))]
|
||||
result = [
|
||||
val for key, val in mod.__dict__.items() if not (key.startswith("_") or ismodule(val))
|
||||
]
|
||||
|
||||
if len(result) == 1:
|
||||
return result[0]
|
||||
|
|
@ -1408,8 +1460,11 @@ def class_from_module(path, defaultpaths=None):
|
|||
cls = None
|
||||
err = ""
|
||||
if defaultpaths:
|
||||
paths = [path] + ["%s.%s" % (dpath, path)
|
||||
for dpath in make_iter(defaultpaths)] if defaultpaths else []
|
||||
paths = (
|
||||
[path] + ["%s.%s" % (dpath, path) for dpath in make_iter(defaultpaths)]
|
||||
if defaultpaths
|
||||
else []
|
||||
)
|
||||
else:
|
||||
paths = [path]
|
||||
|
||||
|
|
@ -1420,13 +1475,13 @@ def class_from_module(path, defaultpaths=None):
|
|||
raise ImportError("the path '%s' is not on the form modulepath.Classname." % path)
|
||||
|
||||
try:
|
||||
if not importlib.util.find_spec(testpath, package='evennia'):
|
||||
if not importlib.util.find_spec(testpath, package="evennia"):
|
||||
continue
|
||||
except ModuleNotFoundError:
|
||||
continue
|
||||
|
||||
try:
|
||||
mod = importlib.import_module(testpath, package='evennia')
|
||||
mod = importlib.import_module(testpath, package="evennia")
|
||||
except ModuleNotFoundError:
|
||||
err = traceback.format_exc(30)
|
||||
break
|
||||
|
|
@ -1441,7 +1496,8 @@ def class_from_module(path, defaultpaths=None):
|
|||
break
|
||||
if not cls:
|
||||
err = "\nCould not load typeclass '{}'{}".format(
|
||||
path, " with the following traceback:\n" + err if err else "")
|
||||
path, " with the following traceback:\n" + err if err else ""
|
||||
)
|
||||
if defaultpaths:
|
||||
err += "\nPaths searched:\n %s" % "\n ".join(paths)
|
||||
else:
|
||||
|
|
@ -1459,6 +1515,7 @@ def init_new_account(account):
|
|||
Deprecated.
|
||||
"""
|
||||
from evennia.utils import logger
|
||||
|
||||
logger.log_dep("evennia.utils.utils.init_new_account is DEPRECATED and should not be used.")
|
||||
|
||||
|
||||
|
|
@ -1483,8 +1540,9 @@ def string_similarity(string1, string2):
|
|||
vec1 = [string1.count(v) for v in vocabulary]
|
||||
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)))
|
||||
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))
|
||||
)
|
||||
except ZeroDivisionError:
|
||||
# can happen if empty-string cmdnames appear for some reason.
|
||||
# This is a no-match.
|
||||
|
|
@ -1509,10 +1567,15 @@ def string_suggestions(string, vocabulary, cutoff=0.6, maxnum=3):
|
|||
Could be empty if there are no matches.
|
||||
|
||||
"""
|
||||
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]
|
||||
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]
|
||||
|
||||
|
||||
def string_partial_matching(alternatives, inp, ret_index=True):
|
||||
|
|
@ -1546,9 +1609,11 @@ def string_partial_matching(alternatives, inp, ret_index=True):
|
|||
for inp_word in inp_words:
|
||||
# loop over parts, making sure only to visit each part once
|
||||
# (this will invalidate input in the wrong word order)
|
||||
submatch = [last_index + alt_num for alt_num, alt_word
|
||||
in enumerate(alt_words[last_index:])
|
||||
if alt_word.startswith(inp_word)]
|
||||
submatch = [
|
||||
last_index + alt_num
|
||||
for alt_num, alt_word in enumerate(alt_words[last_index:])
|
||||
if alt_word.startswith(inp_word)
|
||||
]
|
||||
if submatch:
|
||||
last_index = min(submatch) + 1
|
||||
score += 1
|
||||
|
|
@ -1607,8 +1672,12 @@ def format_table(table, extra_space=1):
|
|||
max_widths = [max([len(str(val)) for val in col]) for col in table]
|
||||
ftable = []
|
||||
for irow in range(len(table[0])):
|
||||
ftable.append([str(col[irow]).ljust(max_widths[icol]) + " " * extra_space
|
||||
for icol, col in enumerate(table)])
|
||||
ftable.append(
|
||||
[
|
||||
str(col[irow]).ljust(max_widths[icol]) + " " * extra_space
|
||||
for icol, col in enumerate(table)
|
||||
]
|
||||
)
|
||||
return ftable
|
||||
|
||||
|
||||
|
|
@ -1631,14 +1700,14 @@ def get_evennia_pids():
|
|||
is_subprocess = self_pid not in (server_pid, portal_pid)
|
||||
```
|
||||
"""
|
||||
server_pidfile = os.path.join(settings.GAME_DIR, 'server.pid')
|
||||
portal_pidfile = os.path.join(settings.GAME_DIR, 'portal.pid')
|
||||
server_pidfile = os.path.join(settings.GAME_DIR, "server.pid")
|
||||
portal_pidfile = os.path.join(settings.GAME_DIR, "portal.pid")
|
||||
server_pid, portal_pid = None, None
|
||||
if os.path.exists(server_pidfile):
|
||||
with open(server_pidfile, 'r') as f:
|
||||
with open(server_pidfile, "r") as f:
|
||||
server_pid = f.read()
|
||||
if os.path.exists(portal_pidfile):
|
||||
with open(portal_pidfile, 'r') as f:
|
||||
with open(portal_pidfile, "r") as f:
|
||||
portal_pid = f.read()
|
||||
if server_pid and portal_pid:
|
||||
return int(server_pid), int(portal_pid)
|
||||
|
|
@ -1667,6 +1736,7 @@ def deepsize(obj, max_depth=4):
|
|||
and their handlers.
|
||||
|
||||
"""
|
||||
|
||||
def _recurse(o, dct, depth):
|
||||
if 0 <= max_depth < depth:
|
||||
return
|
||||
|
|
@ -1675,6 +1745,7 @@ def deepsize(obj, max_depth=4):
|
|||
if idr not in dct:
|
||||
dct[idr] = (ref, sys.getsizeof(ref, default=0))
|
||||
_recurse(ref, dct, depth + 1)
|
||||
|
||||
sizedict = {}
|
||||
_recurse(obj, sizedict, 0)
|
||||
size = sys.getsizeof(obj) + sum([p[1] for p in sizedict.values()])
|
||||
|
|
@ -1724,7 +1795,9 @@ class lazy_property(object):
|
|||
|
||||
|
||||
_STRIP_ANSI = None
|
||||
_RE_CONTROL_CHAR = re.compile('[%s]' % re.escape(''.join([chr(c) for c in range(0, 32)]))) # + range(127,160)])))
|
||||
_RE_CONTROL_CHAR = re.compile(
|
||||
"[%s]" % re.escape("".join([chr(c) for c in range(0, 32)]))
|
||||
) # + range(127,160)])))
|
||||
|
||||
|
||||
def strip_control_sequences(string):
|
||||
|
|
@ -1741,7 +1814,7 @@ def strip_control_sequences(string):
|
|||
global _STRIP_ANSI
|
||||
if not _STRIP_ANSI:
|
||||
from evennia.utils.ansi import strip_raw_ansi as _STRIP_ANSI
|
||||
return _RE_CONTROL_CHAR.sub('', _STRIP_ANSI(string))
|
||||
return _RE_CONTROL_CHAR.sub("", _STRIP_ANSI(string))
|
||||
|
||||
|
||||
def calledby(callerdepth=1):
|
||||
|
|
@ -1759,6 +1832,7 @@ def calledby(callerdepth=1):
|
|||
|
||||
"""
|
||||
import inspect
|
||||
|
||||
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.
|
||||
|
|
@ -1783,10 +1857,12 @@ def m_len(target):
|
|||
"""
|
||||
# Would create circular import if in module root.
|
||||
from evennia.utils.ansi import ANSI_PARSER
|
||||
|
||||
if inherits_from(target, str) and "|lt" in target:
|
||||
return len(ANSI_PARSER.strip_mxp(target))
|
||||
return len(target)
|
||||
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Search handler function
|
||||
# -------------------------------------------------------------------
|
||||
|
|
@ -1841,9 +1917,12 @@ def at_search_result(matches, caller, query="", quiet=False, **kwargs):
|
|||
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,
|
||||
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))
|
||||
info=result.get_extra_info(caller),
|
||||
)
|
||||
matches = None
|
||||
else:
|
||||
# exactly one match
|
||||
|
|
@ -1882,9 +1961,13 @@ class LimitedSizeOrderedDict(OrderedDict):
|
|||
def __eq__(self, other):
|
||||
ret = super().__eq__(other)
|
||||
if ret:
|
||||
return (ret and
|
||||
hasattr(other, 'size_limit') and self.size_limit == other.size_limit and
|
||||
hasattr(other, 'fifo') and self.fifo == other.fifo)
|
||||
return (
|
||||
ret
|
||||
and hasattr(other, "size_limit")
|
||||
and self.size_limit == other.size_limit
|
||||
and hasattr(other, "fifo")
|
||||
and self.fifo == other.fifo
|
||||
)
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
|
|
@ -1943,11 +2026,18 @@ def get_all_typeclasses(parent=None):
|
|||
|
||||
"""
|
||||
from evennia.typeclasses.models import TypedObject
|
||||
typeclasses = {"{}.{}".format(model.__module__, model.__name__): model
|
||||
for model in apps.get_models() if TypedObject in getmro(model)}
|
||||
|
||||
typeclasses = {
|
||||
"{}.{}".format(model.__module__, model.__name__): model
|
||||
for model in apps.get_models()
|
||||
if TypedObject in getmro(model)
|
||||
}
|
||||
if parent:
|
||||
typeclasses = {name: typeclass for name, typeclass in typeclasses.items()
|
||||
if inherits_from(typeclass, parent)}
|
||||
typeclasses = {
|
||||
name: typeclass
|
||||
for name, typeclass in typeclasses.items()
|
||||
if inherits_from(typeclass, parent)
|
||||
}
|
||||
return typeclasses
|
||||
|
||||
|
||||
|
|
@ -1976,6 +2066,7 @@ def interactive(func):
|
|||
|
||||
"""
|
||||
from evennia.utils.evmenu import get_input
|
||||
|
||||
def _process_input(caller, prompt, result, generator):
|
||||
deferLater(reactor, 0, _iterate, generator, caller, response=result)
|
||||
return False
|
||||
|
|
@ -1993,8 +2084,10 @@ def interactive(func):
|
|||
delay(value, _iterate, generator, caller=caller)
|
||||
elif isinstance(value, str):
|
||||
if not caller:
|
||||
raise ValueError("To retrieve input from a @pausable method, that method "
|
||||
"must be called with a 'caller' argument)")
|
||||
raise ValueError(
|
||||
"To retrieve input from a @pausable method, that method "
|
||||
"must be called with a 'caller' argument)"
|
||||
)
|
||||
get_input(caller, value, _process_input, generator=generator)
|
||||
else:
|
||||
raise ValueError("yield(val) in a @pausable method must have an int/float as arg.")
|
||||
|
|
@ -2002,9 +2095,9 @@ def interactive(func):
|
|||
def decorator(*args, **kwargs):
|
||||
argnames = inspect.getfullargspec(func).args
|
||||
caller = None
|
||||
if 'caller' in argnames:
|
||||
if "caller" in argnames:
|
||||
# we assume this is an object
|
||||
caller = args[argnames.index('caller')]
|
||||
caller = args[argnames.index("caller")]
|
||||
|
||||
ret = func(*args, **kwargs)
|
||||
if isinstance(ret, types.GeneratorType):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue