str.split() + match statement (11 files)
This commit is contained in:
parent
d7423a9783
commit
2e5ec4c9e8
13 changed files with 150 additions and 129 deletions
|
|
@ -129,15 +129,18 @@ class MMGenID(HiliteStr, InitErrors, MMGenObject):
|
|||
trunc_ok = False
|
||||
def __new__(cls, proto, id_str):
|
||||
try:
|
||||
ss = str(id_str).split(':')
|
||||
assert len(ss) in (2, 3), 'not 2 or 3 colon-separated items'
|
||||
t = proto.addr_type((ss[1], proto.dfl_mmtype)[len(ss)==2])
|
||||
me = str.__new__(cls, f'{ss[0]}:{t}:{ss[-1]}')
|
||||
me.sid = SeedID(sid=ss[0])
|
||||
me.idx = AddrIdx(ss[-1])
|
||||
me.mmtype = t
|
||||
assert t in proto.mmtypes, f'{t}: invalid address type for {proto.cls_name}'
|
||||
me.al_id = str.__new__(AddrListID, me.sid+':'+me.mmtype) # checks already done
|
||||
match id_str.split(':', 2):
|
||||
case [sid, mmtype, idx]:
|
||||
assert mmtype in proto.mmtypes, f'{mmtype}: invalid address type for {proto.cls_name}'
|
||||
case [sid, idx]:
|
||||
mmtype = proto.dfl_mmtype
|
||||
case _:
|
||||
raise ValueError('not 2 or 3 colon-separated items')
|
||||
me = str.__new__(cls, f'{sid}:{mmtype}:{idx}')
|
||||
me.sid = SeedID(sid=sid)
|
||||
me.mmtype = proto.addr_type(mmtype)
|
||||
me.idx = AddrIdx(idx)
|
||||
me.al_id = str.__new__(AddrListID, me.sid + ':' + me.mmtype) # checks already done
|
||||
me.sort_key = f'{me.sid}:{me.mmtype}:{me.idx:0{me.idx.max_digits}}'
|
||||
me.proto = proto
|
||||
return me
|
||||
|
|
|
|||
|
|
@ -265,10 +265,12 @@ class AddrFile(MMGenObject):
|
|||
|
||||
match len(ls):
|
||||
case 2 if type(p).__name__ == 'PasswordList':
|
||||
ss = ls.pop().split(':')
|
||||
assert len(ss) == 2, f'{ss!r}: invalid password length specifier (must contain colon)'
|
||||
p.set_pw_fmt(ss[0])
|
||||
p.set_pw_len(ss[1])
|
||||
match ls.pop().split(':', 1):
|
||||
case [a, b]:
|
||||
p.set_pw_fmt(a)
|
||||
p.set_pw_len(b)
|
||||
case x:
|
||||
die(1, f'{x!r}: invalid password length specifier (must contain colon)')
|
||||
p.pw_id_str = MMGenPWIDString(ls.pop())
|
||||
modname, funcname = p.pw_info[p.pw_fmt].chk_func.split('.')
|
||||
import importlib
|
||||
|
|
|
|||
|
|
@ -17,28 +17,27 @@ def parse_data():
|
|||
'idx chain name')
|
||||
|
||||
def parse_line(line):
|
||||
l = line.split()
|
||||
|
||||
if l[2] == '-':
|
||||
return _u(
|
||||
idx = int(l[0]),
|
||||
chain = l[1],
|
||||
name = ' '.join(l[3:]),
|
||||
)
|
||||
else:
|
||||
return _d(
|
||||
idx = int(l[0]),
|
||||
chain = l[1],
|
||||
curve = defaults.curve if l[2] == 'x' else l[2],
|
||||
network = 'mainnet' if l[3] == 'm' else 'testnet' if l[3] == 'T' else None,
|
||||
addr_cls = l[4],
|
||||
vb_prv = defaults.vb_prv if l[5] == 'x' else l[5],
|
||||
vb_pub = defaults.vb_pub if l[6] == 'x' else l[6],
|
||||
vb_wif = l[7],
|
||||
vb_addr = l[8],
|
||||
def_path = defaults.def_path if l[9] == 'x' else l[9],
|
||||
name = ' '.join(l[10:]),
|
||||
)
|
||||
match line.split():
|
||||
case [idx, chain, col3, *name] if col3 == '-':
|
||||
return _u(
|
||||
idx = int(idx),
|
||||
chain = chain,
|
||||
name = ' '.join(name))
|
||||
case [idx, chain, curve, net, acls, vprv, vpub, vwif, vaddr, dpath, *name]:
|
||||
return _d(
|
||||
idx = int(idx),
|
||||
chain = chain,
|
||||
curve = defaults.curve if curve == 'x' else curve,
|
||||
network = 'mainnet' if net == 'm' else 'testnet' if net == 'T' else None,
|
||||
addr_cls = acls,
|
||||
vb_prv = defaults.vb_prv if vprv == 'x' else vprv,
|
||||
vb_pub = defaults.vb_pub if vpub == 'x' else vpub,
|
||||
vb_wif = vwif,
|
||||
vb_addr = vaddr,
|
||||
def_path = defaults.def_path if dpath == 'x' else dpath,
|
||||
name = ' '.join(name))
|
||||
case _:
|
||||
raise ValueError(f'{line!r}: invalid line')
|
||||
|
||||
out = {}
|
||||
for line in _data_in.strip().splitlines():
|
||||
|
|
|
|||
64
mmgen/cfg.py
64
mmgen/cfg.py
|
|
@ -848,28 +848,28 @@ def check_opts(cfg): # Raises exception if any check fails
|
|||
out_fmt = in_fmt
|
||||
|
||||
def hidden_incog_params():
|
||||
a = val.rsplit(',', 1) # permit comma in filename
|
||||
if len(a) != 2:
|
||||
display_opt(name, val)
|
||||
die('UserOptError', 'Option requires two comma-separated arguments')
|
||||
|
||||
fn, offset = a
|
||||
opt_is_int(offset)
|
||||
match val.rsplit(',', 1): # permit comma in filename
|
||||
case [fn, offset]:
|
||||
opt_is_int(offset)
|
||||
case _:
|
||||
display_opt(name, val)
|
||||
die('UserOptError', 'Option requires two comma-separated arguments')
|
||||
|
||||
from .fileutil import check_infile, check_outdir, check_outfile
|
||||
if name == 'hidden_incog_input_params':
|
||||
check_infile(fn, blkdev_ok=True)
|
||||
key2 = 'in_fmt'
|
||||
else:
|
||||
try:
|
||||
os.stat(fn)
|
||||
except:
|
||||
b = os.path.dirname(fn)
|
||||
if b:
|
||||
check_outdir(b)
|
||||
else:
|
||||
check_outfile(fn, blkdev_ok=True)
|
||||
key2 = 'out_fmt'
|
||||
match name:
|
||||
case 'hidden_incog_input_params':
|
||||
check_infile(fn, blkdev_ok=True)
|
||||
key2 = 'in_fmt'
|
||||
case 'hidden_incog_output_params':
|
||||
try:
|
||||
os.stat(fn)
|
||||
except:
|
||||
b = os.path.dirname(fn)
|
||||
if b:
|
||||
check_outdir(b)
|
||||
else:
|
||||
check_outfile(fn, blkdev_ok=True)
|
||||
key2 = 'out_fmt'
|
||||
|
||||
if hasattr(cfg, key2):
|
||||
val2 = getattr(cfg, key2)
|
||||
|
|
@ -895,17 +895,19 @@ def check_opts(cfg): # Raises exception if any check fails
|
|||
opt_is_in_list(val, list(Crypto.hash_presets.keys()))
|
||||
|
||||
def brain_params():
|
||||
a = val.split(',')
|
||||
if len(a) != 2:
|
||||
display_opt(name, val)
|
||||
die('UserOptError', 'Option requires two comma-separated arguments')
|
||||
|
||||
opt_is_int(a[0], desc_pfx='seed length')
|
||||
from .seed import Seed
|
||||
opt_is_in_list(int(a[0]), Seed.lens, desc_pfx='seed length')
|
||||
|
||||
from .crypto import Crypto
|
||||
opt_is_in_list(a[1], list(Crypto.hash_presets.keys()), desc_pfx='hash preset')
|
||||
match val.split(',', 1):
|
||||
case [seed_len, hash_preset]:
|
||||
opt_is_int(seed_len, desc_pfx='seed length')
|
||||
from .seed import Seed
|
||||
opt_is_in_list(int(seed_len), Seed.lens, desc_pfx='seed length')
|
||||
from .crypto import Crypto
|
||||
opt_is_in_list(
|
||||
hash_preset,
|
||||
list(Crypto.hash_presets.keys()),
|
||||
desc_pfx = 'hash preset')
|
||||
case _:
|
||||
display_opt(name, val)
|
||||
die('UserOptError', 'Option requires two comma-separated arguments')
|
||||
|
||||
def usr_randchars():
|
||||
if val != 0:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
16.1.dev0
|
||||
16.1.dev1
|
||||
|
|
|
|||
22
mmgen/msg.py
22
mmgen/msg.py
|
|
@ -33,15 +33,19 @@ class MMGenIDRange(HiliteStr, InitErrors, MMGenObject):
|
|||
from .addr import AddrListID
|
||||
from .seed import SeedID
|
||||
try:
|
||||
ss = str(id_str).split(':')
|
||||
assert len(ss) in (2, 3), 'not 2 or 3 colon-separated items'
|
||||
t = proto.addr_type((ss[1], proto.dfl_mmtype)[len(ss)==2])
|
||||
me = str.__new__(cls, '{}:{}:{}'.format(ss[0], t, ss[-1]))
|
||||
me.sid = SeedID(sid=ss[0])
|
||||
me.idxlist = AddrIdxList(fmt_str=ss[-1])
|
||||
me.mmtype = t
|
||||
assert t in proto.mmtypes, f'{t}: invalid address type for {proto.cls_name}'
|
||||
me.al_id = str.__new__(AddrListID, me.sid+':'+me.mmtype) # checks already done
|
||||
match id_str.split(':'):
|
||||
case [sid, t, fmt_str]:
|
||||
assert t in proto.mmtypes, f'{t}: invalid address type for {proto.cls_name}'
|
||||
mmtype = proto.addr_type(t)
|
||||
case [sid, fmt_str]:
|
||||
mmtype = proto.addr_type(proto.dfl_mmtype)
|
||||
case _:
|
||||
raise ValueError('not 2 or 3 colon-separated items')
|
||||
me = str.__new__(cls, f'{sid}:{mmtype}:{fmt_str}')
|
||||
me.sid = SeedID(sid=sid)
|
||||
me.idxlist = AddrIdxList(fmt_str=fmt_str)
|
||||
me.mmtype = mmtype
|
||||
me.al_id = str.__new__(AddrListID, me.sid + ':' + me.mmtype) # checks already done
|
||||
me.proto = proto
|
||||
return me
|
||||
except Exception as e:
|
||||
|
|
|
|||
27
mmgen/obj.py
27
mmgen/obj.py
|
|
@ -223,18 +223,19 @@ class MMGenRange(tuple, InitErrors, MMGenObject):
|
|||
|
||||
def __new__(cls, *args):
|
||||
try:
|
||||
if len(args) == 1:
|
||||
s = args[0]
|
||||
if isinstance(s, cls):
|
||||
return s
|
||||
assert isinstance(s, str), 'not a string or string subclass'
|
||||
ss = s.split('-', 1)
|
||||
first = int(ss[0])
|
||||
last = int(ss.pop())
|
||||
else:
|
||||
s = repr(args) # needed if exception occurs
|
||||
assert len(args) == 2, 'one format string arg or two start, stop args required'
|
||||
first, last = args
|
||||
match args:
|
||||
case [str(s)]:
|
||||
match s.split('-', 1):
|
||||
case [first]:
|
||||
last = first
|
||||
case [first, last]:
|
||||
pass
|
||||
first = int(first)
|
||||
last = int(last)
|
||||
case [int(first), int(last)]:
|
||||
pass
|
||||
case _:
|
||||
raise ValueError('one format string arg or two integer args (start, stop) required')
|
||||
assert first <= last, 'start of range greater than end of range'
|
||||
if cls.min_idx is not None:
|
||||
assert first >= cls.min_idx, f'start of range < {cls.min_idx:,}'
|
||||
|
|
@ -242,7 +243,7 @@ class MMGenRange(tuple, InitErrors, MMGenObject):
|
|||
assert last <= cls.max_idx, f'end of range > {cls.max_idx:,}'
|
||||
return tuple.__new__(cls, (first, last))
|
||||
except Exception as e:
|
||||
return cls.init_fail(e, s)
|
||||
return cls.init_fail(e, args)
|
||||
|
||||
@property
|
||||
def first(self):
|
||||
|
|
|
|||
|
|
@ -43,13 +43,16 @@ class SeedSplitSpecifier(HiliteStr, InitErrors, MMGenObject):
|
|||
if isinstance(s, cls):
|
||||
return s
|
||||
try:
|
||||
arr = s.split(':')
|
||||
assert len(arr) in (2, 3), 'cannot be parsed'
|
||||
a, b, c = arr if len(arr) == 3 else ['default'] + arr
|
||||
me = str.__new__(cls, s)
|
||||
me.id = SeedSplitIDString(a)
|
||||
me.idx = SeedShareIdx(b)
|
||||
me.count = SeedShareCount(c)
|
||||
match s.split(':', 2):
|
||||
case [id_str, idx, count]:
|
||||
me.id = SeedSplitIDString(id_str)
|
||||
case [idx, count]:
|
||||
me.id = SeedSplitIDString('default')
|
||||
case _:
|
||||
raise ValueError('seed split specifier cannot be parsed')
|
||||
me.idx = SeedShareIdx(idx)
|
||||
me.count = SeedShareCount(count)
|
||||
assert me.idx <= me.count, 'share index greater than share count'
|
||||
return me
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -111,13 +111,15 @@ class TwAddresses(TwView):
|
|||
self.used_w = 4 if self.has_used else 0
|
||||
|
||||
if mmgen_addrs:
|
||||
a = mmgen_addrs.rsplit(':', 1)
|
||||
if len(a) != 2:
|
||||
die(1,
|
||||
f'{mmgen_addrs}: invalid address list argument ' +
|
||||
'(must be in form <seed ID>:[<type>:]<idx list>)')
|
||||
from ..addrlist import AddrIdxList
|
||||
self.usr_addr_list = [MMGenID(self.proto, f'{a[0]}:{i}') for i in AddrIdxList(fmt_str=a[1])]
|
||||
match mmgen_addrs.rsplit(':', 1):
|
||||
case [mmid, fmt_str]:
|
||||
from ..addrlist import AddrIdxList
|
||||
self.usr_addr_list = [
|
||||
MMGenID(self.proto, f'{mmid}:{i}') for i in AddrIdxList(fmt_str=fmt_str)]
|
||||
case _:
|
||||
die(1,
|
||||
f'{mmgen_addrs}: invalid address list argument ' +
|
||||
'(must be in form <seed ID>:[<type>:]<idx list>)')
|
||||
else:
|
||||
self.usr_addr_list = []
|
||||
|
||||
|
|
|
|||
|
|
@ -56,9 +56,12 @@ class TwLabel(str, InitErrors, MMGenObject):
|
|||
if isinstance(text, cls):
|
||||
return text
|
||||
try:
|
||||
ts = text.split(None, 1)
|
||||
mmid = TwMMGenID(proto, ts[0])
|
||||
comment = TwComment(ts[1] if len(ts) == 2 else '')
|
||||
match text.split(None, 1):
|
||||
case [mmid_in]:
|
||||
comment = TwComment('')
|
||||
case [mmid_in, comment]:
|
||||
comment = TwComment(comment)
|
||||
mmid = TwMMGenID(proto, mmid_in)
|
||||
me = str.__new__(cls, mmid + (' ' + comment if comment else ''))
|
||||
me.mmid = mmid
|
||||
me.comment = comment
|
||||
|
|
|
|||
|
|
@ -125,28 +125,31 @@ class wallet(wallet):
|
|||
self.check_usr_seed_len(bitlen=int(d3))
|
||||
d.pw_status, d.timestamp = d4, d5
|
||||
|
||||
hpdata = lines[3].split()
|
||||
match lines[3].split():
|
||||
case [hp_lbl, *params] if len(params) == 3:
|
||||
d.hash_preset = hp_lbl.removesuffix(':')
|
||||
case _:
|
||||
raise ValueError(f'{lines[3]}: invalid hash preset line')
|
||||
|
||||
d.hash_preset = hp = hpdata[0][:-1] # a string!
|
||||
self.cfg._util.qmsg(f'Hash preset of wallet: {hp!r}')
|
||||
if self.cfg.hash_preset and self.cfg.hash_preset != hp:
|
||||
self.cfg._util.qmsg(f'Hash preset of wallet: {d.hash_preset!r}')
|
||||
if self.cfg.hash_preset and self.cfg.hash_preset != d.hash_preset:
|
||||
self.cfg._util.qmsg(f'Warning: ignoring user-requested hash preset {self.cfg.hash_preset!r}')
|
||||
|
||||
hash_params = tuple(map(int, hpdata[1:]))
|
||||
|
||||
if hash_params != self.crypto.get_hash_params(d.hash_preset):
|
||||
msg(f'Hash parameters {" ".join(hash_params)!r} don’t match hash preset {d.hash_preset!r}')
|
||||
if tuple(map(int, params)) != self.crypto.get_hash_params(d.hash_preset):
|
||||
msg(f'Hash parameters {" ".join(params)!r} don’t match hash preset {d.hash_preset!r}')
|
||||
return False
|
||||
|
||||
lmin, _, lmax = sorted(baseconv('b58').seedlen_map_rev) # 22, 33, 44
|
||||
for i, key in (4, 'salt'), (5, 'enc_seed'):
|
||||
l = lines[i].split(' ')
|
||||
chksum = l.pop(0)
|
||||
b58_val = ''.join(l)
|
||||
|
||||
if len(b58_val) < lmin or len(b58_val) > lmax:
|
||||
msg(f'Invalid format for {key} in {self.desc}: {l}')
|
||||
return False
|
||||
match lines[i].split(' '):
|
||||
case [chksum, *b58_chunks]:
|
||||
b58_val = ''.join(b58_chunks)
|
||||
if len(b58_val) < lmin or len(b58_val) > lmax:
|
||||
msg(f'Invalid format for {key} in {self.desc}: {lines[i]}')
|
||||
return False
|
||||
case _:
|
||||
msg(f'Invalid format for {key} in {self.desc}: {lines[i]}')
|
||||
return False
|
||||
|
||||
if not self.cfg._util.compare_chksums(
|
||||
chksum,
|
||||
|
|
|
|||
|
|
@ -28,13 +28,12 @@ class wallet(wallet):
|
|||
self.fmt_data = f'{self.ssdata.chksum} {split_into_cols(4, seed_hex)}\n'
|
||||
|
||||
def _deformat(self):
|
||||
d = self.fmt_data.split()
|
||||
try:
|
||||
d[1]
|
||||
chksum, hex_str = d[0], ''.join(d[1:])
|
||||
except:
|
||||
msg(f'{self.fmt_data.strip()!r}: invalid {self.desc}')
|
||||
return False
|
||||
match self.fmt_data.split():
|
||||
case [chksum, *hex_chunks] if hex_chunks:
|
||||
hex_str = ''.join(hex_chunks)
|
||||
case _:
|
||||
msg(f'{self.fmt_data!r}: invalid {self.desc}')
|
||||
return False
|
||||
|
||||
if not len(hex_str) * 4 in Seed.lens:
|
||||
msg(f'Invalid data length ({len(hex_str)}) in {self.desc}')
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ tests = {
|
|||
{'text': 'F00BAA12:Z:99', 'proto': proto},
|
||||
{'text': tw_pfx+' x', 'proto': proto},
|
||||
{'text': tw_pfx+'я x', 'proto': proto},
|
||||
{'text': utf8_ctrl[:40], 'proto': proto},
|
||||
{'text': utf8_ctrl[:40], 'proto': proto, 'exc_name': 'BadTwComment'},
|
||||
{'text': 'F00BAA12:S:1 ' + utf8_ctrl[:40], 'proto': proto, 'exc_name': 'BadTwComment'},
|
||||
{'text': tw_pfx+'x comment', 'proto': proto},
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue