diff --git a/.config/emacs/site-lisp/python-tests.el b/.config/emacs/site-lisp/python-tests.el new file mode 100644 index 0000000..e63ca24 --- /dev/null +++ b/.config/emacs/site-lisp/python-tests.el @@ -0,0 +1,286 @@ +;;; elpy.el --- Emacs Python Development Environment -*- lexical-binding: t -*- + +;; Copyright (C) 2012-2019 Jorgen Schaefer + +;; Author: Jorgen Schaefer , Gaby Launay +;; URL: https://github.com/jorgenschaefer/elpy +;; Version: 1.35.0 +;; Keywords: Python, IDE, Languages, Tools +;; Package-Requires: ((company "0.9.10") (emacs "24.4") (highlight-indentation "0.7.0") (pyvenv "1.20") (yasnippet "0.13.0") (s "1.12.0")) + +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License +;; as published by the Free Software Foundation; either version 3 +;; of the License, or (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Copy of the content necessary to run elpy-test--current-test-name function from the Elpy project + +(defun elpy-library-root () + "Return the root of the Python package chain of the current buffer. + +That is, if you have /foo/package/module.py, it will return /foo, +so that import package.module will pick up module.py." + (locate-dominating-file default-directory + (lambda (dir) + (not (file-exists-p + (format "%s/__init__.py" + dir)))))) + +(defcustom elpy-test-runner 'elpy-test-discover-runner + "The test runner to use to run tests." + :type '(choice (const :tag "Unittest Discover" elpy-test-discover-runner) + (const :tag "Green" elpy-test-green-runner) + (const :tag "Django Discover" elpy-test-django-runner) + (const :tag "Nose" elpy-test-nose-runner) + (const :tag "py.test" elpy-test-pytest-runner) + (const :tag "Twisted Trial" elpy-test-trial-runner)) + :safe 'elpy-test-runner-p + :group 'elpy) + +(defcustom elpy-test-discover-runner-command '("python-shell-interpreter" "-m" "unittest") + "The command to use for `elpy-test-discover-runner'. +If the string \"python-shell-interpreter\" is present, it will be replaced with +the value of `python-shell-interpreter'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-green-runner-command '("green") + "The command to use for `elpy-test-green-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-nose-runner-command '("nosetests") + "The command to use for `elpy-test-nose-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-trial-runner-command '("trial") + "The command to use for `elpy-test-trial-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-pytest-runner-command '("py.test") + "The command to use for `elpy-test-pytest-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-compilation-function 'compile + "Function used by `elpy-test-run' to run a test command. + +The function should behave similarly to `compile'. Another good +option is `pdb'." + :type 'string + :group 'elpy) + +(defvar elpy-set-test-runner-history nil + "History variable for `elpy-set-test-runner'.") + +(defun elpy-test (&optional test-whole-project) + "Run tests on the current test, or the whole project. + +If there is a test at point, run that test. If not, or if a +prefix is given, run all tests in the current project." + (interactive "P") + (let ((current-test (elpy-test-at-point))) + (if test-whole-project + ;; With prefix arg, test the whole project. + (funcall elpy-test-runner + (car current-test) + nil nil nil) + ;; Else, run only this test + (apply elpy-test-runner current-test)))) + +(defun elpy-set-test-runner (test-runner) + "Tell Elpy to use TEST-RUNNER to run tests. + +See `elpy-test' for how to invoke it." + (interactive + (list + (let* ((runners (mapcar (lambda (value) + (cons (nth 2 value) + (nth 3 value))) + (cdr (get 'elpy-test-runner 'custom-type)))) + (current (cdr (assq elpy-test-runner + (mapcar (lambda (cell) + (cons (cdr cell) (car cell))) + runners)))) + (choice (completing-read (if current + (format "Test runner (currently %s): " + current) + "Test runner: ") + runners + nil t nil 'elpy-set-test-runner-history))) + (if (equal choice "") + elpy-test-runner + (cdr (assoc choice runners)))))) + (setq elpy-test-runner test-runner)) + +(defun elpy-test-at-point () + "Return a list specifying the test at point, if any. + +This is used as the interactive + +This list has four elements. + +- Top level directory: + All test files should be importable from here. +- Test file: + The current file name. +- Test module: + The module name, relative to the top level directory. +- Test name: + The full name of the current test within the module, for + example TestClass.test_method + +If there is no test at point, test name is nil. +If the current buffer is not visiting a file, only the top level +directory is not nil." + (if (not buffer-file-name) + (progn + (save-some-buffers) + (list (elpy-library-root) nil nil nil)) + (let* ((top (elpy-library-root)) + (file buffer-file-name) + (module (elpy-test--module-name-for-file top file)) + (test (elpy-test--current-test-name))) + (if (and file (string-match "test" (or module test ""))) + (progn + (save-buffer) + (list top file module test)) + (save-some-buffers) + (list top nil nil nil))))) + +(defun elpy-test--current-test-name () + "Return the name of the test at point." + (let ((name (python-info-current-defun))) + (if (and name + (string-match "\\`\\([^.]+\\.[^.]+\\)\\." name)) + (match-string 1 name) + name))) + +(defun elpy-test--module-name-for-file (top-level module-file) + "Return the module name relative to TOP-LEVEL for MODULE-FILE. + +For example, for a top level of /project/root/ and a module file +of /project/root/package/module.py, this would return +\"package.module\"." + (let* ((relative-name (file-relative-name module-file top-level)) + (no-extension (replace-regexp-in-string "\\.py\\'" "" relative-name)) + (no-init (replace-regexp-in-string "/__init__\\'" "" no-extension)) + (dotted (replace-regexp-in-string "/" "." no-init))) + (if (string-match "^\\." dotted) + (concat "." (replace-regexp-in-string (regexp-quote "...") "." dotted)) + dotted))) + +(defun elpy-test-runner-p (obj) + "Return t iff OBJ is a test runner. + +This uses the `elpy-test-runner-p' symbol property." + (get obj 'elpy-test-runner-p)) + +(defun elpy-test-run (working-directory command &rest args) + "Run COMMAND with ARGS in WORKING-DIRECTORY as a test command." + (let ((default-directory working-directory)) + (funcall elpy-test-compilation-function + (mapconcat #'shell-quote-argument + (cons command args) + " ")))) + +(defun elpy-test-get-discover-runner () + "Return the test discover runner from `elpy-test-discover-runner-command'." + (cl-loop + for string in elpy-test-discover-runner-command + if (string= string "python-shell-interpreter") + collect python-shell-interpreter + else + collect string)) + +(defun elpy-test-discover-runner (top _file module test) + "Test the project using the python unittest discover runner. + +This requires Python 2.7 or later." + (interactive (elpy-test-at-point)) + (let ((test (cond + (test (format "%s.%s" module test)) + (module module) + (t "discover")))) + (apply #'elpy-test-run + top + (append (elpy-test-get-discover-runner) + (list test))))) +(put 'elpy-test-discover-runner 'elpy-test-runner-p t) + +(defun elpy-test-green-runner (top _file module test) + "Test the project using the green runner." + (interactive (elpy-test-at-point)) + (let* ((test (cond + (test (format "%s.%s" module test)) + (module module))) + (command (if test + (append elpy-test-green-runner-command (list test)) + elpy-test-green-runner-command))) + (apply #'elpy-test-run top command))) +(put 'elpy-test-green-runner 'elpy-test-runner-p t) + +(defun elpy-test-nose-runner (top _file module test) + "Test the project using the nose test runner. + +This requires the nose package to be installed." + (interactive (elpy-test-at-point)) + (if module + (apply #'elpy-test-run + top + (append elpy-test-nose-runner-command + (list (if test + (format "%s:%s" module test) + module)))) + (apply #'elpy-test-run + top + elpy-test-nose-runner-command))) +(put 'elpy-test-nose-runner 'elpy-test-runner-p t) + +(defun elpy-test-trial-runner (top _file module test) + "Test the project using Twisted's Trial test runner. + +This requires the twisted-core package to be installed." + (interactive (elpy-test-at-point)) + (if module + (apply #'elpy-test-run + top + (append elpy-test-trial-runner-command + (list (if test + (format "%s.%s" module test) + module)))) + (apply #'elpy-test-run top elpy-test-trial-runner-command))) +(put 'elpy-test-trial-runner 'elpy-test-runner-p t) + +(defun elpy-test-pytest-runner (top file module test) + "Test the project using the py.test test runner. + +This requires the pytest package to be installed." + (interactive (elpy-test-at-point)) + (cond + (test + (let ((test-list (split-string test "\\."))) + (apply #'elpy-test-run + top + (append elpy-test-pytest-runner-command + (list (mapconcat #'identity + (cons file test-list) + "::")))))) + (module + (apply #'elpy-test-run top (append elpy-test-pytest-runner-command + (list file)))) + (t + (apply #'elpy-test-run top elpy-test-pytest-runner-command)))) +(put 'elpy-test-pytest-runner 'elpy-test-runner-p t)