move Hilite,InitErrors to objmethods.py
This commit is contained in:
parent
b877e865bb
commit
74ec5efd63
8 changed files with 140 additions and 107 deletions
|
|
@ -23,6 +23,7 @@ addr.py: Address generation/display routines for the MMGen suite
|
|||
from hashlib import sha256,sha512
|
||||
from .common import *
|
||||
from .base_obj import AsyncInit
|
||||
from .objmethods import Hilite,InitErrors,MMGenObject
|
||||
from .obj import *
|
||||
from .baseconv import *
|
||||
from .protocol import init_proto,hash160
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ amt.py: MMGen CoinAmt and related classes
|
|||
"""
|
||||
|
||||
from decimal import Decimal
|
||||
from .obj import Hilite,InitErrors
|
||||
from .objmethods import Hilite,InitErrors
|
||||
|
||||
class UnknownCoinAmt(Decimal): pass
|
||||
|
||||
|
|
|
|||
105
mmgen/obj.py
105
mmgen/obj.py
|
|
@ -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):
|
||||
|
|
|
|||
131
mmgen/objmethods.py
Executable file
131
mmgen/objmethods.py
Executable file
|
|
@ -0,0 +1,131 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
objmethods.py: Mixin classes for MMGen data objects
|
||||
"""
|
||||
|
||||
import unicodedata
|
||||
from .color import *
|
||||
from .globalvars import g
|
||||
from .devtools import *
|
||||
|
||||
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)
|
||||
|
||||
class Hilite:
|
||||
|
||||
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 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:
|
||||
from .exception import ObjectInitError
|
||||
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__) )
|
||||
|
|
@ -23,6 +23,7 @@ rpc.py: Cryptocoin RPC library for the MMGen suite
|
|||
import base64,json,asyncio
|
||||
from decimal import Decimal
|
||||
from .common import *
|
||||
from .objmethods import Hilite,InitErrors
|
||||
from .base_obj import AsyncInit
|
||||
|
||||
rpc_credentials_msg = '\n'+fmt("""
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ seed.py: Seed-related classes and methods for the MMGen suite
|
|||
"""
|
||||
|
||||
from .common import *
|
||||
from .obj import *
|
||||
from .objmethods import Hilite,InitErrors
|
||||
from .obj import ImmutableAttr,get_obj
|
||||
from .crypto import get_random,scramble_seed
|
||||
|
||||
class SeedID(str,Hilite,InitErrors):
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ from collections import namedtuple
|
|||
from .exception import *
|
||||
from .common import *
|
||||
from .base_obj import AsyncInit
|
||||
from .objmethods import Hilite,InitErrors,MMGenObject
|
||||
from .obj import *
|
||||
from .tx import is_mmgen_id,is_coin_addr
|
||||
from .rpc import rpc_init
|
||||
|
|
|
|||
|
|
@ -23,12 +23,13 @@ xmrwallet.py - MoneroWalletOps class
|
|||
import os,re,time,json
|
||||
from collections import namedtuple
|
||||
from .common import *
|
||||
from .objmethods import Hilite,InitErrors
|
||||
from .addr import KeyAddrList,AddrIdxList
|
||||
from .rpc import MoneroRPCClientRaw,MoneroWalletRPCClient,json_encoder
|
||||
from .seed import SeedID
|
||||
from .daemon import MoneroWalletDaemon
|
||||
from .protocol import _b58a,init_proto
|
||||
from .obj import CoinAddr,CoinTxID,AddrIdx,Hilite,InitErrors
|
||||
from .obj import CoinAddr,CoinTxID,AddrIdx
|
||||
|
||||
xmrwallet_uarg_info = (
|
||||
lambda e,hp: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue