autosign, xmrwallet: minor fixes and cleanups throughout
This commit is contained in:
parent
ee932a40bc
commit
85df7cdd76
8 changed files with 97 additions and 83 deletions
|
|
@ -39,6 +39,9 @@ class Signable:
|
|||
self.parent = parent
|
||||
self.cfg = parent.cfg
|
||||
self.dir = getattr(parent,self.dir_name)
|
||||
self.long_desc = (
|
||||
'non-Monero transaction' if self.desc == 'transaction' and 'XMR' in self.parent.coins else
|
||||
self.desc)
|
||||
|
||||
@property
|
||||
def unsigned(self):
|
||||
|
|
@ -267,9 +270,6 @@ class Autosign:
|
|||
|
||||
self.coins = cfg.coins.upper().split(',') if cfg.coins else []
|
||||
|
||||
if cfg._args and cfg._args[0] == 'clean':
|
||||
return
|
||||
|
||||
if cfg.xmrwallets and not 'XMR' in self.coins:
|
||||
self.coins.append('XMR')
|
||||
|
||||
|
|
@ -401,7 +401,7 @@ class Autosign:
|
|||
target.print_bad_list(bad)
|
||||
return not bad
|
||||
else:
|
||||
msg(f'No unsigned {target.desc}s')
|
||||
msg(f'No unsigned {target.long_desc}s')
|
||||
await asyncio.sleep(0.5)
|
||||
return True
|
||||
|
||||
|
|
@ -579,16 +579,9 @@ class Autosign:
|
|||
bmsg(f'{count} file{suf(count)} shredded')
|
||||
|
||||
def get_insert_status(self):
|
||||
if self.cfg.no_insert_check:
|
||||
return True
|
||||
try:
|
||||
self.dev_disk_path.stat()
|
||||
except:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
return self.cfg.no_insert_check or self.dev_disk_path.exists()
|
||||
|
||||
async def do_loop(self):
|
||||
async def main_loop(self):
|
||||
if not self.cfg.stealth_led:
|
||||
self.led.set('standby')
|
||||
testing_xmr = self.cfg.test_suite_xmr_autosign
|
||||
|
|
|
|||
|
|
@ -117,8 +117,11 @@ class LEDControl:
|
|||
@classmethod
|
||||
def delete_dummy_control_files(cls):
|
||||
db = cls.boards['dummy']
|
||||
os.unlink(db.status)
|
||||
os.unlink(db.trigger)
|
||||
for fn in (db.status, db.trigger):
|
||||
try:
|
||||
os.unlink(fn)
|
||||
except Exception as e:
|
||||
msg(str(e))
|
||||
|
||||
def noop(self,*args,**kwargs):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ def main(do_loop):
|
|||
async def do():
|
||||
await asi.check_daemons_running()
|
||||
if do_loop:
|
||||
await asi.do_loop()
|
||||
await asi.main_loop()
|
||||
else:
|
||||
ret = await asi.do_sign()
|
||||
asi.at_exit(not ret)
|
||||
|
|
@ -188,6 +188,7 @@ if cmd_args:
|
|||
if cfg.xmrwallets and keypress_confirm( cfg, '\nContinue with Monero setup?', default_yes=True ):
|
||||
msg('')
|
||||
asi.xmr_setup()
|
||||
asi.do_umount()
|
||||
elif cmd == 'wait':
|
||||
main(do_loop=True)
|
||||
elif cmd == 'clean':
|
||||
|
|
|
|||
|
|
@ -66,11 +66,11 @@ opts_data = {
|
|||
-d, --outdir=D Save transaction files to directory 'D'
|
||||
instead of the working directory
|
||||
-D, --daemon=H:P Connect to the monerod at {D}
|
||||
-R, --tx-relay-daemon=H:P[:H:P] Relay transactions via a monerod specified by
|
||||
{R}
|
||||
-k, --use-internal-keccak-module Force use of the internal keccak module
|
||||
-p, --hash-preset=P Use scrypt hash preset 'P' for password
|
||||
hashing (default: '{gc.dfl_hash_preset}')
|
||||
-R, --tx-relay-daemon=H:P[:H:P] Relay transactions via a monerod specified by
|
||||
{R}
|
||||
-r, --restore-height=H Scan from height 'H' when creating wallets.
|
||||
Use special value ‘current’ to create empty
|
||||
wallet at current blockchain height.
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ else:
|
|||
|
||||
from mmgen.cfg import Config,gc
|
||||
from mmgen.color import red,yellow,green,blue,cyan,gray,nocolor,init_color
|
||||
from mmgen.util import Msg,bmsg,die,suf,make_timestr,async_run
|
||||
from mmgen.util import msg,Msg,bmsg,die,suf,make_timestr,async_run
|
||||
|
||||
from test.include.common import (
|
||||
set_globals,
|
||||
|
|
@ -222,6 +222,8 @@ type(cfg)._reset_ok += (
|
|||
'resuming',
|
||||
'skipping_deps' )
|
||||
|
||||
logging = cfg.log or os.getenv('MMGEN_EXEC_WRAPPER')
|
||||
|
||||
cfg.resuming = any(k in po.user_opts for k in ('resume','resume_after'))
|
||||
cfg.skipping_deps = cfg.resuming or 'skip_deps' in po.user_opts
|
||||
|
||||
|
|
@ -547,7 +549,7 @@ class CmdTestRunner:
|
|||
'cmdtest.py test runner'
|
||||
|
||||
def __del__(self):
|
||||
if cfg.log:
|
||||
if logging:
|
||||
self.log_fd.close()
|
||||
|
||||
def __init__(self,data_dir,trash_dir):
|
||||
|
|
@ -562,7 +564,7 @@ class CmdTestRunner:
|
|||
self.resume_cmd = None
|
||||
self.deps_only = None
|
||||
|
||||
if cfg.log:
|
||||
if logging:
|
||||
self.log_fd = open(cmdtest_py_log_fn,'a')
|
||||
self.log_fd.write(f'\nLog started: {make_timestr()} UTC\n')
|
||||
omsg(f'INFO → Logging to file {cmdtest_py_log_fn!r}')
|
||||
|
|
@ -630,10 +632,15 @@ class CmdTestRunner:
|
|||
self.tg.extra_spawn_args +
|
||||
args )
|
||||
|
||||
qargs = ['{q}{}{q}'.format( a, q = "'" if ' ' in a else '' ) for a in args]
|
||||
try:
|
||||
qargs = ['{q}{}{q}'.format( a, q = "'" if ' ' in a else '' ) for a in args]
|
||||
except:
|
||||
msg(f'args: {args}')
|
||||
raise
|
||||
|
||||
cmd_disp = ' '.join(qargs).replace('\\','/') # for mingw
|
||||
|
||||
if cfg.log:
|
||||
if logging:
|
||||
self.log_fd.write('[{}][{}:{}] {}\n'.format(
|
||||
proto.coin.lower(),
|
||||
self.tg.group_name,
|
||||
|
|
|
|||
|
|
@ -122,10 +122,10 @@ class CmdTestAutosignBase(CmdTestBase):
|
|||
)
|
||||
self.mountpoint = self.asi.mountpoint
|
||||
|
||||
if self.simulate and not cfg.exact_output:
|
||||
if self.simulate_led and not cfg.exact_output:
|
||||
die(1,red('This command must be run with --exact-output enabled!'))
|
||||
|
||||
if self.simulate or not self.live:
|
||||
if self.simulate_led or not self.live:
|
||||
LEDControl.create_dummy_control_files()
|
||||
self.spawn_env['MMGEN_TEST_SUITE_AUTOSIGN_LED_SIMULATE'] = '1'
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ class CmdTestAutosignBase(CmdTestBase):
|
|||
|
||||
if self.live:
|
||||
check_mountpoint(self.asi)
|
||||
init_led(self.simulate)
|
||||
init_led(self.simulate_led)
|
||||
else:
|
||||
self.asi.tx_dir.mkdir(parents=True,exist_ok=True) # creates mountpoint
|
||||
self.wallet_dir.mkdir(parents=True,exist_ok=True)
|
||||
|
|
@ -163,7 +163,7 @@ class CmdTestAutosignBase(CmdTestBase):
|
|||
def __del__(self):
|
||||
if sys.platform == 'win32' or self.tr is None:
|
||||
return
|
||||
if self.simulate or not self.live:
|
||||
if self.simulate_led or not self.live:
|
||||
LEDControl.delete_dummy_control_files()
|
||||
|
||||
def start_daemons(self):
|
||||
|
|
@ -244,29 +244,34 @@ class CmdTestAutosignBase(CmdTestBase):
|
|||
|
||||
assert op in ('copy','set_count','remove_signed')
|
||||
|
||||
fdata = [e for e in filedir_map if e[0] in (txfile_coins or self.txfile_coins)]
|
||||
|
||||
from .ct_ref import CmdTestRef
|
||||
tfns = [CmdTestRef.sources['ref_tx_file'][c][1] for c,d in fdata] + \
|
||||
[CmdTestRef.sources['ref_tx_file'][c][0] for c,d in fdata] + \
|
||||
['25EFA3[2.34].testnet.rawtx'] # TX with 2 non-MMGen outputs
|
||||
self.tx_count = len([fn for fn in tfns if fn])
|
||||
def gen():
|
||||
d = CmdTestRef.sources['ref_tx_file']
|
||||
dirmap = [e for e in filedir_map if e[0] in (txfile_coins or self.txfile_coins)]
|
||||
for coin,coindir in dirmap:
|
||||
for network in (0,1):
|
||||
fn = d[coin][network]
|
||||
if fn:
|
||||
yield (coindir,fn)
|
||||
|
||||
data = list(gen()) + [('','25EFA3[2.34].testnet.rawtx')] # TX with 2 non-MMGen outputs
|
||||
|
||||
self.tx_count = len(data)
|
||||
if op == 'set_count':
|
||||
return
|
||||
tfs = [joinpath(ref_dir,d[1],fn) for d,fn in zip(fdata+fdata+[('btc','')],tfns)]
|
||||
|
||||
for f,fn in zip(tfs,tfns):
|
||||
if fn: # use empty fn to skip file
|
||||
if cfg.debug_utf8:
|
||||
ext = '.testnet.rawtx' if fn.endswith('.testnet.rawtx') else '.rawtx'
|
||||
fn = fn[:-len(ext)] + '-α' + ext
|
||||
target = joinpath(self.mountpoint,'tx',fn)
|
||||
if not op == 'remove_signed':
|
||||
shutil.copyfile(f,target)
|
||||
try:
|
||||
os.unlink(target.replace('.rawtx','.sigtx'))
|
||||
except:
|
||||
pass
|
||||
for coindir,fn in data:
|
||||
src = joinpath(ref_dir,coindir,fn)
|
||||
if cfg.debug_utf8:
|
||||
ext = '.testnet.rawtx' if fn.endswith('.testnet.rawtx') else '.rawtx'
|
||||
fn = fn[:-len(ext)] + '-α' + ext
|
||||
target = joinpath(self.asi.mountpoint,'tx',fn)
|
||||
if not op == 'remove_signed':
|
||||
shutil.copyfile(src,target)
|
||||
try:
|
||||
os.unlink(target.replace('.rawtx','.sigtx'))
|
||||
except:
|
||||
pass
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
|
@ -276,6 +281,9 @@ class CmdTestAutosignBase(CmdTestBase):
|
|||
def remove_bad_txfiles(self):
|
||||
return self.bad_txfiles('remove')
|
||||
|
||||
create_bad_txfiles2 = create_bad_txfiles
|
||||
remove_bad_txfiles2 = remove_bad_txfiles
|
||||
|
||||
def bad_txfiles(self,op):
|
||||
if self.live:
|
||||
do_mount(self.mountpoint)
|
||||
|
|
@ -367,13 +375,16 @@ class CmdTestAutosignBase(CmdTestBase):
|
|||
imsg('')
|
||||
return t
|
||||
|
||||
def insert_device(self):
|
||||
self.asi.dev_disk_path.touch()
|
||||
|
||||
class CmdTestAutosign(CmdTestAutosignBase):
|
||||
'autosigning transactions for all supported coins'
|
||||
coins = ['btc','bch','ltc','eth']
|
||||
daemon_coins = ['btc','bch','ltc']
|
||||
txfile_coins = ['btc','bch','ltc','eth','mm1','etc']
|
||||
live = False
|
||||
simulate = False
|
||||
simulate_led = False
|
||||
bad_tx_count = 0
|
||||
cmd_group = (
|
||||
('start_daemons', 'starting daemons'),
|
||||
|
|
@ -395,12 +406,12 @@ class CmdTestAutosign(CmdTestAutosignBase):
|
|||
('copy_msgfiles', 'copying message files'),
|
||||
('sign_quiet_msg', 'signing transactions and messages (--quiet)'),
|
||||
('remove_signed_txfiles', 'removing signed transaction files'),
|
||||
('create_bad_txfiles', 'creating bad transaction files'),
|
||||
('create_bad_txfiles2', 'creating bad transaction files'),
|
||||
('remove_signed_msgfiles', 'removing signed message files'),
|
||||
('create_invalid_msgfile', 'creating invalid message file'),
|
||||
('sign_full_summary_msg', 'signing transactions and messages (--full-summary)'),
|
||||
('remove_invalid_msgfile', 'removing invalid message file'),
|
||||
('remove_bad_txfiles', 'removing bad transaction files'),
|
||||
('remove_bad_txfiles2', 'removing bad transaction files'),
|
||||
('sign_no_unsigned_msg', 'signing transactions and messages (nothing to sign)'),
|
||||
('stop_daemons', 'stopping daemons'),
|
||||
)
|
||||
|
|
@ -507,10 +518,10 @@ class CmdTestAutosignLive(CmdTestAutosignBTC):
|
|||
imsg(purple('\nKilling wait loop!'))
|
||||
t.kill(2) # 2 = SIGINT
|
||||
t.req_exit_val = 1
|
||||
if self.simulate and led_opts:
|
||||
if self.simulate_led and led_opts:
|
||||
t.expect("Stopping LED")
|
||||
return t
|
||||
|
||||
class CmdTestAutosignLiveSimulate(CmdTestAutosignLive):
|
||||
'live autosigning BTC transactions with simulated LED support'
|
||||
simulate = True
|
||||
simulate_led = True
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
daemon_coins = []
|
||||
txfile_coins = []
|
||||
live = False
|
||||
simulate = False
|
||||
simulate_led = False
|
||||
bad_tx_count = 0
|
||||
tx_relay_user = 'miner'
|
||||
no_insert_check = False
|
||||
|
|
@ -108,8 +108,8 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
|
||||
def __init__(self,trunner,cfgs,spawn):
|
||||
|
||||
CmdTestXMRWallet.__init__(self,trunner,cfgs,spawn)
|
||||
CmdTestAutosignBase.__init__(self,trunner,cfgs,spawn)
|
||||
CmdTestXMRWallet.__init__(self,trunner,cfgs,spawn)
|
||||
|
||||
if trunner is None:
|
||||
return
|
||||
|
|
@ -221,9 +221,6 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
def fund_alice2(self):
|
||||
return self.fund_alice(wallet=2)
|
||||
|
||||
def insert_device(self):
|
||||
self.asi.dev_disk_path.touch()
|
||||
|
||||
def autosign_setup(self):
|
||||
self.insert_device()
|
||||
Path(self.autosign_xmr_dir).mkdir(parents=True,exist_ok=True)
|
||||
|
|
@ -240,7 +237,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
if self.asi.dev_disk_path.exists():
|
||||
self.asi.dev_disk_path.unlink()
|
||||
def run():
|
||||
t = self.spawn('mmgen-autosign', self.opts + ['wait'], direct_exec=True )
|
||||
t = self.spawn('mmgen-autosign', self.opts + ['wait'], direct_exec=True)
|
||||
self.write_to_tmpfile('autosign_thread_pid',str(t.ep.pid))
|
||||
import threading
|
||||
threading.Thread( target=run, name='Autosign wait loop' ).start()
|
||||
|
|
@ -263,7 +260,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
return self.create_wallets( 'alice', op='restore' )
|
||||
|
||||
def restore_wallets(self):
|
||||
return self.create_wallets( 'alice', op='restore' )
|
||||
return self.create_watchonly_wallets()
|
||||
|
||||
def _create_transfer_tx(self,amt):
|
||||
t = self.do_op('transfer','alice',f'1:0:{self.burn_addr},{amt}',no_relay=True,do_ret=True)
|
||||
|
|
@ -279,6 +276,15 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
get_file_with_ext(self.asi.xmr_tx_dir,'sigtx',delete_all=True)
|
||||
return self._create_transfer_tx('0.257')
|
||||
|
||||
def _wait_signed(self,dtype):
|
||||
oqmsg_r(gray(f'→ offline wallet{"s" if dtype.endswith("s") else ""} signing {dtype}'))
|
||||
while True:
|
||||
oqmsg_r(gray('.'))
|
||||
if not self.asi.dev_disk_path.exists():
|
||||
break
|
||||
time.sleep(0.5)
|
||||
oqmsg(gray('done'))
|
||||
|
||||
def _xmr_autosign_op(
|
||||
self,
|
||||
op,
|
||||
|
|
@ -289,13 +295,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
add_opts = [],
|
||||
wait_signed = False):
|
||||
if wait_signed:
|
||||
oqmsg_r(gray(f'→ offline wallet{"s" if dtype.endswith("s") else ""} signing {dtype}'))
|
||||
while True:
|
||||
oqmsg_r(gray('.'))
|
||||
if not self.asi.dev_disk_path.exists():
|
||||
break
|
||||
time.sleep(0.5)
|
||||
oqmsg(gray('done'))
|
||||
self._wait_signed(dtype)
|
||||
data = self.users['alice']
|
||||
args = (
|
||||
self.extra_opts
|
||||
|
|
@ -380,11 +380,12 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
return self._export_outputs('1-2')
|
||||
|
||||
def _import_key_images(self,wallet_arg):
|
||||
return self._xmr_autosign_op(
|
||||
t = self._xmr_autosign_op(
|
||||
op = 'import-key-images',
|
||||
wallet_arg = wallet_arg,
|
||||
dtype = 'wallet outputs',
|
||||
wait_signed = True )
|
||||
return t
|
||||
|
||||
def import_key_images1(self):
|
||||
return self._import_key_images(None)
|
||||
|
|
@ -448,7 +449,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
self.create_fake_tx_files()
|
||||
before = '\n'.join(self._gen_listing())
|
||||
|
||||
t = self.spawn( 'mmgen-autosign', [f'--mountpoint={self.mountpoint}','clean'] )
|
||||
t = self.spawn('mmgen-autosign', self.opts + ['clean'])
|
||||
out = t.read()
|
||||
|
||||
after = '\n'.join(self._gen_listing())
|
||||
|
|
@ -482,7 +483,7 @@ class CmdTestXMRAutosign(CmdTestXMRWallet,CmdTestAutosignBase):
|
|||
|
||||
def check_tx_dirs(self):
|
||||
before = '\n'.join(self._gen_listing())
|
||||
t = self.spawn( 'mmgen-autosign', [f'--mountpoint={self.mountpoint}','clean'] )
|
||||
t = self.spawn('mmgen-autosign', self.opts + ['clean'])
|
||||
t.read()
|
||||
after = '\n'.join(self._gen_listing())
|
||||
imsg(f'\nBefore cleaning:\n{before}')
|
||||
|
|
|
|||
|
|
@ -124,11 +124,9 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
from mmgen.protocol import init_proto
|
||||
self.proto = init_proto( cfg, 'XMR', network='mainnet' )
|
||||
self.extra_opts = ['--wallet-rpc-password=passw0rd']
|
||||
self.autosign_mountpoint = os.path.join(self.tmpdir,'mmgen_autosign')
|
||||
self.autosign_xmr_dir = os.path.join(self.tmpdir,'mmgen_autosign','xmr')
|
||||
self.init_users()
|
||||
self.init_daemon_args()
|
||||
self.autosign_opts = []
|
||||
|
||||
for v in self.users.values():
|
||||
run(['mkdir','-p',v.udir])
|
||||
|
|
@ -340,9 +338,7 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
|
||||
def gen_kafiles(self):
|
||||
for user,data in self.users.items():
|
||||
if not data.kal_range:
|
||||
continue
|
||||
if data.autosign:
|
||||
if data.autosign or not data.kal_range:
|
||||
continue
|
||||
run(['mkdir','-p',data.udir])
|
||||
run(f'rm -f {data.kafile}',shell=True)
|
||||
|
|
@ -394,12 +390,12 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
data = self.users['alice']
|
||||
t = self.spawn(
|
||||
'mmgen-xmrwallet',
|
||||
self.extra_opts +
|
||||
[f'--wallet-dir={data.udir}'] +
|
||||
[f'--daemon=localhost:{data.md.rpc_port}'] +
|
||||
(['--no-start-wallet-daemon'] if cfg in ('continue','stop') else []) +
|
||||
(['--no-stop-wallet-daemon'] if cfg in ('start','continue') else []) +
|
||||
['new', (kafile or data.kafile), spec] )
|
||||
self.extra_opts
|
||||
+ [f'--wallet-dir={data.udir}']
|
||||
+ [f'--daemon=localhost:{data.md.rpc_port}']
|
||||
+ (['--no-start-wallet-daemon'] if cfg in ('continue','stop') else [])
|
||||
+ (['--no-stop-wallet-daemon'] if cfg in ('start','continue') else [])
|
||||
+ ['new', (kafile or data.kafile), spec])
|
||||
t.expect(expect, 'y', regex=True)
|
||||
return t
|
||||
|
||||
|
|
@ -467,7 +463,9 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
cmd_opts = [f'--wallet-dir={data.udir}', f'--daemon=localhost:{data.md.rpc_port}']
|
||||
t = self.spawn(
|
||||
'mmgen-xmrwallet',
|
||||
self.extra_opts + cmd_opts + ['label', data.kafile, label_spec]
|
||||
self.extra_opts
|
||||
+ cmd_opts
|
||||
+ ['label', data.kafile, label_spec]
|
||||
)
|
||||
t.expect('(y/N): ','y')
|
||||
t.expect(f'Label successfully {expect}')
|
||||
|
|
@ -492,7 +490,7 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
'mmgen-xmrwallet',
|
||||
self.extra_opts
|
||||
+ cmd_opts
|
||||
+ self.autosign_opts
|
||||
+ (self.autosign_opts if data.autosign else [])
|
||||
+ add_opts
|
||||
+ [op]
|
||||
+ ([] if data.autosign else [data.kafile])
|
||||
|
|
@ -536,7 +534,6 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
[f'--daemon=localhost:{data.md.rpc_port}'],
|
||||
[f'--tx-relay-daemon={tx_relay_parm}', tx_relay_parm],
|
||||
['--no-relay', no_relay and not data.autosign],
|
||||
[f'--autosign-mountpoint={self.autosign_mountpoint}', data.autosign],
|
||||
)
|
||||
add_desc = (', ' + add_desc) if add_desc else ''
|
||||
|
||||
|
|
@ -544,6 +541,7 @@ class CmdTestXMRWallet(CmdTestBase):
|
|||
'mmgen-xmrwallet',
|
||||
self.extra_opts
|
||||
+ cmd_opts
|
||||
+ (self.autosign_opts if data.autosign else [])
|
||||
+ [op]
|
||||
+ ([] if data.autosign else [data.kafile])
|
||||
+ [arg2],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue