18
$\begingroup$

I would like a notebook evaluation to entirely stop when an Assert fails, without quitting the kernel. Is this possible (e.g., by setting $AssertFunction to ... something)?

Edit:

For example, if I create a notebook containing a cell with the following lines, I would like the value of test to still be 0, and for no subsequent cells to be exectuted.

test = 0;
Assert[False];
test = 1;

EDIT:

Note that setting $AssertFunction=Abort[]& does not work, because it only aborts the current computation, but afterwards evaluation continues to proceed through the notebook.

A related question: why must we execute On[Assert] before we can set $AssertFunction? Naturally I understand why we must turn assertions on and off; that is not my question. My question is why On[Assert] apparently resets $AssertFunction:

On[Assert] 
$AssertFunction = Abort[] &;
Assert[False]  (* aborts *)
Off[Assert]
On[Assert]
Assert[False]  (* does not abort *)
$\endgroup$
6
  • $\begingroup$ I see, that's because Abort[] aborts the current evaluation. You are evaluating a whole notebook at once. That's different: the front end will queue up all inputs and send them one by one to the kernel. Abort[] only aborts one of these, as it cannot affect the front end state. Abort[] is only for the kernel. I thought $AssertFunction = FrontEndTokenExecute["EvaluatorAbort"] & would work but it doesn't. I suggest editing the question and spelling out what I said above to attract more attention (i.e. spelling out that Abort doesn't work). $\endgroup$
    – Szabolcs
    Commented Nov 10, 2015 at 20:08
  • $\begingroup$ The reason why we need On[Assert] is so that we can easily turn on and off the assertions. It's like -DNDEBUG when compiling C code. $\endgroup$
    – Szabolcs
    Commented Nov 10, 2015 at 20:08
  • 1
    $\begingroup$ @Szabolcs I'd say the fact that "EvaluatorAbort" token is not working is a bug. It doesn't even when I select the cell with SelectionMove. $\endgroup$
    – Kuba
    Commented Nov 16, 2015 at 8:36
  • $\begingroup$ @Kuba aborting evaluation in the debugger also doesn't work properly, that might be related (one example, feel free to add the bugs tag there). $\endgroup$ Commented Nov 17, 2015 at 11:17
  • $\begingroup$ @JacobAkkerboom I don't really know, could you ask support what one should expect after evaluating Abort[] - newline - Print[1] or after Pause[5] - newline - Print[5] where during pause menu item AbortEvaluation is used? My mails to WRI are still being lost. $\endgroup$
    – Kuba
    Commented Nov 17, 2015 at 11:24

4 Answers 4

13
$\begingroup$
On[Assert]
$AssertFunction := (
    (*1*)
   SelectionMove[EvaluationNotebook[], All, Notebook, AutoScroll -> False];
   FrontEndExecute @ FrontEndToken @ "RemoveFromEvaluationQueue";
   SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False];
    (*2*)
   RunScheduledTask[$Pre =., {1}];
       $Pre = Abort[] &; Abort[];
);
  1. First procedure removes all queued cells from the evaluation queue. And puts a selection after a current evaluating cell.

  2. Since no Token or Abort works, let's improvise to abort pending evaluation in current evaluation cell. Each line(not really a line) is a separate CompoundExpression which needs to be aborted separately so we can $Pre the Abort[] operation. But it would be nice to get rid of that later, that's where ScheduledTask comes in. 1 second is arbitrary but I think enough to abort everything and not to interrupt user actions in future.

enter image description here

Everything from main cell after Assert is aborted and the cell with 4 is skipped from evaluation even though it was selected too.

$\endgroup$
2
  • $\begingroup$ Interesting. Needless to say, I supposed something simpler was possible. Can you also address my secondary question? That is, why must the definition of $AssertFunction come after On[Assert]? That is, I find it odd that On[Assert] overrides the current definition of $AssertFunction; is there a good reason for this? $\endgroup$
    – Alan
    Commented Nov 16, 2015 at 13:02
  • $\begingroup$ @Alan I don't know at the moment :/ $\endgroup$
    – Kuba
    Commented Nov 16, 2015 at 13:04
7
$\begingroup$

As of Version 11.2 RunScheduledTask has been superseded by SessionSubmit. @Kuba 's cool function stopped working on 11.2 but does work when RunScheduledTask is replaced.

$\endgroup$
2
  • $\begingroup$ Version 11.2 I just checked portal site and do not see 11.2 released? is this a pre-release you are using? $\endgroup$
    – Nasser
    Commented Jul 28, 2017 at 22:36
  • $\begingroup$ @Nasser - yes, it is a pre-release. $\endgroup$ Commented Jul 28, 2017 at 22:52
0
$\begingroup$

It sounds like you want to inspect the stack when an assertion fails. Will Dialog do what you want? As in

$AssertFunction:=Dialog[]

As already mentioned however, cells queued for evaluation, and even subsequent lines in the current cell, will still execute when you Return or ExitDialog. You can ExitDialog[Unevaluated[Abort[]]] to abort a statement, but

test=0;
Assert[False];
test=1;

is three statements.

$\endgroup$
0
$\begingroup$

This is such a fantastic post! One of my notebooks opens a database that is in the current directory but if I have opened a notebook in a different directory, then it fails to find the database and all subsequent evaluations are wrong. Therefore I wanted to test the directory and Abort the evaluation of all pending cells if it is wrong. But because sometimes I am on my laptop and sometimes on my desktop, only the \Documents part of the path is constant. Using this answer updated to 12.2 produces the following, which works like a charm:

fpath=(NotebookBrowseDirectory/.Options[$FrontEnd])<>"\\";(*save in notebook path*)
(*stop evaluation if the path does not end in \Documents\*)
If[StringTake[fpath,-11]!="\\Documents\\",
(*Remove cells from evaluation queue*)(
SelectionMove[EvaluationNotebook[],All,Notebook,AutoScroll -> False];
FrontEndExecute@FrontEndToken@"RemoveFromEvaluationQueue";
SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False];
(*set $Pre to abort current cell but before that schedule a task to un-define $Pre*)
SessionSubmit[ScheduledTask[$Pre =., {Quantity[3, "Seconds"]}]];
MessageDialog["Wrong working directory! Open and close a file in /Documents and rerun."];
$Pre=Abort[]&;Abort[];)];

Many thanks @Kuba. It could only be made better by avoiding or redirecting the production of an output cell with $Aborted for each subsequent line in the evaluation cell.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.