emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/compat 01a8a9dc90: Add ert-with-temp-directory and ert-


From: ELPA Syncer
Subject: [elpa] externals/compat 01a8a9dc90: Add ert-with-temp-directory and ert-with-temp-file
Date: Sun, 29 Jan 2023 06:57:25 -0500 (EST)

branch: externals/compat
commit 01a8a9dc90dbd4d4a69b906e01488a63d003d65d
Author: Daniel Mendler <mail@daniel-mendler.de>
Commit: Daniel Mendler <mail@daniel-mendler.de>

    Add ert-with-temp-directory and ert-with-temp-file
---
 NEWS.org        |   2 +
 compat-26.el    |  10 ++++
 compat-29.el    | 105 +++++++++++++++++++++++++++++++++++++++++
 compat-tests.el | 142 ++++++++++++++++++++++++++++++++++----------------------
 compat.texi     |  64 +++++++++++++++++++++++++
 5 files changed, 268 insertions(+), 55 deletions(-)

diff --git a/NEWS.org b/NEWS.org
index 6068bc3f48..533725252f 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -2,7 +2,9 @@
 
 * Development
 
+- compat-26: Add ~make-temp-file~ with optional argument TEXT.
 - compat-29: Add ~funcall-with-delayed-message~ and ~with-delayed-message~.
+- compat-29: Add ~ert-with-temp-file~ and ~ert-with-temp-directory~.
 
 * Release of "Compat" Version 29.1.3.1
 
diff --git a/compat-26.el b/compat-26.el
index a63edbbc25..fcb05f86dc 100644
--- a/compat-26.el
+++ b/compat-26.el
@@ -383,6 +383,16 @@ the variable `temporary-file-directory' is returned."
               default-directory
             temporary-file-directory)))))
 
+(compat-defun make-temp-file (prefix &optional dir-flag suffix text) ;; 
<compat-tests:make-temp-file>
+  "Handle optional argument TEXT."
+  :extended t
+  (let ((file (make-temp-file prefix dir-flag suffix)))
+    (when text
+      (with-temp-buffer
+        (insert text)
+        (write-region (point-min) (point-max) file)))
+    file))
+
 (compat-defun make-nearby-temp-file (prefix &optional dir-flag suffix) ;; 
<compat-tests:make-nearby-temp-file>
   "Create a temporary file as close as possible to `default-directory'.
 If PREFIX is a relative file name, and `default-directory' is a
diff --git a/compat-29.el b/compat-29.el
index 665366eefe..fa62c45295 100644
--- a/compat-29.el
+++ b/compat-29.el
@@ -1281,5 +1281,110 @@ Also see `buttonize'."
           (setq sentences (1- sentences)))
         sentences))))
 
+;;;; Defined in ert-x.el
+
+(compat-defmacro ert-with-temp-file (name &rest body) ;; 
<compat-tests:ert-with-temp-file>
+  "Bind NAME to the name of a new temporary file and evaluate BODY.
+Delete the temporary file after BODY exits normally or
+non-locally.  NAME will be bound to the file name of the temporary
+file.
+
+The following keyword arguments are supported:
+
+:prefix STRING  If non-nil, pass STRING to `make-temp-file' as
+                the PREFIX argument.  Otherwise, use the value of
+                `ert-temp-file-prefix'.
+
+:suffix STRING  If non-nil, pass STRING to `make-temp-file' as the
+                SUFFIX argument.  Otherwise, use the value of
+                `ert-temp-file-suffix'; if the value of that
+                variable is nil, generate a suffix based on the
+                name of the file that `ert-with-temp-file' is
+                called from.
+
+:text STRING    If non-nil, pass STRING to `make-temp-file' as
+                the TEXT argument.
+
+:buffer SYMBOL  Open the temporary file using `find-file-noselect'
+                and bind SYMBOL to the buffer.  Kill the buffer
+                after BODY exits normally or non-locally.
+
+:coding CODING  If non-nil, bind `coding-system-for-write' to CODING
+                when executing BODY.  This is handy when STRING includes
+                non-ASCII characters or the temporary file must have a
+                specific encoding or end-of-line format.
+
+See also `ert-with-temp-directory'."
+  :feature ert-x
+  (declare (indent 1) (debug (symbolp body)))
+  (cl-check-type name symbol)
+  (let (keyw prefix suffix directory text extra-keywords buffer coding)
+    (while (keywordp (setq keyw (car body)))
+      (setq body (cdr body))
+      (pcase keyw
+        (:prefix (setq prefix (pop body)))
+        (:suffix (setq suffix (pop body)))
+        ;; This is only for internal use by `ert-with-temp-directory'
+        ;; and is therefore not documented.
+        (:directory (setq directory (pop body)))
+        (:text (setq text (pop body)))
+        (:buffer (setq buffer (pop body)))
+        (:coding (setq coding (pop body)))
+        (_ (push keyw extra-keywords) (pop body))))
+    (when extra-keywords
+      (error "Invalid keywords: %s" (mapconcat #'symbol-name extra-keywords " 
")))
+    (let ((temp-file (make-symbol "temp-file"))
+          (prefix (or prefix "emacs-test-"))
+          (suffix (or suffix
+                      (thread-last
+                        (file-name-base (or (macroexp-file-name) 
buffer-file-name))
+                        (replace-regexp-in-string (rx string-start
+                                                      (group (+? not-newline))
+                                                      (regexp "-?tests?")
+                                                      string-end)
+                                                  "\\1")
+                        (concat "-")))))
+      `(let* ((coding-system-for-write ,(or coding coding-system-for-write))
+              (,temp-file (,(if directory 'file-name-as-directory 'identity)
+                           (,(if (< emacs-major-version 26) 
'compat--make-temp-file 'make-temp-file)
+                            ,prefix ,directory ,suffix ,text)))
+              (,name ,(if directory
+                          `(file-name-as-directory ,temp-file)
+                        temp-file))
+              ,@(when buffer
+                  (list `(,buffer (find-file-literally ,temp-file)))))
+         (unwind-protect
+             (progn ,@body)
+           (ignore-errors
+             ,@(when buffer
+                 (list `(with-current-buffer ,buffer
+                          (set-buffer-modified-p nil))
+                       `(kill-buffer ,buffer))))
+           (ignore-errors
+             ,(if directory
+                  `(delete-directory ,temp-file :recursive)
+                `(delete-file ,temp-file))))))))
+
+(compat-defmacro ert-with-temp-directory (name &rest body) ;; 
<compat-tests:ert-with-temp-directory>
+  "Bind NAME to the name of a new temporary directory and evaluate BODY.
+Delete the temporary directory after BODY exits normally or
+non-locally.
+
+NAME is bound to the directory name, not the directory file
+name.  (In other words, it will end with the directory delimiter;
+on Unix-like systems, it will end with \"/\".)
+
+The same keyword arguments are supported as in
+`ert-with-temp-file' (which see), except for :text."
+  :feature ert-x
+  (declare (indent 1) (debug (symbolp body)))
+  (let ((tail body) keyw)
+    (while (keywordp (setq keyw (car tail)))
+      (setq tail (cddr tail))
+      (pcase keyw (:text (error "Invalid keyword for directory: :text")))))
+  `(ert-with-temp-file ,name
+     :directory t
+     ,@body))
+
 (provide 'compat-29)
 ;;; compat-29.el ends here
diff --git a/compat-tests.el b/compat-tests.el
index 0f317c3f54..11e108c9ee 100644
--- a/compat-tests.el
+++ b/compat-tests.el
@@ -50,8 +50,8 @@
 
 ;;; Code:
 
-(require 'ert)
 (require 'compat)
+(require 'ert-x)
 (require 'subr-x)
 (require 'time-date)
 (require 'image)
@@ -1376,34 +1376,48 @@
   (should-equal t (always 1 2 3 4)))             ;; multiple arguments
 
 (ert-deftest file-backup-file-names ()
-  (let ((file (make-temp-file "compat-tests")) backups)
-    (should-not (file-backup-file-names file))
-    (push (concat file "~") backups)
-    (make-empty-file (car backups))
-    (should-equal backups (file-backup-file-names file))
-    (push (concat file ".~1~") backups)
-    (make-empty-file (car backups))
-    (should-equal backups (sort (file-backup-file-names file) #'string<))))
+  (ert-with-temp-directory dir
+    (let ((file (file-name-concat dir "file")) backups)
+      (make-empty-file file)
+      (should (file-exists-p file))
+      (should-not (file-backup-file-names file))
+      (push (concat file "~") backups)
+      (make-empty-file (car backups))
+      (should-equal backups (file-backup-file-names file))
+      (push (concat file ".~1~") backups)
+      (make-empty-file (car backups))
+      (should-equal backups (sort (file-backup-file-names file) #'string<)))))
+
+(ert-deftest make-temp-file ()
+  (let ((file (compat-call make-temp-file "compat-tests" nil nil 
"test-content")))
+    (unwind-protect
+        (with-temp-buffer
+          (insert-file-contents file)
+          (should-equal "test-content" (buffer-string)))
+      (delete-file file))))
 
 (ert-deftest make-nearby-temp-file ()
   (let ((file1 (make-nearby-temp-file "compat-tests"))
         (file2 (make-nearby-temp-file "compat-tests" nil "suffix"))
         (dir (make-nearby-temp-file "compat-tests" t)))
-    (should (string-suffix-p "suffix" file2))
-    (should (file-regular-p file1))
-    (should (file-regular-p file2))
-    (should (file-directory-p dir))
-    (should-equal (file-name-directory file1) temporary-file-directory)
-    (should-equal (file-name-directory file2) temporary-file-directory)
-    (should-equal (file-name-directory dir) temporary-file-directory)
-    (delete-file file1)
-    (delete-file file2)
-    (delete-directory dir))
-  ;; Tramp test (mock protocol)
-  (let* ((default-directory "/mock::/")
-         (file (make-nearby-temp-file "compat-tests")))
-    (should (string-match-p "\\`/mock:.*:/tmp/compat-tests" file))
-    (delete-file file)))
+    (unwind-protect
+        (progn
+          (should (string-suffix-p "suffix" file2))
+          (should (file-regular-p file1))
+          (should (file-regular-p file2))
+          (should (file-directory-p dir))
+          (should-equal (file-name-directory file1) temporary-file-directory)
+          (should-equal (file-name-directory file2) temporary-file-directory)
+          (should-equal (file-name-directory dir) temporary-file-directory))
+      (delete-file file1)
+      (delete-file file2)
+      (delete-directory dir))
+    ;; Tramp test (mock protocol)
+    (let* ((default-directory "/mock::/")
+           (file (make-nearby-temp-file "compat-tests")))
+      (unwind-protect
+          (should (string-match-p "\\`/mock:.*:/tmp/compat-tests" file))
+        (delete-file file)))))
 
 (ert-deftest executable-find ()
   (should (member (executable-find "sh") '("/usr/bin/sh" "/bin/sh")))
@@ -1462,21 +1476,20 @@
   (should-not (directory-name-p "dir/subdir")))
 
 (ert-deftest directory-empty-p ()
-  (let ((name (make-temp-name "/tmp/compat-tests")))
-    (make-directory name)
-    (should (directory-empty-p name))
-    (make-empty-file (file-name-concat name "file"))
-    (should-not (directory-empty-p name))
-    (delete-file (file-name-concat name "file"))
-    (delete-directory name)))
+  (ert-with-temp-directory dir
+    (should (directory-empty-p dir))
+    (make-empty-file (file-name-concat dir "file"))
+    (should-not (directory-empty-p dir))
+    (delete-file (file-name-concat dir "file"))
+    (should (directory-empty-p dir))))
 
 (ert-deftest make-empty-file ()
-  (let ((name (make-temp-name "/tmp/compat-tests")))
-    (should-not (file-exists-p name))
-    (make-empty-file name)
-    (should-equal 0 (file-attribute-size (file-attributes name)))
-    (should (file-exists-p name))
-    (delete-file name)))
+  (ert-with-temp-directory dir
+    (let ((file (file-name-concat dir "file")))
+      (should-not (file-exists-p file))
+      (make-empty-file file)
+      (should (file-exists-p file))
+      (should-equal 0 (file-attribute-size (file-attributes file))))))
 
 (ert-deftest mounted-file-systems ()
   (should-not (string-match-p mounted-file-systems "/etc/"))
@@ -1500,26 +1513,25 @@
   (should-equal (expand-file-name "bar/.#foo") (make-lock-file-name 
"bar/foo")))
 
 (ert-deftest file-has-changed-p ()
-  (let ((name (make-temp-file "/tmp/compat-tests")))
-    (should (file-has-changed-p name))
-    (should-not (file-has-changed-p name))
-    (should-not (file-has-changed-p name))
-    (should (file-has-changed-p name 'tag1))
-    (should-not (file-has-changed-p name 'tag1))
-    (should-not (file-has-changed-p name 'tag1))
+  (ert-with-temp-file file
+    (should (file-has-changed-p file))
+    (should-not (file-has-changed-p file))
+    (should-not (file-has-changed-p file))
+    (should (file-has-changed-p file 'tag1))
+    (should-not (file-has-changed-p file 'tag1))
+    (should-not (file-has-changed-p file 'tag1))
     (with-temp-buffer
       (insert "changed")
-      (write-region (point-min) (point-max) name))
-    (should (file-has-changed-p name))
-    (should-not (file-has-changed-p name))
-    (should-not (file-has-changed-p name))
-    (should (file-has-changed-p name 'tag1))
-    (should-not (file-has-changed-p name 'tag1))
-    (should-not (file-has-changed-p name 'tag1))
-    (should (file-has-changed-p name 'tag2))
-    (should-not (file-has-changed-p name 'tag2))
-    (should-not (file-has-changed-p name 'tag2))
-    (delete-file name)))
+      (write-region (point-min) (point-max) file))
+    (should (file-has-changed-p file))
+    (should-not (file-has-changed-p file))
+    (should-not (file-has-changed-p file))
+    (should (file-has-changed-p file 'tag1))
+    (should-not (file-has-changed-p file 'tag1))
+    (should-not (file-has-changed-p file 'tag1))
+    (should (file-has-changed-p file 'tag2))
+    (should-not (file-has-changed-p file 'tag2))
+    (should-not (file-has-changed-p file 'tag2))))
 
 (ert-deftest file-attribute-getters ()
   (let ((attrs '(type link-number user-id group-id access-time 
modification-time
@@ -2863,5 +2875,25 @@
   (should-equal 'result (funcall-with-delayed-message
                          1 "timeout" (lambda () 'result))))
 
+(ert-deftest ert-with-temp-file ()
+  (ert-with-temp-file file
+    (should-not (directory-name-p file))
+    (should (file-readable-p file))
+    (should (file-writable-p file)))
+  (ert-with-temp-file dir :directory t
+    (should (directory-name-p dir))
+    (should (file-directory-p dir)))
+  (ert-with-temp-file file :buffer buffer
+    (should (equal (current-buffer) buffer))
+    (should-equal buffer-file-name file)
+    (should-not (directory-name-p file))
+    (should (file-readable-p file))
+    (should (file-writable-p file))))
+
+(ert-deftest ert-with-temp-directory ()
+  (ert-with-temp-directory dir
+    (should (directory-name-p dir))
+    (should (file-directory-p dir))))
+
 (provide 'compat-tests)
 ;;; compat-tests.el ends here
diff --git a/compat.texi b/compat.texi
index 563a4d9deb..e323c59007 100644
--- a/compat.texi
+++ b/compat.texi
@@ -893,6 +893,48 @@ size, modes, inode-number and device-number.
 These functions must be called explicitly via @code{compat-call},
 since their calling convention or behavior was extended in Emacs 26.1:
 
+@c copied from lispref/files.texi
+@defun compat-call make-temp-file prefix &optional dir-flag suffix text
+This function creates a temporary file and returns its name.  Emacs
+creates the temporary file's name by adding to @var{prefix} some
+random characters that are different in each Emacs job.  The result is
+guaranteed to be a newly created file, containing @var{text} if that's
+given as a string and empty otherwise. On MS-DOS, this function can
+truncate @var{prefix} to fit into the 8+3 file-name limits.  If
+@var{prefix} is a relative file name, it is expanded against
+@code{temporary-file-directory}.
+
+The compatibility version adds support for handling the optional
+argument @var{TEXT}.
+
+@example
+@group
+(make-temp-file "foo")
+     @result{} "/tmp/foo232J6v"
+@end group
+@end example
+
+When @code{make-temp-file} returns, the file has been created and is
+empty.  At that point, you should write the intended contents into the
+file.
+
+If @var{dir-flag} is non-@code{nil}, @code{make-temp-file} creates an
+empty directory instead of an empty file.  It returns the file name,
+not the directory name, of that directory.  @xref{Directory Names,,,elisp}.
+
+If @var{suffix} is non-@code{nil}, @code{make-temp-file} adds it at
+the end of the file name.
+
+If @var{text} is a string, @code{make-temp-file} inserts it in the file.
+
+To prevent conflicts among different libraries running in the same
+Emacs, each Lisp program that uses @code{make-temp-file} should have its
+own @var{prefix}.  The number added to the end of @var{prefix}
+distinguishes between the same application running in different Emacs
+jobs.  Additional added characters permit a large number of distinct
+names even in one Emacs job.
+@end defun
+
 @defun compat-call@ assoc key alist &optional testfn
 This function returns the first association for @var{key} in
 @var{alist}, comparing @var{key} against the alist elements using
@@ -2844,6 +2886,28 @@ Like @code{when-let}, but repeat until a binding in 
@var{spec} is
 This is comparable to @code{and-let*}.
 @end defmac
 
+@c based on lisp/emacs-lisp/ert-x.el
+@defmac ert-with-temp-file name &rest body
+Bind @var{name} to the name of a new temporary file and evaluate
+@var{body}.  Delete the temporary file after @var{body} exits normally
+or non-locally.  @var{name} will be bound to the file name of the
+temporary file. See the docstring for supported keyword arguments.
+@end defmac
+
+@c based on lisp/emacs-lisp/ert-x.el
+@defmac ert-with-temp-directory name &rest body
+Bind @var{name} to the name of a new temporary directory and evaluate
+@var{body}.  Delete the temporary directory after @var{body} exits
+normally or non-locally.
+
+@var{name} is bound to the directory name, not the directory file
+name.  (In other words, it will end with the directory delimiter; on
+Unix-like systems, it will end with "/".)
+
+The same keyword arguments are supported as in
+@code{ert-with-temp-file} (which see), except for @code{:text}.
+@end defmac
+
 @subsection Extended Definitions
 These functions must be called explicitly via @code{compat-call},
 since their calling convention or behavior was extended in Emacs 29.1:



reply via email to

[Prev in Thread] Current Thread [Next in Thread]