Deprecate to_str, to_unicode. Fix class_from_module, is_iter, make_iter.

This commit is contained in:
Ryan Stein 2017-10-29 23:29:21 -04:00
parent 5074c112af
commit 93475a6de5

View file

@ -6,8 +6,6 @@ They provide some useful string and conversion methods that might
be of use when designing your own game.
"""
from builtins import object, range
from future.utils import viewkeys, raise_
import os
@ -20,6 +18,7 @@ import textwrap
import random
from os.path import join as osjoin
from importlib import import_module
from importlib.util import find_spec, module_from_spec
from inspect import ismodule, trace, getmembers, getmodule
from collections import defaultdict, OrderedDict
from twisted.internet import threads, reactor, task
@ -32,10 +31,7 @@ _MULTIMATCH_TEMPLATE = settings.SEARCH_MULTIMATCH_TEMPLATE
_EVENNIA_DIR = settings.EVENNIA_DIR
_GAME_DIR = settings.GAME_DIR
try:
import pickle as pickle
except ImportError:
import pickle
import pickle
ENCODINGS = settings.ENCODINGS
_GA = object.__getattribute__
@ -45,15 +41,15 @@ _DA = object.__delattr__
_DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
def is_iter(iterable):
def is_iter(obj):
"""
Checks if an object behaves iterably.
Args:
iterable (any): Entity to check for iterability.
obj (any): Entity to check for iterability.
Returns:
is_iterable (bool): If `iterable` is iterable or not.
is_iterable (bool): If `obj` is iterable or not.
Notes:
Strings are *not* accepted as iterable (although they are
@ -61,7 +57,13 @@ def is_iter(iterable):
what we want to do with a string.
"""
return hasattr(iterable, '__iter__')
if isinstance(obj, (str, bytes, )):
return False
try:
return iter(obj) and True
except TypeError:
return False
def make_iter(obj):
@ -76,7 +78,7 @@ def make_iter(obj):
passed-through or made iterable.
"""
return not hasattr(obj, '__iter__') and [obj] or obj
return not is_iter(obj) and [obj] or obj
def wrap(text, width=_DEFAULT_WIDTH, indent=0):
@ -599,7 +601,7 @@ def dbref(inp, reqhash=True):
inp.startswith("#") and
inp.lstrip('#').isdigit())
else None)
return num if num > 0 else None
return num if isinstance(num, int) and num > 0 else None
elif isinstance(inp, str):
inp = inp.lstrip('#')
return int(inp) if inp.isdigit() and int(inp) > 0 else None
@ -702,6 +704,10 @@ def latinify(unicode_string, default='?', pure_ascii=False):
def to_unicode(obj, encoding='utf-8', force_string=False):
"""
This function is deprecated in the Python 3 version of Evennia and is
likely to be phased out in future releases.
---
This decodes a suitable object to the unicode format.
Args:
@ -723,35 +729,23 @@ def to_unicode(obj, encoding='utf-8', force_string=False):
"""
if force_string and not isinstance(obj, str):
if isinstance(obj, (str, bytes, )):
return obj
if force_string:
# some sort of other object. Try to
# convert it to a string representation.
if hasattr(obj, '__str__'):
obj = obj.__str__()
elif hasattr(obj, '__unicode__'):
obj = obj.__unicode__()
else:
# last resort
obj = str(obj)
obj = str(obj)
if isinstance(obj, str) and not isinstance(obj, str):
try:
obj = str(obj, encoding)
return obj
except UnicodeDecodeError:
for alt_encoding in ENCODINGS:
try:
obj = str(obj, alt_encoding)
return obj
except UnicodeDecodeError:
# if we still have an error, give up
pass
raise Exception("Error: '%s' contains invalid character(s) not in %s." % (obj, encoding))
return obj
def to_str(obj, encoding='utf-8', force_string=False):
"""
This function is deprecated in the Python 3 version of Evennia and is
likely to be phased out in future releases.
---
This encodes a unicode string back to byte-representation,
for printing, writing to disk etc.
@ -768,32 +762,14 @@ def to_str(obj, encoding='utf-8', force_string=False):
conversion of objects to strings.
"""
if force_string and not isinstance(obj, str):
if isinstance(obj, (str, bytes, )):
return obj
if force_string:
# some sort of other object. Try to
# convert it to a string representation.
try:
obj = str(obj)
except Exception:
obj = str(obj)
obj = str(obj)
if isinstance(obj, str) and isinstance(obj, str):
try:
obj = obj.encode(encoding)
return obj
except UnicodeEncodeError:
for alt_encoding in ENCODINGS:
try:
obj = obj.encode(alt_encoding)
return obj
except UnicodeEncodeError:
# if we still have an error, give up
pass
# 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 as err:
raise Exception("%s, Error: Unicode could not encode unicode string '%s'(%s) to a bytestring. " % (err, obj, encoding))
return obj
@ -1355,7 +1331,7 @@ def class_from_module(path, defaultpaths=None):
Args:
path (str): Full Python dot-path to module.
defaultpaths (iterable, optional): If a direc import from `path` fails,
defaultpaths (iterable, optional): If a direct import from `path` fails,
try subsequent imports by prepending those paths to `path`.
Returns:
@ -1376,17 +1352,18 @@ def class_from_module(path, defaultpaths=None):
testpath, clsname = testpath.rsplit(".", 1)
else:
raise ImportError("the path '%s' is not on the form modulepath.Classname." % path)
try:
mod = import_module(testpath, package="evennia")
except ImportError:
if len(trace()) > 2:
# this means the error happened within the called module and
# we must not hide it.
exc = sys.exc_info()
raise_(exc[1], None, exc[2])
else:
# otherwise, try the next suggested path
if not find_spec(testpath, package='evennia'):
continue
except ModuleNotFoundError:
continue
try:
mod = import_module(testpath, package='evennia')
except ModuleNotFoundError:
break
try:
cls = getattr(mod, clsname)
break