babel: convert org-babel-check-confirm-evaluate to defun, add test

* lisp/ob-core.el (org-babel-check-confirm-evaluate): Convert from macro
to function.
(org-babel-check-evaluate):
(org-babel-confirm-evaluate): Adapt to above change.  Convert from
defsubst to defun.
* testing/lisp/test-ob.el (ob/check-eval) New test.
(org-test-babel-confirm-evaluate): New function supporting it.
This commit is contained in:
Aaron Ecay 2015-11-05 15:51:06 +00:00
parent 4750e4427d
commit 40356ae376
2 changed files with 104 additions and 55 deletions

View File

@ -284,75 +284,78 @@ Returns a list
This is used by Babel to resolve references in source blocks.
Its value is dynamically bound during export.")
(defmacro org-babel-check-confirm-evaluate (info &rest body)
"Evaluate BODY with special execution confirmation variables set.
(defun org-babel-check-confirm-evaluate (info)
"Check whether INFO allows code block evaluation.
Specifically; NOEVAL will indicate if evaluation is allowed,
QUERY will indicate if a user query is required, CODE-BLOCK will
hold the language of the code block, and BLOCK-NAME will hold the
name of the code block."
(declare (indent defun))
(org-with-gensyms
(lang block-body headers name head eval eval-no export eval-no-export)
`(let* ((,lang (nth 0 ,info))
(,block-body (nth 1 ,info))
(,headers (nth 2 ,info))
(,name (nth 4 ,info))
(,head (nth 6 ,info))
(,eval (or (cdr (assoc :eval ,headers))
(when (assoc :noeval ,headers) "no")))
(,eval-no (or (equal ,eval "no")
(equal ,eval "never")))
(,export org-babel-exp-reference-buffer)
(,eval-no-export (and ,export (or (equal ,eval "no-export")
(equal ,eval "never-export"))))
(noeval (or ,eval-no ,eval-no-export))
(query (or (equal ,eval "query")
(and ,export (equal ,eval "query-export"))
(if (functionp org-confirm-babel-evaluate)
(save-excursion
(goto-char ,head)
(funcall org-confirm-babel-evaluate
,lang ,block-body))
org-confirm-babel-evaluate)))
(code-block (if ,info (format " %s " ,lang) " "))
(block-name (if ,name (format " (%s) " ,name) " ")))
,@body)))
Returns nil if evaluation is disallowed, t if it is
unconditionally allowed, and the symbol `query' if the user
should be asked whether to allow evaluation."
(let* ((headers (nth 2 info))
(eval (or (cdr (assq :eval headers))
(when (assq :noeval headers) "no")))
(eval-no (member eval '("no" "never")))
(export org-babel-exp-reference-buffer)
(eval-no-export (and export (member eval '("no-export" "never-export"))))
(noeval (or eval-no eval-no-export))
(query (or (equal eval "query")
(and export (equal eval "query-export"))
(if (functionp org-confirm-babel-evaluate)
(save-excursion
(goto-char (nth 6 info))
(funcall org-confirm-babel-evaluate
;; language, code block body
(nth 0 info) (nth 1 info)))
org-confirm-babel-evaluate))))
(cond
(noeval nil)
(query 'query)
(t t))))
(defsubst org-babel-check-evaluate (info)
(defun org-babel-check-evaluate (info)
"Check if code block INFO should be evaluated.
Do not query the user."
(org-babel-check-confirm-evaluate info
(not (when noeval
(message "Evaluation of this%scode-block%sis disabled."
code-block block-name)))))
;; dynamically scoped for asynchronous export
Do not query the user, but do display an informative message if
evaluation is blocked. Returns non-nil if evaluation is not blocked."
(let ((evalp (org-babel-check-confirm-evaluate info)))
(when (null evalp)
(message "Evaluation of this %s code-block%sis disabled."
(nth 0 info)
(let ((name (nth 4 info))) (if name (format " (%s) " name) ""))))
evalp))
;; Dynamically scoped for asynchronous export.
(defvar org-babel-confirm-evaluate-answer-no)
(defsubst org-babel-confirm-evaluate (info)
(defun org-babel-confirm-evaluate (info)
"Confirm evaluation of the code block INFO.
If the variable `org-babel-confirm-evaluate-answer-no' is bound
to a non-nil value, auto-answer with \"no\".
This query can also be suppressed by setting the value of
`org-confirm-babel-evaluate' to nil, in which case all future
interactive code block evaluations will proceed without any
confirmation from the user.
Note disabling confirmation may result in accidental evaluation
of potentially harmful code."
(org-babel-check-confirm-evaluate info
(not (when query
(unless
(and (not (org-bound-and-true-p
org-babel-confirm-evaluate-answer-no))
(yes-or-no-p
(format "Evaluate this%scode block%son your system? "
code-block block-name)))
(message "Evaluation of this%scode-block%sis aborted."
code-block block-name))))))
of potentially harmful code.
The variable `org-babel-confirm-evaluate-answer-no' is used by
the async export process, which requires a non-interactive
environment, to override this check."
(let* ((evalp (org-babel-check-confirm-evaluate info))
(lang (nth 0 info))
(name (nth 4 info))
(name-string (if name (format " (%s) " name) "")))
(pcase evalp
(`nil nil)
(`t t)
(`query (unless
(and (not (org-bound-and-true-p
org-babel-confirm-evaluate-answer-no))
(yes-or-no-p
(format "Evaluate this %s code block%son your system? "
lang name-string)))
(message "Evaluation of this %s code-block%sis aborted."
lang name-string)))
(x (error "Unexepcted value `%s' from `org-babel-check-confirm-evaluate'" x)))))
;;;###autoload
(defun org-babel-execute-safely-maybe ()

View File

@ -1493,6 +1493,52 @@ echo \"$data\"
(:result-params . 1)
(:result-type . value)))))
(defun org-test-babel-confirm-evaluate (eval-value)
(org-test-with-temp-text (format "#+begin_src emacs-lisp :eval %s
nil
#+end_src" eval-value)
(goto-char (point-min))
(let ((info (org-babel-get-src-block-info)))
(org-babel-check-confirm-evaluate info))))
(ert-deftest ob/check-eval ()
(let ((org-confirm-babel-evaluate t))
;; Non-export tests
(dolist (pair '(("no" . nil)
("never" . nil)
("query" . query)
("yes" . query)))
(should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair))))
;; Export tests
(let ((org-babel-exp-reference-buffer t))
(dolist (pair '(("no" . nil)
("never" . nil)
("query" . query)
("yes" . query)
("never-export" . nil)
("no-export" . nil)
("query-export" . query)))
(message (car pair))
(should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair))))))
(let ((org-confirm-babel-evaluate nil))
;; Non-export tests
(dolist (pair '(("no" . nil)
("never" . nil)
("query" . query)
("yes" . t)))
(should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair))))
;; Export tests
(let ((org-babel-exp-reference-buffer t))
(dolist (pair '(("no" . nil)
("never" . nil)
("query" . query)
("yes" . t)
("never-export" . nil)
("no-export" . nil)
("query-export" . query)))
(message (car pair))
(should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair)))))))
(provide 'test-ob)
;;; test-ob ends here