diff --git a/NEWS b/NEWS index c31a782d..ae29b0b4 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,19 @@ Python Mode News New in version 6.1.4 --------------------- +Support for large output + + new commands py-fast-process, py-fast-... + Fixes: large output makes Emacs freeze, lp:1253907 + + Python code now might be processed by an + - interactive Python shell (DEFAULT) + - non-interactive Python (`py-fast-process-p', if large output) + + Both processes might run in + - session, i.e. start from possible previous state (DEFAULT) + - dedicated, run in separate process + - new indent feature/behavior, lp:1280982 If an empty line was dedented deliberatly, this is honored by next lines indent @@ -18,6 +31,11 @@ Calls to IPython are to customizable now via New commands +- py-kill-shell-unconditional + With optional argument SHELL, otherwise kill default + (I)Python shell. + +Receives a buffer-name as optional argument" - py-info-lookup-symbol () Calls `info-lookup-symbol'. Sends help if stuff is missing. @@ -36,6 +54,11 @@ New commands - py-kill-buffer-unconditional Kill buffer unconditional; kill also any buffer-process. +Booleans +- py-fast-process-p + If `t', stuff is executed through `py-fast-...'- + commands, suitable for large output. Result arrives + in py-output-buffer, which is not in comint-mode New in version 6.1.3 --------------------- diff --git a/README b/README index 76e4af0d..a6c5752f 100644 --- a/README +++ b/README @@ -51,17 +51,18 @@ Install a local shell by evaluating ;;;;;;;;; -When code is executed from current buffer, either -- python-mode-v5-behavior, a quite simple and effective way. - Setting `python-mode-v5-behavior-p' to `t' makes it the default. +Python code might be processed by an -- if a buffer-file exists and buffer is unchanged, it's file is executed as is. +- interactive Python shell (DEFAULT) +- non-interactive Python (`py-fast-process-p', if large output) -- in all other cases a temporary file is created. - Setback: in case of error, returned error code points - here, i.e. indicated error-line-numbers are not that of - orginal buffer. +Both processes might run in +- session, i.e. start from possible previous state (DEFAULT) +- dedicated, (`py-dedicated-process-p') run in separate process + +There is also +- python-mode-v5-behavior ;;;;;;;;; To enable code auto-completion: diff --git a/ToDo.org b/ToDo.org index bf12182c..25d206cf 100644 --- a/ToDo.org +++ b/ToDo.org @@ -1,3 +1,4 @@ +* TODO py-max-help-buffer-p * TODO py-beginning-of-elif * TODO py-execute-python-mode-v5 returns position, now result use orig diff --git a/devel/python-mode-utils.el b/devel/python-mode-utils.el index a28d2595..00b4dd02 100644 --- a/devel/python-mode-utils.el +++ b/devel/python-mode-utils.el @@ -194,6 +194,37 @@ ;;; python-components-exec-forms.el ends here\n ") (emacs-lisp-mode)) +(defun write-fast-execute-forms (&optional command) + "Write `py-process-block...' etc. " + (interactive) + (let ((py-bounds-command-names (if command (list command) py-execute-forms-names))) + (set-buffer (get-buffer-create "python-components-fast-forms.el")) + (erase-buffer) + (switch-to-buffer (current-buffer)) + (insert ";;; python-components-fast-forms.el --- Execute forms at point\n") + (insert arkopf) + (insert ";;; Process forms fast\n\n") + (dolist (ele py-bounds-command-names) + (insert (concat "(defun py-execute-" ele "-fast ()")) + (insert (concat " + \"Process " ele " at point by a Python interpreter. + +Suitable for large output, doesn't mess up interactive shell. +Result arrives in `py-output-buffer', which is not in +comint-mode\"\n")) + (insert (concat " (interactive) + (let ((py-fast-process-p t) + (beg (prog1 + (or (py-beginning-of-" ele "-p) + (save-excursion + (py-beginning-of-" ele "))))) + (end (save-excursion + (py-end-of-" ele")))) + (py-execute-region beg end)))\n\n")))) + (insert "(provide 'python-components-fast-forms) +;;; python-components-fast-forms.el ends here\n ") + (emacs-lisp-mode)) + (defun write-options-dokumentation-subform (pyo) (cond ((string-match "dedicated" pyo) (insert "\n\nUses a dedicated shell."))) diff --git a/python-components-edit.el b/python-components-edit.el index 66eb79d6..219f467a 100644 --- a/python-components-edit.el +++ b/python-components-edit.el @@ -84,9 +84,7 @@ With optional \\[universal-argument] an indent with length `py-indent-offset' is (forward-line 1) (beginning-of-line) (delete-region (point) (progn (skip-chars-forward " \t\r\n\f") (point))) - (indent-to (py-compute-indentation)))))) - ;; (exchange-point-and-mark) - ) + (indent-to (py-compute-indentation))))))) (defun py--indent-line-intern (need cui py-indent-offset col &optional beg end region) (if py-tab-indent @@ -125,8 +123,6 @@ With optional \\[universal-argument] an indent with length `py-indent-offset' is (t (if (and py-tab-shifts-region-p region) (progn - ;; (when (eq (point) (region-end)) - ;; (exchange-point-and-mark)) (while (< (current-indentation) need) (py-shift-region-right 1))) (beginning-of-line) @@ -416,111 +412,6 @@ downwards from beginning of block followed by a statement. Otherwise default-val (when (interactive-p) (message "%s" py-indent-offset)) py-indent-offset))) -;; (defun py-guess-indent-offset (&optional global orig origline) -;; "Guess a value for, and change, `py-indent-offset'. -;; -;; By default, make a buffer-local copy of `py-indent-offset' with the -;; new value. -;; With optional argument GLOBAL change the global value of `py-indent-offset'. -;; -;; Returns `py-indent-offset'" -;; (interactive "P") -;; (save-excursion -;; (let* ((orig (or orig (point))) -;; (origline (or origline (py-count-lines))) -;; last down done firstindent secondindent -;; (count 0) -;; guessed) -;; (back-to-indentation) -;; (when (looking-at py-block-closing-keywords-re) -;; (setq count (1+ count))) -;; (skip-chars-backward " \t\r\n\f") -;; (back-to-indentation) -;; (when (looking-at py-block-closing-keywords-re) -;; (setq count (1+ count))) -;; (when (< 0 count) -;; (while (and (< 0 count)(re-search-backward py-block-re nil t 1) -;; (or -;; (nth 8 (parse-partial-sexp (point-min) (point))) -;; (progn (setq count (1- count)) t)))) -;; (setq firstindent (current-indentation))) -;; (unless firstindent -;; (setq firstindent -;; (cond ((and (py-beginning-of-statement-p) (looking-at py-extended-block-or-clause-re)) -;; (current-indentation)) -;; ((and (py-beginning-of-statement-p)(looking-at py-block-closing-keywords-re)) -;; (while (and (re-search-backward py-extended-block-or-clause-re nil t 1)(nth 8 (syntax-ppss)))) -;; ;; (py-beginning-of-statement) -;; (when (py-beginning-of-statement-p) (current-indentation))) -;; ((and (py-beginning-of-statement)(looking-at py-extended-block-or-clause-re)) -;; (current-indentation)) -;; (t (while (and (setq last (py-beginning-of-statement))(not (looking-at py-extended-block-or-clause-re)))) -;; (if last -;; (progn -;; (setq last (point)) -;; (setq down t) -;; (current-indentation)) -;; (if (and (goto-char orig) -;; (py-end-of-statement) -;; (py-end-of-statement) -;; (py-beginning-of-statement) -;; (looking-at py-extended-block-or-clause-re)) -;; -;; (prog1 -;; (current-indentation) -;; (setq last (point)) -;; (goto-char orig)) -;; (while (and (setq last (py-down-statement))(not (looking-at py-extended-block-or-clause-re))) -;; (if last -;; (progn (setq last (point)) -;; (setq down t) -;; (current-column)) -;; ;; if nothing suitable around, us default -;; (setq done t) -;; (default-value 'py-indent-offset))))))))) -;; (setq secondindent -;; (unless done -;; (if (and firstindent (numberp firstindent)) -;; ;; let's look if inside a clause -;; (cond ((and -;; ;; (goto-char orig) -;; (not (eobp))(py-end-of-statement)(py-end-of-statement)(setq last (point)) -;; (save-excursion (< firstindent (progn (py-beginning-of-statement)(current-indentation)))) -;; (py-end-of-statement-p)) -;; (py-beginning-of-statement) (current-indentation)) -;; (t (if (progn (setq orig (point)) (while (and (py-beginning-of-statement)(>= firstindent (current-indentation)) (setq last (point)) (not (looking-at py-extended-block-or-clause-re)))) last) -;; (current-indentation) -;; (goto-char orig) -;; (while (and (not (eobp))(py-end-of-statement)(setq last (point)) -;; (save-excursion (or (>= firstindent (progn (py-beginning-of-statement)(current-indentation)))(eq last (line-beginning-position)))) -;; (py-end-of-statement-p))) -;; (when last (py-beginning-of-statement) (current-indentation)))))))) -;; (unless (or done secondindent) -;; (setq secondindent -;; (when (and (py-end-of-statement) -;; (py-end-of-statement) -;; (py-beginning-of-statement)) -;; (current-indentation)))) -;; (when (and secondindent (numberp secondindent) (numberp firstindent)) -;; (when (eq 0 (abs (- secondindent firstindent))) -;; (when (if (py-beginning-of-statement) (< (current-indentation) secondindent)) -;; (setq secondindent (current-indentation)))) -;; (setq guessed -;; (abs (- secondindent firstindent))) -;; (when (and (eq 0 guessed)(not (eq 0 secondindent))) -;; (setq guessed secondindent))) -;; (if (and guessed (py-guessed-sanity-check guessed)) -;; (setq py-indent-offset guessed) -;; (setq py-indent-offset (default-value 'py-indent-offset))) -;; (funcall (if global 'kill-local-variable 'make-local-variable) -;; 'py-indent-offset) -;; (when (and py-verbose-p (interactive-p)) -;; (message "%s value of py-indent-offset: %d" -;; (if global "Global" "Local") -;; py-indent-offset)) -;; py-indent-offset)) - ;; ) - (defun py-comment-indent-function () "Python version of `comment-indent-function'." ;; This is required when filladapt is turned off. Without it, when @@ -556,17 +447,6 @@ The defun visible is the one that contains point or follows point. " (when (and py-verbose-p (interactive-p)) (message "%s" erg)) erg)) -;; (defun py-beginning-of-paragraph () -;; "Go to beginning of paragraph. -;; -;; Consider a string starting at current indentation as beginning too " -;; (interactive) -;; (let* ((pps (syntax-ppss)) -;; (erg (and (nth 3 pps)(nth 8 pps)))) -;; (if (and erg (progn (back-to-indentation) (looking-at "\"\"\"\\|'''\\|\"\\|'"))) -;; erg -;; (backward-paragraph)))) - ;; (defalias 'py-end-of-paragraph 'forward-paragraph) (defun py-end-of-paragraph () (interactive) diff --git a/python-components-exec-forms.el b/python-components-exec-forms.el index 1e806805..f3117f5e 100644 --- a/python-components-exec-forms.el +++ b/python-components-exec-forms.el @@ -1,5 +1,6 @@ ;;; python-components-exec-forms.el --- Execute forms at point +;; Copyright (C) 2011-2014 Andreas Roehler ;; Author: Andreas Roehler ;; Keywords: languages, convenience @@ -21,116 +22,56 @@ ;;; Code: ;;; Execute forms at point - (defun py-execute-statement () "Send statement at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-statement-p) - (save-excursion - (py-beginning-of-statement))))) - (end (save-excursion - (py-end-of-statement)))) - (py-execute-region beg end))) + (py-execute-prepare "statement")) (defun py-execute-block () "Send block at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-block-p) - (save-excursion - (py-beginning-of-block))))) - (end (save-excursion - (py-end-of-block)))) - (py-execute-region beg end))) + (py-execute-prepare "block")) (defun py-execute-block-or-clause () "Send block-or-clause at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-block-or-clause-p) - (save-excursion - (py-beginning-of-block-or-clause))))) - (end (save-excursion - (py-end-of-block-or-clause)))) - (py-execute-region beg end))) + (py-execute-prepare "block-or-clause")) (defun py-execute-def () "Send def at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-def-p) - (save-excursion - (py-beginning-of-def))))) - (end (save-excursion - (py-end-of-def)))) - (py-execute-region beg end))) + (py-execute-prepare "def")) (defun py-execute-class () "Send class at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-class-p) - (save-excursion - (py-beginning-of-class))))) - (end (save-excursion - (py-end-of-class)))) - (py-execute-region beg end))) + (py-execute-prepare "class")) (defun py-execute-def-or-class () "Send def-or-class at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-def-or-class-p) - (save-excursion - (py-beginning-of-def-or-class))))) - (end (save-excursion - (py-end-of-def-or-class)))) - (py-execute-region beg end))) + (py-execute-prepare "def-or-class")) (defun py-execute-expression () "Send expression at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-expression-p) - (save-excursion - (py-beginning-of-expression))))) - (end (save-excursion - (py-end-of-expression)))) - (py-execute-region beg end))) + (py-execute-prepare "expression")) (defun py-execute-partial-expression () "Send partial-expression at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-partial-expression-p) - (save-excursion - (py-beginning-of-partial-expression))))) - (end (save-excursion - (py-end-of-partial-expression)))) - (py-execute-region beg end))) + (py-execute-prepare "partial-expression")) (defun py-execute-top-level () "Send top-level at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-top-level-p) - (save-excursion - (py-beginning-of-top-level))))) - (end (save-excursion - (py-end-of-top-level)))) - (py-execute-region beg end))) + (py-execute-prepare "top-level")) (defun py-execute-clause () "Send clause at point to a Python interpreter. " (interactive) - (let ((beg (prog1 - (or (py-beginning-of-clause-p) - (save-excursion - (py-beginning-of-clause))))) - (end (save-excursion - (py-end-of-clause)))) - (py-execute-region beg end))) + (py-execute-prepare "clause")) (provide 'python-components-exec-forms) ;;; python-components-exec-forms.el ends here + diff --git a/python-components-execute.el b/python-components-execute.el index 8395d1d2..33974fa3 100644 --- a/python-components-execute.el +++ b/python-components-execute.el @@ -331,10 +331,10 @@ interpreter. (unless (string-match "^\*" erg)(setq erg (concat "*" erg "*"))) erg)) -(defun py-buffer-name-prepare () +(defun py-buffer-name-prepare (&optional name) "Return an appropriate name to display in modeline. SEPCHAR is the file-path separator of your system. " - (let ((name (capitalize py-shell-name)) + (let ((name (or name (capitalize py-shell-name))) prefix erg suffix liste) (when (string-match py-separator-char name) (unless py-modeline-acronym-display-home-p @@ -367,7 +367,7 @@ SEPCHAR is the file-path separator of your system. " (prefix (setq erg (concat "*" prefix " " erg "*"))) - (t (setq erg (concat "*" erg "*")))) + (t (unless (string-match "^\*" erg)(setq erg (concat "*" erg "*"))))) erg)) (defun py-delete-numbers-and-stars-from-string (string) @@ -386,7 +386,7 @@ Needed when file-path names are contructed from maybe numbered buffer names like ;; (message "%s" (current-buffer)) (goto-char (point-min)) (forward-line (1- origline)) - (switch-to-buffer (current-buffer)) +;; (switch-to-buffer (current-buffer)) (push-mark) (and (search-forward action (line-end-position) t) (and py-verbose-p (message "Exception in file %s on line %d" py-exception-buffer origline)) @@ -415,7 +415,7 @@ Needed when file-path names are contructed from maybe numbered buffer names like (py-jump-to-exception-intern action (get-buffer (file-name-nondirectory file)))) ((buffer-live-p (get-buffer file)) (set-buffer file) - (switch-to-buffer (current-buffer)) +;; (switch-to-buffer (current-buffer)) (py-jump-to-exception-intern action file)) (t (setq file (find-file (read-file-name "Exception file: " nil @@ -490,6 +490,21 @@ Internal use" (py-restore-window-configuration)))) nil) +(defun py-kill-shell-unconditional (&optional shell) + "With optional argument SHELL. + +Otherwise kill default (I)Python shell. +Kill buffer and its process. +Receives a buffer-name as argument" + (interactive) + (let ((shell (or shell (py-shell)))) + (py-kill-buffer-unconditional shell))) + +(defun py-kill-default-shell-unconditional () + "Kill buffer \"\*Python\*\" and its process. " + (interactive) + (py-kill-buffer-unconditional "*Python*")) + (defun py-report-executable (py-buffer-name) (let ((erg (downcase (replace-regexp-in-string "<\\([0-9]+\\)>" "" @@ -585,6 +600,32 @@ Internal use" (remove-hook 'comint-output-filter-functions 'python-pdbtrack-track-stack-file t)) (set-syntax-table python-mode-syntax-table)) +(defun py--guess-buffer-name () + "Guess the buffer-name core string. " + (cond + ((and py-fast-process-p (not py-dedicated-process-p)) py-output-buffer) + (buffer-name) + (t (and (not dedicated) argprompt + (cond + ((eq 4 (prefix-numeric-value argprompt)) + (prog1 + (read-buffer "Py-Shell buffer: " + (generate-new-buffer-name (py-buffer-name-prepare))) + (when (file-remote-p default-directory) + ;; It must be possible to declare a local default-directory. + (setq default-directory + (expand-file-name + (read-file-name + "Default directory: " default-directory default-directory + t nil 'file-directory-p))) + (setq py-separator-char (py-separator-char))))) + ((and (eq 2 (prefix-numeric-value argprompt)) + (fboundp 'split-string)) + (setq args (split-string + (read-string "Py-Shell arguments: " + (concat + (mapconcat 'identity py-python-command-args " ") " ")))))))))) + (defun py-shell (&optional argprompt dedicated shell buffer-name no-window-managment) "Start an interactive Python interpreter in another window. Interactively, \\[universal-argument] 4 prompts for a buffer. @@ -600,37 +641,17 @@ When DONE is `t', `py-shell-manage-windows' is omitted (interactive "P") (setenv "PAGER" "cat") (setenv "TERM" "dumb") - (let* ((dedicated (or dedicated py-dedicated-process-p)) + (let* ((py-fast-process-p (when (not (interactive-p)) py-fast-process-p)) + (dedicated (or dedicated py-dedicated-process-p)) (py-exception-buffer (or py-exception-buffer (current-buffer))) ;; (coding-system-for-read 'utf-8) ;; (coding-system-for-write 'utf-8) (path (getenv "PYTHONPATH")) (py-shell-name (or shell py-shell-name (py-choose-shell))) - (args (if (string-match "^[Ii]" py-shell-name) py-ipython-command-args py-python-command-args)) - - ;; reset later on - (py-buffer-name - (cond (buffer-name) - (t (and (not dedicated) argprompt - (cond - ((eq 4 (prefix-numeric-value argprompt)) - (prog1 - (read-buffer "Py-Shell buffer: " - (generate-new-buffer-name (py-buffer-name-prepare))) - (when (file-remote-p default-directory) - ;; It must be possible to declare a local default-directory. - (setq default-directory - (expand-file-name - (read-file-name - "Default directory: " default-directory default-directory - t nil 'file-directory-p))) - (setq py-separator-char (py-separator-char))))) - ((and (eq 2 (prefix-numeric-value argprompt)) - (fboundp 'split-string)) - (setq args (split-string - (read-string "Py-Shell arguments: " - (concat - (mapconcat 'identity py-python-command-args " ") " ")))))))))) + (args + (cond (py-fast-process-p nil) + ((string-match "^[Ii]" py-shell-name) py-ipython-command-args) + (t py-python-command-args))) ;; If we use a pipe, Unicode characters are not printed ;; correctly (Bug#5794) and IPython does not work at ;; all (Bug#5390). python.el @@ -641,6 +662,7 @@ When DONE is `t', `py-shell-manage-windows' is omitted (expand-file-name py-shell-local-path) (when py-use-local-default (error "Abort: `py-use-local-default' is set to `t' but `py-shell-local-path' is empty. Maybe call `py-toggle-local-default-use'")))) + (py-buffer-name (py--guess-buffer-name)) (py-buffer-name (or py-buffer-name (py-buffer-name-prepare))) (executable (cond (py-shell-name) (py-buffer-name @@ -649,16 +671,19 @@ When DONE is `t', `py-shell-manage-windows' is omitted ;; lp:1169687, if called from within an existing py-shell, open a new one (and (bufferp py-exception-buffer)(string= py-buffer-name (buffer-name py-exception-buffer)) (setq py-buffer-name (generate-new-buffer-name py-buffer-name))) - - (unless (comint-check-proc py-buffer-name) - (py--shell-make-comint) - (py--shell-setup (get-buffer-process (current-buffer)))) - ;; (py--init-easy-menu) - ;; (add-hook 'py-shell-hook 'py-dirstack-hook) - (and py-fontify-shell-buffer-p (font-lock-fontify-buffer)) - (goto-char (point-max)) - (unless no-window-managment (py-shell-manage-windows py-buffer-name)) - (when py-shell-hook (run-hooks 'py-shell-hook)) + (if py-fast-process-p + (unless (get-buffer-process (get-buffer py-buffer-name)) + (py-fast-process) + (setq py-output-buffer py-buffer-name)) + (unless (comint-check-proc py-buffer-name) + (py--shell-make-comint) + (py--shell-setup (get-buffer-process (current-buffer)))) + ;; (py--init-easy-menu) + ;; (add-hook 'py-shell-hook 'py-dirstack-hook) + (and py-fontify-shell-buffer-p (font-lock-fontify-buffer)) + (goto-char (point-max)) + (unless no-window-managment (py-shell-manage-windows py-buffer-name)) + (when py-shell-hook (run-hooks 'py-shell-hook))) py-buffer-name)) (defun py-shell-get-process (&optional argprompt py-dedicated-process-p shell switch py-buffer-name) @@ -687,6 +712,24 @@ Per default it's \"(format \"execfile(r'%s') # PYTHON-MODE\\n\" filename)\" for (when (interactive-p) (message "%s" (prin1-to-string cmd))) cmd)) +(defun py--choose-buffer-name () + "Python code might be processed by an +- interactive Python shell (DEFAULT) +- non-interactive Python (py-fast-process-p), select for large + output + +Both processes might run in + +- session, i.e. start from previous state (DEFAULT) +- dedicated, open or follow a separate line of execution + +Default is interactive, i.e. py-fast-process-p nil, and `py-session'" + + (cond ((and py-fast-process-p py-dedicated-process-p) + (py-buffer-name-prepare py-output-buffer)) + (py-fast-process-p py-output-buffer) + (t (py-buffer-name-prepare)))) + (defun py-execute-base (&optional start end shell filename proc file wholebuf) "Select the handler. @@ -715,14 +758,19 @@ When optional FILE is `t', no temporary file is needed. " py-execute-directory) ((getenv "VIRTUAL_ENV")) (t (getenv "HOME")))) - (py-buffer-name (or py-buffer-name (py-buffer-name-prepare))) + (py-buffer-name (py--choose-buffer-name)) (filename (or (and filename (expand-file-name filename)) (and (not (buffer-modified-p)) (buffer-file-name)))) (py-orig-buffer-or-file (or filename (current-buffer))) - (proc (or proc (if py-dedicated-process-p - (get-buffer-process (py-shell nil py-dedicated-process-p py-shell-name py-buffer-name t)) - (or (and (boundp 'py-buffer-name) (get-buffer-process py-buffer-name)) - (get-buffer-process (py-shell nil py-dedicated-process-p py-shell-name (and (boundp 'py-buffer-name) py-buffer-name) t)))))) + (proc (cond (proc) + (py-fast-process-p + (or (get-buffer-process (get-buffer py-buffer-name)) + (py-fast-process py-buffer-name))) + (py-dedicated-process-p + (get-buffer-process (py-shell nil py-dedicated-process-p py-shell-name py-buffer-name t))) + (t (or (and (boundp 'py-buffer-name) (get-buffer-process py-buffer-name)) + (get-buffer-process (py-shell nil py-dedicated-process-p py-shell-name (and (boundp 'py-buffer-name) py-buffer-name) t)))))) err-p) + (and py-debug-p (with-temp-file "/tmp/py-buffer-name.txt" (insert py-buffer-name))) (set-buffer py-exception-buffer) (py-update-execute-directory proc py-buffer-name execute-directory) (cond (;; enforce proceeding as python-mode.el v5 @@ -733,9 +781,7 @@ When optional FILE is `t', no temporary file is needed. " ;; No need for a temporary filename than ((and filename wholebuf) (py-execute-file-base proc filename nil py-buffer-name filename execute-directory)) - (t - ;; (message "%s" (current-buffer)) - (py-execute-buffer-finally start end execute-directory wholebuf))))) + (t (py-execute-buffer-finally start end execute-directory wholebuf))))) (defun py-execute-buffer-finally (start end execute-directory wholebuf) (let* ((strg (buffer-substring-no-properties start end)) @@ -755,14 +801,20 @@ When optional FILE is `t', no temporary file is needed. " "if __name__ == '__main__ ':" strg))) (insert strg) (py-fix-start (point-min)(point-max)) - (set-buffer tempbuf) - (write-region (point-min) (point-max) tempfile nil t nil 'ask) - (set-buffer-modified-p 'nil) - (unwind-protect - (setq erg (py-execute-file-base proc tempfile nil py-buffer-name py-orig-buffer-or-file execute-directory)) - (sit-for 0.1) - (and (or py-debug-p py-cleanup-temporary) - (py-delete-temporary tempfile tempbuf))) + (if py-fast-process-p + (progn + (with-current-buffer py-buffer-name + (erase-buffer)) + (setq strg (buffer-substring-no-properties (point-min) (point-max))) + (py-fast-send-string strg) + (py--postprocess)) + (write-region (point-min) (point-max) tempfile nil t nil 'ask) + (set-buffer-modified-p 'nil) + (unwind-protect + (setq erg (py-execute-file-base proc tempfile nil py-buffer-name py-orig-buffer-or-file execute-directory)) + (sit-for 0.1) + (when py-cleanup-temporary + (py-delete-temporary tempfile tempbuf)))) (and erg (or py-debug-p py-store-result-p) (unless (string= (car kill-ring) erg) (kill-new erg))) erg)) @@ -817,33 +869,38 @@ May we get rid of the temporary file? " (defalias 'py-send-region 'py-execute-region) ;;; execute region - (defun py-execute-region (start end &optional shell dedicated) "Send the region to a Python interpreter. -When called with \\[universal-argument], execution through `default-value' of `py-shell-name' is forced. -When called with \\[universal-argument] followed by a number different from 4 and 1, user is prompted to specify a shell. This might be the name of a system-wide shell or include the path to a virtual environment. +When called with \\[universal-argument], execution through +`default-value' of `py-shell-name' is forced. + +When called with \\[universal-argument] followed by a number +different from 4 and 1, user is prompted to specify a shell. This +might be the name of a system-wide shell or include the path to a +virtual environment. -When called from a programm, it accepts a string specifying a shell which will be forced upon execute as argument. +When called from a programm, it accepts a string specifying a +shell which will be forced upon execute as argument. Optional DEDICATED " (interactive "r\nP") - (let ((orig (point)) - (py-shell-name (cond ((or py-force-py-shell-name-p (eq 4 (prefix-numeric-value shell))) (default-value 'py-shell-name)) - ((and (numberp shell) (not (eq 1 (prefix-numeric-value shell)))) - (read-from-minibuffer "(path-to-)shell-name: " (default-value 'py-shell-name))) - (t shell))) - (py-dedicated-process-p (or dedicated py-dedicated-process-p))) - (py-execute-base start end) -;; (goto-char orig) - )) + (save-excursion + (let ((orig (point)) + (py-shell-name (cond ((or py-force-py-shell-name-p (eq 4 (prefix-numeric-value shell))) (default-value 'py-shell-name)) + ((and (numberp shell) (not (eq 1 (prefix-numeric-value shell)))) + (read-from-minibuffer "(path-to-)shell-name: " (default-value 'py-shell-name))) + (t shell))) + (py-dedicated-process-p (or dedicated py-dedicated-process-p))) + (py-execute-base start end)))) (defun py-execute-region-default (start end) "Send the region to the systems default Python interpreter. " (interactive "r") - (let ((py-dedicated-process-p (default-value 'py-dedicated-process-p)) - (py-shell-name (default-value 'py-shell-name))) - (py-execute-base start end))) + (save-excursion + (let ((py-dedicated-process-p (default-value 'py-dedicated-process-p)) + (py-shell-name (default-value 'py-shell-name))) + (py-execute-base start end)))) (defun py-execute-region-no-switch (start end) "Send the region to a Python interpreter. @@ -857,17 +914,25 @@ Ignores setting of `py-switch-buffers-on-execute-p', buffer with region stays cu (defun py-execute-region-dedicated (start end &optional shell) "Get the region processed by an unique Python interpreter. -When called with \\[universal-argument], execution through `default-value' of `py-shell-name' is forced. -When called with \\[universal-argument] followed by a number different from 4 and 1, user is prompted to specify a shell. This might be the name of a system-wide shell or include the path to a virtual environment. +When called with \\[universal-argument], execution through +`default-value' of `py-shell-name' is forced. + +When called with \\[universal-argument] followed by a number +different from 4 and 1, user is prompted to specify a shell. This +might be the name of a system-wide shell or include the path to a +virtual environment. + +When called from a programm, it accepts a string specifying a +shell which will be forced upon execute as argument. " -When called from a programm, it accepts a string specifying a shell which will be forced upon execute as argument. " (interactive "r\nP") - (let ((py-shell-name (cond ((eq 4 (prefix-numeric-value shell)) (default-value 'py-shell-name)) - ((and (numberp shell) (not (eq 1 (prefix-numeric-value shell)))) - (read-from-minibuffer "(path-to-)shell-name: " (default-value 'py-shell-name))) - (t shell))) - (py-dedicated-process-p t)) - (py-execute-base start end))) + (save-excursion + (let ((py-shell-name (cond ((eq 4 (prefix-numeric-value shell)) (default-value 'py-shell-name)) + ((and (numberp shell) (not (eq 1 (prefix-numeric-value shell)))) + (read-from-minibuffer "(path-to-)shell-name: " (default-value 'py-shell-name))) + (t shell))) + (py-dedicated-process-p t)) + (py-execute-base start end)))) (defun py-execute-region-switch (start end) "Send the region to a Python interpreter. @@ -882,8 +947,9 @@ Ignores setting of `py-switch-buffers-on-execute-p', output-buffer will being sw (defun py-execute-region-default-dedicated (start end) "Send the region to an unique shell of systems default Python. " (interactive "r") - (let ((py-dedicated-process-p t)) - (py-execute-base start end (default-value 'py-shell-name)))) + (save-excursion + (let ((py-dedicated-process-p t)) + (py-execute-base start end (default-value 'py-shell-name))))) (defun py-delete-temporary (&optional file filebuf) (when (file-readable-p file) @@ -953,6 +1019,24 @@ Ignores setting of `py-switch-buffers-on-execute-p', output-buffer will being sw (delete-region orig (point-max))) (set-buffer oldbuf))) +(defun py--postprocess () + "Provide return values, check result for error, manage windows. " + (if + (setq err-p (save-excursion (py-postprocess-output-buffer py-output-buffer))) + (py-shell-manage-windows py-buffer-name nil windows-config) + (when py-fast-process-p + (goto-char (point-min)) + (while (re-search-forward py-shell-prompt-regexp nil t 1) + (replace-match ""))) + (and py-store-result-p + (sit-for 0.1) + (setq erg + (py-output-filter + (buffer-substring-no-properties orig (point-max)))) + (unless (string= (car kill-ring) erg) (kill-new erg))) + (py-shell-manage-windows py-output-buffer nil windows-config) + erg)) + (defun py-execute-file-base (&optional proc filename cmd procbuf origfile execute-directory) "Send to Python interpreter process PROC, in Python version 2.. \"execfile('FILENAME')\". @@ -962,26 +1046,14 @@ comint believe the user typed this string so that Returns position where output starts. " (let* ((cmd (or cmd (format "exec(compile(open('%s').read(), '%s', 'exec')) # PYTHON-MODE\n" filename filename))) (msg (and py-verbose-p (format "## executing %s...\n" (or origfile filename)))) - (procbuf (or procbuf (py-shell nil nil nil procbuf t))) - (proc (or proc (get-buffer-process procbuf))) + (py-output-buffer (or procbuf (py-shell nil nil nil procbuf t))) + (proc (or proc (get-buffer-process py-output-buffer))) erg orig err-p) - (set-buffer procbuf) + (set-buffer py-output-buffer) (goto-char (point-max)) - (switch-to-buffer (current-buffer)) (setq orig (point)) (comint-send-string proc cmd) - (if - (setq err-p (save-excursion (py-postprocess-output-buffer procbuf))) - (py-shell-manage-windows py-buffer-name nil windows-config) - (and py-store-result-p - (sit-for 0.1) - (setq erg - (py-output-filter - (buffer-substring-no-properties orig (point-max)))) - (unless (string= (car kill-ring) erg) (kill-new erg))) - ;; (py-shell-manage-windows (current-buffer) nil windows-config) - (py-shell-manage-windows procbuf nil windows-config) - erg))) + (py--postprocess))) (defun py-execute-string (&optional string shell) "Send the argument STRING to a Python interpreter. @@ -1556,7 +1628,7 @@ Indicate LINE if code wasn't run from a file, thus remember line of source buffe (py-last-exeption-buffer (buffer-name py-last-exeption-buffer)) (t (error "Don't see exeption buffer"))))) (when buffer (set-buffer (get-buffer buffer))) - (switch-to-buffer (current-buffer)) +;; (switch-to-buffer (current-buffer)) (if (eq direction 'up) (if (string= start "TOP") (py-find-next-exception 'bob buffer 're-search-forward "Top") diff --git a/python-components-intern.el b/python-components-intern.el index 88802373..b8b169bb 100644 --- a/python-components-intern.el +++ b/python-components-intern.el @@ -70,6 +70,20 @@ Use `defcustom' to keep value across sessions " (when (interactive-p) (message "%s" erg)) erg)) +(defun py-kill-buffer-unconditional (&optional buffer) + "Kill buffer unconditional, kill buffer-process if existing. " + (interactive) + (let ((buffer (or buffer (current-buffer))) + proc kill-buffer-query-functions) + (if (buffer-live-p buffer) + (progn + (setq proc (get-buffer-process buffer)) + (and proc (kill-process proc)) + (set-buffer buffer) + (set-buffer-modified-p 'nil) + (kill-buffer (current-buffer))) + (and (interactive-p) (message "Can't see a buffer %s" buffer))))) + (defun py-line-backward-maybe () (let ((orig (point))) (skip-chars-backward " \t\f" (line-beginning-position)) @@ -530,7 +544,8 @@ will work. (let ((orig (point)) erg) (save-excursion - (py-end-of-statement) + (unless (and (eolp) (not (empty-line-p))) + (py-end-of-statement)) (py-beginning-of-statement) (when (eq orig (point)) (setq erg orig)) @@ -1047,7 +1062,7 @@ Eval resulting buffer to install it, see customizable `py-extensions'. " erg newshell prefix akt end orig curexe aktpath) (set-buffer (get-buffer-create py-extensions)) (erase-buffer) - (switch-to-buffer (current-buffer)) +;; (switch-to-buffer (current-buffer)) (dolist (elt shells) (setq prefix "") (setq curexe (substring elt (1+ (string-match "/[^/]+$" elt)))) @@ -1121,12 +1136,6 @@ When `py-verbose-p' and MSG is non-nil messages the first line of STRING." (file-name (or filename (buffer-file-name) temp-file-name))) (if (> (length lines) 1) (let* () - ;; ((temporary-file-directory - ;; (if (file-remote-p default-directory) - ;; (concat (file-remote-p default-directory) "/tmp") - ;; temporary-file-directory)) - ;; (temp-file-name (make-temp-file "py")) - ;; (file-name (or (buffer-file-name) temp-file-name))) (with-temp-file temp-file-name (insert string) (delete-trailing-whitespace)) diff --git a/python-components-mode.el b/python-components-mode.el index 2c1c612a..aa8a633b 100644 --- a/python-components-mode.el +++ b/python-components-mode.el @@ -109,6 +109,29 @@ Default is non-nil. If nil, `py-pylint-run' offers filename from history " :type 'boolean :group 'python-mode) +(defcustom py-fast-process-p nil + "Use `py-fast-process'. + +Commands prefixed \"py-fast-...\" suitable for large output + +See: large output makes Emacs freeze, lp:1253907 + +Results arrive in py-output-buffer, which is not in comint-mode" + + :type 'boolean + :group 'python-mode) + +(defcustom py-session-p t + "If commands would use an existing process. + +If nil, a maybe existing process at py-buffer-name would be killed and re-started + +See also `py-dedicated-process-p' +" + + :type 'boolean + :group 'python-mode) + (defcustom py-max-help-buffer-p nil "If \"\*Python-Help\*\"-buffer should appear as the only visible. @@ -163,7 +186,10 @@ Default is `t'" (defcustom py-dedicated-process-p nil "If commands executing code use a dedicated shell. -Default is nil") +Default is nil + +When non-nil and `py-session-p', an existing dedicated process is re-used instead of default - which allows executing stuff in parallel. +") (defcustom py-store-result-p nil "When non-nil, put resulting string of `py-execute-...' into kill-ring, so it might be yanked. @@ -2692,8 +2718,10 @@ See original source: http://pymacs.progiciels-bpi.ca" (require 'python-components-shift-forms) (require 'python-components-execute-file) (require 'python-components-comment) +(require 'python-components-fast) (require 'python-components-forms) (require 'python-components-forms-code) +(require 'python-components-fast-forms) (require 'python-components-auto-fill) (require 'highlight-indentation) @@ -3310,6 +3338,22 @@ Ignores default of `py-switch-buffers-on-execute-p', uses it with value "non-nil ) ) + "-" + + ["Kill shell unconditional" py-kill-shell-unconditional + :help " `py-kill-shell-unconditional' + +With optional argument SHELL\. + +Otherwise kill default (I)Python shell\. +Kill buffer and its process. +Receives a buffer-name as argument "] + + ["Kill default shell unconditional" py-kill-default-shell-unconditional + :help " `py-kill-default-shell-unconditional' + +Kill buffer \"*Python*\" and its process\. "] + ) "-" @@ -5202,6 +5246,18 @@ Toggle flymake-mode running `pyflakespep8' "]) ("Interpreter" + ["Fast process " + (setq py-fast-process-p + (not py-fast-process-p)) + :help "Use `py-fast-process'\. + +Commands prefixed "py-fast-\.\.\." suitable for large output + +See: large output makes Emacs freeze, lp:1253907 + +Results arrive in py-output-buffer, which is not in comint-modeUse `M-x customize-variable' to set it permanently" +:style toggle :selected py-fast-process-p] + ["Run Python shell at start" (setq py-start-run-py-shell (not py-start-run-py-shell)) @@ -6444,6 +6500,11 @@ Shift block-or-clause left. "] ("More" :help "extended edit commands'" + ["Kill buffer unconditional" py-kill-buffer-unconditional + :help " `py-kill-buffer-unconditional' + +Kill buffer unconditional, kill buffer-process if existing\. "] + ["Empty out list backward" py-empty-out-list-backward :help " `py-empty-out-list-backward' Deletes all elements from list before point. "] @@ -7686,25 +7747,6 @@ This is a no-op if `py-check-comint-prompt' returns nil." (prog1 py-preoutput-result (kill-local-variable 'py-preoutput-result))))))) -;;; FFAP support -(defalias 'py-module-path 'py-ffap-module-path) - -(defun py-ffap-module-path (module) - "Function for `ffap-alist' to return path for MODULE." - (let ((process (or - (and (eq major-mode 'inferior-python-mode) - (get-buffer-process (current-buffer))) - (py-shell-get-process)))) - (if (not process) - nil - (let ((module-file - (py-send-string-no-output - (format py-ffap-string-code module) process))) - (when module-file - (substring-no-properties module-file 1 -1)))))) - -(add-hook 'python-mode-hook 'py-set-ffap-form) - ;;;; Modes. ;; pdb tracking is alert once this file is loaded, but takes no action if diff --git a/python-components-move.el b/python-components-move.el index 54b2fc4e..32285f83 100644 --- a/python-components-move.el +++ b/python-components-move.el @@ -965,15 +965,6 @@ From a programm use macro `py-beginning-of-comment' instead " (funcall function) (setq done t) (not (and (eq indent (current-indentation)) (looking-at "try")))))) - ;; ((and (looking-at "\\[: \n\t]")(save-match-data (string-match "else" regexp))) - ;; (setq indent (current-indentation)) - ;; (setq count (1+ count)) - ;; (while - ;; (and - ;; (not (eval stop)) - ;; (funcall function) - ;; (setq done t) - ;; (not (and (eq indent (current-indentation)) (looking-at "try\\|if")))))) ((and (looking-at "\\[: \n\t]")(save-match-data (string-match "else" regexp))) (setq indent (current-indentation)) (setq count (1+ count)) diff --git a/python-components-named-shells.el b/python-components-named-shells.el index 9c7f45fa..b89b6aae 100644 --- a/python-components-named-shells.el +++ b/python-components-named-shells.el @@ -28,7 +28,9 @@ Optional \\[universal-argument] prompts for options to pass to the Python interpreter. See `py-python-command-args'. " (interactive "P") - (py-shell argprompt nil "python")) + (let ((py-fast-process-p + (if (interactive-p) nil py-fast-process-p))) + (py-shell argprompt nil "python"))) (defalias 'iypthon 'ipython) (defun ipython (&optional argprompt) diff --git a/python-components-send.el b/python-components-send.el index cb848cd6..4e281c44 100644 --- a/python-components-send.el +++ b/python-components-send.el @@ -44,7 +44,8 @@ "Clear output buffer from py-shell-input prompt etc. " (interactive "*") (replace-regexp-in-string - (concat "\\(\n\\|" py-shell-input-prompt-1-regexp "\\|" py-shell-input-prompt-2-regexp "\\|" "^In \\[[0-9]+\\]: *" "\\)") "" string)) + (concat "\\(\n\\|" py-shell-input-prompt-1-regexp "\\|" + py-shell-input-prompt-2-regexp "\\|" "^In \\[[0-9]+\\]: *" "\\)") "" string)) (defun py-send-string (string &optional process) "Evaluate STRING in inferior Python process." diff --git a/python-components-shell-complete.el b/python-components-shell-complete.el index 9f2c2d3c..e647197b 100644 --- a/python-components-shell-complete.el +++ b/python-components-shell-complete.el @@ -41,9 +41,7 @@ completions on the current context." input process code)) (completion (when completions (try-completion input completions)))) - ;; (set-buffer oldbuf) (with-current-buffer oldbuf - ;; (goto-char orig) (cond ((eq completion t) (if py-no-completion-calls-dabbrev-expand-p (or (ignore-errors (dabbrev-expand nil))(when py-indent-no-completion-p diff --git a/python-extended-executes.el b/python-extended-executes.el index ed7b6c93..7a91b3aa 100644 --- a/python-extended-executes.el +++ b/python-extended-executes.el @@ -29,7 +29,6 @@ (find-file-noselect filename)))) (set-buffer buffer)))) - (defun py-execute-prepare (form &optional shell dedicated switch beg end file wholebuf) "Used by python-extended-executes ." (save-excursion @@ -41,8 +40,8 @@ (push-mark))))) (end (unless file (or end (funcall (intern-soft (concat "py-end-of-" form)))))) - (py-shell-name (or shell py-shell-name)) - (py-dedicated-process-p dedicated) + ;; (shell (or shell py-shell-name)) + (py-dedicated-process-p (or py-dedicated-process-p dedicated)) (py-switch-buffers-on-execute-p (cond ((eq 'switch switch) t) ((eq 'no-switch switch) diff --git a/test/py-ert-tests.el b/test/py-ert-tests.el index e86bf043..9e8805de 100644 --- a/test/py-ert-tests.el +++ b/test/py-ert-tests.el @@ -23,7 +23,10 @@ ;; (require 'ert) ;; tests are expected to run from directory test -(add-to-list 'load-path default-directory) + +(setq ert-test-default-buffer "*Python*") + +(add-to-list 'load-path default-directory) (require 'python-mode-test) (defmacro py-tests-with-temp-buffer (contents &rest body) @@ -549,24 +552,6 @@ with file(\"roulette-\" + zeit + \".csv\", 'w') as datei: " (should (and (not (py-copy-statement))(string-match "from foo.bar.baz import something" (car kill-ring)))))) -;; (ert-deftest py-ert-execute-runs-full-file-lp-1269855 () -;; (interactive) -;; (py-tests-with-temp-buffer -;; (let (py-switch-buffers-on-execute-p -;; py-split-windows-on-execute-p -;; py-smart-indentation) -;; ;; (switch-to-buffer (buffer-name (current-buffer))) -;; "a = 0 -;; a += 8 -;; a += 1 -;; print(a) -;; " -;; (py-execute-buffer) -;; (goto-char 14) -;; (py-execute-statement) -;; (goto-char 22) -;; (py-execute-statement)))) - (ert-deftest py-ert-abbrevs-changed-lp-1270631 () (interactive) (with-temp-buffer @@ -577,15 +562,6 @@ with file(\"roulette-\" + zeit + \".csv\", 'w') as datei: (python-mode) (should abbrevs-changed))) - -;; (ert-deftest py-ert-toggle-split-on-execute-function () -;; (py-tests-with-temp-buffer -;; "print(123)" -;; (let ((py-split-windows-on-execute-p t)) -;; (py-toggle-split-windows-function) -;; (py-execute-statement) -;; (should (not (one-window-p)))))) - (ert-deftest py-ert-honor-dedent-lp-1280982 () (py-tests-with-temp-buffer "def foo(): @@ -601,10 +577,10 @@ with file(\"roulette-\" + zeit + \".csv\", 'w') as datei: (ert-deftest py-ert-socket-modul-completion-lp-1284141 () (py-tests-with-temp-buffer "import socket" - (let (oldbuf) + (let ((py-debug-p t) + oldbuf) (py-execute-buffer-dedicated) - (set-buffer (py--fetch-first-python-buffer))(goto-char (point-min)) - (message "this-buf: %s" (current-buffer)) + (set-buffer (progn (find-file "/tmp/py-buffer-name.txt")(buffer-substring-no-properties (point-min) (point-max)))) (setq oldbuf (current-buffer)) (goto-char (point-max)) (insert "socket.") @@ -612,11 +588,12 @@ with file(\"roulette-\" + zeit + \".csv\", 'w') as datei: (set-buffer "*Python Completions*") (goto-char (point-min)) (sit-for 0.1) - (and (should (search-forward "socket.")) - (py-kill-buffer-unconditional oldbuf))))) + (prog1 (should (search-forward "socket.")) + (py-kill-buffer-unconditional oldbuf) + (py-kill-buffer-unconditional "py-buffer-name.txt"))))) (ert-deftest fill-paragraph-lp-1286318 () - (let ((fill-column 72)) + (let ((fill-column 72)) (py-tests-with-temp-buffer "# r1416 @@ -630,9 +607,9 @@ def baz(): # The last line of the docstring is longer than fill-column (set to # 78 = for me). Put point on the 'T' in 'This' and hit M-q= . Nothing # happens. -# +# # Another example: -# +# def baz(): \"\"\"Hello there. @@ -646,9 +623,9 @@ def baz(): # All of those lines are shorter than fill-column. Put point anywhere # = in that paragraph and hit M-q. Nothing happens. -# +# # In both cases I would expect to end up with: -# +# def baz(): \"\"\"Hello there. @@ -658,17 +635,17 @@ def baz(): return 7 " (goto-char 49) - (switch-to-buffer (current-buffer)) + (switch-to-buffer (current-buffer)) (fill-paragraph) - (end-of-line) + (end-of-line) (should (eq 72 (current-column))) (goto-char 409) (fill-paragraph) - (end-of-line) + (end-of-line) (should (eq 72 (current-column))) (goto-char 731) (fill-paragraph) - (end-of-line) + (end-of-line) (should (eq 72 (current-column))) ))) @@ -677,52 +654,44 @@ def baz(): (py-tests-with-temp-buffer "print(\"I'm the py-execute-expression-test\")" (py-execute-expression) - (message "%s" (buffer-list)) - (set-buffer (py--fetch-first-python-buffer)) - (goto-char (point-max)) - (and (should (search-backward "py-execute-expression-test" nil t 1)) + (set-buffer ert-test-default-buffer) + (and (should (search-forward "py-execute-expression-test" nil t 1)) (py-kill-buffer-unconditional (current-buffer))))) (ert-deftest py-ert-execute-line-test () (py-tests-with-temp-buffer "print(\"I'm the py-execute-line-test\")" (py-execute-line) - (message "%s" (buffer-list)) - (set-buffer (py--fetch-first-python-buffer)) - (goto-char (point-max)) - (and (should (search-backward "py-execute-line-test" nil t 1)) + (set-buffer ert-test-default-buffer) + (and (should (search-forward "py-execute-line-test" nil t 1)) (py-kill-buffer-unconditional (current-buffer))))) - (ert-deftest py-ert-execute-statement-test () (py-tests-with-temp-buffer "print(\"I'm the py-execute-statement-test\")" (py-execute-statement) - (message "%s" (buffer-list)) - (set-buffer (py--fetch-first-python-buffer)) - (goto-char (point-max)) - (and (should (search-backward "py-execute-statement-test" nil t 1)) + (set-buffer ert-test-default-buffer) + (and (should (search-forward "py-execute-statement-test" nil t 1)) (py-kill-buffer-unconditional (current-buffer))))) (ert-deftest py-ert-execute-statement-python2-test () (py-tests-with-temp-buffer "print(\"I'm the py-execute-statement-python2-test\")" (py-execute-statement-python2) - (set-buffer (py--fetch-first-python-buffer)) - (goto-char (point-max)) - (and (should (search-backward "py-execute-statement-python2-test" nil t 1)) + (set-buffer "*Python2*") + (and (should (search-forward "py-execute-statement-python2-test" nil t 1)) (py-kill-buffer-unconditional (current-buffer))))) (ert-deftest py-ert-execute-statement-python3-dedicated-test () (py-tests-with-temp-buffer "print(\"I'm the py-execute-statement-python3-dedicated-test\")" - (py-execute-statement-python3-dedicated) - (set-buffer (py--fetch-first-python-buffer)) - (message "%s" (current-buffer)) - (goto-char (point-min)) - (sit-for 1) - (and (should (search-forward "py-execute-statement-python3-dedicated-test" nil t 1)) - (py-kill-buffer-unconditional (current-buffer))))) + (let ((py-debug-p t)) + (py-execute-statement-python3-dedicated) + (set-buffer (progn (find-file "/tmp/py-buffer-name.txt")(buffer-substring-no-properties (point-min) (point-max)))) + (prog1 (should (search-forward "py-execute-statement-python3-dedicated-test" nil t 1)) + (py-kill-buffer-unconditional (current-buffer)) + (py-kill-buffer-unconditional (get-buffer "py-buffer-name.txt")) + )))) (ert-deftest py-ert-execute-statement-split () (py-tests-with-temp-buffer @@ -741,9 +710,32 @@ def baz(): (insert "import os;print(os.get") (py-shell-complete)) -;; py-execute-buffer -;; --funcall py-execute-expression-test \ -;; --funcall py-execute-line-test \ -;; \ +(ert-deftest py-ert-execute-statement-fast () + (py-tests-with-temp-buffer + "print(1)" + (let ((py-fast-process-p t)) + (py-execute-statement) + (set-buffer py-output-buffer) + (eq 1 (char-after))))) + +(ert-deftest py-ert-execute-block-fast () + (py-tests-with-temp-buffer + "if True: + a = 1 + print(a)" + (let ((py-fast-process-p t)) + (py-execute-block) + (set-buffer py-output-buffer) + (eq 1 (char-after))))) + +(ert-deftest py-ert-execute-block-fast-2 () + (py-tests-with-temp-buffer + "if True: + a += 1 + print(a)" + (let ((py-fast-process-p t)) + (py-execute-block) + (set-buffer py-output-buffer) + (eq 2 (char-after))))) (provide 'py-ert-tests) diff --git a/test/python-mode-test.el b/test/python-mode-test.el index 76e6b387..3739f131 100644 --- a/test/python-mode-test.el +++ b/test/python-mode-test.el @@ -25,21 +25,6 @@ ;;; Code: (require 'py-bug-numbered-tests) - -(defun py-kill-buffer-unconditional (&optional buffer) - "Kill buffer unconditional, kill buffer-process if existing. - -Sometimes being queried sucks... -Used by tests" - (interactive) - (let ((proc (get-buffer-process (or buffer (current-buffer)))) - kill-buffer-query-functions) - (and proc (kill-process proc)) - (when buffer - (set-buffer buffer)) - (set-buffer-modified-p 'nil) - (kill-buffer (current-buffer)))) - (defvar py-variables (list 'py-version 'python-mode-modeline-display 'py-indent-offset 'pdb-path 'py-verbose-p 'py-load-pymacs-p 'py-smart-operator-mode-p 'py-sexp-function 'py-autopair-mode 'py-no-completion-calls-dabbrev-expand-p 'py-indent-no-completion-p 'py-fontify-shell-buffer-p 'py-modeline-display-full-path-p 'py-modeline-acronym-display-home-p 'py-install-directory 'py-guess-py-install-directory-p 'py-extensions 'py-hide-show-minor-mode-p 'empty-comment-line-separates-paragraph-p 'py-org-cycle-p 'ipython-complete-use-separate-shell-p 'py-outline-minor-mode-p 'py-outline-mode-keywords 'py-start-run-py-shell 'py-start-run-ipython-shell 'py-close-provides-newline 'py-dedent-keep-relative-column 'py-indent-honors-inline-comment 'py-closing-list-dedents-bos 'py-electric-colon-active-p 'py-electric-colon-greedy-p 'py-electric-colon-newline-and-indent-p 'py-electric-comment-p 'py-electric-comment-add-space-p 'py-mark-decorators 'py-tab-indent 'py-complete-function 'py-encoding-string 'py-shebang-startstring 'py-python-command-args 'py-jython-command-args 'py-cleanup-temporary 'py-lhs-inbound-indent 'py-continuation-offset 'py-indent-tabs-mode 'py-smart-indentation 'py-block-comment-prefix 'py-indent-comments 'py-separator-char 'py-custom-temp-directory 'py-jump-on-exception 'py-ask-about-save 'py-pdbtrack-do-tracking-p 'py-pdbtrack-filename-mapping 'py-pdbtrack-minor-mode-string 'py-import-check-point-max 'py-jython-packages 'py-current-defun-show 'py-current-defun-delay 'py-honor-IPYTHONDIR-p 'py-ipython-history 'py-honor-PYTHONHISTORY-p 'py-master-file 'py-pychecker-command 'py-pychecker-command-args 'py-pep8-command 'py-pep8-command-args 'py-pyflakespep8-command 'py-pep8-command 'py-pep8-command-args 'py-pyflakespep8-command-args 'py-pyflakes-command 'py-pyflakes-command-args 'py-pep8-command-args 'py-pylint-command 'py-pylint-command-args 'py-shell-input-prompt-1-regexp 'py-shell-input-prompt-2-regexp 'py-shell-prompt-read-only 'py-switch-buffers-on-execute-p 'py-split-windows-on-execute-p 'py-max-split-windows 'py-split-windows-on-execute-function 'py-hide-show-keywords 'py-hide-show-hide-docstrings 'python-mode-hook 'py-imenu-create-index-p 'py-imenu-create-index-function 'py-shell-name 'py-shell-toggle-1 'py-shell-toggle-2 'py-match-paren-mode 'py-kill-empty-line 'py-remove-cwd-from-path 'py-imenu-show-method-args-p 'py-history-filter-regexp 'py-use-local-default 'py-shell-local-path 'py-underscore-word-syntax-p 'py-edit-only-p 'py-force-py-shell-name-p 'python-mode-v5-behavior-p 'py-trailing-whitespace-smart-delete-p 'py-warn-tmp-files-left-p 'py-ipython-execute-delay 'strip-chars-before 'strip-chars-after 'py-fill-docstring-style 'py-number-face 'py-XXX-tag-face 'py-pseudo-keyword-face 'py-variable-name-face 'py-decorators-face 'py-builtins-face 'py-class-name-face 'py-exception-name-face 'python-mode-message-string 'py-local-command 'py-local-versioned-command 'py-shell-complete-debug 'py-encoding-string-re 'symbol-definition-start-re 'symbol-definition-start-re 'py-shebang-regexp 'py-separator-char 'py-temp-directory 'py-exec-command 'py-exec-string-command 'py-which-bufname 'py-pychecker-history 'py-pep8-history 'py-pyflakespep8-history 'py-pyflakes-history 'py-pylint-history 'ipython-de-input-prompt-regexp 'ipython-de-input-prompt-regexp 'ipython-de-output-prompt-regexp 'py-force-local-shell-p 'python-mode-v5-behavior 'python--prompt-regexp 'py-bol-forms-last-indent 'python-mode-syntax-table 'outline-heading-end-regexp 'eldoc-documentation-function 'py-completion-last-window-configuration 'ipython-version 'py-shell-template 'py-imports 'py-execute-directory 'py-use-current-dir-when-execute-p 'py-exception-buffer 'py-output-buffer 'py-string-delim-re 'py-labelled-re 'py-expression-skip-regexp 'py-expression-skip-chars 'py-expression-looking-re 'py-not-expression-regexp 'py-not-expression-chars 'py-not-expression-chars 'py-partial-expression-skip-chars 'py-partial-expression-forward-regexp 'py-partial-expression-skip-backward-chars 'py-not-partial-expression-skip-chars 'py-partial-expression-looking-regexp 'py-not-partial-expression-regexp 'py-operator-regexp 'py-assignment-regexp 'py-delimiter-regexp 'py-delimiter-chars 'py-line-number-offset 'match-paren-no-use-syntax-pps 'py-traceback-line-re 'py-traceback-line-re 'python-preoutput-result 'python-preoutput-leftover 'python-preoutput-skip-next-prompt 'py-mode-syntax-table 'py-file-queue 'python-mode-abbrev-table 'inferior-python-mode-abbrev-table 'py-pdbtrack-input-prompt 'py-pydbtrack-input-prompt 'py-pdbtrack-is-tracking-p 'py-shell-map 'py-font-lock-keywords 'py-dotted-expression-syntax-table 'jython-mode-hook 'py-shell-hook 'ipython-completion-command-string 'ipython0.10-completion-command-string 'ipython0.11-completion-command-string 'py-last-exeption-buffer 'python-preoutput-result 'py-imenu-class-regexp 'py-imenu-method-regexp 'py-imenu-method-no-arg-parens 'py-imenu-method-arg-parens 'py-imenu-generic-expression 'py-imenu-generic-regexp 'py-imenu-generic-parens 'py-mode-output-map 'py-menu 'py-already-guessed-indent-offset 'python-mode-map 'skeleton-further-elements 'virtualenv-workon-home 'virtualenv-name 'python-mode-syntax-table 'python-dotty-syntax-table 'py-shell-template 'py-blank-or-comment-re 'py-block-closing-keywords-re 'py-finally-re 'py-except-re 'py-else-re 'py-no-outdent-re 'py-assignment-re 'py-block-re 'py-minor-block-re 'py-try-block-re 'py-class-re 'py-def-or-class-re 'py-def-re 'py-block-or-clause-re 'py-extended-block-or-clause-re 'py-clause-re 'py-elif-re 'py-if-re 'py-try-re 'py-mode-syntax-table 'py-pdbtrack-stack-entry-regexp 'py-pdbtrack-input-prompt 'py-pydbtrack-input-prompt 'py-pdbtrack-marker-regexp-file-group 'py-pdbtrack-marker-regexp-line-group 'py-pdbtrack-marker-regexp-funcname-group 'py-pdbtrack-track-range 'python-compilation-regexp-alist 'py-font-lock-syntactic-keywords 'virtualenv-name ) "Used for bug-tracking by `py-list-settings'") @@ -2398,8 +2383,6 @@ else: (assert (and (re-search-backward py-shell-prompt-regexp nil t 2) (search-forward "line 5")) nil "py-execute-statement-error-test failed")) - - (defun beginning-of-block-fails-from-wrong-indent-test (&optional arg) (interactive "p") (let ((teststring "#! /usr/bin/env python diff --git a/test/python-mode-tests.sh b/test/python-mode-tests.sh index 76e2b745..1e0b036b 100755 --- a/test/python-mode-tests.sh +++ b/test/python-mode-tests.sh @@ -1135,16 +1135,12 @@ $EMACS -Q --batch --eval "(message (emacs-version))" --eval "(when (featurep 'py --funcall filename-completion-fails-in-ipython-lp-1027265-n2-test \ --funcall master-file-not-honored-lp:794850-test \ --funcall tab-results-in-never-ending-process-lp-1163423-test \ ---funcall C-c-C-c-lp:1221310-and-store-result-test \ --funcall completion-at-gentoo-lp-1008842-test \ --funcall incorrect-use-of-region-in-py-shift-left-lp:875951-test \ --funcall py-end-of-block-test \ ---funcall inconvenient-window-splitting-behavior-python-lp-1018996-test \ --funcall not-that-useful-completion-lp:1003580-test \ --funcall several-new-bugs-with-paragraph-filling-lp-1066489-test \ --funcall py-shell-in-a-shell-buffer-doesnt-work-lp:1182696-test \ ---funcall IndentationError-expected-an-indented-block-when-execute-lp-1055569-test \ -\ --funcall py-execute-region-python2.7-switch-test \ --funcall execute-indented-code-lp:828314-test \ --funcall py-shell-invoking-python3-lp:835151-test \ @@ -1414,3 +1410,6 @@ $EMACS -Q --batch --eval "(message (emacs-version))" --eval "(when (featurep 'py --funcall py-electric-comment-add-space-t-lp:828398-test \ --funcall missing-py-variable-name-face-lp-1215791-test \ --funcall switch-windows-on-execute-p-test \ +--funcall C-c-C-c-lp:1221310-and-store-result-test \ +--funcall inconvenient-window-splitting-behavior-python-lp-1018996-test \ +--funcall IndentationError-expected-an-indented-block-when-execute-lp-1055569-test \