support macOS (BTC-only, no autosign)

Testing:

    $ test/test-release.sh -FCSTA

Tested on macOS 13.6.7 (Ventura) + Xcode 15.0.1
This commit is contained in:
The MMGen Project 2024-07-27 09:42:50 +00:00
commit 91991a13de
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
19 changed files with 59 additions and 25 deletions

View file

@ -55,7 +55,7 @@ class GlobalConstants(Lockable):
prog_name = os.path.basename(sys.argv[0])
is_txprog = prog_name == 'mmgen-regtest' or prog_name.startswith('mmgen-tx')
if sys.platform not in ('linux','win32'):
if sys.platform not in ('linux', 'win32', 'darwin'):
die2(1,f'{sys.platform!r}: platform not supported by {proj_name}')
if os.getenv('HOME'): # Linux or MSYS2

View file

@ -133,7 +133,7 @@ class Daemon(Lockable):
if len(pids) > 1:
self.pids = pids
return pids[0]
elif self.platform == 'linux':
elif self.platform in ('linux', 'darwin'):
ss = ' '.join(self.start_cmd)
cp = self.run_cmd(['pgrep','-f',ss],silent=True)
if cp.stdout:

View file

@ -1 +1 @@
15.0.dev0
15.0.dev1

View file

@ -24,7 +24,7 @@ import sys,os
def launch(*, mod=None, func=None, fqmod=None, package='mmgen'):
if sys.platform == 'linux' and sys.stdin.isatty():
if sys.platform in ('linux', 'darwin') and sys.stdin.isatty():
import termios,atexit
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)

View file

@ -29,6 +29,7 @@ class bitcoin_core_daemon(CoinDaemon):
nonstd_datadir = False
datadirs = {
'linux': [gc.home_dir,'.bitcoin'],
'darwin': [gc.home_dir, '.bitcoin'],
'win32': [os.getenv('APPDATA'),'Bitcoin']
}
avail_opts = ('no_daemonize', 'online', 'bdb_wallet')
@ -76,7 +77,7 @@ class bitcoin_core_daemon(CoinDaemon):
['--rpcallowip=127.0.0.1'],
[f'--rpcbind=127.0.0.1:{self.rpc_port}'],
['--pid='+self.pidfile, self.use_pidfile],
['--daemon', self.platform == 'linux' and not self.opt.no_daemonize],
['--daemon', self.platform in ('linux', 'darwin') and not self.opt.no_daemonize],
['--fallbackfee=0.0002', self.coin == 'BTC' and self.network == 'regtest'],
['--usecashaddr=0', self.coin == 'BCH'],
['--deprecatedrpc=create_bdb', self.coin == 'BTC' and self.opt.bdb_wallet],

View file

@ -293,6 +293,7 @@ class RPCClient(MMGenObject):
if backend_id == 'auto':
return {
'linux': RPCBackends.httplib,
'darwin': RPCBackends.httplib,
'win32': RPCBackends.requests
}[sys.platform](self)
else:

View file

@ -27,9 +27,10 @@ from collections import namedtuple
from .util import msg,msg_r,die
if sys.platform == 'linux':
if sys.platform in ('linux', 'darwin'):
import tty,termios
from select import select
hold_protect_timeout = 2 if sys.platform == 'darwin' else 0.3
elif sys.platform == 'win32':
try:
import msvcrt
@ -118,9 +119,8 @@ class MMGenTermLinux(MMGenTerm):
if cls.cfg.hold_protect_disable:
return
tty.setcbreak(cls.stdin_fd)
timeout = 0.3
while True:
key = select([sys.stdin], [], [], timeout)[0]
key = select([sys.stdin], [], [], hold_protect_timeout)[0]
if key:
sys.stdin.read(1)
else:
@ -285,6 +285,7 @@ class MMGenTermMSWinStub(MMGenTermMSWin):
def get_term():
return {
'linux': (MMGenTermLinux if sys.stdin.isatty() else MMGenTermLinuxStub),
'darwin': (MMGenTermLinux if sys.stdin.isatty() else MMGenTermLinuxStub),
'win32': (MMGenTermMSWin if sys.stdin.isatty() else MMGenTermMSWinStub),
}[sys.platform]

View file

@ -181,6 +181,7 @@ class TwView(MMGenObject,metaclass=AsyncInit):
'\xe0O': 'm_bot',
}
}
scroll_keys['darwin'] = scroll_keys['linux']
def __new__(cls,cfg,proto,*args,**kwargs):
return MMGenObject.__new__(proto.base_proto_subclass(cls,cls.mod_subpath))

View file

@ -30,7 +30,7 @@ def create_shm_dir(data_dir,trash_dir):
# under '/dev/shm' and put datadir and tmpdirs here.
import shutil
from subprocess import run
if sys.platform == 'win32':
if sys.platform in ('win32', 'darwin'):
for tdir in (data_dir,trash_dir):
try:
os.listdir(tdir)
@ -293,7 +293,7 @@ def do_between():
sys.stderr.write('\n')
def create_tmp_dirs(shm_dir):
if sys.platform == 'win32':
if sys.platform in ('win32', 'darwin'):
for cfg in sorted(cfgs):
mk_tmpdir(cfgs[cfg]['tmpdir'])
else:
@ -664,6 +664,10 @@ class CmdTestRunner:
omsg(gray(f'INFO → skipping test {gname!r} (platform=win32)'))
return None
if sys.platform == 'darwin' and ct_cls.mac_skip:
omsg(gray(f'INFO → skipping test {gname!r} (platform=darwin)'))
return None
for k in ('segwit','segwit_random','bech32'):
if getattr(cfg,k):
segwit_opt = k

View file

@ -54,6 +54,7 @@ class CmdTestAutosignBase(CmdTestBase):
tmpdir_nums = [18]
color = True
win_skip = True
mac_skip = True
threaded = False
daemon_coins = []

View file

@ -38,6 +38,7 @@ class CmdTestBase:
color = False
need_daemon = False
win_skip = False
mac_skip = False
tmpdir_nums = []
test_name = None
@ -94,6 +95,9 @@ class CmdTestBase:
else:
return False
def skip_for_mac(self, extra_msg=None):
return self.skip_for_platform('darwin', extra_msg)
def skip_for_win(self, extra_msg=None):
return self.skip_for_platform('win32', extra_msg)

View file

@ -29,6 +29,8 @@ from .common import Ctrl_U,ref_dir
from .ct_base import CmdTestBase
from .input import stealth_mnemonic_entry,user_dieroll_entry
hold_protect_delay = 2 if sys.platform == 'darwin' else None
class CmdTestInput(CmdTestBase):
'user input'
networks = ('btc',)
@ -238,7 +240,7 @@ class CmdTestInput(CmdTestBase):
return t
def _input_func(self,func_name,arg_dfls,func_args,text,expect,term):
def _input_func(self, func_name, arg_dfls, func_args, text, expect, term, delay=None):
if term and sys.platform == 'win32':
return ('skip_warn','pexpect_spawn not supported on Windows platform')
func_args = dict(zip(arg_dfls.keys(),func_args))
@ -259,9 +261,9 @@ class CmdTestInput(CmdTestBase):
prompt = func_args['prompt'] + prompt_add
t.expect('Calling ')
if prompt:
t.expect(prompt,text)
t.expect(prompt, text, delay=delay)
else:
t.send(text)
t.send(text, delay=delay)
ret = t.expect_getend(' ==> ')
assert ret == repr(expect), f'Text mismatch! {ret} != {repr(expect)}'
return t
@ -275,14 +277,14 @@ class CmdTestInput(CmdTestBase):
}
return self._input_func('get_char',arg_dfls,func_args,text,expect,term)
def _line_input(self,func_args,text,expect,term):
def _line_input(self, func_args, text, expect, term, delay=None):
arg_dfls = {
'prompt': '', # positional
'echo': True,
'insert_txt': '',
'hold_protect': True,
}
return self._input_func('line_input',arg_dfls,func_args,text+'\n',expect,term)
return self._input_func('line_input', arg_dfls, func_args, text+'\n', expect, term, delay=delay)
def get_char1(self):
return self._get_char(['prompt> ','',True,5],'x','x',False)
@ -321,7 +323,8 @@ class CmdTestInput(CmdTestBase):
['prompt> ', True, '', True],
'foo',
'foo',
True)
True,
hold_protect_delay)
def line_input_term2(self):
return self._line_input(
@ -338,13 +341,18 @@ class CmdTestInput(CmdTestBase):
False)
def line_input_insert_term1(self):
if self.skip_for_mac('readline text buffer issues'):
return 'skip'
return self._line_input(
['prompt> ', True, 'foo', True],
'bar',
'foobar',
True)
True,
hold_protect_delay)
def line_input_insert_term2(self):
if self.skip_for_mac('readline text buffer issues'):
return 'skip'
return self._line_input(
['prompt> ', True, 'foo', False],
'bar',
@ -356,7 +364,8 @@ class CmdTestInput(CmdTestBase):
['prompt> ', True, '', True],
'\b\bφυφυ\b\bβαρ',
'φυβαρ',
True)
True,
hold_protect_delay)
def line_input_edit_term_insert(self):
if self.skip_for_mac('readline text buffer issues'):
@ -365,14 +374,18 @@ class CmdTestInput(CmdTestBase):
['prompt> ', True, 'φυφυ', True],
'\b\bβαρ',
'φυβαρ',
True)
True,
hold_protect_delay)
def line_input_erase_term(self):
if self.skip_for_mac('readline text buffer issues'):
return 'skip'
return self._line_input(
['prompt> ', True, 'foobarbaz', True],
Ctrl_U + 'foobar',
'foobar',
True)
True,
hold_protect_delay)
def _password_entry(self,prompt,opts=[],term=False):
if term and sys.platform == 'win32':

View file

@ -135,7 +135,7 @@ class CmdTestMisc(CmdTestBase):
die('TestSuiteException', 'Terminal echoed in noecho mode!')
t.send('x')
if self.skip_for_win('no termios support'):
if self.skip_for_win('no termios support') or self.skip_for_mac('termios.ECHO issues'):
return 'skip'
t = self.spawn('test/misc/term_ni.py',['echo'],cmd_dir='.',pexpect_spawn=True,timeout=1)

View file

@ -57,7 +57,7 @@ def stop_miner_wallet_daemon(self):
async_run(self.users['miner'].wd_rpc.stop_daemon())
def kill_proxy(cls,args):
if sys.platform == 'linux':
if sys.platform in ('linux', 'darwin'):
omsg(f'Killing SSH SOCKS server at localhost:{cls.socks_port}')
cmd = [ 'pkill', '-f', ' '.join(args) ]
run(cmd)

View file

@ -21,7 +21,7 @@ commands = [
'get_char_one',
'get_char_one_raw',
]
if sys.platform == 'linux':
if sys.platform in ('linux', 'darwin'):
commands.extend([
'get_char',
'get_char_immed_chars',

View file

@ -55,7 +55,7 @@ def overlay_setup(repo_root):
sys.stderr.write(f'Setting up overlay tree: {pkgname}\n')
make_link = os.symlink if sys.platform == 'linux' else shutil.copy2
make_link = os.symlink if sys.platform in ('linux', 'darwin') else shutil.copy2
shutil.rmtree(os.path.join(overlay_tree_dir,pkgname),ignore_errors=True)
import configparser

View file

@ -117,7 +117,7 @@ print_ver_hash() {
}
do_typescript() {
script -O "$1" -c "$2"
if [ "$DARWIN" ]; then script "$1" $2; else script -O "$1" -c "$2"; fi
}
install_package() {
@ -234,6 +234,9 @@ if [ "$(uname -m)" == 'armv7l' ]; then
ARM32=1
elif [ "$(uname -m)" == 'aarch64' ]; then
ARM64=1
elif [ "$(uname -s)" == 'Darwin' ]; then
DARWIN=1
DISTRO='DARWIN'
elif [ "$MSYSTEM" ] && uname -a | grep -qi 'msys'; then
MSYS2=1
DISTRO='MSYS2'

View file

@ -187,6 +187,7 @@ def run_test(test,subtest=None):
t = getattr(mod,'unit_tests')()
altcoin_deps = getattr(t,'altcoin_deps',())
win_skip = getattr(t, 'win_skip', ())
mac_skip = getattr(t, 'mac_skip', ())
arm_skip = getattr(t, 'arm_skip', ())
subtests = (
[subtest] if subtest else
@ -202,6 +203,9 @@ def run_test(test,subtest=None):
if sys.platform == 'win32' and subtest in win_skip:
cfg._util.qmsg(gray(f'Skipping unit subtest {subtest_disp!r} for Windows platform'))
continue
elif sys.platform == 'darwin' and subtest in mac_skip:
cfg._util.qmsg(gray(f'Skipping unit subtest {subtest_disp!r} for macOS platform'))
continue
elif platform.machine() == 'aarch64' and subtest in arm_skip:
cfg._util.qmsg(gray(f'Skipping unit subtest {subtest_disp!r} for ARM platform'))
continue

View file

@ -16,6 +16,7 @@ class unit_tests:
altcoin_deps = ('pycoin','monero_python','keyconv','zcash_mini','ethkey','ssh_socks_proxy')
win_skip = ('losetup','zcash_mini')
mac_skip = ('losetup',)
def pylint(self,name,ut):
try: