@@ -406,6 +406,9 @@ def __init__(self, bash: pexpect.spawn, sendintr: bool = False):
406
406
self .saved_variables : Dict [str , int ] = {}
407
407
self .sendintr = sendintr
408
408
409
+ self .noexcept : bool = False
410
+ self .captured_error : Optional [Exception ] = None
411
+
409
412
def __enter__ (self ):
410
413
return self
411
414
@@ -418,55 +421,87 @@ def __exit__(
418
421
self ._restore_env ()
419
422
return None
420
423
424
+ def _safe_sendintr (self ):
425
+ try :
426
+ self .bash .sendintr ()
427
+ self .bash .expect_exact (PS1 )
428
+ except Exception as e :
429
+ if self .noexcept :
430
+ self .captured_error = e
431
+ else :
432
+ raise
433
+
434
+ def _safe_exec (self , cmd : str ):
435
+ try :
436
+ self .bash .sendline (cmd )
437
+ self .bash .expect_exact (cmd )
438
+ self .bash .expect_exact ("\r \n " + PS1 )
439
+ except Exception as e :
440
+ if self .noexcept :
441
+ self ._safe_sendintr ()
442
+ self .captured_error = e
443
+ else :
444
+ raise
445
+
446
+ def _safe_assert (self , cmd : str ):
447
+ try :
448
+ assert_bash_exec (self .bash , cmd , want_output = None )
449
+ except Exception as e :
450
+ if self .noexcept :
451
+ self ._safe_sendintr ()
452
+ self .captured_error = e
453
+ else :
454
+ raise
455
+
421
456
def _copy_variable (self , src_var : str , dst_var : str ):
422
- assert_bash_exec (
423
- self .bash ,
457
+ self ._safe_exec (
424
458
"if [[ ${%s+set} ]]; then %s=${%s}; else unset -v %s; fi"
425
459
% (src_var , dst_var , src_var , dst_var ),
426
460
)
427
461
428
462
def _unset_variable (self , varname : str ):
429
- assert_bash_exec ( self .bash , "unset -v %s" % varname )
463
+ self ._safe_exec ( "unset -v %s" % varname )
430
464
431
465
def _save_cwd (self ):
432
466
if not self .cwd_changed :
433
467
self .cwd_changed = True
434
468
self ._copy_variable ("PWD" , "_BASHCOMP_TEST_OLDPWD" )
435
469
436
470
def _check_shopt (self , name : str ):
437
- assert_bash_exec (
438
- self .bash ,
471
+ self ._safe_assert (
439
472
'[[ $(shopt -p %s) == "${_BASHCOMP_TEST_NEWSHOPT_%s}" ]]'
440
473
% (name , name ),
441
474
)
442
475
443
476
def _unprotect_shopt (self , name : str ):
444
477
if name not in self .saved_shopt :
445
478
self .saved_shopt [name ] = 1
446
- assert_bash_exec (
447
- self .bash ,
448
- "_BASHCOMP_TEST_OLDSHOPT_%s=$(shopt -p %s; true)"
479
+ self ._safe_exec (
480
+ "_BASHCOMP_TEST_OLDSHOPT_%s=$(shopt -p %s || true)"
449
481
% (name , name ),
450
482
)
451
483
else :
452
484
self ._check_shopt (name )
453
485
454
486
def _protect_shopt (self , name : str ):
455
- assert_bash_exec (
456
- self .bash ,
457
- "_BASHCOMP_TEST_NEWSHOPT_%s=$(shopt -p %s; true)" % (name , name ),
487
+ self ._safe_exec (
488
+ "_BASHCOMP_TEST_NEWSHOPT_%s=$(shopt -p %s || true)" % (name , name ),
458
489
)
459
490
460
491
def _check_variable (self , varname : str ):
461
492
try :
462
- assert_bash_exec (
463
- self .bash ,
493
+ self ._safe_assert (
464
494
'[[ ${%s-%s} == "${_BASHCOMP_TEST_NEWVAR_%s-%s}" ]]'
465
495
% (varname , MAGIC_MARK2 , varname , MAGIC_MARK2 ),
466
496
)
467
- except AssertionError :
497
+ except Exception :
468
498
self ._copy_variable ("_BASHCOMP_TEST_NEWVAR_" + varname , varname )
469
499
raise
500
+ else :
501
+ if self .noexcept and self .captured_error :
502
+ self ._copy_variable (
503
+ "_BASHCOMP_TEST_NEWVAR_" + varname , varname
504
+ )
470
505
471
506
def _unprotect_variable (self , varname : str ):
472
507
if varname not in self .saved_variables :
@@ -479,24 +514,23 @@ def _protect_variable(self, varname: str):
479
514
self ._copy_variable (varname , "_BASHCOMP_TEST_NEWVAR_" + varname )
480
515
481
516
def _restore_env (self ):
517
+ self .noexcept = True
518
+
482
519
if self .sendintr :
483
- self .bash .sendintr ()
484
- self .bash .expect_exact (PS1 )
520
+ self ._safe_sendintr ()
485
521
486
522
# We first go back to the original directory before restoring
487
523
# variables because "cd" affects "OLDPWD".
488
524
if self .cwd_changed :
489
525
self ._unprotect_variable ("OLDPWD" )
490
- assert_bash_exec ( self .bash , 'cd "$_BASHCOMP_TEST_OLDPWD"' )
526
+ self ._safe_exec ( 'cd "$_BASHCOMP_TEST_OLDPWD"' % self . prefix )
491
527
self ._protect_variable ("OLDPWD" )
492
528
self ._unset_variable ("_BASHCOMP_TEST_OLDPWD" )
493
529
self .cwd_changed = False
494
530
495
531
for name in self .saved_shopt :
496
532
self ._check_shopt (name )
497
- assert_bash_exec (
498
- self .bash , 'eval "$_BASHCOMP_TEST_OLDSHOPT_%s"' % name
499
- )
533
+ self ._safe_exec ('eval "$_BASHCOMP_TEST_OLDSHOPT_%s"' % name )
500
534
self ._unset_variable ("_BASHCOMP_TEST_OLDSHOPT_" + name )
501
535
self ._unset_variable ("_BASHCOMP_TEST_NEWSHOPT_" + name )
502
536
self .saved_shopt = {}
@@ -508,26 +542,30 @@ def _restore_env(self):
508
542
self ._unset_variable ("_BASHCOMP_TEST_NEWVAR_" + varname )
509
543
self .saved_variables = {}
510
544
545
+ self .noexcept = False
546
+ if self .captured_error :
547
+ raise self .captured_error
548
+
511
549
def chdir (self , path : str ):
512
550
self ._save_cwd ()
513
551
self .cwd_changed = True
514
552
self ._unprotect_variable ("OLDPWD" )
515
- assert_bash_exec ( self .bash , "cd %s" % shlex .quote (path ))
553
+ self ._safe_exec ( "cd %s" % shlex .quote (path ))
516
554
self ._protect_variable ("OLDPWD" )
517
555
518
556
def shopt (self , name : str , value : bool ):
519
557
self ._unprotect_shopt (name )
520
558
if value :
521
- assert_bash_exec ( self .bash , "shopt -s %s" % name )
559
+ self ._safe_exec ( "shopt -s %s" % name )
522
560
else :
523
- assert_bash_exec ( self .bash , "shopt -u %s" % name )
561
+ self ._safe_exec ( "shopt -u %s" % name )
524
562
self ._protect_shopt (name )
525
563
526
564
def write_variable (self , varname : str , new_value : str , quote : bool = True ):
527
565
if quote :
528
566
new_value = shlex .quote (new_value )
529
567
self ._unprotect_variable (varname )
530
- assert_bash_exec ( self .bash , "%s=%s" % (varname , new_value ))
568
+ self ._safe_exec ( "%s=%s" % (varname , new_value ))
531
569
self ._protect_variable (varname )
532
570
533
571
# TODO: We may restore the "export" attribute as well though it is
@@ -536,7 +574,7 @@ def write_env(self, envname: str, new_value: str, quote: bool = True):
536
574
if quote :
537
575
new_value = shlex .quote (new_value )
538
576
self ._unprotect_variable (envname )
539
- assert_bash_exec ( self .bash , "export %s=%s" % (envname , new_value ))
577
+ self ._safe_exec ( "export %s=%s" % (envname , new_value ))
540
578
self ._protect_variable (envname )
541
579
542
580
0 commit comments