|
@@ -27,6 +27,7 @@ from string import hexdigits,ascii_letters,digits
|
|
|
from .exception import *
|
|
|
from .globalvars import *
|
|
|
from .color import *
|
|
|
+from .objmethods import *
|
|
|
|
|
|
def get_obj(objname,*args,**kwargs):
|
|
|
"""
|
|
@@ -63,17 +64,6 @@ def is_mmgen_id(proto,s): return get_obj(MMGenID, proto=proto, id_str=s, silen
|
|
|
def is_coin_addr(proto,s): return get_obj(CoinAddr, proto=proto, addr=s, silent=True,return_bool=True)
|
|
|
def is_wif(proto,s): return get_obj(WifKey, proto=proto, wif=s, silent=True,return_bool=True)
|
|
|
|
|
|
-def truncate_str(s,width): # width = screen width
|
|
|
- wide_count = 0
|
|
|
- for i in range(len(s)):
|
|
|
- wide_count += unicodedata.east_asian_width(s[i]) in ('F','W')
|
|
|
- if wide_count + i >= width:
|
|
|
- return s[:i] + ('',' ')[
|
|
|
- unicodedata.east_asian_width(s[i]) in ('F','W')
|
|
|
- and wide_count + i == width]
|
|
|
- else: # pad the string to width if necessary
|
|
|
- return s + ' '*(width-len(s)-wide_count)
|
|
|
-
|
|
|
# dict that keeps a list of keys for efficient lookup by index
|
|
|
class IndexedDict(dict):
|
|
|
|
|
@@ -108,99 +98,6 @@ class MMGenList(list,MMGenObject): pass
|
|
|
class MMGenDict(dict,MMGenObject): pass
|
|
|
class AddrListData(list,MMGenObject): pass
|
|
|
|
|
|
-class InitErrors:
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def init_fail(cls,e,m,e2=None,m2=None,objname=None,preformat=False):
|
|
|
-
|
|
|
- if preformat:
|
|
|
- errmsg = m
|
|
|
- else:
|
|
|
- errmsg = '{!r}: value cannot be converted to {} {}({!s})'.format(
|
|
|
- m,
|
|
|
- (objname or cls.__name__),
|
|
|
- (f'({e2!s}) ' if e2 else ''),
|
|
|
- e )
|
|
|
-
|
|
|
- if m2:
|
|
|
- errmsg = repr(m2) + '\n' + errmsg
|
|
|
-
|
|
|
- if hasattr(cls,'passthru_excs') and type(e) in cls.passthru_excs:
|
|
|
- raise
|
|
|
- elif hasattr(cls,'exc'):
|
|
|
- raise cls.exc(errmsg)
|
|
|
- else:
|
|
|
- raise ObjectInitError(errmsg)
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def method_not_implemented(cls):
|
|
|
- import traceback
|
|
|
- raise NotImplementedError(
|
|
|
- 'method {}() not implemented for class {!r}'.format(
|
|
|
- traceback.extract_stack()[-2].name, cls.__name__) )
|
|
|
-
|
|
|
-class Hilite(object):
|
|
|
-
|
|
|
- color = 'red'
|
|
|
- width = 0
|
|
|
- trunc_ok = True
|
|
|
-
|
|
|
- @classmethod
|
|
|
- # 'width' is screen width (greater than len(s) for CJK strings)
|
|
|
- # 'append_chars' and 'encl' must consist of single-width chars only
|
|
|
- def fmtc(cls,s,width=None,color=False,encl='',trunc_ok=None,
|
|
|
- center=False,nullrepl='',append_chars='',append_color=False):
|
|
|
- s_wide_count = len([1 for ch in s if unicodedata.east_asian_width(ch) in ('F','W')])
|
|
|
- if encl:
|
|
|
- a,b = list(encl)
|
|
|
- add_len = len(append_chars) + 2
|
|
|
- else:
|
|
|
- a,b = ('','')
|
|
|
- add_len = len(append_chars)
|
|
|
- if width == None:
|
|
|
- width = cls.width
|
|
|
- if trunc_ok == None:
|
|
|
- trunc_ok = cls.trunc_ok
|
|
|
- if g.test_suite:
|
|
|
- assert isinstance(encl,str) and len(encl) in (0,2),"'encl' must be 2-character str"
|
|
|
- assert width >= 2 + add_len, f'{s!r}: invalid width ({width}) (must be at least 2)' # CJK: 2 cells
|
|
|
- if len(s) + s_wide_count + add_len > width:
|
|
|
- assert trunc_ok, "If 'trunc_ok' is false, 'width' must be >= screen width of string"
|
|
|
- s = truncate_str(s,width-add_len)
|
|
|
- if s == '' and nullrepl:
|
|
|
- s = nullrepl.center(width)
|
|
|
- else:
|
|
|
- s = a+s+b
|
|
|
- if center:
|
|
|
- s = s.center(width)
|
|
|
- if append_chars:
|
|
|
- return (
|
|
|
- cls.colorize(s,color=color)
|
|
|
- + cls.colorize(
|
|
|
- append_chars.ljust(width-len(s)-s_wide_count),
|
|
|
- color_override = append_color ))
|
|
|
- else:
|
|
|
- return cls.colorize(s.ljust(width-s_wide_count),color=color)
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def colorize(cls,s,color=True,color_override=''):
|
|
|
- return globals()[color_override or cls.color](s) if color else s
|
|
|
-
|
|
|
- def fmt(self,*args,**kwargs):
|
|
|
- assert args == () # forbid invocation w/o keywords
|
|
|
- return self.fmtc(self,*args,**kwargs)
|
|
|
-
|
|
|
- @classmethod
|
|
|
- def hlc(cls,s,color=True,encl=''):
|
|
|
- if encl:
|
|
|
- assert isinstance(encl,str) and len(encl) == 2, "'encl' must be 2-character str"
|
|
|
- s = encl[0] + s + encl[1]
|
|
|
- return cls.colorize(s,color=color)
|
|
|
-
|
|
|
- def hl(self,*args,**kwargs):
|
|
|
- assert args == () # forbid invocation w/o keywords
|
|
|
- return self.hlc(self,*args,**kwargs)
|
|
|
-
|
|
|
class Str(str,Hilite): pass
|
|
|
|
|
|
class Int(int,Hilite,InitErrors):
|