-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clear scrollback #158
Clear scrollback #158
Conversation
40df59f
to
c391b7f
Compare
da855f6
to
0047d3d
Compare
I appear to be breaking the new-mnemonic or test_generate_bls_to_execution_change_keystore.py test on Windows with this, though I am unclear how. If the Windows tests don't complete (hang), then I'll need to find a Windows machine to test this PR on. |
I'll check on my Windows dev machine to see if I can find the issue. |
This is the failures I see when running the test suite on Window with Python 3.11: $ uv run pytest tests
========================================= test session starts ========================================== platform win32 -- Python 3.11.4, pytest-8.3.2, pluggy-1.5.0
rootdir: C:\Users\Test\Projects\ethstaker-deposit-cli
configfile: pytest.ini
plugins: asyncio-0.24.0
asyncio: mode=Mode.STRICT, default_loop_scope=function
collected 903 items
tests\test_cli\test_existing_mnemonic.py ....FF. [ 0%] tests\test_cli\test_exit_transaction_keystore.py ...... [ 1%] tests\test_cli\test_exit_transaction_mnemonic.py .F...... [ 2%] tests\test_cli\test_generate_bls_to_execution_change.py .... [ 2%] tests\test_cli\test_generate_bls_to_execution_change_keystore.py ....... [ 3%] tests\test_cli\test_new_mnemonic.py .......FF. [ 4%] tests\test_cli\test_partial_deposit.py ......... [ 5%] tests\test_cli\test_regeneration.py . [ 5%] tests\test_cli\test_test_keystore.py . [ 5%] tests\test_credentials.py . [ 5%] tests\test_deposit.py ........ [ 6%] tests\test_intl\test_json_schema.py ............................................................. [ 13%] ........... [ 14%] tests\test_key_handling\test_key_derivation\test_mnemonic.py .................................... [ 18%] ................................................................................................. [ 29%] ................................................................................................. [ 40%] ................................................................................................. [ 51%] ................................................................................................. [ 61%] ................................................................................................. [ 72%] ................................................................................................. [ 83%] ................................. [ 86%] tests\test_key_handling\test_key_derivation\test_path.py ........ [ 87%] tests\test_key_handling\test_key_derivation\test_tree.py ....................... [ 90%] tests\test_key_handling\test_keystore.py ............ [ 91%] tests\test_utils\test_constants.py .. [ 91%] tests\test_utils\test_crypto.py .......... [ 93%] tests\test_utils\test_intl.py .......... [ 94%] tests\test_utils\test_ssz.py ......... [ 95%] tests\test_utils\test_validation.py ............................................ [100%]
=============================================== FAILURES =============================================== _____________________________________________ test_script ______________________________________________
@pytest.mark.asyncio
async def test_script() -> None:
my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER')
if not os.path.exists(my_folder_path):
os.mkdir(my_folder_path)
if os.name == 'nt': # Windows
run_script_cmd = 'sh deposit.sh'
else: # Mac or Linux
run_script_cmd = './deposit.sh'
install_cmd = run_script_cmd + ' install'
proc = await asyncio.create_subprocess_shell(
install_cmd,
)
await proc.wait()
cmd_args = [
run_script_cmd,
'--language', 'english',
'--non_interactive',
'existing-mnemonic',
'--num_validators', '1',
'--mnemonic="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"',
'--mnemonic_password', 'TREZOR',
'--validator_start_index', '1',
'--chain', 'mainnet',
'--keystore_password', 'MyPasswordIs',
'--withdrawal_address', '""',
'--folder', my_folder_path,
]
proc = await asyncio.create_subprocess_shell(
' '.join(cmd_args),
)
await proc.wait()
# Check files
validator_keys_folder_path = os.path.join(my_folder_path, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME)
> _, _, key_files = next(os.walk(validator_keys_folder_path))
E StopIteration
tests\test_cli\test_existing_mnemonic.py:287: StopIteration
The above exception was the direct cause of the following exception:
self = <Coroutine test_script>
def runtest(self) -> None:
self.obj = wrap_in_sync(
# https://github.com/pytest-dev/pytest-asyncio/issues/596
self.obj, # type: ignore[has-type]
)
> super().runtest()
.venv\Lib\site-packages\pytest_asyncio\plugin.py:457:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv\Lib\site-packages\pytest_asyncio\plugin.py:929: in inner
_loop.run_until_complete(task)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <ProactorEventLoop running=False closed=False debug=False>
future = <Task finished name='Task-1' coro=<test_script() done, defined at C:\Users\Test\Projects\ethstaker-deposit-cli\tests\test_cli\test_existing_mnemonic.py:249> exception=RuntimeError('coroutine raised StopIteration')>
def run_until_complete(self, future):
"""Run until the Future is done.
If the argument is a coroutine, it is wrapped in a Task.
WARNING: It would be disastrous to call run_until_complete()
with the same coroutine twice -- it would wrap it in two
different Tasks and that can't be good.
Return the Future's result, or raise its exception.
"""
self._check_closed()
self._check_running()
new_task = not futures.isfuture(future)
future = tasks.ensure_future(future, loop=self)
if new_task:
# An exception is raised if the future didn't complete, so there
# is no need to log the "destroy pending task" message
future._log_destroy_pending = False
future.add_done_callback(_run_until_complete_cb)
try:
self.run_forever()
except:
if new_task and future.done() and not future.cancelled():
# The coroutine raised a BaseException. Consume the exception
# to not log a warning, the caller doesn't have access to the
# local task.
future.exception()
raise
finally:
future.remove_done_callback(_run_until_complete_cb)
if not future.done():
raise RuntimeError('Event loop stopped before Future completed.')
> return future.result()
E RuntimeError: coroutine raised StopIteration
..\..\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py:653: RuntimeError
----------------------------------------- Captured stderr call ----------------------------------------- 'sh' is not recognized as an internal or external command,
operable program or batch file.
'sh' is not recognized as an internal or external command,
operable program or batch file.
___________________________________ test_script_abbreviated_mnemonic ___________________________________
@pytest.mark.asyncio
async def test_script_abbreviated_mnemonic() -> None:
my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER')
if not os.path.exists(my_folder_path):
os.mkdir(my_folder_path)
if os.name == 'nt': # Windows
run_script_cmd = 'sh deposit.sh'
else: # Mac or Linux
run_script_cmd = './deposit.sh'
install_cmd = run_script_cmd + ' install'
proc = await asyncio.create_subprocess_shell(
install_cmd,
)
await proc.wait()
cmd_args = [
run_script_cmd,
'--language', 'english',
'--non_interactive',
'existing-mnemonic',
'--num_validators', '1',
'--mnemonic="aban aban aban aban aban aban aban aban aban aban aban abou"',
'--mnemonic_password', 'TREZOR',
'--validator_start_index', '1',
'--chain', 'mainnet',
'--keystore_password', 'MyPasswordIs',
'--withdrawal_address', '""',
'--folder', my_folder_path,
]
proc = await asyncio.create_subprocess_shell(
' '.join(cmd_args),
)
await proc.wait()
# Check files
validator_keys_folder_path = os.path.join(my_folder_path, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME)
> _, _, key_files = next(os.walk(validator_keys_folder_path))
E StopIteration
tests\test_cli\test_existing_mnemonic.py:336: StopIteration
The above exception was the direct cause of the following exception:
self = <Coroutine test_script_abbreviated_mnemonic>
def runtest(self) -> None:
self.obj = wrap_in_sync(
# https://github.com/pytest-dev/pytest-asyncio/issues/596
self.obj, # type: ignore[has-type]
)
> super().runtest()
.venv\Lib\site-packages\pytest_asyncio\plugin.py:457:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv\Lib\site-packages\pytest_asyncio\plugin.py:929: in inner
_loop.run_until_complete(task)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <ProactorEventLoop running=False closed=False debug=False>
future = <Task finished name='Task-4' coro=<test_script_abbreviated_mnemonic() done, defined at C:\Users\Test\Projects\ethstaker-deposit-cli\tests\test_cli\test_existing_mnemonic.py:298> exception=RuntimeError('coroutine raised StopIteration')>
def run_until_complete(self, future):
"""Run until the Future is done.
If the argument is a coroutine, it is wrapped in a Task.
WARNING: It would be disastrous to call run_until_complete()
with the same coroutine twice -- it would wrap it in two
different Tasks and that can't be good.
Return the Future's result, or raise its exception.
"""
self._check_closed()
self._check_running()
new_task = not futures.isfuture(future)
future = tasks.ensure_future(future, loop=self)
if new_task:
# An exception is raised if the future didn't complete, so there
# is no need to log the "destroy pending task" message
future._log_destroy_pending = False
future.add_done_callback(_run_until_complete_cb)
try:
self.run_forever()
except:
if new_task and future.done() and not future.cancelled():
# The coroutine raised a BaseException. Consume the exception
# to not log a warning, the caller doesn't have access to the
# local task.
future.exception()
raise
finally:
future.remove_done_callback(_run_until_complete_cb)
if not future.done():
raise RuntimeError('Event loop stopped before Future completed.')
> return future.result()
E RuntimeError: coroutine raised StopIteration
..\..\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py:653: RuntimeError
----------------------------------------- Captured stderr call ----------------------------------------- 'sh' is not recognized as an internal or external command,
operable program or batch file.
'sh' is not recognized as an internal or external command,
operable program or batch file.
_______________________________ test_exit_transaction_mnemonic_multiple ________________________________
@pytest.mark.asyncio
async def test_exit_transaction_mnemonic_multiple() -> None:
# Prepare folder
my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER')
clean_exit_transaction_folder(my_folder_path)
if not os.path.exists(my_folder_path):
os.mkdir(my_folder_path)
if os.name == 'nt': # Windows
run_script_cmd = 'sh deposit.sh'
else: # Mac or Linux
run_script_cmd = './deposit.sh'
install_cmd = run_script_cmd + ' install'
proc = await asyncio.create_subprocess_shell(
install_cmd,
)
await proc.wait()
cmd_args = [
run_script_cmd,
'--language', 'english',
'--non_interactive',
'exit-transaction-mnemonic',
'--output_folder', my_folder_path,
'--chain', 'mainnet',
'--mnemonic', '"aban aban aban aban aban aban aban aban aban aban aban abou"',
'--validator_start_index', '0',
'--validator_indices', '0,1,2,3',
'--epoch', '1234',
]
proc = await asyncio.create_subprocess_shell(
' '.join(cmd_args),
)
await proc.wait()
> assert proc.returncode == 0
E assert 1 == 0
E + where 1 = <Process 8272>.returncode
tests\test_cli\test_exit_transaction_mnemonic.py:95: AssertionError
----------------------------------------- Captured stderr call ----------------------------------------- 'sh' is not recognized as an internal or external command,
operable program or batch file.
'sh' is not recognized as an internal or external command,
operable program or batch file.
______________________________________ test_script_bls_withdrawal ______________________________________
@pytest.mark.skipif(sys.version_info[:2] == (3, 9) and sys.platform == "darwin", reason="breaks on macOS Python 3.9")
@pytest.mark.asyncio
async def test_script_bls_withdrawal() -> None:
# Prepare folder
my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER')
clean_key_folder(my_folder_path)
if not os.path.exists(my_folder_path):
os.mkdir(my_folder_path)
if os.name == 'nt': # Windows
run_script_cmd = 'sh deposit.sh'
else: # Mac or Linux
run_script_cmd = './deposit.sh'
install_cmd = run_script_cmd + ' install'
proc = await asyncio.create_subprocess_shell(
install_cmd,
)
await proc.wait()
cmd_args = [
run_script_cmd,
'--language', 'english',
'--non_interactive',
'new-mnemonic',
'--num_validators', '5',
'--mnemonic_language', 'english',
'--chain', 'mainnet',
'--keystore_password', 'MyPasswordIs',
'--withdrawal_address', '""',
'--folder', my_folder_path,
]
proc = await asyncio.create_subprocess_shell(
' '.join(cmd_args),
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
)
seed_phrase = ''
parsing = False
mnemonic_json_file = os.path.join(os.getcwd(), 'ethstaker_deposit/../ethstaker_deposit/cli/', 'new_mnemonic.json')
async for out in proc.stdout:
output = out.decode('utf-8').rstrip()
if output.startswith(load_text(['msg_mnemonic_presentation'], mnemonic_json_file, 'new_mnemonic')):
parsing = True
elif output.startswith(load_text(['msg_mnemonic_retype_prompt'], mnemonic_json_file, 'new_mnemonic')):
parsing = False
elif parsing:
seed_phrase += output
if len(seed_phrase) > 0:
encoded_phrase = seed_phrase.encode()
proc.stdin.write(encoded_phrase)
proc.stdin.write(b'\n')
> assert len(seed_phrase) > 0
E AssertionError: assert 0 > 0
E + where 0 = len('')
tests\test_cli\test_new_mnemonic.py:496: AssertionError
----------------------------------------- Captured stderr call ----------------------------------------- 'sh' is not recognized as an internal or external command,
operable program or batch file.
'sh' is not recognized as an internal or external command,
operable program or batch file.
___________________________________ test_script_abbreviated_mnemonic ___________________________________
@pytest.mark.skipif(sys.version_info[:2] == (3, 9) and sys.platform == "darwin", reason="breaks on macOS Python 3.9")
@pytest.mark.asyncio
async def test_script_abbreviated_mnemonic() -> None:
# Prepare folder
my_folder_path = os.path.join(os.getcwd(), 'TESTING_TEMP_FOLDER')
clean_key_folder(my_folder_path)
if not os.path.exists(my_folder_path):
os.mkdir(my_folder_path)
if os.name == 'nt': # Windows
run_script_cmd = 'sh deposit.sh'
else: # Mac or Linux
run_script_cmd = './deposit.sh'
install_cmd = run_script_cmd + ' install'
proc = await asyncio.create_subprocess_shell(
install_cmd,
)
await proc.wait()
cmd_args = [
run_script_cmd,
'--language', 'english',
'--non_interactive',
'new-mnemonic',
'--num_validators', '5',
'--mnemonic_language', 'english',
'--chain', 'mainnet',
'--keystore_password', 'MyPasswordIs',
'--withdrawal_address', '""',
'--folder', my_folder_path,
]
proc = await asyncio.create_subprocess_shell(
' '.join(cmd_args),
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
)
seed_phrase = ''
parsing = False
mnemonic_json_file = os.path.join(os.getcwd(), 'ethstaker_deposit/../ethstaker_deposit/cli/', 'new_mnemonic.json')
async for out in proc.stdout:
output = out.decode('utf-8').rstrip()
if output.startswith(load_text(['msg_mnemonic_presentation'], mnemonic_json_file, 'new_mnemonic')):
parsing = True
elif output.startswith(load_text(['msg_mnemonic_retype_prompt'], mnemonic_json_file, 'new_mnemonic')):
parsing = False
elif parsing:
seed_phrase += output
if len(seed_phrase) > 0:
abbreviated_mnemonic = ' '.join(abbreviate_words(seed_phrase.split(' ')))
encoded_phrase = abbreviated_mnemonic.encode()
proc.stdin.write(encoded_phrase)
proc.stdin.write(b'\n')
> assert len(seed_phrase) > 0
E AssertionError: assert 0 > 0
E + where 0 = len('')
tests\test_cli\test_new_mnemonic.py:585: AssertionError
----------------------------------------- Captured stderr call ----------------------------------------- 'sh' is not recognized as an internal or external command,
operable program or batch file.
'sh' is not recognized as an internal or external command,
operable program or batch file.
======================================= short test summary info ======================================== FAILED tests/test_cli/test_existing_mnemonic.py::test_script - RuntimeError: coroutine raised StopIteration
FAILED tests/test_cli/test_existing_mnemonic.py::test_script_abbreviated_mnemonic - RuntimeError: coroutine raised StopIteration
FAILED tests/test_cli/test_exit_transaction_mnemonic.py::test_exit_transaction_mnemonic_multiple - assert 1 == 0
FAILED tests/test_cli/test_new_mnemonic.py::test_script_bls_withdrawal - AssertionError: assert 0 > 0
FAILED tests/test_cli/test_new_mnemonic.py::test_script_abbreviated_mnemonic - AssertionError: assert 0 > 0
============================== 5 failed, 898 passed in 365.97s (0:06:05) =============================== |
All those tests seem to fail on my system because we are calling |
Wait but this used to work …. and that part does work in CI. So, that’s specific to your dev machine and we have another issue here. |
It might be something else. Let me try to debug this. |
b8e0f03
to
34bed94
Compare
34bed94
to
82abec9
Compare
I am special-casing for asyncio on win32 now, to catch these two tests. I also manually tried |
Test Coverage: Download HTML Report
|
Test Coverage: Download HTML Report
|
Test Coverage: Download HTML Report
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still having some troubles running this on my Windows dev machine sucessfully, but since it works with the test suite now on Github runners and the feature is working on my side so I guess we are good to go.
Resolves #32 , together with #130
Changes
Instead of
click.clear()
usecls
ortput reset
, depending on OS. This clears the scrollback of the terminal, at least on "modern" versions of Windows, Linux and macOSTypes of changes
What types of changes does your code introduce?
Testing
Requires testing
If yes, did you write tests?