]> code.delx.au - gnu-emacs/blob - test/automated/python-tests.el
; Remove extraneous "coding: utf-8" specifications in Elisp files
[gnu-emacs] / test / automated / python-tests.el
1 ;;; python-tests.el --- Test suite for python.el
2
3 ;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
4
5 ;; This file is part of GNU Emacs.
6
7 ;; GNU Emacs is free software: you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
11
12 ;; GNU Emacs is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19
20 ;;; Commentary:
21
22 ;;; Code:
23
24 (require 'ert)
25 (require 'python)
26
27 ;; Dependencies for testing:
28 (require 'electric)
29 (require 'hideshow)
30 (require 'tramp-sh)
31
32
33 (defmacro python-tests-with-temp-buffer (contents &rest body)
34 "Create a `python-mode' enabled temp buffer with CONTENTS.
35 BODY is code to be executed within the temp buffer. Point is
36 always located at the beginning of buffer."
37 (declare (indent 1) (debug t))
38 `(with-temp-buffer
39 (python-mode)
40 (insert ,contents)
41 (goto-char (point-min))
42 ,@body))
43
44 (defmacro python-tests-with-temp-file (contents &rest body)
45 "Create a `python-mode' enabled file with CONTENTS.
46 BODY is code to be executed within the temp buffer. Point is
47 always located at the beginning of buffer."
48 (declare (indent 1) (debug t))
49 ;; temp-file never actually used for anything?
50 `(let* ((temp-file (make-temp-file "python-tests" nil ".py"))
51 (buffer (find-file-noselect temp-file)))
52 (unwind-protect
53 (with-current-buffer buffer
54 (python-mode)
55 (insert ,contents)
56 (goto-char (point-min))
57 ,@body)
58 (and buffer (kill-buffer buffer))
59 (delete-file temp-file))))
60
61 (defun python-tests-look-at (string &optional num restore-point)
62 "Move point at beginning of STRING in the current buffer.
63 Optional argument NUM defaults to 1 and is an integer indicating
64 how many occurrences must be found, when positive the search is
65 done forwards, otherwise backwards. When RESTORE-POINT is
66 non-nil the point is not moved but the position found is still
67 returned. When searching forward and point is already looking at
68 STRING, it is skipped so the next STRING occurrence is selected."
69 (let* ((num (or num 1))
70 (starting-point (point))
71 (string (regexp-quote string))
72 (search-fn (if (> num 0) #'re-search-forward #'re-search-backward))
73 (deinc-fn (if (> num 0) #'1- #'1+))
74 (found-point))
75 (prog2
76 (catch 'exit
77 (while (not (= num 0))
78 (when (and (> num 0)
79 (looking-at string))
80 ;; Moving forward and already looking at STRING, skip it.
81 (forward-char (length (match-string-no-properties 0))))
82 (and (not (funcall search-fn string nil t))
83 (throw 'exit t))
84 (when (> num 0)
85 ;; `re-search-forward' leaves point at the end of the
86 ;; occurrence, move back so point is at the beginning
87 ;; instead.
88 (forward-char (- (length (match-string-no-properties 0)))))
89 (setq
90 num (funcall deinc-fn num)
91 found-point (point))))
92 found-point
93 (and restore-point (goto-char starting-point)))))
94
95 (defun python-tests-self-insert (char-or-str)
96 "Call `self-insert-command' for chars in CHAR-OR-STR."
97 (let ((chars
98 (cond
99 ((characterp char-or-str)
100 (list char-or-str))
101 ((stringp char-or-str)
102 (string-to-list char-or-str))
103 ((not
104 (cl-remove-if #'characterp char-or-str))
105 char-or-str)
106 (t (error "CHAR-OR-STR must be a char, string, or list of char")))))
107 (mapc
108 (lambda (char)
109 (let ((last-command-event char))
110 (call-interactively 'self-insert-command)))
111 chars)))
112
113 (defun python-tests-visible-string (&optional min max)
114 "Return the buffer string excluding invisible overlays.
115 Argument MIN and MAX delimit the region to be returned and
116 default to `point-min' and `point-max' respectively."
117 (let* ((min (or min (point-min)))
118 (max (or max (point-max)))
119 (buffer (current-buffer))
120 (buffer-contents (buffer-substring-no-properties min max))
121 (overlays
122 (sort (overlays-in min max)
123 (lambda (a b)
124 (let ((overlay-end-a (overlay-end a))
125 (overlay-end-b (overlay-end b)))
126 (> overlay-end-a overlay-end-b))))))
127 (with-temp-buffer
128 (insert buffer-contents)
129 (dolist (overlay overlays)
130 (if (overlay-get overlay 'invisible)
131 (delete-region (overlay-start overlay)
132 (overlay-end overlay))))
133 (buffer-substring-no-properties (point-min) (point-max)))))
134
135 \f
136 ;;; Tests for your tests, so you can test while you test.
137
138 (ert-deftest python-tests-look-at-1 ()
139 "Test forward movement."
140 (python-tests-with-temp-buffer
141 "Lorem ipsum dolor sit amet, consectetur adipisicing elit,
142 sed do eiusmod tempor incididunt ut labore et dolore magna
143 aliqua."
144 (let ((expected (save-excursion
145 (dotimes (i 3)
146 (re-search-forward "et" nil t))
147 (forward-char -2)
148 (point))))
149 (should (= (python-tests-look-at "et" 3 t) expected))
150 ;; Even if NUM is bigger than found occurrences the point of last
151 ;; one should be returned.
152 (should (= (python-tests-look-at "et" 6 t) expected))
153 ;; If already looking at STRING, it should skip it.
154 (dotimes (i 2) (re-search-forward "et"))
155 (forward-char -2)
156 (should (= (python-tests-look-at "et") expected)))))
157
158 (ert-deftest python-tests-look-at-2 ()
159 "Test backward movement."
160 (python-tests-with-temp-buffer
161 "Lorem ipsum dolor sit amet, consectetur adipisicing elit,
162 sed do eiusmod tempor incididunt ut labore et dolore magna
163 aliqua."
164 (let ((expected
165 (save-excursion
166 (re-search-forward "et" nil t)
167 (forward-char -2)
168 (point))))
169 (dotimes (i 3)
170 (re-search-forward "et" nil t))
171 (should (= (python-tests-look-at "et" -3 t) expected))
172 (should (= (python-tests-look-at "et" -6 t) expected)))))
173
174 \f
175 ;;; Bindings
176
177 \f
178 ;;; Python specialized rx
179
180 \f
181 ;;; Font-lock and syntax
182
183 (ert-deftest python-syntax-after-python-backspace ()
184 ;; `python-indent-dedent-line-backspace' garbles syntax
185 :expected-result :failed
186 (python-tests-with-temp-buffer
187 "\"\"\""
188 (goto-char (point-max))
189 (python-indent-dedent-line-backspace 1)
190 (should (string= (buffer-string) "\"\""))
191 (should (null (nth 3 (syntax-ppss))))))
192
193 \f
194 ;;; Indentation
195
196 ;; See: http://www.python.org/dev/peps/pep-0008/#indentation
197
198 (ert-deftest python-indent-pep8-1 ()
199 "First pep8 case."
200 (python-tests-with-temp-buffer
201 "# Aligned with opening delimiter
202 foo = long_function_name(var_one, var_two,
203 var_three, var_four)
204 "
205 (should (eq (car (python-indent-context)) :no-indent))
206 (should (= (python-indent-calculate-indentation) 0))
207 (python-tests-look-at "foo = long_function_name(var_one, var_two,")
208 (should (eq (car (python-indent-context)) :after-comment))
209 (should (= (python-indent-calculate-indentation) 0))
210 (python-tests-look-at "var_three, var_four)")
211 (should (eq (car (python-indent-context)) :inside-paren))
212 (should (= (python-indent-calculate-indentation) 25))))
213
214 (ert-deftest python-indent-pep8-2 ()
215 "Second pep8 case."
216 (python-tests-with-temp-buffer
217 "# More indentation included to distinguish this from the rest.
218 def long_function_name(
219 var_one, var_two, var_three,
220 var_four):
221 print (var_one)
222 "
223 (should (eq (car (python-indent-context)) :no-indent))
224 (should (= (python-indent-calculate-indentation) 0))
225 (python-tests-look-at "def long_function_name(")
226 (should (eq (car (python-indent-context)) :after-comment))
227 (should (= (python-indent-calculate-indentation) 0))
228 (python-tests-look-at "var_one, var_two, var_three,")
229 (should (eq (car (python-indent-context))
230 :inside-paren-newline-start-from-block))
231 (should (= (python-indent-calculate-indentation) 8))
232 (python-tests-look-at "var_four):")
233 (should (eq (car (python-indent-context))
234 :inside-paren-newline-start-from-block))
235 (should (= (python-indent-calculate-indentation) 8))
236 (python-tests-look-at "print (var_one)")
237 (should (eq (car (python-indent-context))
238 :after-block-start))
239 (should (= (python-indent-calculate-indentation) 4))))
240
241 (ert-deftest python-indent-pep8-3 ()
242 "Third pep8 case."
243 (python-tests-with-temp-buffer
244 "# Extra indentation is not necessary.
245 foo = long_function_name(
246 var_one, var_two,
247 var_three, var_four)
248 "
249 (should (eq (car (python-indent-context)) :no-indent))
250 (should (= (python-indent-calculate-indentation) 0))
251 (python-tests-look-at "foo = long_function_name(")
252 (should (eq (car (python-indent-context)) :after-comment))
253 (should (= (python-indent-calculate-indentation) 0))
254 (python-tests-look-at "var_one, var_two,")
255 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
256 (should (= (python-indent-calculate-indentation) 4))
257 (python-tests-look-at "var_three, var_four)")
258 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
259 (should (= (python-indent-calculate-indentation) 4))))
260
261 (ert-deftest python-indent-base-case ()
262 "Check base case does not trigger errors."
263 (python-tests-with-temp-buffer
264 "
265
266 "
267 (goto-char (point-min))
268 (should (eq (car (python-indent-context)) :no-indent))
269 (should (= (python-indent-calculate-indentation) 0))
270 (forward-line 1)
271 (should (eq (car (python-indent-context)) :no-indent))
272 (should (= (python-indent-calculate-indentation) 0))
273 (forward-line 1)
274 (should (eq (car (python-indent-context)) :no-indent))
275 (should (= (python-indent-calculate-indentation) 0))))
276
277 (ert-deftest python-indent-after-comment-1 ()
278 "The most simple after-comment case that shouldn't fail."
279 (python-tests-with-temp-buffer
280 "# Contents will be modified to correct indentation
281 class Blag(object):
282 def _on_child_complete(self, child_future):
283 if self.in_terminal_state():
284 pass
285 # We only complete when all our async children have entered a
286 # terminal state. At that point, if any child failed, we fail
287 # with the exception with which the first child failed.
288 "
289 (python-tests-look-at "# We only complete")
290 (should (eq (car (python-indent-context)) :after-block-end))
291 (should (= (python-indent-calculate-indentation) 8))
292 (python-tests-look-at "# terminal state")
293 (should (eq (car (python-indent-context)) :after-comment))
294 (should (= (python-indent-calculate-indentation) 8))
295 (python-tests-look-at "# with the exception")
296 (should (eq (car (python-indent-context)) :after-comment))
297 ;; This one indents relative to previous block, even given the fact
298 ;; that it was under-indented.
299 (should (= (python-indent-calculate-indentation) 4))
300 (python-tests-look-at "# terminal state" -1)
301 ;; It doesn't hurt to check again.
302 (should (eq (car (python-indent-context)) :after-comment))
303 (python-indent-line)
304 (should (= (current-indentation) 8))
305 (python-tests-look-at "# with the exception")
306 (should (eq (car (python-indent-context)) :after-comment))
307 ;; Now everything should be lined up.
308 (should (= (python-indent-calculate-indentation) 8))))
309
310 (ert-deftest python-indent-after-comment-2 ()
311 "Test after-comment in weird cases."
312 (python-tests-with-temp-buffer
313 "# Contents will be modified to correct indentation
314 def func(arg):
315 # I don't do much
316 return arg
317 # This comment is badly indented because the user forced so.
318 # At this line python.el wont dedent, user is always right.
319
320 comment_wins_over_ender = True
321
322 # yeah, that.
323 "
324 (python-tests-look-at "# I don't do much")
325 (should (eq (car (python-indent-context)) :after-block-start))
326 (should (= (python-indent-calculate-indentation) 4))
327 (python-tests-look-at "return arg")
328 ;; Comment here just gets ignored, this line is not a comment so
329 ;; the rules won't apply here.
330 (should (eq (car (python-indent-context)) :after-block-start))
331 (should (= (python-indent-calculate-indentation) 4))
332 (python-tests-look-at "# This comment is badly indented")
333 (should (eq (car (python-indent-context)) :after-block-end))
334 ;; The return keyword do make indentation lose a level...
335 (should (= (python-indent-calculate-indentation) 0))
336 ;; ...but the current indentation was forced by the user.
337 (python-tests-look-at "# At this line python.el wont dedent")
338 (should (eq (car (python-indent-context)) :after-comment))
339 (should (= (python-indent-calculate-indentation) 4))
340 ;; Should behave the same for blank lines: potentially a comment.
341 (forward-line 1)
342 (should (eq (car (python-indent-context)) :after-comment))
343 (should (= (python-indent-calculate-indentation) 4))
344 (python-tests-look-at "comment_wins_over_ender")
345 ;; The comment won over the ender because the user said so.
346 (should (eq (car (python-indent-context)) :after-comment))
347 (should (= (python-indent-calculate-indentation) 4))
348 ;; The indentation calculated fine for the assignment, but the user
349 ;; choose to force it back to the first column. Next line should
350 ;; be aware of that.
351 (python-tests-look-at "# yeah, that.")
352 (should (eq (car (python-indent-context)) :after-line))
353 (should (= (python-indent-calculate-indentation) 0))))
354
355 (ert-deftest python-indent-after-comment-3 ()
356 "Test after-comment in buggy case."
357 (python-tests-with-temp-buffer
358 "
359 class A(object):
360
361 def something(self, arg):
362 if True:
363 return arg
364
365 # A comment
366
367 @adecorator
368 def method(self, a, b):
369 pass
370 "
371 (python-tests-look-at "@adecorator")
372 (should (eq (car (python-indent-context)) :after-comment))
373 (should (= (python-indent-calculate-indentation) 4))))
374
375 (ert-deftest python-indent-inside-paren-1 ()
376 "The most simple inside-paren case that shouldn't fail."
377 (python-tests-with-temp-buffer
378 "
379 data = {
380 'key':
381 {
382 'objlist': [
383 {
384 'pk': 1,
385 'name': 'first',
386 },
387 {
388 'pk': 2,
389 'name': 'second',
390 }
391 ]
392 }
393 }
394 "
395 (python-tests-look-at "data = {")
396 (should (eq (car (python-indent-context)) :no-indent))
397 (should (= (python-indent-calculate-indentation) 0))
398 (python-tests-look-at "'key':")
399 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
400 (should (= (python-indent-calculate-indentation) 4))
401 (python-tests-look-at "{")
402 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
403 (should (= (python-indent-calculate-indentation) 4))
404 (python-tests-look-at "'objlist': [")
405 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
406 (should (= (python-indent-calculate-indentation) 8))
407 (python-tests-look-at "{")
408 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
409 (should (= (python-indent-calculate-indentation) 12))
410 (python-tests-look-at "'pk': 1,")
411 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
412 (should (= (python-indent-calculate-indentation) 16))
413 (python-tests-look-at "'name': 'first',")
414 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
415 (should (= (python-indent-calculate-indentation) 16))
416 (python-tests-look-at "},")
417 (should (eq (car (python-indent-context))
418 :inside-paren-at-closing-nested-paren))
419 (should (= (python-indent-calculate-indentation) 12))
420 (python-tests-look-at "{")
421 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
422 (should (= (python-indent-calculate-indentation) 12))
423 (python-tests-look-at "'pk': 2,")
424 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
425 (should (= (python-indent-calculate-indentation) 16))
426 (python-tests-look-at "'name': 'second',")
427 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
428 (should (= (python-indent-calculate-indentation) 16))
429 (python-tests-look-at "}")
430 (should (eq (car (python-indent-context))
431 :inside-paren-at-closing-nested-paren))
432 (should (= (python-indent-calculate-indentation) 12))
433 (python-tests-look-at "]")
434 (should (eq (car (python-indent-context))
435 :inside-paren-at-closing-nested-paren))
436 (should (= (python-indent-calculate-indentation) 8))
437 (python-tests-look-at "}")
438 (should (eq (car (python-indent-context))
439 :inside-paren-at-closing-nested-paren))
440 (should (= (python-indent-calculate-indentation) 4))
441 (python-tests-look-at "}")
442 (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
443 (should (= (python-indent-calculate-indentation) 0))))
444
445 (ert-deftest python-indent-inside-paren-2 ()
446 "Another more compact paren group style."
447 (python-tests-with-temp-buffer
448 "
449 data = {'key': {
450 'objlist': [
451 {'pk': 1,
452 'name': 'first'},
453 {'pk': 2,
454 'name': 'second'}
455 ]
456 }}
457 "
458 (python-tests-look-at "data = {")
459 (should (eq (car (python-indent-context)) :no-indent))
460 (should (= (python-indent-calculate-indentation) 0))
461 (python-tests-look-at "'objlist': [")
462 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
463 (should (= (python-indent-calculate-indentation) 4))
464 (python-tests-look-at "{'pk': 1,")
465 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
466 (should (= (python-indent-calculate-indentation) 8))
467 (python-tests-look-at "'name': 'first'},")
468 (should (eq (car (python-indent-context)) :inside-paren))
469 (should (= (python-indent-calculate-indentation) 9))
470 (python-tests-look-at "{'pk': 2,")
471 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
472 (should (= (python-indent-calculate-indentation) 8))
473 (python-tests-look-at "'name': 'second'}")
474 (should (eq (car (python-indent-context)) :inside-paren))
475 (should (= (python-indent-calculate-indentation) 9))
476 (python-tests-look-at "]")
477 (should (eq (car (python-indent-context))
478 :inside-paren-at-closing-nested-paren))
479 (should (= (python-indent-calculate-indentation) 4))
480 (python-tests-look-at "}}")
481 (should (eq (car (python-indent-context))
482 :inside-paren-at-closing-nested-paren))
483 (should (= (python-indent-calculate-indentation) 0))
484 (python-tests-look-at "}")
485 (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
486 (should (= (python-indent-calculate-indentation) 0))))
487
488 (ert-deftest python-indent-inside-paren-3 ()
489 "The simplest case possible."
490 (python-tests-with-temp-buffer
491 "
492 data = ('these',
493 'are',
494 'the',
495 'tokens')
496 "
497 (python-tests-look-at "data = ('these',")
498 (should (eq (car (python-indent-context)) :no-indent))
499 (should (= (python-indent-calculate-indentation) 0))
500 (forward-line 1)
501 (should (eq (car (python-indent-context)) :inside-paren))
502 (should (= (python-indent-calculate-indentation) 8))
503 (forward-line 1)
504 (should (eq (car (python-indent-context)) :inside-paren))
505 (should (= (python-indent-calculate-indentation) 8))
506 (forward-line 1)
507 (should (eq (car (python-indent-context)) :inside-paren))
508 (should (= (python-indent-calculate-indentation) 8))))
509
510 (ert-deftest python-indent-inside-paren-4 ()
511 "Respect indentation of first column."
512 (python-tests-with-temp-buffer
513 "
514 data = [ [ 'these', 'are'],
515 ['the', 'tokens' ] ]
516 "
517 (python-tests-look-at "data = [ [ 'these', 'are'],")
518 (should (eq (car (python-indent-context)) :no-indent))
519 (should (= (python-indent-calculate-indentation) 0))
520 (forward-line 1)
521 (should (eq (car (python-indent-context)) :inside-paren))
522 (should (= (python-indent-calculate-indentation) 9))))
523
524 (ert-deftest python-indent-inside-paren-5 ()
525 "Test when :inside-paren initial parens are skipped in context start."
526 (python-tests-with-temp-buffer
527 "
528 while ((not some_condition) and
529 another_condition):
530 do_something_interesting(
531 with_some_arg)
532 "
533 (python-tests-look-at "while ((not some_condition) and")
534 (should (eq (car (python-indent-context)) :no-indent))
535 (should (= (python-indent-calculate-indentation) 0))
536 (forward-line 1)
537 (should (eq (car (python-indent-context)) :inside-paren))
538 (should (= (python-indent-calculate-indentation) 7))
539 (forward-line 1)
540 (should (eq (car (python-indent-context)) :after-block-start))
541 (should (= (python-indent-calculate-indentation) 4))
542 (forward-line 1)
543 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
544 (should (= (python-indent-calculate-indentation) 8))))
545
546 (ert-deftest python-indent-inside-paren-6 ()
547 "This should be aligned.."
548 (python-tests-with-temp-buffer
549 "
550 CHOICES = (('some', 'choice'),
551 ('another', 'choice'),
552 ('more', 'choices'))
553 "
554 (python-tests-look-at "CHOICES = (('some', 'choice'),")
555 (should (eq (car (python-indent-context)) :no-indent))
556 (should (= (python-indent-calculate-indentation) 0))
557 (forward-line 1)
558 (should (eq (car (python-indent-context)) :inside-paren))
559 (should (= (python-indent-calculate-indentation) 11))
560 (forward-line 1)
561 (should (eq (car (python-indent-context)) :inside-paren))
562 (should (= (python-indent-calculate-indentation) 11))))
563
564 (ert-deftest python-indent-after-block-1 ()
565 "The most simple after-block case that shouldn't fail."
566 (python-tests-with-temp-buffer
567 "
568 def foo(a, b, c=True):
569 "
570 (should (eq (car (python-indent-context)) :no-indent))
571 (should (= (python-indent-calculate-indentation) 0))
572 (goto-char (point-max))
573 (should (eq (car (python-indent-context)) :after-block-start))
574 (should (= (python-indent-calculate-indentation) 4))))
575
576 (ert-deftest python-indent-after-block-2 ()
577 "A weird (malformed) multiline block statement."
578 (python-tests-with-temp-buffer
579 "
580 def foo(a, b, c={
581 'a':
582 }):
583 "
584 (goto-char (point-max))
585 (should (eq (car (python-indent-context)) :after-block-start))
586 (should (= (python-indent-calculate-indentation) 4))))
587
588 (ert-deftest python-indent-after-block-3 ()
589 "A weird (malformed) sample, usually found in python shells."
590 (python-tests-with-temp-buffer
591 "
592 In [1]:
593 def func():
594 pass
595
596 In [2]:
597 something
598 "
599 (python-tests-look-at "pass")
600 (should (eq (car (python-indent-context)) :after-block-start))
601 (should (= (python-indent-calculate-indentation) 4))
602 (python-tests-look-at "something")
603 (end-of-line)
604 (should (eq (car (python-indent-context)) :after-line))
605 (should (= (python-indent-calculate-indentation) 0))))
606
607 (ert-deftest python-indent-after-backslash-1 ()
608 "The most common case."
609 (python-tests-with-temp-buffer
610 "
611 from foo.bar.baz import something, something_1 \\\\
612 something_2 something_3, \\\\
613 something_4, something_5
614 "
615 (python-tests-look-at "from foo.bar.baz import something, something_1")
616 (should (eq (car (python-indent-context)) :no-indent))
617 (should (= (python-indent-calculate-indentation) 0))
618 (python-tests-look-at "something_2 something_3,")
619 (should (eq (car (python-indent-context)) :after-backslash-first-line))
620 (should (= (python-indent-calculate-indentation) 4))
621 (python-tests-look-at "something_4, something_5")
622 (should (eq (car (python-indent-context)) :after-backslash))
623 (should (= (python-indent-calculate-indentation) 4))
624 (goto-char (point-max))
625 (should (eq (car (python-indent-context)) :after-line))
626 (should (= (python-indent-calculate-indentation) 0))))
627
628 (ert-deftest python-indent-after-backslash-2 ()
629 "A pretty extreme complicated case."
630 (python-tests-with-temp-buffer
631 "
632 objects = Thing.objects.all() \\\\
633 .filter(
634 type='toy',
635 status='bought'
636 ) \\\\
637 .aggregate(
638 Sum('amount')
639 ) \\\\
640 .values_list()
641 "
642 (python-tests-look-at "objects = Thing.objects.all()")
643 (should (eq (car (python-indent-context)) :no-indent))
644 (should (= (python-indent-calculate-indentation) 0))
645 (python-tests-look-at ".filter(")
646 (should (eq (car (python-indent-context))
647 :after-backslash-dotted-continuation))
648 (should (= (python-indent-calculate-indentation) 23))
649 (python-tests-look-at "type='toy',")
650 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
651 (should (= (python-indent-calculate-indentation) 27))
652 (python-tests-look-at "status='bought'")
653 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
654 (should (= (python-indent-calculate-indentation) 27))
655 (python-tests-look-at ") \\\\")
656 (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
657 (should (= (python-indent-calculate-indentation) 23))
658 (python-tests-look-at ".aggregate(")
659 (should (eq (car (python-indent-context))
660 :after-backslash-dotted-continuation))
661 (should (= (python-indent-calculate-indentation) 23))
662 (python-tests-look-at "Sum('amount')")
663 (should (eq (car (python-indent-context)) :inside-paren-newline-start))
664 (should (= (python-indent-calculate-indentation) 27))
665 (python-tests-look-at ") \\\\")
666 (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
667 (should (= (python-indent-calculate-indentation) 23))
668 (python-tests-look-at ".values_list()")
669 (should (eq (car (python-indent-context))
670 :after-backslash-dotted-continuation))
671 (should (= (python-indent-calculate-indentation) 23))
672 (forward-line 1)
673 (should (eq (car (python-indent-context)) :after-line))
674 (should (= (python-indent-calculate-indentation) 0))))
675
676 (ert-deftest python-indent-after-backslash-3 ()
677 "Backslash continuation from block start."
678 (python-tests-with-temp-buffer
679 "
680 with open('/path/to/some/file/you/want/to/read') as file_1, \\\\
681 open('/path/to/some/file/being/written', 'w') as file_2:
682 file_2.write(file_1.read())
683 "
684 (python-tests-look-at
685 "with open('/path/to/some/file/you/want/to/read') as file_1, \\\\")
686 (should (eq (car (python-indent-context)) :no-indent))
687 (should (= (python-indent-calculate-indentation) 0))
688 (python-tests-look-at
689 "open('/path/to/some/file/being/written', 'w') as file_2")
690 (should (eq (car (python-indent-context))
691 :after-backslash-block-continuation))
692 (should (= (python-indent-calculate-indentation) 5))
693 (python-tests-look-at "file_2.write(file_1.read())")
694 (should (eq (car (python-indent-context)) :after-block-start))
695 (should (= (python-indent-calculate-indentation) 4))))
696
697 (ert-deftest python-indent-after-backslash-4 ()
698 "Backslash continuation from assignment."
699 (python-tests-with-temp-buffer
700 "
701 super_awful_assignment = some_calculation() and \\\\
702 another_calculation() and \\\\
703 some_final_calculation()
704 "
705 (python-tests-look-at
706 "super_awful_assignment = some_calculation() and \\\\")
707 (should (eq (car (python-indent-context)) :no-indent))
708 (should (= (python-indent-calculate-indentation) 0))
709 (python-tests-look-at "another_calculation() and \\\\")
710 (should (eq (car (python-indent-context))
711 :after-backslash-assignment-continuation))
712 (should (= (python-indent-calculate-indentation) 25))
713 (python-tests-look-at "some_final_calculation()")
714 (should (eq (car (python-indent-context)) :after-backslash))
715 (should (= (python-indent-calculate-indentation) 25))))
716
717 (ert-deftest python-indent-after-backslash-5 ()
718 "Dotted continuation bizarre example."
719 (python-tests-with-temp-buffer
720 "
721 def delete_all_things():
722 Thing \\\\
723 .objects.all() \\\\
724 .delete()
725 "
726 (python-tests-look-at "Thing \\\\")
727 (should (eq (car (python-indent-context)) :after-block-start))
728 (should (= (python-indent-calculate-indentation) 4))
729 (python-tests-look-at ".objects.all() \\\\")
730 (should (eq (car (python-indent-context)) :after-backslash-first-line))
731 (should (= (python-indent-calculate-indentation) 8))
732 (python-tests-look-at ".delete()")
733 (should (eq (car (python-indent-context))
734 :after-backslash-dotted-continuation))
735 (should (= (python-indent-calculate-indentation) 16))))
736
737 (ert-deftest python-indent-block-enders-1 ()
738 "Test de-indentation for pass keyword."
739 (python-tests-with-temp-buffer
740 "
741 Class foo(object):
742
743 def bar(self):
744 if self.baz:
745 return (1,
746 2,
747 3)
748
749 else:
750 pass
751 "
752 (python-tests-look-at "3)")
753 (forward-line 1)
754 (should (= (python-indent-calculate-indentation) 8))
755 (python-tests-look-at "pass")
756 (forward-line 1)
757 (should (eq (car (python-indent-context)) :after-block-end))
758 (should (= (python-indent-calculate-indentation) 8))))
759
760 (ert-deftest python-indent-block-enders-2 ()
761 "Test de-indentation for return keyword."
762 (python-tests-with-temp-buffer
763 "
764 Class foo(object):
765 '''raise lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
766
767 eiusmod tempor incididunt ut labore et dolore magna aliqua.
768 '''
769 def bar(self):
770 \"return (1, 2, 3).\"
771 if self.baz:
772 return (1,
773 2,
774 3)
775 "
776 (python-tests-look-at "def")
777 (should (= (python-indent-calculate-indentation) 4))
778 (python-tests-look-at "if")
779 (should (= (python-indent-calculate-indentation) 8))
780 (python-tests-look-at "return")
781 (should (= (python-indent-calculate-indentation) 12))
782 (goto-char (point-max))
783 (should (eq (car (python-indent-context)) :after-block-end))
784 (should (= (python-indent-calculate-indentation) 8))))
785
786 (ert-deftest python-indent-block-enders-3 ()
787 "Test de-indentation for continue keyword."
788 (python-tests-with-temp-buffer
789 "
790 for element in lst:
791 if element is None:
792 continue
793 "
794 (python-tests-look-at "if")
795 (should (= (python-indent-calculate-indentation) 4))
796 (python-tests-look-at "continue")
797 (should (= (python-indent-calculate-indentation) 8))
798 (forward-line 1)
799 (should (eq (car (python-indent-context)) :after-block-end))
800 (should (= (python-indent-calculate-indentation) 4))))
801
802 (ert-deftest python-indent-block-enders-4 ()
803 "Test de-indentation for break keyword."
804 (python-tests-with-temp-buffer
805 "
806 for element in lst:
807 if element is None:
808 break
809 "
810 (python-tests-look-at "if")
811 (should (= (python-indent-calculate-indentation) 4))
812 (python-tests-look-at "break")
813 (should (= (python-indent-calculate-indentation) 8))
814 (forward-line 1)
815 (should (eq (car (python-indent-context)) :after-block-end))
816 (should (= (python-indent-calculate-indentation) 4))))
817
818 (ert-deftest python-indent-block-enders-5 ()
819 "Test de-indentation for raise keyword."
820 (python-tests-with-temp-buffer
821 "
822 for element in lst:
823 if element is None:
824 raise ValueError('Element cannot be None')
825 "
826 (python-tests-look-at "if")
827 (should (= (python-indent-calculate-indentation) 4))
828 (python-tests-look-at "raise")
829 (should (= (python-indent-calculate-indentation) 8))
830 (forward-line 1)
831 (should (eq (car (python-indent-context)) :after-block-end))
832 (should (= (python-indent-calculate-indentation) 4))))
833
834 (ert-deftest python-indent-dedenters-1 ()
835 "Test de-indentation for the elif keyword."
836 (python-tests-with-temp-buffer
837 "
838 if save:
839 try:
840 write_to_disk(data)
841 finally:
842 cleanup()
843 elif
844 "
845 (python-tests-look-at "elif\n")
846 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
847 (should (= (python-indent-calculate-indentation) 0))
848 (should (= (python-indent-calculate-indentation t) 0))))
849
850 (ert-deftest python-indent-dedenters-2 ()
851 "Test de-indentation for the else keyword."
852 (python-tests-with-temp-buffer
853 "
854 if save:
855 try:
856 write_to_disk(data)
857 except IOError:
858 msg = 'Error saving to disk'
859 message(msg)
860 logger.exception(msg)
861 except Exception:
862 if hide_details:
863 logger.exception('Unhandled exception')
864 else
865 finally:
866 data.free()
867 "
868 (python-tests-look-at "else\n")
869 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
870 (should (= (python-indent-calculate-indentation) 8))
871 (python-indent-line t)
872 (should (= (python-indent-calculate-indentation t) 4))
873 (python-indent-line t)
874 (should (= (python-indent-calculate-indentation t) 0))
875 (python-indent-line t)
876 (should (= (python-indent-calculate-indentation t) 8))))
877
878 (ert-deftest python-indent-dedenters-3 ()
879 "Test de-indentation for the except keyword."
880 (python-tests-with-temp-buffer
881 "
882 if save:
883 try:
884 write_to_disk(data)
885 except
886 "
887 (python-tests-look-at "except\n")
888 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
889 (should (= (python-indent-calculate-indentation) 4))
890 (python-indent-line t)
891 (should (= (python-indent-calculate-indentation t) 4))))
892
893 (ert-deftest python-indent-dedenters-4 ()
894 "Test de-indentation for the finally keyword."
895 (python-tests-with-temp-buffer
896 "
897 if save:
898 try:
899 write_to_disk(data)
900 finally
901 "
902 (python-tests-look-at "finally\n")
903 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
904 (should (= (python-indent-calculate-indentation) 4))
905 (python-indent-line t)
906 (should (= (python-indent-calculate-indentation) 4))))
907
908 (ert-deftest python-indent-dedenters-5 ()
909 "Test invalid levels are skipped in a complex example."
910 (python-tests-with-temp-buffer
911 "
912 if save:
913 try:
914 write_to_disk(data)
915 except IOError:
916 msg = 'Error saving to disk'
917 message(msg)
918 logger.exception(msg)
919 finally:
920 if cleanup:
921 do_cleanup()
922 else
923 "
924 (python-tests-look-at "else\n")
925 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
926 (should (= (python-indent-calculate-indentation) 8))
927 (should (= (python-indent-calculate-indentation t) 0))
928 (python-indent-line t)
929 (should (= (python-indent-calculate-indentation t) 8))))
930
931 (ert-deftest python-indent-dedenters-6 ()
932 "Test indentation is zero when no opening block for dedenter."
933 (python-tests-with-temp-buffer
934 "
935 try:
936 # if save:
937 write_to_disk(data)
938 else
939 "
940 (python-tests-look-at "else\n")
941 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
942 (should (= (python-indent-calculate-indentation) 0))
943 (should (= (python-indent-calculate-indentation t) 0))))
944
945 (ert-deftest python-indent-dedenters-7 ()
946 "Test indentation case from Bug#15163."
947 (python-tests-with-temp-buffer
948 "
949 if a:
950 if b:
951 pass
952 else:
953 pass
954 else:
955 "
956 (python-tests-look-at "else:" 2)
957 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
958 (should (= (python-indent-calculate-indentation) 0))
959 (should (= (python-indent-calculate-indentation t) 0))))
960
961 (ert-deftest python-indent-dedenters-8 ()
962 "Test indentation for Bug#18432."
963 (python-tests-with-temp-buffer
964 "
965 if (a == 1 or
966 a == 2):
967 pass
968 elif (a == 3 or
969 a == 4):
970 "
971 (python-tests-look-at "elif (a == 3 or")
972 (should (eq (car (python-indent-context)) :at-dedenter-block-start))
973 (should (= (python-indent-calculate-indentation) 0))
974 (should (= (python-indent-calculate-indentation t) 0))
975 (python-tests-look-at "a == 4):\n")
976 (should (eq (car (python-indent-context)) :inside-paren))
977 (should (= (python-indent-calculate-indentation) 6))
978 (python-indent-line)
979 (should (= (python-indent-calculate-indentation t) 4))
980 (python-indent-line t)
981 (should (= (python-indent-calculate-indentation t) 0))
982 (python-indent-line t)
983 (should (= (python-indent-calculate-indentation t) 6))))
984
985 (ert-deftest python-indent-inside-string-1 ()
986 "Test indentation for strings."
987 (python-tests-with-temp-buffer
988 "
989 multiline = '''
990 bunch
991 of
992 lines
993 '''
994 "
995 (python-tests-look-at "multiline = '''")
996 (should (eq (car (python-indent-context)) :no-indent))
997 (should (= (python-indent-calculate-indentation) 0))
998 (python-tests-look-at "bunch")
999 (should (eq (car (python-indent-context)) :inside-string))
1000 (should (= (python-indent-calculate-indentation) 0))
1001 (python-tests-look-at "of")
1002 (should (eq (car (python-indent-context)) :inside-string))
1003 (should (= (python-indent-calculate-indentation) 0))
1004 (python-tests-look-at "lines")
1005 (should (eq (car (python-indent-context)) :inside-string))
1006 (should (= (python-indent-calculate-indentation) 0))
1007 (python-tests-look-at "'''")
1008 (should (eq (car (python-indent-context)) :inside-string))
1009 (should (= (python-indent-calculate-indentation) 0))))
1010
1011 (ert-deftest python-indent-inside-string-2 ()
1012 "Test indentation for docstrings."
1013 (python-tests-with-temp-buffer
1014 "
1015 def fn(a, b, c=True):
1016 '''docstring
1017 bunch
1018 of
1019 lines
1020 '''
1021 "
1022 (python-tests-look-at "'''docstring")
1023 (should (eq (car (python-indent-context)) :after-block-start))
1024 (should (= (python-indent-calculate-indentation) 4))
1025 (python-tests-look-at "bunch")
1026 (should (eq (car (python-indent-context)) :inside-docstring))
1027 (should (= (python-indent-calculate-indentation) 4))
1028 (python-tests-look-at "of")
1029 (should (eq (car (python-indent-context)) :inside-docstring))
1030 ;; Any indentation deeper than the base-indent must remain unmodified.
1031 (should (= (python-indent-calculate-indentation) 8))
1032 (python-tests-look-at "lines")
1033 (should (eq (car (python-indent-context)) :inside-docstring))
1034 (should (= (python-indent-calculate-indentation) 4))
1035 (python-tests-look-at "'''")
1036 (should (eq (car (python-indent-context)) :inside-docstring))
1037 (should (= (python-indent-calculate-indentation) 4))))
1038
1039 (ert-deftest python-indent-inside-string-3 ()
1040 "Test indentation for nested strings."
1041 (python-tests-with-temp-buffer
1042 "
1043 def fn(a, b, c=True):
1044 some_var = '''
1045 bunch
1046 of
1047 lines
1048 '''
1049 "
1050 (python-tests-look-at "some_var = '''")
1051 (should (eq (car (python-indent-context)) :after-block-start))
1052 (should (= (python-indent-calculate-indentation) 4))
1053 (python-tests-look-at "bunch")
1054 (should (eq (car (python-indent-context)) :inside-string))
1055 (should (= (python-indent-calculate-indentation) 4))
1056 (python-tests-look-at "of")
1057 (should (eq (car (python-indent-context)) :inside-string))
1058 (should (= (python-indent-calculate-indentation) 4))
1059 (python-tests-look-at "lines")
1060 (should (eq (car (python-indent-context)) :inside-string))
1061 (should (= (python-indent-calculate-indentation) 4))
1062 (python-tests-look-at "'''")
1063 (should (eq (car (python-indent-context)) :inside-string))
1064 (should (= (python-indent-calculate-indentation) 4))))
1065
1066 (ert-deftest python-indent-electric-colon-1 ()
1067 "Test indentation case from Bug#18228."
1068 (python-tests-with-temp-buffer
1069 "
1070 def a():
1071 pass
1072
1073 def b()
1074 "
1075 (python-tests-look-at "def b()")
1076 (goto-char (line-end-position))
1077 (python-tests-self-insert ":")
1078 (should (= (current-indentation) 0))))
1079
1080 (ert-deftest python-indent-electric-colon-2 ()
1081 "Test indentation case for dedenter."
1082 (python-tests-with-temp-buffer
1083 "
1084 if do:
1085 something()
1086 else
1087 "
1088 (python-tests-look-at "else")
1089 (goto-char (line-end-position))
1090 (python-tests-self-insert ":")
1091 (should (= (current-indentation) 0))))
1092
1093 (ert-deftest python-indent-electric-colon-3 ()
1094 "Test indentation case for multi-line dedenter."
1095 (python-tests-with-temp-buffer
1096 "
1097 if do:
1098 something()
1099 elif (this
1100 and
1101 that)
1102 "
1103 (python-tests-look-at "that)")
1104 (goto-char (line-end-position))
1105 (python-tests-self-insert ":")
1106 (python-tests-look-at "elif" -1)
1107 (should (= (current-indentation) 0))
1108 (python-tests-look-at "and")
1109 (should (= (current-indentation) 6))
1110 (python-tests-look-at "that)")
1111 (should (= (current-indentation) 6))))
1112
1113 (ert-deftest python-indent-region-1 ()
1114 "Test indentation case from Bug#18843."
1115 (let ((contents "
1116 def foo ():
1117 try:
1118 pass
1119 except:
1120 pass
1121 "))
1122 (python-tests-with-temp-buffer
1123 contents
1124 (python-indent-region (point-min) (point-max))
1125 (should (string= (buffer-substring-no-properties (point-min) (point-max))
1126 contents)))))
1127
1128 (ert-deftest python-indent-region-2 ()
1129 "Test region indentation on comments."
1130 (let ((contents "
1131 def f():
1132 if True:
1133 pass
1134
1135 # This is
1136 # some multiline
1137 # comment
1138 "))
1139 (python-tests-with-temp-buffer
1140 contents
1141 (python-indent-region (point-min) (point-max))
1142 (should (string= (buffer-substring-no-properties (point-min) (point-max))
1143 contents)))))
1144
1145 (ert-deftest python-indent-region-3 ()
1146 "Test region indentation on comments."
1147 (let ((contents "
1148 def f():
1149 if True:
1150 pass
1151 # This is
1152 # some multiline
1153 # comment
1154 ")
1155 (expected "
1156 def f():
1157 if True:
1158 pass
1159 # This is
1160 # some multiline
1161 # comment
1162 "))
1163 (python-tests-with-temp-buffer
1164 contents
1165 (python-indent-region (point-min) (point-max))
1166 (should (string= (buffer-substring-no-properties (point-min) (point-max))
1167 expected)))))
1168
1169 (ert-deftest python-indent-region-4 ()
1170 "Test region indentation block starts, dedenters and enders."
1171 (let ((contents "
1172 def f():
1173 if True:
1174 a = 5
1175 else:
1176 a = 10
1177 return a
1178 ")
1179 (expected "
1180 def f():
1181 if True:
1182 a = 5
1183 else:
1184 a = 10
1185 return a
1186 "))
1187 (python-tests-with-temp-buffer
1188 contents
1189 (python-indent-region (point-min) (point-max))
1190 (should (string= (buffer-substring-no-properties (point-min) (point-max))
1191 expected)))))
1192
1193 (ert-deftest python-indent-region-5 ()
1194 "Test region indentation for docstrings."
1195 (let ((contents "
1196 def f():
1197 '''
1198 this is
1199 a multiline
1200 string
1201 '''
1202 x = \\
1203 '''
1204 this is an arbitrarily
1205 indented multiline
1206 string
1207 '''
1208 ")
1209 (expected "
1210 def f():
1211 '''
1212 this is
1213 a multiline
1214 string
1215 '''
1216 x = \\
1217 '''
1218 this is an arbitrarily
1219 indented multiline
1220 string
1221 '''
1222 "))
1223 (python-tests-with-temp-buffer
1224 contents
1225 (python-indent-region (point-min) (point-max))
1226 (should (string= (buffer-substring-no-properties (point-min) (point-max))
1227 expected)))))
1228
1229 \f
1230 ;;; Mark
1231
1232 (ert-deftest python-mark-defun-1 ()
1233 """Test `python-mark-defun' with point at defun symbol start."""
1234 (python-tests-with-temp-buffer
1235 "
1236 def foo(x):
1237 return x
1238
1239 class A:
1240 pass
1241
1242 class B:
1243
1244 def __init__(self):
1245 self.b = 'b'
1246
1247 def fun(self):
1248 return self.b
1249
1250 class C:
1251 '''docstring'''
1252 "
1253 (let ((expected-mark-beginning-position
1254 (progn
1255 (python-tests-look-at "class A:")
1256 (1- (point))))
1257 (expected-mark-end-position-1
1258 (save-excursion
1259 (python-tests-look-at "pass")
1260 (forward-line)
1261 (point)))
1262 (expected-mark-end-position-2
1263 (save-excursion
1264 (python-tests-look-at "return self.b")
1265 (forward-line)
1266 (point)))
1267 (expected-mark-end-position-3
1268 (save-excursion
1269 (python-tests-look-at "'''docstring'''")
1270 (forward-line)
1271 (point))))
1272 ;; Select class A only, with point at bol.
1273 (python-mark-defun 1)
1274 (should (= (point) expected-mark-beginning-position))
1275 (should (= (marker-position (mark-marker))
1276 expected-mark-end-position-1))
1277 ;; expand to class B, start position should remain the same.
1278 (python-mark-defun 1)
1279 (should (= (point) expected-mark-beginning-position))
1280 (should (= (marker-position (mark-marker))
1281 expected-mark-end-position-2))
1282 ;; expand to class C, start position should remain the same.
1283 (python-mark-defun 1)
1284 (should (= (point) expected-mark-beginning-position))
1285 (should (= (marker-position (mark-marker))
1286 expected-mark-end-position-3)))))
1287
1288 (ert-deftest python-mark-defun-2 ()
1289 """Test `python-mark-defun' with point at nested defun symbol start."""
1290 (python-tests-with-temp-buffer
1291 "
1292 def foo(x):
1293 return x
1294
1295 class A:
1296 pass
1297
1298 class B:
1299
1300 def __init__(self):
1301 self.b = 'b'
1302
1303 def fun(self):
1304 return self.b
1305
1306 class C:
1307 '''docstring'''
1308 "
1309 (let ((expected-mark-beginning-position
1310 (progn
1311 (python-tests-look-at "def __init__(self):")
1312 (1- (line-beginning-position))))
1313 (expected-mark-end-position-1
1314 (save-excursion
1315 (python-tests-look-at "self.b = 'b'")
1316 (forward-line)
1317 (point)))
1318 (expected-mark-end-position-2
1319 (save-excursion
1320 (python-tests-look-at "return self.b")
1321 (forward-line)
1322 (point)))
1323 (expected-mark-end-position-3
1324 (save-excursion
1325 (python-tests-look-at "'''docstring'''")
1326 (forward-line)
1327 (point))))
1328 ;; Select B.__init only, with point at its start.
1329 (python-mark-defun 1)
1330 (should (= (point) expected-mark-beginning-position))
1331 (should (= (marker-position (mark-marker))
1332 expected-mark-end-position-1))
1333 ;; expand to B.fun, start position should remain the same.
1334 (python-mark-defun 1)
1335 (should (= (point) expected-mark-beginning-position))
1336 (should (= (marker-position (mark-marker))
1337 expected-mark-end-position-2))
1338 ;; expand to class C, start position should remain the same.
1339 (python-mark-defun 1)
1340 (should (= (point) expected-mark-beginning-position))
1341 (should (= (marker-position (mark-marker))
1342 expected-mark-end-position-3)))))
1343
1344 (ert-deftest python-mark-defun-3 ()
1345 """Test `python-mark-defun' with point inside defun symbol."""
1346 (python-tests-with-temp-buffer
1347 "
1348 def foo(x):
1349 return x
1350
1351 class A:
1352 pass
1353
1354 class B:
1355
1356 def __init__(self):
1357 self.b = 'b'
1358
1359 def fun(self):
1360 return self.b
1361
1362 class C:
1363 '''docstring'''
1364 "
1365 (let ((expected-mark-beginning-position
1366 (progn
1367 (python-tests-look-at "def fun(self):")
1368 (python-tests-look-at "(self):")
1369 (1- (line-beginning-position))))
1370 (expected-mark-end-position
1371 (save-excursion
1372 (python-tests-look-at "return self.b")
1373 (forward-line)
1374 (point))))
1375 ;; Should select B.fun, despite point is inside the defun symbol.
1376 (python-mark-defun 1)
1377 (should (= (point) expected-mark-beginning-position))
1378 (should (= (marker-position (mark-marker))
1379 expected-mark-end-position)))))
1380
1381 \f
1382 ;;; Navigation
1383
1384 (ert-deftest python-nav-beginning-of-defun-1 ()
1385 (python-tests-with-temp-buffer
1386 "
1387 def decoratorFunctionWithArguments(arg1, arg2, arg3):
1388 '''print decorated function call data to stdout.
1389
1390 Usage:
1391
1392 @decoratorFunctionWithArguments('arg1', 'arg2')
1393 def func(a, b, c=True):
1394 pass
1395 '''
1396
1397 def wwrap(f):
1398 print 'Inside wwrap()'
1399 def wrapped_f(*args):
1400 print 'Inside wrapped_f()'
1401 print 'Decorator arguments:', arg1, arg2, arg3
1402 f(*args)
1403 print 'After f(*args)'
1404 return wrapped_f
1405 return wwrap
1406 "
1407 (python-tests-look-at "return wrap")
1408 (should (= (save-excursion
1409 (python-nav-beginning-of-defun)
1410 (point))
1411 (save-excursion
1412 (python-tests-look-at "def wrapped_f(*args):" -1)
1413 (beginning-of-line)
1414 (point))))
1415 (python-tests-look-at "def wrapped_f(*args):" -1)
1416 (should (= (save-excursion
1417 (python-nav-beginning-of-defun)
1418 (point))
1419 (save-excursion
1420 (python-tests-look-at "def wwrap(f):" -1)
1421 (beginning-of-line)
1422 (point))))
1423 (python-tests-look-at "def wwrap(f):" -1)
1424 (should (= (save-excursion
1425 (python-nav-beginning-of-defun)
1426 (point))
1427 (save-excursion
1428 (python-tests-look-at "def decoratorFunctionWithArguments" -1)
1429 (beginning-of-line)
1430 (point))))))
1431
1432 (ert-deftest python-nav-beginning-of-defun-2 ()
1433 (python-tests-with-temp-buffer
1434 "
1435 class C(object):
1436
1437 def m(self):
1438 self.c()
1439
1440 def b():
1441 pass
1442
1443 def a():
1444 pass
1445
1446 def c(self):
1447 pass
1448 "
1449 ;; Nested defuns, are handled with care.
1450 (python-tests-look-at "def c(self):")
1451 (should (= (save-excursion
1452 (python-nav-beginning-of-defun)
1453 (point))
1454 (save-excursion
1455 (python-tests-look-at "def m(self):" -1)
1456 (beginning-of-line)
1457 (point))))
1458 ;; Defuns on same levels should be respected.
1459 (python-tests-look-at "def a():" -1)
1460 (should (= (save-excursion
1461 (python-nav-beginning-of-defun)
1462 (point))
1463 (save-excursion
1464 (python-tests-look-at "def b():" -1)
1465 (beginning-of-line)
1466 (point))))
1467 ;; Jump to a top level defun.
1468 (python-tests-look-at "def b():" -1)
1469 (should (= (save-excursion
1470 (python-nav-beginning-of-defun)
1471 (point))
1472 (save-excursion
1473 (python-tests-look-at "def m(self):" -1)
1474 (beginning-of-line)
1475 (point))))
1476 ;; Jump to a top level defun again.
1477 (python-tests-look-at "def m(self):" -1)
1478 (should (= (save-excursion
1479 (python-nav-beginning-of-defun)
1480 (point))
1481 (save-excursion
1482 (python-tests-look-at "class C(object):" -1)
1483 (beginning-of-line)
1484 (point))))))
1485
1486 (ert-deftest python-nav-end-of-defun-1 ()
1487 (python-tests-with-temp-buffer
1488 "
1489 class C(object):
1490
1491 def m(self):
1492 self.c()
1493
1494 def b():
1495 pass
1496
1497 def a():
1498 pass
1499
1500 def c(self):
1501 pass
1502 "
1503 (should (= (save-excursion
1504 (python-tests-look-at "class C(object):")
1505 (python-nav-end-of-defun)
1506 (point))
1507 (save-excursion
1508 (point-max))))
1509 (should (= (save-excursion
1510 (python-tests-look-at "def m(self):")
1511 (python-nav-end-of-defun)
1512 (point))
1513 (save-excursion
1514 (python-tests-look-at "def c(self):")
1515 (forward-line -1)
1516 (point))))
1517 (should (= (save-excursion
1518 (python-tests-look-at "def b():")
1519 (python-nav-end-of-defun)
1520 (point))
1521 (save-excursion
1522 (python-tests-look-at "def b():")
1523 (forward-line 2)
1524 (point))))
1525 (should (= (save-excursion
1526 (python-tests-look-at "def c(self):")
1527 (python-nav-end-of-defun)
1528 (point))
1529 (save-excursion
1530 (point-max))))))
1531
1532 (ert-deftest python-nav-end-of-defun-2 ()
1533 (python-tests-with-temp-buffer
1534 "
1535 def decoratorFunctionWithArguments(arg1, arg2, arg3):
1536 '''print decorated function call data to stdout.
1537
1538 Usage:
1539
1540 @decoratorFunctionWithArguments('arg1', 'arg2')
1541 def func(a, b, c=True):
1542 pass
1543 '''
1544
1545 def wwrap(f):
1546 print 'Inside wwrap()'
1547 def wrapped_f(*args):
1548 print 'Inside wrapped_f()'
1549 print 'Decorator arguments:', arg1, arg2, arg3
1550 f(*args)
1551 print 'After f(*args)'
1552 return wrapped_f
1553 return wwrap
1554 "
1555 (should (= (save-excursion
1556 (python-tests-look-at "def decoratorFunctionWithArguments")
1557 (python-nav-end-of-defun)
1558 (point))
1559 (save-excursion
1560 (point-max))))
1561 (should (= (save-excursion
1562 (python-tests-look-at "@decoratorFunctionWithArguments")
1563 (python-nav-end-of-defun)
1564 (point))
1565 (save-excursion
1566 (point-max))))
1567 (should (= (save-excursion
1568 (python-tests-look-at "def wwrap(f):")
1569 (python-nav-end-of-defun)
1570 (point))
1571 (save-excursion
1572 (python-tests-look-at "return wwrap")
1573 (line-beginning-position))))
1574 (should (= (save-excursion
1575 (python-tests-look-at "def wrapped_f(*args):")
1576 (python-nav-end-of-defun)
1577 (point))
1578 (save-excursion
1579 (python-tests-look-at "return wrapped_f")
1580 (line-beginning-position))))
1581 (should (= (save-excursion
1582 (python-tests-look-at "f(*args)")
1583 (python-nav-end-of-defun)
1584 (point))
1585 (save-excursion
1586 (python-tests-look-at "return wrapped_f")
1587 (line-beginning-position))))))
1588
1589 (ert-deftest python-nav-backward-defun-1 ()
1590 (python-tests-with-temp-buffer
1591 "
1592 class A(object): # A
1593
1594 def a(self): # a
1595 pass
1596
1597 def b(self): # b
1598 pass
1599
1600 class B(object): # B
1601
1602 class C(object): # C
1603
1604 def d(self): # d
1605 pass
1606
1607 # def e(self): # e
1608 # pass
1609
1610 def c(self): # c
1611 pass
1612
1613 # def d(self): # d
1614 # pass
1615 "
1616 (goto-char (point-max))
1617 (should (= (save-excursion (python-nav-backward-defun))
1618 (python-tests-look-at " def c(self): # c" -1)))
1619 (should (= (save-excursion (python-nav-backward-defun))
1620 (python-tests-look-at " def d(self): # d" -1)))
1621 (should (= (save-excursion (python-nav-backward-defun))
1622 (python-tests-look-at " class C(object): # C" -1)))
1623 (should (= (save-excursion (python-nav-backward-defun))
1624 (python-tests-look-at " class B(object): # B" -1)))
1625 (should (= (save-excursion (python-nav-backward-defun))
1626 (python-tests-look-at " def b(self): # b" -1)))
1627 (should (= (save-excursion (python-nav-backward-defun))
1628 (python-tests-look-at " def a(self): # a" -1)))
1629 (should (= (save-excursion (python-nav-backward-defun))
1630 (python-tests-look-at "class A(object): # A" -1)))
1631 (should (not (python-nav-backward-defun)))))
1632
1633 (ert-deftest python-nav-backward-defun-2 ()
1634 (python-tests-with-temp-buffer
1635 "
1636 def decoratorFunctionWithArguments(arg1, arg2, arg3):
1637 '''print decorated function call data to stdout.
1638
1639 Usage:
1640
1641 @decoratorFunctionWithArguments('arg1', 'arg2')
1642 def func(a, b, c=True):
1643 pass
1644 '''
1645
1646 def wwrap(f):
1647 print 'Inside wwrap()'
1648 def wrapped_f(*args):
1649 print 'Inside wrapped_f()'
1650 print 'Decorator arguments:', arg1, arg2, arg3
1651 f(*args)
1652 print 'After f(*args)'
1653 return wrapped_f
1654 return wwrap
1655 "
1656 (goto-char (point-max))
1657 (should (= (save-excursion (python-nav-backward-defun))
1658 (python-tests-look-at " def wrapped_f(*args):" -1)))
1659 (should (= (save-excursion (python-nav-backward-defun))
1660 (python-tests-look-at " def wwrap(f):" -1)))
1661 (should (= (save-excursion (python-nav-backward-defun))
1662 (python-tests-look-at "def decoratorFunctionWithArguments(arg1, arg2, arg3):" -1)))
1663 (should (not (python-nav-backward-defun)))))
1664
1665 (ert-deftest python-nav-backward-defun-3 ()
1666 (python-tests-with-temp-buffer
1667 "
1668 '''
1669 def u(self):
1670 pass
1671
1672 def v(self):
1673 pass
1674
1675 def w(self):
1676 pass
1677 '''
1678
1679 class A(object):
1680 pass
1681 "
1682 (goto-char (point-min))
1683 (let ((point (python-tests-look-at "class A(object):")))
1684 (should (not (python-nav-backward-defun)))
1685 (should (= point (point))))))
1686
1687 (ert-deftest python-nav-forward-defun-1 ()
1688 (python-tests-with-temp-buffer
1689 "
1690 class A(object): # A
1691
1692 def a(self): # a
1693 pass
1694
1695 def b(self): # b
1696 pass
1697
1698 class B(object): # B
1699
1700 class C(object): # C
1701
1702 def d(self): # d
1703 pass
1704
1705 # def e(self): # e
1706 # pass
1707
1708 def c(self): # c
1709 pass
1710
1711 # def d(self): # d
1712 # pass
1713 "
1714 (goto-char (point-min))
1715 (should (= (save-excursion (python-nav-forward-defun))
1716 (python-tests-look-at "(object): # A")))
1717 (should (= (save-excursion (python-nav-forward-defun))
1718 (python-tests-look-at "(self): # a")))
1719 (should (= (save-excursion (python-nav-forward-defun))
1720 (python-tests-look-at "(self): # b")))
1721 (should (= (save-excursion (python-nav-forward-defun))
1722 (python-tests-look-at "(object): # B")))
1723 (should (= (save-excursion (python-nav-forward-defun))
1724 (python-tests-look-at "(object): # C")))
1725 (should (= (save-excursion (python-nav-forward-defun))
1726 (python-tests-look-at "(self): # d")))
1727 (should (= (save-excursion (python-nav-forward-defun))
1728 (python-tests-look-at "(self): # c")))
1729 (should (not (python-nav-forward-defun)))))
1730
1731 (ert-deftest python-nav-forward-defun-2 ()
1732 (python-tests-with-temp-buffer
1733 "
1734 def decoratorFunctionWithArguments(arg1, arg2, arg3):
1735 '''print decorated function call data to stdout.
1736
1737 Usage:
1738
1739 @decoratorFunctionWithArguments('arg1', 'arg2')
1740 def func(a, b, c=True):
1741 pass
1742 '''
1743
1744 def wwrap(f):
1745 print 'Inside wwrap()'
1746 def wrapped_f(*args):
1747 print 'Inside wrapped_f()'
1748 print 'Decorator arguments:', arg1, arg2, arg3
1749 f(*args)
1750 print 'After f(*args)'
1751 return wrapped_f
1752 return wwrap
1753 "
1754 (goto-char (point-min))
1755 (should (= (save-excursion (python-nav-forward-defun))
1756 (python-tests-look-at "(arg1, arg2, arg3):")))
1757 (should (= (save-excursion (python-nav-forward-defun))
1758 (python-tests-look-at "(f):")))
1759 (should (= (save-excursion (python-nav-forward-defun))
1760 (python-tests-look-at "(*args):")))
1761 (should (not (python-nav-forward-defun)))))
1762
1763 (ert-deftest python-nav-forward-defun-3 ()
1764 (python-tests-with-temp-buffer
1765 "
1766 class A(object):
1767 pass
1768
1769 '''
1770 def u(self):
1771 pass
1772
1773 def v(self):
1774 pass
1775
1776 def w(self):
1777 pass
1778 '''
1779 "
1780 (goto-char (point-min))
1781 (let ((point (python-tests-look-at "(object):")))
1782 (should (not (python-nav-forward-defun)))
1783 (should (= point (point))))))
1784
1785 (ert-deftest python-nav-beginning-of-statement-1 ()
1786 (python-tests-with-temp-buffer
1787 "
1788 v1 = 123 + \
1789 456 + \
1790 789
1791 v2 = (value1,
1792 value2,
1793
1794 value3,
1795 value4)
1796 v3 = ('this is a string'
1797
1798 'that is continued'
1799 'between lines'
1800 'within a paren',
1801 # this is a comment, yo
1802 'continue previous line')
1803 v4 = '''
1804 a very long
1805 string
1806 '''
1807 "
1808 (python-tests-look-at "v2 =")
1809 (python-util-forward-comment -1)
1810 (should (= (save-excursion
1811 (python-nav-beginning-of-statement)
1812 (point))
1813 (python-tests-look-at "v1 =" -1 t)))
1814 (python-tests-look-at "v3 =")
1815 (python-util-forward-comment -1)
1816 (should (= (save-excursion
1817 (python-nav-beginning-of-statement)
1818 (point))
1819 (python-tests-look-at "v2 =" -1 t)))
1820 (python-tests-look-at "v4 =")
1821 (python-util-forward-comment -1)
1822 (should (= (save-excursion
1823 (python-nav-beginning-of-statement)
1824 (point))
1825 (python-tests-look-at "v3 =" -1 t)))
1826 (goto-char (point-max))
1827 (python-util-forward-comment -1)
1828 (should (= (save-excursion
1829 (python-nav-beginning-of-statement)
1830 (point))
1831 (python-tests-look-at "v4 =" -1 t)))))
1832
1833 (ert-deftest python-nav-end-of-statement-1 ()
1834 (python-tests-with-temp-buffer
1835 "
1836 v1 = 123 + \
1837 456 + \
1838 789
1839 v2 = (value1,
1840 value2,
1841
1842 value3,
1843 value4)
1844 v3 = ('this is a string'
1845
1846 'that is continued'
1847 'between lines'
1848 'within a paren',
1849 # this is a comment, yo
1850 'continue previous line')
1851 v4 = '''
1852 a very long
1853 string
1854 '''
1855 "
1856 (python-tests-look-at "v1 =")
1857 (should (= (save-excursion
1858 (python-nav-end-of-statement)
1859 (point))
1860 (save-excursion
1861 (python-tests-look-at "789")
1862 (line-end-position))))
1863 (python-tests-look-at "v2 =")
1864 (should (= (save-excursion
1865 (python-nav-end-of-statement)
1866 (point))
1867 (save-excursion
1868 (python-tests-look-at "value4)")
1869 (line-end-position))))
1870 (python-tests-look-at "v3 =")
1871 (should (= (save-excursion
1872 (python-nav-end-of-statement)
1873 (point))
1874 (save-excursion
1875 (python-tests-look-at
1876 "'continue previous line')")
1877 (line-end-position))))
1878 (python-tests-look-at "v4 =")
1879 (should (= (save-excursion
1880 (python-nav-end-of-statement)
1881 (point))
1882 (save-excursion
1883 (goto-char (point-max))
1884 (python-util-forward-comment -1)
1885 (point))))))
1886
1887 (ert-deftest python-nav-forward-statement-1 ()
1888 (python-tests-with-temp-buffer
1889 "
1890 v1 = 123 + \
1891 456 + \
1892 789
1893 v2 = (value1,
1894 value2,
1895
1896 value3,
1897 value4)
1898 v3 = ('this is a string'
1899
1900 'that is continued'
1901 'between lines'
1902 'within a paren',
1903 # this is a comment, yo
1904 'continue previous line')
1905 v4 = '''
1906 a very long
1907 string
1908 '''
1909 "
1910 (python-tests-look-at "v1 =")
1911 (should (= (save-excursion
1912 (python-nav-forward-statement)
1913 (point))
1914 (python-tests-look-at "v2 =")))
1915 (should (= (save-excursion
1916 (python-nav-forward-statement)
1917 (point))
1918 (python-tests-look-at "v3 =")))
1919 (should (= (save-excursion
1920 (python-nav-forward-statement)
1921 (point))
1922 (python-tests-look-at "v4 =")))
1923 (should (= (save-excursion
1924 (python-nav-forward-statement)
1925 (point))
1926 (point-max)))))
1927
1928 (ert-deftest python-nav-backward-statement-1 ()
1929 (python-tests-with-temp-buffer
1930 "
1931 v1 = 123 + \
1932 456 + \
1933 789
1934 v2 = (value1,
1935 value2,
1936
1937 value3,
1938 value4)
1939 v3 = ('this is a string'
1940
1941 'that is continued'
1942 'between lines'
1943 'within a paren',
1944 # this is a comment, yo
1945 'continue previous line')
1946 v4 = '''
1947 a very long
1948 string
1949 '''
1950 "
1951 (goto-char (point-max))
1952 (should (= (save-excursion
1953 (python-nav-backward-statement)
1954 (point))
1955 (python-tests-look-at "v4 =" -1)))
1956 (should (= (save-excursion
1957 (python-nav-backward-statement)
1958 (point))
1959 (python-tests-look-at "v3 =" -1)))
1960 (should (= (save-excursion
1961 (python-nav-backward-statement)
1962 (point))
1963 (python-tests-look-at "v2 =" -1)))
1964 (should (= (save-excursion
1965 (python-nav-backward-statement)
1966 (point))
1967 (python-tests-look-at "v1 =" -1)))))
1968
1969 (ert-deftest python-nav-backward-statement-2 ()
1970 :expected-result :failed
1971 (python-tests-with-temp-buffer
1972 "
1973 v1 = 123 + \
1974 456 + \
1975 789
1976 v2 = (value1,
1977 value2,
1978
1979 value3,
1980 value4)
1981 "
1982 ;; FIXME: For some reason `python-nav-backward-statement' is moving
1983 ;; back two sentences when starting from 'value4)'.
1984 (goto-char (point-max))
1985 (python-util-forward-comment -1)
1986 (should (= (save-excursion
1987 (python-nav-backward-statement)
1988 (point))
1989 (python-tests-look-at "v2 =" -1 t)))))
1990
1991 (ert-deftest python-nav-beginning-of-block-1 ()
1992 (python-tests-with-temp-buffer
1993 "
1994 def decoratorFunctionWithArguments(arg1, arg2, arg3):
1995 '''print decorated function call data to stdout.
1996
1997 Usage:
1998
1999 @decoratorFunctionWithArguments('arg1', 'arg2')
2000 def func(a, b, c=True):
2001 pass
2002 '''
2003
2004 def wwrap(f):
2005 print 'Inside wwrap()'
2006 def wrapped_f(*args):
2007 print 'Inside wrapped_f()'
2008 print 'Decorator arguments:', arg1, arg2, arg3
2009 f(*args)
2010 print 'After f(*args)'
2011 return wrapped_f
2012 return wwrap
2013 "
2014 (python-tests-look-at "return wwrap")
2015 (should (= (save-excursion
2016 (python-nav-beginning-of-block)
2017 (point))
2018 (python-tests-look-at "def decoratorFunctionWithArguments" -1)))
2019 (python-tests-look-at "print 'Inside wwrap()'")
2020 (should (= (save-excursion
2021 (python-nav-beginning-of-block)
2022 (point))
2023 (python-tests-look-at "def wwrap(f):" -1)))
2024 (python-tests-look-at "print 'After f(*args)'")
2025 (end-of-line)
2026 (should (= (save-excursion
2027 (python-nav-beginning-of-block)
2028 (point))
2029 (python-tests-look-at "def wrapped_f(*args):" -1)))
2030 (python-tests-look-at "return wrapped_f")
2031 (should (= (save-excursion
2032 (python-nav-beginning-of-block)
2033 (point))
2034 (python-tests-look-at "def wwrap(f):" -1)))))
2035
2036 (ert-deftest python-nav-end-of-block-1 ()
2037 (python-tests-with-temp-buffer
2038 "
2039 def decoratorFunctionWithArguments(arg1, arg2, arg3):
2040 '''print decorated function call data to stdout.
2041
2042 Usage:
2043
2044 @decoratorFunctionWithArguments('arg1', 'arg2')
2045 def func(a, b, c=True):
2046 pass
2047 '''
2048
2049 def wwrap(f):
2050 print 'Inside wwrap()'
2051 def wrapped_f(*args):
2052 print 'Inside wrapped_f()'
2053 print 'Decorator arguments:', arg1, arg2, arg3
2054 f(*args)
2055 print 'After f(*args)'
2056 return wrapped_f
2057 return wwrap
2058 "
2059 (python-tests-look-at "def decoratorFunctionWithArguments")
2060 (should (= (save-excursion
2061 (python-nav-end-of-block)
2062 (point))
2063 (save-excursion
2064 (goto-char (point-max))
2065 (python-util-forward-comment -1)
2066 (point))))
2067 (python-tests-look-at "def wwrap(f):")
2068 (should (= (save-excursion
2069 (python-nav-end-of-block)
2070 (point))
2071 (save-excursion
2072 (python-tests-look-at "return wrapped_f")
2073 (line-end-position))))
2074 (end-of-line)
2075 (should (= (save-excursion
2076 (python-nav-end-of-block)
2077 (point))
2078 (save-excursion
2079 (python-tests-look-at "return wrapped_f")
2080 (line-end-position))))
2081 (python-tests-look-at "f(*args)")
2082 (should (= (save-excursion
2083 (python-nav-end-of-block)
2084 (point))
2085 (save-excursion
2086 (python-tests-look-at "print 'After f(*args)'")
2087 (line-end-position))))))
2088
2089 (ert-deftest python-nav-forward-block-1 ()
2090 "This also accounts as a test for `python-nav-backward-block'."
2091 (python-tests-with-temp-buffer
2092 "
2093 if request.user.is_authenticated():
2094 # def block():
2095 # pass
2096 try:
2097 profile = request.user.get_profile()
2098 except Profile.DoesNotExist:
2099 profile = Profile.objects.create(user=request.user)
2100 else:
2101 if profile.stats:
2102 profile.recalculate_stats()
2103 else:
2104 profile.clear_stats()
2105 finally:
2106 profile.views += 1
2107 profile.save()
2108 "
2109 (should (= (save-excursion (python-nav-forward-block))
2110 (python-tests-look-at "if request.user.is_authenticated():")))
2111 (should (= (save-excursion (python-nav-forward-block))
2112 (python-tests-look-at "try:")))
2113 (should (= (save-excursion (python-nav-forward-block))
2114 (python-tests-look-at "except Profile.DoesNotExist:")))
2115 (should (= (save-excursion (python-nav-forward-block))
2116 (python-tests-look-at "else:")))
2117 (should (= (save-excursion (python-nav-forward-block))
2118 (python-tests-look-at "if profile.stats:")))
2119 (should (= (save-excursion (python-nav-forward-block))
2120 (python-tests-look-at "else:")))
2121 (should (= (save-excursion (python-nav-forward-block))
2122 (python-tests-look-at "finally:")))
2123 ;; When point is at the last block, leave it there and return nil
2124 (should (not (save-excursion (python-nav-forward-block))))
2125 ;; Move backwards, and even if the number of moves is less than the
2126 ;; provided argument return the point.
2127 (should (= (save-excursion (python-nav-forward-block -10))
2128 (python-tests-look-at
2129 "if request.user.is_authenticated():" -1)))))
2130
2131 (ert-deftest python-nav-forward-sexp-1 ()
2132 (python-tests-with-temp-buffer
2133 "
2134 a()
2135 b()
2136 c()
2137 "
2138 (python-tests-look-at "a()")
2139 (python-nav-forward-sexp)
2140 (should (looking-at "$"))
2141 (should (save-excursion
2142 (beginning-of-line)
2143 (looking-at "a()")))
2144 (python-nav-forward-sexp)
2145 (should (looking-at "$"))
2146 (should (save-excursion
2147 (beginning-of-line)
2148 (looking-at "b()")))
2149 (python-nav-forward-sexp)
2150 (should (looking-at "$"))
2151 (should (save-excursion
2152 (beginning-of-line)
2153 (looking-at "c()")))
2154 ;; The default behavior when next to a paren should do what lisp
2155 ;; does and, otherwise `blink-matching-open' breaks.
2156 (python-nav-forward-sexp -1)
2157 (should (looking-at "()"))
2158 (should (save-excursion
2159 (beginning-of-line)
2160 (looking-at "c()")))
2161 (end-of-line)
2162 ;; Skipping parens should jump to `bolp'
2163 (python-nav-forward-sexp -1 nil t)
2164 (should (looking-at "c()"))
2165 (forward-line -1)
2166 (end-of-line)
2167 ;; b()
2168 (python-nav-forward-sexp -1)
2169 (should (looking-at "()"))
2170 (python-nav-forward-sexp -1)
2171 (should (looking-at "b()"))
2172 (end-of-line)
2173 (python-nav-forward-sexp -1 nil t)
2174 (should (looking-at "b()"))
2175 (forward-line -1)
2176 (end-of-line)
2177 ;; a()
2178 (python-nav-forward-sexp -1)
2179 (should (looking-at "()"))
2180 (python-nav-forward-sexp -1)
2181 (should (looking-at "a()"))
2182 (end-of-line)
2183 (python-nav-forward-sexp -1 nil t)
2184 (should (looking-at "a()"))))
2185
2186 (ert-deftest python-nav-forward-sexp-2 ()
2187 (python-tests-with-temp-buffer
2188 "
2189 def func():
2190 if True:
2191 aaa = bbb
2192 ccc = ddd
2193 eee = fff
2194 return ggg
2195 "
2196 (python-tests-look-at "aa =")
2197 (python-nav-forward-sexp)
2198 (should (looking-at " = bbb"))
2199 (python-nav-forward-sexp)
2200 (should (looking-at "$"))
2201 (should (save-excursion
2202 (back-to-indentation)
2203 (looking-at "aaa = bbb")))
2204 (python-nav-forward-sexp)
2205 (should (looking-at "$"))
2206 (should (save-excursion
2207 (back-to-indentation)
2208 (looking-at "ccc = ddd")))
2209 (python-nav-forward-sexp)
2210 (should (looking-at "$"))
2211 (should (save-excursion
2212 (back-to-indentation)
2213 (looking-at "eee = fff")))
2214 (python-nav-forward-sexp)
2215 (should (looking-at "$"))
2216 (should (save-excursion
2217 (back-to-indentation)
2218 (looking-at "return ggg")))
2219 (python-nav-forward-sexp -1)
2220 (should (looking-at "def func():"))))
2221
2222 (ert-deftest python-nav-forward-sexp-3 ()
2223 (python-tests-with-temp-buffer
2224 "
2225 from some_module import some_sub_module
2226 from another_module import another_sub_module
2227
2228 def another_statement():
2229 pass
2230 "
2231 (python-tests-look-at "some_module")
2232 (python-nav-forward-sexp)
2233 (should (looking-at " import"))
2234 (python-nav-forward-sexp)
2235 (should (looking-at " some_sub_module"))
2236 (python-nav-forward-sexp)
2237 (should (looking-at "$"))
2238 (should
2239 (save-excursion
2240 (back-to-indentation)
2241 (looking-at
2242 "from some_module import some_sub_module")))
2243 (python-nav-forward-sexp)
2244 (should (looking-at "$"))
2245 (should
2246 (save-excursion
2247 (back-to-indentation)
2248 (looking-at
2249 "from another_module import another_sub_module")))
2250 (python-nav-forward-sexp)
2251 (should (looking-at "$"))
2252 (should
2253 (save-excursion
2254 (back-to-indentation)
2255 (looking-at
2256 "pass")))
2257 (python-nav-forward-sexp -1)
2258 (should (looking-at "def another_statement():"))
2259 (python-nav-forward-sexp -1)
2260 (should (looking-at "from another_module import another_sub_module"))
2261 (python-nav-forward-sexp -1)
2262 (should (looking-at "from some_module import some_sub_module"))))
2263
2264 (ert-deftest python-nav-forward-sexp-safe-1 ()
2265 (python-tests-with-temp-buffer
2266 "
2267 profile = Profile.objects.create(user=request.user)
2268 profile.notify()
2269 "
2270 (python-tests-look-at "profile =")
2271 (python-nav-forward-sexp-safe 1)
2272 (should (looking-at "$"))
2273 (beginning-of-line 1)
2274 (python-tests-look-at "user=request.user")
2275 (python-nav-forward-sexp-safe -1)
2276 (should (looking-at "(user=request.user)"))
2277 (python-nav-forward-sexp-safe -4)
2278 (should (looking-at "profile ="))
2279 (python-tests-look-at "user=request.user")
2280 (python-nav-forward-sexp-safe 3)
2281 (should (looking-at ")"))
2282 (python-nav-forward-sexp-safe 1)
2283 (should (looking-at "$"))
2284 (python-nav-forward-sexp-safe 1)
2285 (should (looking-at "$"))))
2286
2287 (ert-deftest python-nav-up-list-1 ()
2288 (python-tests-with-temp-buffer
2289 "
2290 def f():
2291 if True:
2292 return [i for i in range(3)]
2293 "
2294 (python-tests-look-at "3)]")
2295 (python-nav-up-list)
2296 (should (looking-at "]"))
2297 (python-nav-up-list)
2298 (should (looking-at "$"))))
2299
2300 (ert-deftest python-nav-backward-up-list-1 ()
2301 :expected-result :failed
2302 (python-tests-with-temp-buffer
2303 "
2304 def f():
2305 if True:
2306 return [i for i in range(3)]
2307 "
2308 (python-tests-look-at "3)]")
2309 (python-nav-backward-up-list)
2310 (should (looking-at "(3)\\]"))
2311 (python-nav-backward-up-list)
2312 (should (looking-at
2313 "\\[i for i in range(3)\\]"))
2314 ;; FIXME: Need to move to beginning-of-statement.
2315 (python-nav-backward-up-list)
2316 (should (looking-at
2317 "return \\[i for i in range(3)\\]"))
2318 (python-nav-backward-up-list)
2319 (should (looking-at "if True:"))
2320 (python-nav-backward-up-list)
2321 (should (looking-at "def f():"))))
2322
2323 (ert-deftest python-indent-dedent-line-backspace-1 ()
2324 "Check de-indentation on first call. Bug#18319."
2325 (python-tests-with-temp-buffer
2326 "
2327 if True:
2328 x ()
2329 if False:
2330 "
2331 (python-tests-look-at "if False:")
2332 (call-interactively #'python-indent-dedent-line-backspace)
2333 (should (zerop (current-indentation)))
2334 ;; XXX: This should be a call to `undo' but it's triggering errors.
2335 (insert " ")
2336 (should (= (current-indentation) 4))
2337 (call-interactively #'python-indent-dedent-line-backspace)
2338 (should (zerop (current-indentation)))))
2339
2340 (ert-deftest python-indent-dedent-line-backspace-2 ()
2341 "Check de-indentation with tabs. Bug#19730."
2342 (let ((tab-width 8))
2343 (python-tests-with-temp-buffer
2344 "
2345 if x:
2346 \tabcdefg
2347 "
2348 (python-tests-look-at "abcdefg")
2349 (goto-char (line-end-position))
2350 (call-interactively #'python-indent-dedent-line-backspace)
2351 (should
2352 (string= (buffer-substring-no-properties
2353 (line-beginning-position) (line-end-position))
2354 "\tabcdef")))))
2355
2356 (ert-deftest python-indent-dedent-line-backspace-3 ()
2357 "Paranoid check of de-indentation with tabs. Bug#19730."
2358 (let ((tab-width 8))
2359 (python-tests-with-temp-buffer
2360 "
2361 if x:
2362 \tif y:
2363 \t abcdefg
2364 "
2365 (python-tests-look-at "abcdefg")
2366 (goto-char (line-end-position))
2367 (call-interactively #'python-indent-dedent-line-backspace)
2368 (should
2369 (string= (buffer-substring-no-properties
2370 (line-beginning-position) (line-end-position))
2371 "\t abcdef"))
2372 (back-to-indentation)
2373 (call-interactively #'python-indent-dedent-line-backspace)
2374 (should
2375 (string= (buffer-substring-no-properties
2376 (line-beginning-position) (line-end-position))
2377 "\tabcdef"))
2378 (call-interactively #'python-indent-dedent-line-backspace)
2379 (should
2380 (string= (buffer-substring-no-properties
2381 (line-beginning-position) (line-end-position))
2382 " abcdef"))
2383 (call-interactively #'python-indent-dedent-line-backspace)
2384 (should
2385 (string= (buffer-substring-no-properties
2386 (line-beginning-position) (line-end-position))
2387 "abcdef")))))
2388
2389 \f
2390 ;;; Shell integration
2391
2392 (defvar python-tests-shell-interpreter "python")
2393
2394 (ert-deftest python-shell-get-process-name-1 ()
2395 "Check process name calculation sans `buffer-file-name'."
2396 (python-tests-with-temp-buffer
2397 ""
2398 (should (string= (python-shell-get-process-name nil)
2399 python-shell-buffer-name))
2400 (should (string= (python-shell-get-process-name t)
2401 (format "%s[%s]" python-shell-buffer-name (buffer-name))))))
2402
2403 (ert-deftest python-shell-get-process-name-2 ()
2404 "Check process name calculation with `buffer-file-name'."
2405 (python-tests-with-temp-file
2406 ""
2407 ;; `buffer-file-name' is non-nil but the dedicated flag is nil and
2408 ;; should be respected.
2409 (should (string= (python-shell-get-process-name nil)
2410 python-shell-buffer-name))
2411 (should (string=
2412 (python-shell-get-process-name t)
2413 (format "%s[%s]" python-shell-buffer-name (buffer-name))))))
2414
2415 (ert-deftest python-shell-internal-get-process-name-1 ()
2416 "Check the internal process name is buffer-unique sans `buffer-file-name'."
2417 (python-tests-with-temp-buffer
2418 ""
2419 (should (string= (python-shell-internal-get-process-name)
2420 (format "%s[%s]" python-shell-internal-buffer-name (buffer-name))))))
2421
2422 (ert-deftest python-shell-internal-get-process-name-2 ()
2423 "Check the internal process name is buffer-unique with `buffer-file-name'."
2424 (python-tests-with-temp-file
2425 ""
2426 (should (string= (python-shell-internal-get-process-name)
2427 (format "%s[%s]" python-shell-internal-buffer-name (buffer-name))))))
2428
2429 (ert-deftest python-shell-calculate-command-1 ()
2430 "Check the command to execute is calculated correctly.
2431 Using `python-shell-interpreter' and
2432 `python-shell-interpreter-args'."
2433 (skip-unless (executable-find python-tests-shell-interpreter))
2434 (let ((python-shell-interpreter (executable-find
2435 python-tests-shell-interpreter))
2436 (python-shell-interpreter-args "-B"))
2437 (should (string=
2438 (format "%s %s"
2439 (shell-quote-argument python-shell-interpreter)
2440 python-shell-interpreter-args)
2441 (python-shell-calculate-command)))))
2442
2443 (ert-deftest python-shell-calculate-pythonpath-1 ()
2444 "Test PYTHONPATH calculation."
2445 (let ((process-environment '("PYTHONPATH=/path0"))
2446 (python-shell-extra-pythonpaths '("/path1" "/path2")))
2447 (should (string= (python-shell-calculate-pythonpath)
2448 (concat "/path1" path-separator
2449 "/path2" path-separator "/path0")))))
2450
2451 (ert-deftest python-shell-calculate-pythonpath-2 ()
2452 "Test existing paths are moved to front."
2453 (let ((process-environment
2454 (list (concat "PYTHONPATH=/path0" path-separator "/path1")))
2455 (python-shell-extra-pythonpaths '("/path1" "/path2")))
2456 (should (string= (python-shell-calculate-pythonpath)
2457 (concat "/path1" path-separator
2458 "/path2" path-separator "/path0")))))
2459
2460 (ert-deftest python-shell-calculate-process-environment-1 ()
2461 "Test `python-shell-process-environment' modification."
2462 (let* ((python-shell-process-environment
2463 '("TESTVAR1=value1" "TESTVAR2=value2"))
2464 (process-environment (python-shell-calculate-process-environment)))
2465 (should (equal (getenv "TESTVAR1") "value1"))
2466 (should (equal (getenv "TESTVAR2") "value2"))))
2467
2468 (ert-deftest python-shell-calculate-process-environment-2 ()
2469 "Test `python-shell-extra-pythonpaths' modification."
2470 (let* ((process-environment process-environment)
2471 (original-pythonpath (setenv "PYTHONPATH" "/path0"))
2472 (python-shell-extra-pythonpaths '("/path1" "/path2"))
2473 (process-environment (python-shell-calculate-process-environment)))
2474 (should (equal (getenv "PYTHONPATH")
2475 (concat "/path1" path-separator
2476 "/path2" path-separator "/path0")))))
2477
2478 (ert-deftest python-shell-calculate-process-environment-3 ()
2479 "Test `python-shell-virtualenv-root' modification."
2480 (let* ((python-shell-virtualenv-root "/env")
2481 (process-environment
2482 (let (process-environment process-environment)
2483 (setenv "PYTHONHOME" "/home")
2484 (setenv "VIRTUAL_ENV")
2485 (python-shell-calculate-process-environment))))
2486 (should (not (getenv "PYTHONHOME")))
2487 (should (string= (getenv "VIRTUAL_ENV") "/env"))))
2488
2489 (ert-deftest python-shell-calculate-process-environment-4 ()
2490 "Test PYTHONUNBUFFERED when `python-shell-unbuffered' is non-nil."
2491 (let* ((python-shell-unbuffered t)
2492 (process-environment
2493 (let ((process-environment process-environment))
2494 (setenv "PYTHONUNBUFFERED")
2495 (python-shell-calculate-process-environment))))
2496 (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
2497
2498 (ert-deftest python-shell-calculate-process-environment-5 ()
2499 "Test PYTHONUNBUFFERED when `python-shell-unbuffered' is nil."
2500 (let* ((python-shell-unbuffered nil)
2501 (process-environment
2502 (let ((process-environment process-environment))
2503 (setenv "PYTHONUNBUFFERED")
2504 (python-shell-calculate-process-environment))))
2505 (should (not (getenv "PYTHONUNBUFFERED")))))
2506
2507 (ert-deftest python-shell-calculate-process-environment-6 ()
2508 "Test PYTHONUNBUFFERED=1 when `python-shell-unbuffered' is nil."
2509 (let* ((python-shell-unbuffered nil)
2510 (process-environment
2511 (let ((process-environment process-environment))
2512 (setenv "PYTHONUNBUFFERED" "1")
2513 (python-shell-calculate-process-environment))))
2514 ;; User default settings must remain untouched:
2515 (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
2516
2517 (ert-deftest python-shell-calculate-process-environment-7 ()
2518 "Test no side-effects on `process-environment'."
2519 (let* ((python-shell-process-environment
2520 '("TESTVAR1=value1" "TESTVAR2=value2"))
2521 (python-shell-virtualenv-root "/env")
2522 (python-shell-unbuffered t)
2523 (python-shell-extra-pythonpaths'("/path1" "/path2"))
2524 (original-process-environment (copy-sequence process-environment)))
2525 (python-shell-calculate-process-environment)
2526 (should (equal process-environment original-process-environment))))
2527
2528 (ert-deftest python-shell-calculate-process-environment-8 ()
2529 "Test no side-effects on `tramp-remote-process-environment'."
2530 (let* ((default-directory "/ssh::/example/dir/")
2531 (python-shell-process-environment
2532 '("TESTVAR1=value1" "TESTVAR2=value2"))
2533 (python-shell-virtualenv-root "/env")
2534 (python-shell-unbuffered t)
2535 (python-shell-extra-pythonpaths'("/path1" "/path2"))
2536 (original-process-environment
2537 (copy-sequence tramp-remote-process-environment)))
2538 (python-shell-calculate-process-environment)
2539 (should (equal tramp-remote-process-environment original-process-environment))))
2540
2541 (ert-deftest python-shell-calculate-exec-path-1 ()
2542 "Test `python-shell-exec-path' modification."
2543 (let* ((exec-path '("/path0"))
2544 (python-shell-exec-path '("/path1" "/path2"))
2545 (new-exec-path (python-shell-calculate-exec-path)))
2546 (should (equal new-exec-path '("/path1" "/path2" "/path0")))))
2547
2548 (ert-deftest python-shell-calculate-exec-path-2 ()
2549 "Test `python-shell-virtualenv-root' modification."
2550 (let* ((exec-path '("/path0"))
2551 (python-shell-virtualenv-root "/env")
2552 (new-exec-path (python-shell-calculate-exec-path)))
2553 (should (equal new-exec-path
2554 (list (expand-file-name "/env/bin") "/path0")))))
2555
2556 (ert-deftest python-shell-calculate-exec-path-3 ()
2557 "Test complete `python-shell-virtualenv-root' modification."
2558 (let* ((exec-path '("/path0"))
2559 (python-shell-exec-path '("/path1" "/path2"))
2560 (python-shell-virtualenv-root "/env")
2561 (new-exec-path (python-shell-calculate-exec-path)))
2562 (should (equal new-exec-path
2563 (list (expand-file-name "/env/bin")
2564 "/path1" "/path2" "/path0")))))
2565
2566 (ert-deftest python-shell-calculate-exec-path-4 ()
2567 "Test complete `python-shell-virtualenv-root' with remote."
2568 (let* ((default-directory "/ssh::/example/dir/")
2569 (python-shell-remote-exec-path '("/path0"))
2570 (python-shell-exec-path '("/path1" "/path2"))
2571 (python-shell-virtualenv-root "/env")
2572 (new-exec-path (python-shell-calculate-exec-path)))
2573 (should (equal new-exec-path
2574 (list (expand-file-name "/env/bin")
2575 "/path1" "/path2" "/path0")))))
2576
2577 (ert-deftest python-shell-calculate-exec-path-5 ()
2578 "Test no side-effects on `exec-path'."
2579 (let* ((exec-path '("/path0"))
2580 (python-shell-exec-path '("/path1" "/path2"))
2581 (python-shell-virtualenv-root "/env")
2582 (original-exec-path (copy-sequence exec-path)))
2583 (python-shell-calculate-exec-path)
2584 (should (equal exec-path original-exec-path))))
2585
2586 (ert-deftest python-shell-calculate-exec-path-6 ()
2587 "Test no side-effects on `python-shell-remote-exec-path'."
2588 (let* ((default-directory "/ssh::/example/dir/")
2589 (python-shell-remote-exec-path '("/path0"))
2590 (python-shell-exec-path '("/path1" "/path2"))
2591 (python-shell-virtualenv-root "/env")
2592 (original-exec-path (copy-sequence python-shell-remote-exec-path)))
2593 (python-shell-calculate-exec-path)
2594 (should (equal python-shell-remote-exec-path original-exec-path))))
2595
2596 (ert-deftest python-shell-with-environment-1 ()
2597 "Test environment with local `default-directory'."
2598 (let* ((exec-path '("/path0"))
2599 (python-shell-exec-path '("/path1" "/path2"))
2600 (original-exec-path exec-path)
2601 (python-shell-virtualenv-root "/env"))
2602 (python-shell-with-environment
2603 (should (equal exec-path
2604 (list (expand-file-name "/env/bin")
2605 "/path1" "/path2" "/path0")))
2606 (should (not (getenv "PYTHONHOME")))
2607 (should (string= (getenv "VIRTUAL_ENV") "/env")))
2608 (should (equal exec-path original-exec-path))))
2609
2610 (ert-deftest python-shell-with-environment-2 ()
2611 "Test environment with remote `default-directory'."
2612 (let* ((default-directory "/ssh::/example/dir/")
2613 (python-shell-remote-exec-path '("/remote1" "/remote2"))
2614 (python-shell-exec-path '("/path1" "/path2"))
2615 (tramp-remote-process-environment '("EMACS=t"))
2616 (original-process-environment (copy-sequence tramp-remote-process-environment))
2617 (python-shell-virtualenv-root "/env"))
2618 (python-shell-with-environment
2619 (should (equal (python-shell-calculate-exec-path)
2620 (list (expand-file-name "/env/bin")
2621 "/path1" "/path2" "/remote1" "/remote2")))
2622 (let ((process-environment (python-shell-calculate-process-environment)))
2623 (should (not (getenv "PYTHONHOME")))
2624 (should (string= (getenv "VIRTUAL_ENV") "/env"))
2625 (should (equal tramp-remote-process-environment process-environment))))
2626 (should (equal tramp-remote-process-environment original-process-environment))))
2627
2628 (ert-deftest python-shell-with-environment-3 ()
2629 "Test `python-shell-with-environment' is idempotent."
2630 (let* ((python-shell-extra-pythonpaths '("/example/dir/"))
2631 (python-shell-exec-path '("path1" "path2"))
2632 (python-shell-virtualenv-root "/home/user/env")
2633 (single-call
2634 (python-shell-with-environment
2635 (list exec-path process-environment)))
2636 (nested-call
2637 (python-shell-with-environment
2638 (python-shell-with-environment
2639 (list exec-path process-environment)))))
2640 (should (equal single-call nested-call))))
2641
2642 (ert-deftest python-shell-make-comint-1 ()
2643 "Check comint creation for global shell buffer."
2644 (skip-unless (executable-find python-tests-shell-interpreter))
2645 ;; The interpreter can get killed too quickly to allow it to clean
2646 ;; up the tempfiles that the default python-shell-setup-codes create,
2647 ;; so it leaves tempfiles behind, which is a minor irritation.
2648 (let* ((python-shell-setup-codes nil)
2649 (python-shell-interpreter
2650 (executable-find python-tests-shell-interpreter))
2651 (proc-name (python-shell-get-process-name nil))
2652 (shell-buffer
2653 (python-tests-with-temp-buffer
2654 "" (python-shell-make-comint
2655 (python-shell-calculate-command) proc-name)))
2656 (process (get-buffer-process shell-buffer)))
2657 (unwind-protect
2658 (progn
2659 (set-process-query-on-exit-flag process nil)
2660 (should (process-live-p process))
2661 (with-current-buffer shell-buffer
2662 (should (eq major-mode 'inferior-python-mode))
2663 (should (string= (buffer-name) (format "*%s*" proc-name)))))
2664 (kill-buffer shell-buffer))))
2665
2666 (ert-deftest python-shell-make-comint-2 ()
2667 "Check comint creation for internal shell buffer."
2668 (skip-unless (executable-find python-tests-shell-interpreter))
2669 (let* ((python-shell-setup-codes nil)
2670 (python-shell-interpreter
2671 (executable-find python-tests-shell-interpreter))
2672 (proc-name (python-shell-internal-get-process-name))
2673 (shell-buffer
2674 (python-tests-with-temp-buffer
2675 "" (python-shell-make-comint
2676 (python-shell-calculate-command) proc-name nil t)))
2677 (process (get-buffer-process shell-buffer)))
2678 (unwind-protect
2679 (progn
2680 (set-process-query-on-exit-flag process nil)
2681 (should (process-live-p process))
2682 (with-current-buffer shell-buffer
2683 (should (eq major-mode 'inferior-python-mode))
2684 (should (string= (buffer-name) (format " *%s*" proc-name)))))
2685 (kill-buffer shell-buffer))))
2686
2687 (ert-deftest python-shell-make-comint-3 ()
2688 "Check comint creation with overridden python interpreter and args.
2689 The command passed to `python-shell-make-comint' as argument must
2690 locally override global values set in `python-shell-interpreter'
2691 and `python-shell-interpreter-args' in the new shell buffer."
2692 (skip-unless (executable-find python-tests-shell-interpreter))
2693 (let* ((python-shell-setup-codes nil)
2694 (python-shell-interpreter "interpreter")
2695 (python-shell-interpreter-args "--some-args")
2696 (proc-name (python-shell-get-process-name nil))
2697 (interpreter-override
2698 (concat (executable-find python-tests-shell-interpreter) " " "-i"))
2699 (shell-buffer
2700 (python-tests-with-temp-buffer
2701 "" (python-shell-make-comint interpreter-override proc-name nil)))
2702 (process (get-buffer-process shell-buffer)))
2703 (unwind-protect
2704 (progn
2705 (set-process-query-on-exit-flag process nil)
2706 (should (process-live-p process))
2707 (with-current-buffer shell-buffer
2708 (should (eq major-mode 'inferior-python-mode))
2709 (should (file-equal-p
2710 python-shell-interpreter
2711 (executable-find python-tests-shell-interpreter)))
2712 (should (string= python-shell-interpreter-args "-i"))))
2713 (kill-buffer shell-buffer))))
2714
2715 (ert-deftest python-shell-make-comint-4 ()
2716 "Check shell calculated prompts regexps are set."
2717 (skip-unless (executable-find python-tests-shell-interpreter))
2718 (let* ((process-environment process-environment)
2719 (python-shell-setup-codes nil)
2720 (python-shell-interpreter
2721 (executable-find python-tests-shell-interpreter))
2722 (python-shell-interpreter-args "-i")
2723 (python-shell--prompt-calculated-input-regexp nil)
2724 (python-shell--prompt-calculated-output-regexp nil)
2725 (python-shell-prompt-detect-enabled t)
2726 (python-shell-prompt-input-regexps '("extralargeinputprompt" "sml"))
2727 (python-shell-prompt-output-regexps '("extralargeoutputprompt" "sml"))
2728 (python-shell-prompt-regexp "in")
2729 (python-shell-prompt-block-regexp "block")
2730 (python-shell-prompt-pdb-regexp "pdf")
2731 (python-shell-prompt-output-regexp "output")
2732 (startup-code (concat "import sys\n"
2733 "sys.ps1 = 'py> '\n"
2734 "sys.ps2 = '..> '\n"
2735 "sys.ps3 = 'out '\n"))
2736 (startup-file (python-shell--save-temp-file startup-code))
2737 (proc-name (python-shell-get-process-name nil))
2738 (shell-buffer
2739 (progn
2740 (setenv "PYTHONSTARTUP" startup-file)
2741 (python-tests-with-temp-buffer
2742 "" (python-shell-make-comint
2743 (python-shell-calculate-command) proc-name nil))))
2744 (process (get-buffer-process shell-buffer)))
2745 (unwind-protect
2746 (progn
2747 (set-process-query-on-exit-flag process nil)
2748 (should (process-live-p process))
2749 (with-current-buffer shell-buffer
2750 (should (eq major-mode 'inferior-python-mode))
2751 (should (string=
2752 python-shell--prompt-calculated-input-regexp
2753 (concat "^\\(extralargeinputprompt\\|\\.\\.> \\|"
2754 "block\\|py> \\|pdf\\|sml\\|in\\)")))
2755 (should (string=
2756 python-shell--prompt-calculated-output-regexp
2757 "^\\(extralargeoutputprompt\\|output\\|out \\|sml\\)"))))
2758 (delete-file startup-file)
2759 (kill-buffer shell-buffer))))
2760
2761 (ert-deftest python-shell-get-process-1 ()
2762 "Check dedicated shell process preference over global."
2763 (skip-unless (executable-find python-tests-shell-interpreter))
2764 (python-tests-with-temp-file
2765 ""
2766 (let* ((python-shell-setup-codes nil)
2767 (python-shell-interpreter
2768 (executable-find python-tests-shell-interpreter))
2769 (global-proc-name (python-shell-get-process-name nil))
2770 (dedicated-proc-name (python-shell-get-process-name t))
2771 (global-shell-buffer
2772 (python-shell-make-comint
2773 (python-shell-calculate-command) global-proc-name))
2774 (dedicated-shell-buffer
2775 (python-shell-make-comint
2776 (python-shell-calculate-command) dedicated-proc-name))
2777 (global-process (get-buffer-process global-shell-buffer))
2778 (dedicated-process (get-buffer-process dedicated-shell-buffer)))
2779 (unwind-protect
2780 (progn
2781 (set-process-query-on-exit-flag global-process nil)
2782 (set-process-query-on-exit-flag dedicated-process nil)
2783 ;; Prefer dedicated if global also exists.
2784 (should (equal (python-shell-get-process) dedicated-process))
2785 (kill-buffer dedicated-shell-buffer)
2786 ;; If there's only global, use it.
2787 (should (equal (python-shell-get-process) global-process))
2788 (kill-buffer global-shell-buffer)
2789 ;; No buffer available.
2790 (should (not (python-shell-get-process))))
2791 (ignore-errors (kill-buffer global-shell-buffer))
2792 (ignore-errors (kill-buffer dedicated-shell-buffer))))))
2793
2794 (ert-deftest python-shell-internal-get-or-create-process-1 ()
2795 "Check internal shell process creation fallback."
2796 (skip-unless (executable-find python-tests-shell-interpreter))
2797 (python-tests-with-temp-file
2798 ""
2799 (should (not (process-live-p (python-shell-internal-get-process-name))))
2800 (let* ((python-shell-interpreter
2801 (executable-find python-tests-shell-interpreter))
2802 (internal-process-name (python-shell-internal-get-process-name))
2803 (internal-process (python-shell-internal-get-or-create-process))
2804 (internal-shell-buffer (process-buffer internal-process)))
2805 (unwind-protect
2806 (progn
2807 (set-process-query-on-exit-flag internal-process nil)
2808 (should (equal (process-name internal-process)
2809 internal-process-name))
2810 (should (equal internal-process
2811 (python-shell-internal-get-or-create-process)))
2812 ;; Assert the internal process is not a user process
2813 (should (not (python-shell-get-process)))
2814 (kill-buffer internal-shell-buffer))
2815 (ignore-errors (kill-buffer internal-shell-buffer))))))
2816
2817 (ert-deftest python-shell-prompt-detect-1 ()
2818 "Check prompt autodetection."
2819 (skip-unless (executable-find python-tests-shell-interpreter))
2820 (let ((process-environment process-environment))
2821 ;; Ensure no startup file is enabled
2822 (setenv "PYTHONSTARTUP" "")
2823 (should python-shell-prompt-detect-enabled)
2824 (should (equal (python-shell-prompt-detect) '(">>> " "... " "")))))
2825
2826 (ert-deftest python-shell-prompt-detect-2 ()
2827 "Check prompt autodetection with startup file. Bug#17370."
2828 (skip-unless (executable-find python-tests-shell-interpreter))
2829 (let* ((process-environment process-environment)
2830 (startup-code (concat "import sys\n"
2831 "sys.ps1 = 'py> '\n"
2832 "sys.ps2 = '..> '\n"
2833 "sys.ps3 = 'out '\n"))
2834 (startup-file (python-shell--save-temp-file startup-code)))
2835 (unwind-protect
2836 (progn
2837 ;; Ensure startup file is enabled
2838 (setenv "PYTHONSTARTUP" startup-file)
2839 (should python-shell-prompt-detect-enabled)
2840 (should (equal (python-shell-prompt-detect) '("py> " "..> " "out "))))
2841 (ignore-errors (delete-file startup-file)))))
2842
2843 (ert-deftest python-shell-prompt-detect-3 ()
2844 "Check prompts are not autodetected when feature is disabled."
2845 (skip-unless (executable-find python-tests-shell-interpreter))
2846 (let ((process-environment process-environment)
2847 (python-shell-prompt-detect-enabled nil))
2848 ;; Ensure no startup file is enabled
2849 (should (not python-shell-prompt-detect-enabled))
2850 (should (not (python-shell-prompt-detect)))))
2851
2852 (ert-deftest python-shell-prompt-detect-4 ()
2853 "Check warning is shown when detection fails."
2854 (skip-unless (executable-find python-tests-shell-interpreter))
2855 (let* ((process-environment process-environment)
2856 ;; Trigger failure by removing prompts in the startup file
2857 (startup-code (concat "import sys\n"
2858 "sys.ps1 = ''\n"
2859 "sys.ps2 = ''\n"
2860 "sys.ps3 = ''\n"))
2861 (startup-file (python-shell--save-temp-file startup-code)))
2862 (unwind-protect
2863 (progn
2864 (kill-buffer (get-buffer-create "*Warnings*"))
2865 (should (not (get-buffer "*Warnings*")))
2866 (setenv "PYTHONSTARTUP" startup-file)
2867 (should python-shell-prompt-detect-failure-warning)
2868 (should python-shell-prompt-detect-enabled)
2869 (should (not (python-shell-prompt-detect)))
2870 (should (get-buffer "*Warnings*")))
2871 (ignore-errors (delete-file startup-file)))))
2872
2873 (ert-deftest python-shell-prompt-detect-5 ()
2874 "Check disabled warnings are not shown when detection fails."
2875 (skip-unless (executable-find python-tests-shell-interpreter))
2876 (let* ((process-environment process-environment)
2877 (startup-code (concat "import sys\n"
2878 "sys.ps1 = ''\n"
2879 "sys.ps2 = ''\n"
2880 "sys.ps3 = ''\n"))
2881 (startup-file (python-shell--save-temp-file startup-code))
2882 (python-shell-prompt-detect-failure-warning nil))
2883 (unwind-protect
2884 (progn
2885 (kill-buffer (get-buffer-create "*Warnings*"))
2886 (should (not (get-buffer "*Warnings*")))
2887 (setenv "PYTHONSTARTUP" startup-file)
2888 (should (not python-shell-prompt-detect-failure-warning))
2889 (should python-shell-prompt-detect-enabled)
2890 (should (not (python-shell-prompt-detect)))
2891 (should (not (get-buffer "*Warnings*"))))
2892 (ignore-errors (delete-file startup-file)))))
2893
2894 (ert-deftest python-shell-prompt-detect-6 ()
2895 "Warnings are not shown when detection is disabled."
2896 (skip-unless (executable-find python-tests-shell-interpreter))
2897 (let* ((process-environment process-environment)
2898 (startup-code (concat "import sys\n"
2899 "sys.ps1 = ''\n"
2900 "sys.ps2 = ''\n"
2901 "sys.ps3 = ''\n"))
2902 (startup-file (python-shell--save-temp-file startup-code))
2903 (python-shell-prompt-detect-failure-warning t)
2904 (python-shell-prompt-detect-enabled nil))
2905 (unwind-protect
2906 (progn
2907 (kill-buffer (get-buffer-create "*Warnings*"))
2908 (should (not (get-buffer "*Warnings*")))
2909 (setenv "PYTHONSTARTUP" startup-file)
2910 (should python-shell-prompt-detect-failure-warning)
2911 (should (not python-shell-prompt-detect-enabled))
2912 (should (not (python-shell-prompt-detect)))
2913 (should (not (get-buffer "*Warnings*"))))
2914 (ignore-errors (delete-file startup-file)))))
2915
2916 (ert-deftest python-shell-prompt-validate-regexps-1 ()
2917 "Check `python-shell-prompt-input-regexps' are validated."
2918 (let* ((python-shell-prompt-input-regexps '("\\("))
2919 (error-data (should-error (python-shell-prompt-validate-regexps)
2920 :type 'user-error)))
2921 (should
2922 (string= (cadr error-data)
2923 (format-message
2924 "Invalid regexp \\( in `python-shell-prompt-input-regexps'")))))
2925
2926 (ert-deftest python-shell-prompt-validate-regexps-2 ()
2927 "Check `python-shell-prompt-output-regexps' are validated."
2928 (let* ((python-shell-prompt-output-regexps '("\\("))
2929 (error-data (should-error (python-shell-prompt-validate-regexps)
2930 :type 'user-error)))
2931 (should
2932 (string= (cadr error-data)
2933 (format-message
2934 "Invalid regexp \\( in `python-shell-prompt-output-regexps'")))))
2935
2936 (ert-deftest python-shell-prompt-validate-regexps-3 ()
2937 "Check `python-shell-prompt-regexp' is validated."
2938 (let* ((python-shell-prompt-regexp "\\(")
2939 (error-data (should-error (python-shell-prompt-validate-regexps)
2940 :type 'user-error)))
2941 (should
2942 (string= (cadr error-data)
2943 (format-message
2944 "Invalid regexp \\( in `python-shell-prompt-regexp'")))))
2945
2946 (ert-deftest python-shell-prompt-validate-regexps-4 ()
2947 "Check `python-shell-prompt-block-regexp' is validated."
2948 (let* ((python-shell-prompt-block-regexp "\\(")
2949 (error-data (should-error (python-shell-prompt-validate-regexps)
2950 :type 'user-error)))
2951 (should
2952 (string= (cadr error-data)
2953 (format-message
2954 "Invalid regexp \\( in `python-shell-prompt-block-regexp'")))))
2955
2956 (ert-deftest python-shell-prompt-validate-regexps-5 ()
2957 "Check `python-shell-prompt-pdb-regexp' is validated."
2958 (let* ((python-shell-prompt-pdb-regexp "\\(")
2959 (error-data (should-error (python-shell-prompt-validate-regexps)
2960 :type 'user-error)))
2961 (should
2962 (string= (cadr error-data)
2963 (format-message
2964 "Invalid regexp \\( in `python-shell-prompt-pdb-regexp'")))))
2965
2966 (ert-deftest python-shell-prompt-validate-regexps-6 ()
2967 "Check `python-shell-prompt-output-regexp' is validated."
2968 (let* ((python-shell-prompt-output-regexp "\\(")
2969 (error-data (should-error (python-shell-prompt-validate-regexps)
2970 :type 'user-error)))
2971 (should
2972 (string= (cadr error-data)
2973 (format-message
2974 "Invalid regexp \\( in `python-shell-prompt-output-regexp'")))))
2975
2976 (ert-deftest python-shell-prompt-validate-regexps-7 ()
2977 "Check default regexps are valid."
2978 ;; should not signal error
2979 (python-shell-prompt-validate-regexps))
2980
2981 (ert-deftest python-shell-prompt-set-calculated-regexps-1 ()
2982 "Check regexps are validated."
2983 (let* ((python-shell-prompt-output-regexp '("\\("))
2984 (python-shell--prompt-calculated-input-regexp nil)
2985 (python-shell--prompt-calculated-output-regexp nil)
2986 (python-shell-prompt-detect-enabled nil)
2987 (error-data (should-error (python-shell-prompt-set-calculated-regexps)
2988 :type 'user-error)))
2989 (should
2990 (string= (cadr error-data)
2991 (format-message
2992 "Invalid regexp \\( in `python-shell-prompt-output-regexp'")))))
2993
2994 (ert-deftest python-shell-prompt-set-calculated-regexps-2 ()
2995 "Check `python-shell-prompt-input-regexps' are set."
2996 (let* ((python-shell-prompt-input-regexps '("my" "prompt"))
2997 (python-shell-prompt-output-regexps '(""))
2998 (python-shell-prompt-regexp "")
2999 (python-shell-prompt-block-regexp "")
3000 (python-shell-prompt-pdb-regexp "")
3001 (python-shell-prompt-output-regexp "")
3002 (python-shell--prompt-calculated-input-regexp nil)
3003 (python-shell--prompt-calculated-output-regexp nil)
3004 (python-shell-prompt-detect-enabled nil))
3005 (python-shell-prompt-set-calculated-regexps)
3006 (should (string= python-shell--prompt-calculated-input-regexp
3007 "^\\(prompt\\|my\\|\\)"))))
3008
3009 (ert-deftest python-shell-prompt-set-calculated-regexps-3 ()
3010 "Check `python-shell-prompt-output-regexps' are set."
3011 (let* ((python-shell-prompt-input-regexps '(""))
3012 (python-shell-prompt-output-regexps '("my" "prompt"))
3013 (python-shell-prompt-regexp "")
3014 (python-shell-prompt-block-regexp "")
3015 (python-shell-prompt-pdb-regexp "")
3016 (python-shell-prompt-output-regexp "")
3017 (python-shell--prompt-calculated-input-regexp nil)
3018 (python-shell--prompt-calculated-output-regexp nil)
3019 (python-shell-prompt-detect-enabled nil))
3020 (python-shell-prompt-set-calculated-regexps)
3021 (should (string= python-shell--prompt-calculated-output-regexp
3022 "^\\(prompt\\|my\\|\\)"))))
3023
3024 (ert-deftest python-shell-prompt-set-calculated-regexps-4 ()
3025 "Check user defined prompts are set."
3026 (let* ((python-shell-prompt-input-regexps '(""))
3027 (python-shell-prompt-output-regexps '(""))
3028 (python-shell-prompt-regexp "prompt")
3029 (python-shell-prompt-block-regexp "block")
3030 (python-shell-prompt-pdb-regexp "pdb")
3031 (python-shell-prompt-output-regexp "output")
3032 (python-shell--prompt-calculated-input-regexp nil)
3033 (python-shell--prompt-calculated-output-regexp nil)
3034 (python-shell-prompt-detect-enabled nil))
3035 (python-shell-prompt-set-calculated-regexps)
3036 (should (string= python-shell--prompt-calculated-input-regexp
3037 "^\\(prompt\\|block\\|pdb\\|\\)"))
3038 (should (string= python-shell--prompt-calculated-output-regexp
3039 "^\\(output\\|\\)"))))
3040
3041 (ert-deftest python-shell-prompt-set-calculated-regexps-5 ()
3042 "Check order of regexps (larger first)."
3043 (let* ((python-shell-prompt-input-regexps '("extralargeinputprompt" "sml"))
3044 (python-shell-prompt-output-regexps '("extralargeoutputprompt" "sml"))
3045 (python-shell-prompt-regexp "in")
3046 (python-shell-prompt-block-regexp "block")
3047 (python-shell-prompt-pdb-regexp "pdf")
3048 (python-shell-prompt-output-regexp "output")
3049 (python-shell--prompt-calculated-input-regexp nil)
3050 (python-shell--prompt-calculated-output-regexp nil)
3051 (python-shell-prompt-detect-enabled nil))
3052 (python-shell-prompt-set-calculated-regexps)
3053 (should (string= python-shell--prompt-calculated-input-regexp
3054 "^\\(extralargeinputprompt\\|block\\|pdf\\|sml\\|in\\)"))
3055 (should (string= python-shell--prompt-calculated-output-regexp
3056 "^\\(extralargeoutputprompt\\|output\\|sml\\)"))))
3057
3058 (ert-deftest python-shell-prompt-set-calculated-regexps-6 ()
3059 "Check detected prompts are included `regexp-quote'd."
3060 (skip-unless (executable-find python-tests-shell-interpreter))
3061 (let* ((python-shell-prompt-input-regexps '(""))
3062 (python-shell-prompt-output-regexps '(""))
3063 (python-shell-prompt-regexp "")
3064 (python-shell-prompt-block-regexp "")
3065 (python-shell-prompt-pdb-regexp "")
3066 (python-shell-prompt-output-regexp "")
3067 (python-shell--prompt-calculated-input-regexp nil)
3068 (python-shell--prompt-calculated-output-regexp nil)
3069 (python-shell-prompt-detect-enabled t)
3070 (process-environment process-environment)
3071 (startup-code (concat "import sys\n"
3072 "sys.ps1 = 'p.> '\n"
3073 "sys.ps2 = '..> '\n"
3074 "sys.ps3 = 'o.t '\n"))
3075 (startup-file (python-shell--save-temp-file startup-code)))
3076 (unwind-protect
3077 (progn
3078 (setenv "PYTHONSTARTUP" startup-file)
3079 (python-shell-prompt-set-calculated-regexps)
3080 (should (string= python-shell--prompt-calculated-input-regexp
3081 "^\\(\\.\\.> \\|p\\.> \\|\\)"))
3082 (should (string= python-shell--prompt-calculated-output-regexp
3083 "^\\(o\\.t \\|\\)")))
3084 (ignore-errors (delete-file startup-file)))))
3085
3086 (ert-deftest python-shell-buffer-substring-1 ()
3087 "Selecting a substring of the whole buffer must match its contents."
3088 (python-tests-with-temp-buffer
3089 "
3090 class Foo(models.Model):
3091 pass
3092
3093
3094 class Bar(models.Model):
3095 pass
3096 "
3097 (should (string= (buffer-string)
3098 (python-shell-buffer-substring (point-min) (point-max))))))
3099
3100 (ert-deftest python-shell-buffer-substring-2 ()
3101 "Main block should be removed if NOMAIN is non-nil."
3102 (python-tests-with-temp-buffer
3103 "
3104 class Foo(models.Model):
3105 pass
3106
3107 class Bar(models.Model):
3108 pass
3109
3110 if __name__ == \"__main__\":
3111 foo = Foo()
3112 print (foo)
3113 "
3114 (should (string= (python-shell-buffer-substring (point-min) (point-max) t)
3115 "
3116 class Foo(models.Model):
3117 pass
3118
3119 class Bar(models.Model):
3120 pass
3121
3122
3123
3124
3125 "))))
3126
3127 (ert-deftest python-shell-buffer-substring-3 ()
3128 "Main block should be removed if NOMAIN is non-nil."
3129 (python-tests-with-temp-buffer
3130 "
3131 class Foo(models.Model):
3132 pass
3133
3134 if __name__ == \"__main__\":
3135 foo = Foo()
3136 print (foo)
3137
3138 class Bar(models.Model):
3139 pass
3140 "
3141 (should (string= (python-shell-buffer-substring (point-min) (point-max) t)
3142 "
3143 class Foo(models.Model):
3144 pass
3145
3146
3147
3148
3149
3150 class Bar(models.Model):
3151 pass
3152 "))))
3153
3154 (ert-deftest python-shell-buffer-substring-4 ()
3155 "Coding cookie should be added for substrings."
3156 (python-tests-with-temp-buffer
3157 "# coding: latin-1
3158
3159 class Foo(models.Model):
3160 pass
3161
3162 if __name__ == \"__main__\":
3163 foo = Foo()
3164 print (foo)
3165
3166 class Bar(models.Model):
3167 pass
3168 "
3169 (should (string= (python-shell-buffer-substring
3170 (python-tests-look-at "class Foo(models.Model):")
3171 (progn (python-nav-forward-sexp) (point)))
3172 "# -*- coding: latin-1 -*-
3173
3174 class Foo(models.Model):
3175 pass"))))
3176
3177 (ert-deftest python-shell-buffer-substring-5 ()
3178 "The proper amount of blank lines is added for a substring."
3179 (python-tests-with-temp-buffer
3180 "# coding: latin-1
3181
3182 class Foo(models.Model):
3183 pass
3184
3185 if __name__ == \"__main__\":
3186 foo = Foo()
3187 print (foo)
3188
3189 class Bar(models.Model):
3190 pass
3191 "
3192 (should (string= (python-shell-buffer-substring
3193 (python-tests-look-at "class Bar(models.Model):")
3194 (progn (python-nav-forward-sexp) (point)))
3195 "# -*- coding: latin-1 -*-
3196
3197
3198
3199
3200
3201
3202
3203
3204 class Bar(models.Model):
3205 pass"))))
3206
3207 (ert-deftest python-shell-buffer-substring-6 ()
3208 "Handle substring with coding cookie in the second line."
3209 (python-tests-with-temp-buffer
3210 "
3211 # coding: latin-1
3212
3213 class Foo(models.Model):
3214 pass
3215
3216 if __name__ == \"__main__\":
3217 foo = Foo()
3218 print (foo)
3219
3220 class Bar(models.Model):
3221 pass
3222 "
3223 (should (string= (python-shell-buffer-substring
3224 (python-tests-look-at "# coding: latin-1")
3225 (python-tests-look-at "if __name__ == \"__main__\":"))
3226 "# -*- coding: latin-1 -*-
3227
3228
3229 class Foo(models.Model):
3230 pass
3231
3232 "))))
3233
3234 (ert-deftest python-shell-buffer-substring-7 ()
3235 "Ensure first coding cookie gets precedence."
3236 (python-tests-with-temp-buffer
3237 "# coding: utf-8
3238 # coding: latin-1
3239
3240 class Foo(models.Model):
3241 pass
3242
3243 if __name__ == \"__main__\":
3244 foo = Foo()
3245 print (foo)
3246
3247 class Bar(models.Model):
3248 pass
3249 "
3250 (should (string= (python-shell-buffer-substring
3251 (python-tests-look-at "# coding: latin-1")
3252 (python-tests-look-at "if __name__ == \"__main__\":"))
3253 "# -*- coding: utf-8 -*-
3254
3255
3256 class Foo(models.Model):
3257 pass
3258
3259 "))))
3260
3261 (ert-deftest python-shell-buffer-substring-8 ()
3262 "Ensure first coding cookie gets precedence when sending whole buffer."
3263 (python-tests-with-temp-buffer
3264 "# coding: utf-8
3265 # coding: latin-1
3266
3267 class Foo(models.Model):
3268 pass
3269 "
3270 (should (string= (python-shell-buffer-substring (point-min) (point-max))
3271 "# coding: utf-8
3272
3273
3274 class Foo(models.Model):
3275 pass
3276 "))))
3277
3278 (ert-deftest python-shell-buffer-substring-9 ()
3279 "Check substring starting from `point-min'."
3280 (python-tests-with-temp-buffer
3281 "# coding: utf-8
3282
3283 class Foo(models.Model):
3284 pass
3285
3286 class Bar(models.Model):
3287 pass
3288 "
3289 (should (string= (python-shell-buffer-substring
3290 (point-min)
3291 (python-tests-look-at "class Bar(models.Model):"))
3292 "# coding: utf-8
3293
3294 class Foo(models.Model):
3295 pass
3296
3297 "))))
3298
3299 (ert-deftest python-shell-buffer-substring-10 ()
3300 "Check substring from partial block."
3301 (python-tests-with-temp-buffer
3302 "
3303 def foo():
3304 print ('a')
3305 "
3306 (should (string= (python-shell-buffer-substring
3307 (python-tests-look-at "print ('a')")
3308 (point-max))
3309 "if True:
3310
3311 print ('a')
3312 "))))
3313
3314 (ert-deftest python-shell-buffer-substring-11 ()
3315 "Check substring from partial block and point within indentation."
3316 (python-tests-with-temp-buffer
3317 "
3318 def foo():
3319 print ('a')
3320 "
3321 (should (string= (python-shell-buffer-substring
3322 (progn
3323 (python-tests-look-at "print ('a')")
3324 (backward-char 1)
3325 (point))
3326 (point-max))
3327 "if True:
3328
3329 print ('a')
3330 "))))
3331
3332 (ert-deftest python-shell-buffer-substring-12 ()
3333 "Check substring from partial block and point in whitespace."
3334 (python-tests-with-temp-buffer
3335 "
3336 def foo():
3337
3338 # Whitespace
3339
3340 print ('a')
3341 "
3342 (should (string= (python-shell-buffer-substring
3343 (python-tests-look-at "# Whitespace")
3344 (point-max))
3345 "if True:
3346
3347
3348 # Whitespace
3349
3350 print ('a')
3351 "))))
3352
3353
3354 \f
3355 ;;; Shell completion
3356
3357 (ert-deftest python-shell-completion-native-interpreter-disabled-p-1 ()
3358 (let* ((python-shell-completion-native-disabled-interpreters (list "pypy"))
3359 (python-shell-interpreter "/some/path/to/bin/pypy"))
3360 (should (python-shell-completion-native-interpreter-disabled-p))))
3361
3362
3363
3364 \f
3365 ;;; PDB Track integration
3366
3367 \f
3368 ;;; Symbol completion
3369
3370 \f
3371 ;;; Fill paragraph
3372
3373 \f
3374 ;;; Skeletons
3375
3376 \f
3377 ;;; FFAP
3378
3379 \f
3380 ;;; Code check
3381
3382 \f
3383 ;;; Eldoc
3384
3385 (ert-deftest python-eldoc--get-symbol-at-point-1 ()
3386 "Test paren handling."
3387 (python-tests-with-temp-buffer
3388 "
3389 map(xx
3390 map(codecs.open('somefile'
3391 "
3392 (python-tests-look-at "ap(xx")
3393 (should (string= (python-eldoc--get-symbol-at-point) "map"))
3394 (goto-char (line-end-position))
3395 (should (string= (python-eldoc--get-symbol-at-point) "map"))
3396 (python-tests-look-at "('somefile'")
3397 (should (string= (python-eldoc--get-symbol-at-point) "map"))
3398 (goto-char (line-end-position))
3399 (should (string= (python-eldoc--get-symbol-at-point) "codecs.open"))))
3400
3401 (ert-deftest python-eldoc--get-symbol-at-point-2 ()
3402 "Ensure self is replaced with the class name."
3403 (python-tests-with-temp-buffer
3404 "
3405 class TheClass:
3406
3407 def some_method(self, n):
3408 return n
3409
3410 def other(self):
3411 return self.some_method(1234)
3412
3413 "
3414 (python-tests-look-at "self.some_method")
3415 (should (string= (python-eldoc--get-symbol-at-point)
3416 "TheClass.some_method"))
3417 (python-tests-look-at "1234)")
3418 (should (string= (python-eldoc--get-symbol-at-point)
3419 "TheClass.some_method"))))
3420
3421 (ert-deftest python-eldoc--get-symbol-at-point-3 ()
3422 "Ensure symbol is found when point is at end of buffer."
3423 (python-tests-with-temp-buffer
3424 "
3425 some_symbol
3426
3427 "
3428 (goto-char (point-max))
3429 (should (string= (python-eldoc--get-symbol-at-point)
3430 "some_symbol"))))
3431
3432 (ert-deftest python-eldoc--get-symbol-at-point-4 ()
3433 "Ensure symbol is found when point is at whitespace."
3434 (python-tests-with-temp-buffer
3435 "
3436 some_symbol some_other_symbol
3437 "
3438 (python-tests-look-at " some_other_symbol")
3439 (should (string= (python-eldoc--get-symbol-at-point)
3440 "some_symbol"))))
3441
3442 \f
3443 ;;; Imenu
3444
3445 (ert-deftest python-imenu-create-index-1 ()
3446 (python-tests-with-temp-buffer
3447 "
3448 class Foo(models.Model):
3449 pass
3450
3451
3452 class Bar(models.Model):
3453 pass
3454
3455
3456 def decorator(arg1, arg2, arg3):
3457 '''print decorated function call data to stdout.
3458
3459 Usage:
3460
3461 @decorator('arg1', 'arg2')
3462 def func(a, b, c=True):
3463 pass
3464 '''
3465
3466 def wrap(f):
3467 print ('wrap')
3468 def wrapped_f(*args):
3469 print ('wrapped_f')
3470 print ('Decorator arguments:', arg1, arg2, arg3)
3471 f(*args)
3472 print ('called f(*args)')
3473 return wrapped_f
3474 return wrap
3475
3476
3477 class Baz(object):
3478
3479 def a(self):
3480 pass
3481
3482 def b(self):
3483 pass
3484
3485 class Frob(object):
3486
3487 def c(self):
3488 pass
3489 "
3490 (goto-char (point-max))
3491 (should (equal
3492 (list
3493 (cons "Foo (class)" (copy-marker 2))
3494 (cons "Bar (class)" (copy-marker 38))
3495 (list
3496 "decorator (def)"
3497 (cons "*function definition*" (copy-marker 74))
3498 (list
3499 "wrap (def)"
3500 (cons "*function definition*" (copy-marker 254))
3501 (cons "wrapped_f (def)" (copy-marker 294))))
3502 (list
3503 "Baz (class)"
3504 (cons "*class definition*" (copy-marker 519))
3505 (cons "a (def)" (copy-marker 539))
3506 (cons "b (def)" (copy-marker 570))
3507 (list
3508 "Frob (class)"
3509 (cons "*class definition*" (copy-marker 601))
3510 (cons "c (def)" (copy-marker 626)))))
3511 (python-imenu-create-index)))))
3512
3513 (ert-deftest python-imenu-create-index-2 ()
3514 (python-tests-with-temp-buffer
3515 "
3516 class Foo(object):
3517 def foo(self):
3518 def foo1():
3519 pass
3520
3521 def foobar(self):
3522 pass
3523 "
3524 (goto-char (point-max))
3525 (should (equal
3526 (list
3527 (list
3528 "Foo (class)"
3529 (cons "*class definition*" (copy-marker 2))
3530 (list
3531 "foo (def)"
3532 (cons "*function definition*" (copy-marker 21))
3533 (cons "foo1 (def)" (copy-marker 40)))
3534 (cons "foobar (def)" (copy-marker 78))))
3535 (python-imenu-create-index)))))
3536
3537 (ert-deftest python-imenu-create-index-3 ()
3538 (python-tests-with-temp-buffer
3539 "
3540 class Foo(object):
3541 def foo(self):
3542 def foo1():
3543 pass
3544 def foo2():
3545 pass
3546 "
3547 (goto-char (point-max))
3548 (should (equal
3549 (list
3550 (list
3551 "Foo (class)"
3552 (cons "*class definition*" (copy-marker 2))
3553 (list
3554 "foo (def)"
3555 (cons "*function definition*" (copy-marker 21))
3556 (cons "foo1 (def)" (copy-marker 40))
3557 (cons "foo2 (def)" (copy-marker 77)))))
3558 (python-imenu-create-index)))))
3559
3560 (ert-deftest python-imenu-create-index-4 ()
3561 (python-tests-with-temp-buffer
3562 "
3563 class Foo(object):
3564 class Bar(object):
3565 def __init__(self):
3566 pass
3567
3568 def __str__(self):
3569 pass
3570
3571 def __init__(self):
3572 pass
3573 "
3574 (goto-char (point-max))
3575 (should (equal
3576 (list
3577 (list
3578 "Foo (class)"
3579 (cons "*class definition*" (copy-marker 2))
3580 (list
3581 "Bar (class)"
3582 (cons "*class definition*" (copy-marker 21))
3583 (cons "__init__ (def)" (copy-marker 44))
3584 (cons "__str__ (def)" (copy-marker 90)))
3585 (cons "__init__ (def)" (copy-marker 135))))
3586 (python-imenu-create-index)))))
3587
3588 (ert-deftest python-imenu-create-flat-index-1 ()
3589 (python-tests-with-temp-buffer
3590 "
3591 class Foo(models.Model):
3592 pass
3593
3594
3595 class Bar(models.Model):
3596 pass
3597
3598
3599 def decorator(arg1, arg2, arg3):
3600 '''print decorated function call data to stdout.
3601
3602 Usage:
3603
3604 @decorator('arg1', 'arg2')
3605 def func(a, b, c=True):
3606 pass
3607 '''
3608
3609 def wrap(f):
3610 print ('wrap')
3611 def wrapped_f(*args):
3612 print ('wrapped_f')
3613 print ('Decorator arguments:', arg1, arg2, arg3)
3614 f(*args)
3615 print ('called f(*args)')
3616 return wrapped_f
3617 return wrap
3618
3619
3620 class Baz(object):
3621
3622 def a(self):
3623 pass
3624
3625 def b(self):
3626 pass
3627
3628 class Frob(object):
3629
3630 def c(self):
3631 pass
3632 "
3633 (goto-char (point-max))
3634 (should (equal
3635 (list (cons "Foo" (copy-marker 2))
3636 (cons "Bar" (copy-marker 38))
3637 (cons "decorator" (copy-marker 74))
3638 (cons "decorator.wrap" (copy-marker 254))
3639 (cons "decorator.wrap.wrapped_f" (copy-marker 294))
3640 (cons "Baz" (copy-marker 519))
3641 (cons "Baz.a" (copy-marker 539))
3642 (cons "Baz.b" (copy-marker 570))
3643 (cons "Baz.Frob" (copy-marker 601))
3644 (cons "Baz.Frob.c" (copy-marker 626)))
3645 (python-imenu-create-flat-index)))))
3646
3647 (ert-deftest python-imenu-create-flat-index-2 ()
3648 (python-tests-with-temp-buffer
3649 "
3650 class Foo(object):
3651 class Bar(object):
3652 def __init__(self):
3653 pass
3654
3655 def __str__(self):
3656 pass
3657
3658 def __init__(self):
3659 pass
3660 "
3661 (goto-char (point-max))
3662 (should (equal
3663 (list
3664 (cons "Foo" (copy-marker 2))
3665 (cons "Foo.Bar" (copy-marker 21))
3666 (cons "Foo.Bar.__init__" (copy-marker 44))
3667 (cons "Foo.Bar.__str__" (copy-marker 90))
3668 (cons "Foo.__init__" (copy-marker 135)))
3669 (python-imenu-create-flat-index)))))
3670
3671 \f
3672 ;;; Misc helpers
3673
3674 (ert-deftest python-info-current-defun-1 ()
3675 (python-tests-with-temp-buffer
3676 "
3677 def foo(a, b):
3678 "
3679 (forward-line 1)
3680 (should (string= "foo" (python-info-current-defun)))
3681 (should (string= "def foo" (python-info-current-defun t)))
3682 (forward-line 1)
3683 (should (not (python-info-current-defun)))
3684 (indent-for-tab-command)
3685 (should (string= "foo" (python-info-current-defun)))
3686 (should (string= "def foo" (python-info-current-defun t)))))
3687
3688 (ert-deftest python-info-current-defun-2 ()
3689 (python-tests-with-temp-buffer
3690 "
3691 class C(object):
3692
3693 def m(self):
3694 if True:
3695 return [i for i in range(3)]
3696 else:
3697 return []
3698
3699 def b():
3700 do_b()
3701
3702 def a():
3703 do_a()
3704
3705 def c(self):
3706 do_c()
3707 "
3708 (forward-line 1)
3709 (should (string= "C" (python-info-current-defun)))
3710 (should (string= "class C" (python-info-current-defun t)))
3711 (python-tests-look-at "return [i for ")
3712 (should (string= "C.m" (python-info-current-defun)))
3713 (should (string= "def C.m" (python-info-current-defun t)))
3714 (python-tests-look-at "def b():")
3715 (should (string= "C.m.b" (python-info-current-defun)))
3716 (should (string= "def C.m.b" (python-info-current-defun t)))
3717 (forward-line 2)
3718 (indent-for-tab-command)
3719 (python-indent-dedent-line-backspace 1)
3720 (should (string= "C.m" (python-info-current-defun)))
3721 (should (string= "def C.m" (python-info-current-defun t)))
3722 (python-tests-look-at "def c(self):")
3723 (forward-line -1)
3724 (indent-for-tab-command)
3725 (should (string= "C.m.a" (python-info-current-defun)))
3726 (should (string= "def C.m.a" (python-info-current-defun t)))
3727 (python-indent-dedent-line-backspace 1)
3728 (should (string= "C.m" (python-info-current-defun)))
3729 (should (string= "def C.m" (python-info-current-defun t)))
3730 (python-indent-dedent-line-backspace 1)
3731 (should (string= "C" (python-info-current-defun)))
3732 (should (string= "class C" (python-info-current-defun t)))
3733 (python-tests-look-at "def c(self):")
3734 (should (string= "C.c" (python-info-current-defun)))
3735 (should (string= "def C.c" (python-info-current-defun t)))
3736 (python-tests-look-at "do_c()")
3737 (should (string= "C.c" (python-info-current-defun)))
3738 (should (string= "def C.c" (python-info-current-defun t)))))
3739
3740 (ert-deftest python-info-current-defun-3 ()
3741 (python-tests-with-temp-buffer
3742 "
3743 def decoratorFunctionWithArguments(arg1, arg2, arg3):
3744 '''print decorated function call data to stdout.
3745
3746 Usage:
3747
3748 @decoratorFunctionWithArguments('arg1', 'arg2')
3749 def func(a, b, c=True):
3750 pass
3751 '''
3752
3753 def wwrap(f):
3754 print 'Inside wwrap()'
3755 def wrapped_f(*args):
3756 print 'Inside wrapped_f()'
3757 print 'Decorator arguments:', arg1, arg2, arg3
3758 f(*args)
3759 print 'After f(*args)'
3760 return wrapped_f
3761 return wwrap
3762 "
3763 (python-tests-look-at "def wwrap(f):")
3764 (forward-line -1)
3765 (should (not (python-info-current-defun)))
3766 (indent-for-tab-command 1)
3767 (should (string= (python-info-current-defun)
3768 "decoratorFunctionWithArguments"))
3769 (should (string= (python-info-current-defun t)
3770 "def decoratorFunctionWithArguments"))
3771 (python-tests-look-at "def wrapped_f(*args):")
3772 (should (string= (python-info-current-defun)
3773 "decoratorFunctionWithArguments.wwrap.wrapped_f"))
3774 (should (string= (python-info-current-defun t)
3775 "def decoratorFunctionWithArguments.wwrap.wrapped_f"))
3776 (python-tests-look-at "return wrapped_f")
3777 (should (string= (python-info-current-defun)
3778 "decoratorFunctionWithArguments.wwrap"))
3779 (should (string= (python-info-current-defun t)
3780 "def decoratorFunctionWithArguments.wwrap"))
3781 (end-of-line 1)
3782 (python-tests-look-at "return wwrap")
3783 (should (string= (python-info-current-defun)
3784 "decoratorFunctionWithArguments"))
3785 (should (string= (python-info-current-defun t)
3786 "def decoratorFunctionWithArguments"))))
3787
3788 (ert-deftest python-info-current-symbol-1 ()
3789 (python-tests-with-temp-buffer
3790 "
3791 class C(object):
3792
3793 def m(self):
3794 self.c()
3795
3796 def c(self):
3797 print ('a')
3798 "
3799 (python-tests-look-at "self.c()")
3800 (should (string= "self.c" (python-info-current-symbol)))
3801 (should (string= "C.c" (python-info-current-symbol t)))))
3802
3803 (ert-deftest python-info-current-symbol-2 ()
3804 (python-tests-with-temp-buffer
3805 "
3806 class C(object):
3807
3808 class M(object):
3809
3810 def a(self):
3811 self.c()
3812
3813 def c(self):
3814 pass
3815 "
3816 (python-tests-look-at "self.c()")
3817 (should (string= "self.c" (python-info-current-symbol)))
3818 (should (string= "C.M.c" (python-info-current-symbol t)))))
3819
3820 (ert-deftest python-info-current-symbol-3 ()
3821 "Keywords should not be considered symbols."
3822 :expected-result :failed
3823 (python-tests-with-temp-buffer
3824 "
3825 class C(object):
3826 pass
3827 "
3828 ;; FIXME: keywords are not symbols.
3829 (python-tests-look-at "class C")
3830 (should (not (python-info-current-symbol)))
3831 (should (not (python-info-current-symbol t)))
3832 (python-tests-look-at "C(object)")
3833 (should (string= "C" (python-info-current-symbol)))
3834 (should (string= "class C" (python-info-current-symbol t)))))
3835
3836 (ert-deftest python-info-statement-starts-block-p-1 ()
3837 (python-tests-with-temp-buffer
3838 "
3839 def long_function_name(
3840 var_one, var_two, var_three,
3841 var_four):
3842 print (var_one)
3843 "
3844 (python-tests-look-at "def long_function_name")
3845 (should (python-info-statement-starts-block-p))
3846 (python-tests-look-at "print (var_one)")
3847 (python-util-forward-comment -1)
3848 (should (python-info-statement-starts-block-p))))
3849
3850 (ert-deftest python-info-statement-starts-block-p-2 ()
3851 (python-tests-with-temp-buffer
3852 "
3853 if width == 0 and height == 0 and \\\\
3854 color == 'red' and emphasis == 'strong' or \\\\
3855 highlight > 100:
3856 raise ValueError('sorry, you lose')
3857 "
3858 (python-tests-look-at "if width == 0 and")
3859 (should (python-info-statement-starts-block-p))
3860 (python-tests-look-at "raise ValueError(")
3861 (python-util-forward-comment -1)
3862 (should (python-info-statement-starts-block-p))))
3863
3864 (ert-deftest python-info-statement-ends-block-p-1 ()
3865 (python-tests-with-temp-buffer
3866 "
3867 def long_function_name(
3868 var_one, var_two, var_three,
3869 var_four):
3870 print (var_one)
3871 "
3872 (python-tests-look-at "print (var_one)")
3873 (should (python-info-statement-ends-block-p))))
3874
3875 (ert-deftest python-info-statement-ends-block-p-2 ()
3876 (python-tests-with-temp-buffer
3877 "
3878 if width == 0 and height == 0 and \\\\
3879 color == 'red' and emphasis == 'strong' or \\\\
3880 highlight > 100:
3881 raise ValueError(
3882 'sorry, you lose'
3883
3884 )
3885 "
3886 (python-tests-look-at "raise ValueError(")
3887 (should (python-info-statement-ends-block-p))))
3888
3889 (ert-deftest python-info-beginning-of-statement-p-1 ()
3890 (python-tests-with-temp-buffer
3891 "
3892 def long_function_name(
3893 var_one, var_two, var_three,
3894 var_four):
3895 print (var_one)
3896 "
3897 (python-tests-look-at "def long_function_name")
3898 (should (python-info-beginning-of-statement-p))
3899 (forward-char 10)
3900 (should (not (python-info-beginning-of-statement-p)))
3901 (python-tests-look-at "print (var_one)")
3902 (should (python-info-beginning-of-statement-p))
3903 (goto-char (line-beginning-position))
3904 (should (not (python-info-beginning-of-statement-p)))))
3905
3906 (ert-deftest python-info-beginning-of-statement-p-2 ()
3907 (python-tests-with-temp-buffer
3908 "
3909 if width == 0 and height == 0 and \\\\
3910 color == 'red' and emphasis == 'strong' or \\\\
3911 highlight > 100:
3912 raise ValueError(
3913 'sorry, you lose'
3914
3915 )
3916 "
3917 (python-tests-look-at "if width == 0 and")
3918 (should (python-info-beginning-of-statement-p))
3919 (forward-char 10)
3920 (should (not (python-info-beginning-of-statement-p)))
3921 (python-tests-look-at "raise ValueError(")
3922 (should (python-info-beginning-of-statement-p))
3923 (goto-char (line-beginning-position))
3924 (should (not (python-info-beginning-of-statement-p)))))
3925
3926 (ert-deftest python-info-end-of-statement-p-1 ()
3927 (python-tests-with-temp-buffer
3928 "
3929 def long_function_name(
3930 var_one, var_two, var_three,
3931 var_four):
3932 print (var_one)
3933 "
3934 (python-tests-look-at "def long_function_name")
3935 (should (not (python-info-end-of-statement-p)))
3936 (end-of-line)
3937 (should (not (python-info-end-of-statement-p)))
3938 (python-tests-look-at "print (var_one)")
3939 (python-util-forward-comment -1)
3940 (should (python-info-end-of-statement-p))
3941 (python-tests-look-at "print (var_one)")
3942 (should (not (python-info-end-of-statement-p)))
3943 (end-of-line)
3944 (should (python-info-end-of-statement-p))))
3945
3946 (ert-deftest python-info-end-of-statement-p-2 ()
3947 (python-tests-with-temp-buffer
3948 "
3949 if width == 0 and height == 0 and \\\\
3950 color == 'red' and emphasis == 'strong' or \\\\
3951 highlight > 100:
3952 raise ValueError(
3953 'sorry, you lose'
3954
3955 )
3956 "
3957 (python-tests-look-at "if width == 0 and")
3958 (should (not (python-info-end-of-statement-p)))
3959 (end-of-line)
3960 (should (not (python-info-end-of-statement-p)))
3961 (python-tests-look-at "raise ValueError(")
3962 (python-util-forward-comment -1)
3963 (should (python-info-end-of-statement-p))
3964 (python-tests-look-at "raise ValueError(")
3965 (should (not (python-info-end-of-statement-p)))
3966 (end-of-line)
3967 (should (not (python-info-end-of-statement-p)))
3968 (goto-char (point-max))
3969 (python-util-forward-comment -1)
3970 (should (python-info-end-of-statement-p))))
3971
3972 (ert-deftest python-info-beginning-of-block-p-1 ()
3973 (python-tests-with-temp-buffer
3974 "
3975 def long_function_name(
3976 var_one, var_two, var_three,
3977 var_four):
3978 print (var_one)
3979 "
3980 (python-tests-look-at "def long_function_name")
3981 (should (python-info-beginning-of-block-p))
3982 (python-tests-look-at "var_one, var_two, var_three,")
3983 (should (not (python-info-beginning-of-block-p)))
3984 (python-tests-look-at "print (var_one)")
3985 (should (not (python-info-beginning-of-block-p)))))
3986
3987 (ert-deftest python-info-beginning-of-block-p-2 ()
3988 (python-tests-with-temp-buffer
3989 "
3990 if width == 0 and height == 0 and \\\\
3991 color == 'red' and emphasis == 'strong' or \\\\
3992 highlight > 100:
3993 raise ValueError(
3994 'sorry, you lose'
3995
3996 )
3997 "
3998 (python-tests-look-at "if width == 0 and")
3999 (should (python-info-beginning-of-block-p))
4000 (python-tests-look-at "color == 'red' and emphasis")
4001 (should (not (python-info-beginning-of-block-p)))
4002 (python-tests-look-at "raise ValueError(")
4003 (should (not (python-info-beginning-of-block-p)))))
4004
4005 (ert-deftest python-info-end-of-block-p-1 ()
4006 (python-tests-with-temp-buffer
4007 "
4008 def long_function_name(
4009 var_one, var_two, var_three,
4010 var_four):
4011 print (var_one)
4012 "
4013 (python-tests-look-at "def long_function_name")
4014 (should (not (python-info-end-of-block-p)))
4015 (python-tests-look-at "var_one, var_two, var_three,")
4016 (should (not (python-info-end-of-block-p)))
4017 (python-tests-look-at "var_four):")
4018 (end-of-line)
4019 (should (not (python-info-end-of-block-p)))
4020 (python-tests-look-at "print (var_one)")
4021 (should (not (python-info-end-of-block-p)))
4022 (end-of-line 1)
4023 (should (python-info-end-of-block-p))))
4024
4025 (ert-deftest python-info-end-of-block-p-2 ()
4026 (python-tests-with-temp-buffer
4027 "
4028 if width == 0 and height == 0 and \\\\
4029 color == 'red' and emphasis == 'strong' or \\\\
4030 highlight > 100:
4031 raise ValueError(
4032 'sorry, you lose'
4033
4034 )
4035 "
4036 (python-tests-look-at "if width == 0 and")
4037 (should (not (python-info-end-of-block-p)))
4038 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
4039 (should (not (python-info-end-of-block-p)))
4040 (python-tests-look-at "highlight > 100:")
4041 (end-of-line)
4042 (should (not (python-info-end-of-block-p)))
4043 (python-tests-look-at "raise ValueError(")
4044 (should (not (python-info-end-of-block-p)))
4045 (end-of-line 1)
4046 (should (not (python-info-end-of-block-p)))
4047 (goto-char (point-max))
4048 (python-util-forward-comment -1)
4049 (should (python-info-end-of-block-p))))
4050
4051 (ert-deftest python-info-dedenter-opening-block-position-1 ()
4052 (python-tests-with-temp-buffer
4053 "
4054 if request.user.is_authenticated():
4055 try:
4056 profile = request.user.get_profile()
4057 except Profile.DoesNotExist:
4058 profile = Profile.objects.create(user=request.user)
4059 else:
4060 if profile.stats:
4061 profile.recalculate_stats()
4062 else:
4063 profile.clear_stats()
4064 finally:
4065 profile.views += 1
4066 profile.save()
4067 "
4068 (python-tests-look-at "try:")
4069 (should (not (python-info-dedenter-opening-block-position)))
4070 (python-tests-look-at "except Profile.DoesNotExist:")
4071 (should (= (python-tests-look-at "try:" -1 t)
4072 (python-info-dedenter-opening-block-position)))
4073 (python-tests-look-at "else:")
4074 (should (= (python-tests-look-at "except Profile.DoesNotExist:" -1 t)
4075 (python-info-dedenter-opening-block-position)))
4076 (python-tests-look-at "if profile.stats:")
4077 (should (not (python-info-dedenter-opening-block-position)))
4078 (python-tests-look-at "else:")
4079 (should (= (python-tests-look-at "if profile.stats:" -1 t)
4080 (python-info-dedenter-opening-block-position)))
4081 (python-tests-look-at "finally:")
4082 (should (= (python-tests-look-at "else:" -2 t)
4083 (python-info-dedenter-opening-block-position)))))
4084
4085 (ert-deftest python-info-dedenter-opening-block-position-2 ()
4086 (python-tests-with-temp-buffer
4087 "
4088 if request.user.is_authenticated():
4089 profile = Profile.objects.get_or_create(user=request.user)
4090 if profile.stats:
4091 profile.recalculate_stats()
4092
4093 data = {
4094 'else': 'do it'
4095 }
4096 'else'
4097 "
4098 (python-tests-look-at "'else': 'do it'")
4099 (should (not (python-info-dedenter-opening-block-position)))
4100 (python-tests-look-at "'else'")
4101 (should (not (python-info-dedenter-opening-block-position)))))
4102
4103 (ert-deftest python-info-dedenter-opening-block-position-3 ()
4104 (python-tests-with-temp-buffer
4105 "
4106 if save:
4107 try:
4108 write_to_disk(data)
4109 except IOError:
4110 msg = 'Error saving to disk'
4111 message(msg)
4112 logger.exception(msg)
4113 except Exception:
4114 if hide_details:
4115 logger.exception('Unhandled exception')
4116 else
4117 finally:
4118 data.free()
4119 "
4120 (python-tests-look-at "try:")
4121 (should (not (python-info-dedenter-opening-block-position)))
4122
4123 (python-tests-look-at "except IOError:")
4124 (should (= (python-tests-look-at "try:" -1 t)
4125 (python-info-dedenter-opening-block-position)))
4126
4127 (python-tests-look-at "except Exception:")
4128 (should (= (python-tests-look-at "except IOError:" -1 t)
4129 (python-info-dedenter-opening-block-position)))
4130
4131 (python-tests-look-at "if hide_details:")
4132 (should (not (python-info-dedenter-opening-block-position)))
4133
4134 ;; check indentation modifies the detected opening block
4135 (python-tests-look-at "else")
4136 (should (= (python-tests-look-at "if hide_details:" -1 t)
4137 (python-info-dedenter-opening-block-position)))
4138
4139 (indent-line-to 8)
4140 (should (= (python-tests-look-at "if hide_details:" -1 t)
4141 (python-info-dedenter-opening-block-position)))
4142
4143 (indent-line-to 4)
4144 (should (= (python-tests-look-at "except Exception:" -1 t)
4145 (python-info-dedenter-opening-block-position)))
4146
4147 (indent-line-to 0)
4148 (should (= (python-tests-look-at "if save:" -1 t)
4149 (python-info-dedenter-opening-block-position)))))
4150
4151 (ert-deftest python-info-dedenter-opening-block-positions-1 ()
4152 (python-tests-with-temp-buffer
4153 "
4154 if save:
4155 try:
4156 write_to_disk(data)
4157 except IOError:
4158 msg = 'Error saving to disk'
4159 message(msg)
4160 logger.exception(msg)
4161 except Exception:
4162 if hide_details:
4163 logger.exception('Unhandled exception')
4164 else
4165 finally:
4166 data.free()
4167 "
4168 (python-tests-look-at "try:")
4169 (should (not (python-info-dedenter-opening-block-positions)))
4170
4171 (python-tests-look-at "except IOError:")
4172 (should
4173 (equal (list
4174 (python-tests-look-at "try:" -1 t))
4175 (python-info-dedenter-opening-block-positions)))
4176
4177 (python-tests-look-at "except Exception:")
4178 (should
4179 (equal (list
4180 (python-tests-look-at "except IOError:" -1 t))
4181 (python-info-dedenter-opening-block-positions)))
4182
4183 (python-tests-look-at "if hide_details:")
4184 (should (not (python-info-dedenter-opening-block-positions)))
4185
4186 ;; check indentation does not modify the detected opening blocks
4187 (python-tests-look-at "else")
4188 (should
4189 (equal (list
4190 (python-tests-look-at "if hide_details:" -1 t)
4191 (python-tests-look-at "except Exception:" -1 t)
4192 (python-tests-look-at "if save:" -1 t))
4193 (python-info-dedenter-opening-block-positions)))
4194
4195 (indent-line-to 8)
4196 (should
4197 (equal (list
4198 (python-tests-look-at "if hide_details:" -1 t)
4199 (python-tests-look-at "except Exception:" -1 t)
4200 (python-tests-look-at "if save:" -1 t))
4201 (python-info-dedenter-opening-block-positions)))
4202
4203 (indent-line-to 4)
4204 (should
4205 (equal (list
4206 (python-tests-look-at "if hide_details:" -1 t)
4207 (python-tests-look-at "except Exception:" -1 t)
4208 (python-tests-look-at "if save:" -1 t))
4209 (python-info-dedenter-opening-block-positions)))
4210
4211 (indent-line-to 0)
4212 (should
4213 (equal (list
4214 (python-tests-look-at "if hide_details:" -1 t)
4215 (python-tests-look-at "except Exception:" -1 t)
4216 (python-tests-look-at "if save:" -1 t))
4217 (python-info-dedenter-opening-block-positions)))))
4218
4219 (ert-deftest python-info-dedenter-opening-block-positions-2 ()
4220 "Test detection of opening blocks for elif."
4221 (python-tests-with-temp-buffer
4222 "
4223 if var:
4224 if var2:
4225 something()
4226 elif var3:
4227 something_else()
4228 elif
4229 "
4230 (python-tests-look-at "elif var3:")
4231 (should
4232 (equal (list
4233 (python-tests-look-at "if var2:" -1 t)
4234 (python-tests-look-at "if var:" -1 t))
4235 (python-info-dedenter-opening-block-positions)))
4236
4237 (python-tests-look-at "elif\n")
4238 (should
4239 (equal (list
4240 (python-tests-look-at "elif var3:" -1 t)
4241 (python-tests-look-at "if var:" -1 t))
4242 (python-info-dedenter-opening-block-positions)))))
4243
4244 (ert-deftest python-info-dedenter-opening-block-positions-3 ()
4245 "Test detection of opening blocks for else."
4246 (python-tests-with-temp-buffer
4247 "
4248 try:
4249 something()
4250 except:
4251 if var:
4252 if var2:
4253 something()
4254 elif var3:
4255 something_else()
4256 else
4257
4258 if var4:
4259 while var5:
4260 var4.pop()
4261 else
4262
4263 for value in var6:
4264 if value > 0:
4265 print value
4266 else
4267 "
4268 (python-tests-look-at "else\n")
4269 (should
4270 (equal (list
4271 (python-tests-look-at "elif var3:" -1 t)
4272 (python-tests-look-at "if var:" -1 t)
4273 (python-tests-look-at "except:" -1 t))
4274 (python-info-dedenter-opening-block-positions)))
4275
4276 (python-tests-look-at "else\n")
4277 (should
4278 (equal (list
4279 (python-tests-look-at "while var5:" -1 t)
4280 (python-tests-look-at "if var4:" -1 t))
4281 (python-info-dedenter-opening-block-positions)))
4282
4283 (python-tests-look-at "else\n")
4284 (should
4285 (equal (list
4286 (python-tests-look-at "if value > 0:" -1 t)
4287 (python-tests-look-at "for value in var6:" -1 t)
4288 (python-tests-look-at "if var4:" -1 t))
4289 (python-info-dedenter-opening-block-positions)))))
4290
4291 (ert-deftest python-info-dedenter-opening-block-positions-4 ()
4292 "Test detection of opening blocks for except."
4293 (python-tests-with-temp-buffer
4294 "
4295 try:
4296 something()
4297 except ValueError:
4298 something_else()
4299 except
4300 "
4301 (python-tests-look-at "except ValueError:")
4302 (should
4303 (equal (list (python-tests-look-at "try:" -1 t))
4304 (python-info-dedenter-opening-block-positions)))
4305
4306 (python-tests-look-at "except\n")
4307 (should
4308 (equal (list (python-tests-look-at "except ValueError:" -1 t))
4309 (python-info-dedenter-opening-block-positions)))))
4310
4311 (ert-deftest python-info-dedenter-opening-block-positions-5 ()
4312 "Test detection of opening blocks for finally."
4313 (python-tests-with-temp-buffer
4314 "
4315 try:
4316 something()
4317 finally
4318
4319 try:
4320 something_else()
4321 except:
4322 logger.exception('something went wrong')
4323 finally
4324
4325 try:
4326 something_else_else()
4327 except Exception:
4328 logger.exception('something else went wrong')
4329 else:
4330 print ('all good')
4331 finally
4332 "
4333 (python-tests-look-at "finally\n")
4334 (should
4335 (equal (list (python-tests-look-at "try:" -1 t))
4336 (python-info-dedenter-opening-block-positions)))
4337
4338 (python-tests-look-at "finally\n")
4339 (should
4340 (equal (list (python-tests-look-at "except:" -1 t))
4341 (python-info-dedenter-opening-block-positions)))
4342
4343 (python-tests-look-at "finally\n")
4344 (should
4345 (equal (list (python-tests-look-at "else:" -1 t))
4346 (python-info-dedenter-opening-block-positions)))))
4347
4348 (ert-deftest python-info-dedenter-opening-block-message-1 ()
4349 "Test dedenters inside strings are ignored."
4350 (python-tests-with-temp-buffer
4351 "'''
4352 try:
4353 something()
4354 except:
4355 logger.exception('something went wrong')
4356 '''
4357 "
4358 (python-tests-look-at "except\n")
4359 (should (not (python-info-dedenter-opening-block-message)))))
4360
4361 (ert-deftest python-info-dedenter-opening-block-message-2 ()
4362 "Test except keyword."
4363 (python-tests-with-temp-buffer
4364 "
4365 try:
4366 something()
4367 except:
4368 logger.exception('something went wrong')
4369 "
4370 (python-tests-look-at "except:")
4371 (should (string=
4372 "Closes try:"
4373 (substring-no-properties
4374 (python-info-dedenter-opening-block-message))))
4375 (end-of-line)
4376 (should (string=
4377 "Closes try:"
4378 (substring-no-properties
4379 (python-info-dedenter-opening-block-message))))))
4380
4381 (ert-deftest python-info-dedenter-opening-block-message-3 ()
4382 "Test else keyword."
4383 (python-tests-with-temp-buffer
4384 "
4385 try:
4386 something()
4387 except:
4388 logger.exception('something went wrong')
4389 else:
4390 logger.debug('all good')
4391 "
4392 (python-tests-look-at "else:")
4393 (should (string=
4394 "Closes except:"
4395 (substring-no-properties
4396 (python-info-dedenter-opening-block-message))))
4397 (end-of-line)
4398 (should (string=
4399 "Closes except:"
4400 (substring-no-properties
4401 (python-info-dedenter-opening-block-message))))))
4402
4403 (ert-deftest python-info-dedenter-opening-block-message-4 ()
4404 "Test finally keyword."
4405 (python-tests-with-temp-buffer
4406 "
4407 try:
4408 something()
4409 except:
4410 logger.exception('something went wrong')
4411 else:
4412 logger.debug('all good')
4413 finally:
4414 clean()
4415 "
4416 (python-tests-look-at "finally:")
4417 (should (string=
4418 "Closes else:"
4419 (substring-no-properties
4420 (python-info-dedenter-opening-block-message))))
4421 (end-of-line)
4422 (should (string=
4423 "Closes else:"
4424 (substring-no-properties
4425 (python-info-dedenter-opening-block-message))))))
4426
4427 (ert-deftest python-info-dedenter-opening-block-message-5 ()
4428 "Test elif keyword."
4429 (python-tests-with-temp-buffer
4430 "
4431 if a:
4432 something()
4433 elif b:
4434 "
4435 (python-tests-look-at "elif b:")
4436 (should (string=
4437 "Closes if a:"
4438 (substring-no-properties
4439 (python-info-dedenter-opening-block-message))))
4440 (end-of-line)
4441 (should (string=
4442 "Closes if a:"
4443 (substring-no-properties
4444 (python-info-dedenter-opening-block-message))))))
4445
4446
4447 (ert-deftest python-info-dedenter-statement-p-1 ()
4448 "Test dedenters inside strings are ignored."
4449 (python-tests-with-temp-buffer
4450 "'''
4451 try:
4452 something()
4453 except:
4454 logger.exception('something went wrong')
4455 '''
4456 "
4457 (python-tests-look-at "except\n")
4458 (should (not (python-info-dedenter-statement-p)))))
4459
4460 (ert-deftest python-info-dedenter-statement-p-2 ()
4461 "Test except keyword."
4462 (python-tests-with-temp-buffer
4463 "
4464 try:
4465 something()
4466 except:
4467 logger.exception('something went wrong')
4468 "
4469 (python-tests-look-at "except:")
4470 (should (= (point) (python-info-dedenter-statement-p)))
4471 (end-of-line)
4472 (should (= (save-excursion
4473 (back-to-indentation)
4474 (point))
4475 (python-info-dedenter-statement-p)))))
4476
4477 (ert-deftest python-info-dedenter-statement-p-3 ()
4478 "Test else keyword."
4479 (python-tests-with-temp-buffer
4480 "
4481 try:
4482 something()
4483 except:
4484 logger.exception('something went wrong')
4485 else:
4486 logger.debug('all good')
4487 "
4488 (python-tests-look-at "else:")
4489 (should (= (point) (python-info-dedenter-statement-p)))
4490 (end-of-line)
4491 (should (= (save-excursion
4492 (back-to-indentation)
4493 (point))
4494 (python-info-dedenter-statement-p)))))
4495
4496 (ert-deftest python-info-dedenter-statement-p-4 ()
4497 "Test finally keyword."
4498 (python-tests-with-temp-buffer
4499 "
4500 try:
4501 something()
4502 except:
4503 logger.exception('something went wrong')
4504 else:
4505 logger.debug('all good')
4506 finally:
4507 clean()
4508 "
4509 (python-tests-look-at "finally:")
4510 (should (= (point) (python-info-dedenter-statement-p)))
4511 (end-of-line)
4512 (should (= (save-excursion
4513 (back-to-indentation)
4514 (point))
4515 (python-info-dedenter-statement-p)))))
4516
4517 (ert-deftest python-info-dedenter-statement-p-5 ()
4518 "Test elif keyword."
4519 (python-tests-with-temp-buffer
4520 "
4521 if a:
4522 something()
4523 elif b:
4524 "
4525 (python-tests-look-at "elif b:")
4526 (should (= (point) (python-info-dedenter-statement-p)))
4527 (end-of-line)
4528 (should (= (save-excursion
4529 (back-to-indentation)
4530 (point))
4531 (python-info-dedenter-statement-p)))))
4532
4533 (ert-deftest python-info-line-ends-backslash-p-1 ()
4534 (python-tests-with-temp-buffer
4535 "
4536 objects = Thing.objects.all() \\\\
4537 .filter(
4538 type='toy',
4539 status='bought'
4540 ) \\\\
4541 .aggregate(
4542 Sum('amount')
4543 ) \\\\
4544 .values_list()
4545 "
4546 (should (python-info-line-ends-backslash-p 2)) ; .filter(...
4547 (should (python-info-line-ends-backslash-p 3))
4548 (should (python-info-line-ends-backslash-p 4))
4549 (should (python-info-line-ends-backslash-p 5))
4550 (should (python-info-line-ends-backslash-p 6)) ; ) \...
4551 (should (python-info-line-ends-backslash-p 7))
4552 (should (python-info-line-ends-backslash-p 8))
4553 (should (python-info-line-ends-backslash-p 9))
4554 (should (not (python-info-line-ends-backslash-p 10))))) ; .values_list()...
4555
4556 (ert-deftest python-info-beginning-of-backslash-1 ()
4557 (python-tests-with-temp-buffer
4558 "
4559 objects = Thing.objects.all() \\\\
4560 .filter(
4561 type='toy',
4562 status='bought'
4563 ) \\\\
4564 .aggregate(
4565 Sum('amount')
4566 ) \\\\
4567 .values_list()
4568 "
4569 (let ((first 2)
4570 (second (python-tests-look-at ".filter("))
4571 (third (python-tests-look-at ".aggregate(")))
4572 (should (= first (python-info-beginning-of-backslash 2)))
4573 (should (= second (python-info-beginning-of-backslash 3)))
4574 (should (= second (python-info-beginning-of-backslash 4)))
4575 (should (= second (python-info-beginning-of-backslash 5)))
4576 (should (= second (python-info-beginning-of-backslash 6)))
4577 (should (= third (python-info-beginning-of-backslash 7)))
4578 (should (= third (python-info-beginning-of-backslash 8)))
4579 (should (= third (python-info-beginning-of-backslash 9)))
4580 (should (not (python-info-beginning-of-backslash 10))))))
4581
4582 (ert-deftest python-info-continuation-line-p-1 ()
4583 (python-tests-with-temp-buffer
4584 "
4585 if width == 0 and height == 0 and \\\\
4586 color == 'red' and emphasis == 'strong' or \\\\
4587 highlight > 100:
4588 raise ValueError(
4589 'sorry, you lose'
4590
4591 )
4592 "
4593 (python-tests-look-at "if width == 0 and height == 0 and")
4594 (should (not (python-info-continuation-line-p)))
4595 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
4596 (should (python-info-continuation-line-p))
4597 (python-tests-look-at "highlight > 100:")
4598 (should (python-info-continuation-line-p))
4599 (python-tests-look-at "raise ValueError(")
4600 (should (not (python-info-continuation-line-p)))
4601 (python-tests-look-at "'sorry, you lose'")
4602 (should (python-info-continuation-line-p))
4603 (forward-line 1)
4604 (should (python-info-continuation-line-p))
4605 (python-tests-look-at ")")
4606 (should (python-info-continuation-line-p))
4607 (forward-line 1)
4608 (should (not (python-info-continuation-line-p)))))
4609
4610 (ert-deftest python-info-block-continuation-line-p-1 ()
4611 (python-tests-with-temp-buffer
4612 "
4613 if width == 0 and height == 0 and \\\\
4614 color == 'red' and emphasis == 'strong' or \\\\
4615 highlight > 100:
4616 raise ValueError(
4617 'sorry, you lose'
4618
4619 )
4620 "
4621 (python-tests-look-at "if width == 0 and")
4622 (should (not (python-info-block-continuation-line-p)))
4623 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
4624 (should (= (python-info-block-continuation-line-p)
4625 (python-tests-look-at "if width == 0 and" -1 t)))
4626 (python-tests-look-at "highlight > 100:")
4627 (should (not (python-info-block-continuation-line-p)))))
4628
4629 (ert-deftest python-info-block-continuation-line-p-2 ()
4630 (python-tests-with-temp-buffer
4631 "
4632 def foo(a,
4633 b,
4634 c):
4635 pass
4636 "
4637 (python-tests-look-at "def foo(a,")
4638 (should (not (python-info-block-continuation-line-p)))
4639 (python-tests-look-at "b,")
4640 (should (= (python-info-block-continuation-line-p)
4641 (python-tests-look-at "def foo(a," -1 t)))
4642 (python-tests-look-at "c):")
4643 (should (not (python-info-block-continuation-line-p)))))
4644
4645 (ert-deftest python-info-assignment-statement-p-1 ()
4646 (python-tests-with-temp-buffer
4647 "
4648 data = foo(), bar() \\\\
4649 baz(), 4 \\\\
4650 5, 6
4651 "
4652 (python-tests-look-at "data = foo(), bar()")
4653 (should (python-info-assignment-statement-p))
4654 (should (python-info-assignment-statement-p t))
4655 (python-tests-look-at "baz(), 4")
4656 (should (python-info-assignment-statement-p))
4657 (should (not (python-info-assignment-statement-p t)))
4658 (python-tests-look-at "5, 6")
4659 (should (python-info-assignment-statement-p))
4660 (should (not (python-info-assignment-statement-p t)))))
4661
4662 (ert-deftest python-info-assignment-statement-p-2 ()
4663 (python-tests-with-temp-buffer
4664 "
4665 data = (foo(), bar()
4666 baz(), 4
4667 5, 6)
4668 "
4669 (python-tests-look-at "data = (foo(), bar()")
4670 (should (python-info-assignment-statement-p))
4671 (should (python-info-assignment-statement-p t))
4672 (python-tests-look-at "baz(), 4")
4673 (should (python-info-assignment-statement-p))
4674 (should (not (python-info-assignment-statement-p t)))
4675 (python-tests-look-at "5, 6)")
4676 (should (python-info-assignment-statement-p))
4677 (should (not (python-info-assignment-statement-p t)))))
4678
4679 (ert-deftest python-info-assignment-statement-p-3 ()
4680 (python-tests-with-temp-buffer
4681 "
4682 data '=' 42
4683 "
4684 (python-tests-look-at "data '=' 42")
4685 (should (not (python-info-assignment-statement-p)))
4686 (should (not (python-info-assignment-statement-p t)))))
4687
4688 (ert-deftest python-info-assignment-continuation-line-p-1 ()
4689 (python-tests-with-temp-buffer
4690 "
4691 data = foo(), bar() \\\\
4692 baz(), 4 \\\\
4693 5, 6
4694 "
4695 (python-tests-look-at "data = foo(), bar()")
4696 (should (not (python-info-assignment-continuation-line-p)))
4697 (python-tests-look-at "baz(), 4")
4698 (should (= (python-info-assignment-continuation-line-p)
4699 (python-tests-look-at "foo()," -1 t)))
4700 (python-tests-look-at "5, 6")
4701 (should (not (python-info-assignment-continuation-line-p)))))
4702
4703 (ert-deftest python-info-assignment-continuation-line-p-2 ()
4704 (python-tests-with-temp-buffer
4705 "
4706 data = (foo(), bar()
4707 baz(), 4
4708 5, 6)
4709 "
4710 (python-tests-look-at "data = (foo(), bar()")
4711 (should (not (python-info-assignment-continuation-line-p)))
4712 (python-tests-look-at "baz(), 4")
4713 (should (= (python-info-assignment-continuation-line-p)
4714 (python-tests-look-at "(foo()," -1 t)))
4715 (python-tests-look-at "5, 6)")
4716 (should (not (python-info-assignment-continuation-line-p)))))
4717
4718 (ert-deftest python-info-looking-at-beginning-of-defun-1 ()
4719 (python-tests-with-temp-buffer
4720 "
4721 def decorat0r(deff):
4722 '''decorates stuff.
4723
4724 @decorat0r
4725 def foo(arg):
4726 ...
4727 '''
4728 def wrap():
4729 deff()
4730 return wwrap
4731 "
4732 (python-tests-look-at "def decorat0r(deff):")
4733 (should (python-info-looking-at-beginning-of-defun))
4734 (python-tests-look-at "def foo(arg):")
4735 (should (not (python-info-looking-at-beginning-of-defun)))
4736 (python-tests-look-at "def wrap():")
4737 (should (python-info-looking-at-beginning-of-defun))
4738 (python-tests-look-at "deff()")
4739 (should (not (python-info-looking-at-beginning-of-defun)))))
4740
4741 (ert-deftest python-info-current-line-comment-p-1 ()
4742 (python-tests-with-temp-buffer
4743 "
4744 # this is a comment
4745 foo = True # another comment
4746 '#this is a string'
4747 if foo:
4748 # more comments
4749 print ('bar') # print bar
4750 "
4751 (python-tests-look-at "# this is a comment")
4752 (should (python-info-current-line-comment-p))
4753 (python-tests-look-at "foo = True # another comment")
4754 (should (not (python-info-current-line-comment-p)))
4755 (python-tests-look-at "'#this is a string'")
4756 (should (not (python-info-current-line-comment-p)))
4757 (python-tests-look-at "# more comments")
4758 (should (python-info-current-line-comment-p))
4759 (python-tests-look-at "print ('bar') # print bar")
4760 (should (not (python-info-current-line-comment-p)))))
4761
4762 (ert-deftest python-info-current-line-empty-p ()
4763 (python-tests-with-temp-buffer
4764 "
4765 # this is a comment
4766
4767 foo = True # another comment
4768 "
4769 (should (python-info-current-line-empty-p))
4770 (python-tests-look-at "# this is a comment")
4771 (should (not (python-info-current-line-empty-p)))
4772 (forward-line 1)
4773 (should (python-info-current-line-empty-p))))
4774
4775 (ert-deftest python-info-docstring-p-1 ()
4776 "Test module docstring detection."
4777 (python-tests-with-temp-buffer
4778 "# -*- coding: utf-8 -*-
4779 #!/usr/bin/python
4780
4781 '''
4782 Module Docstring Django style.
4783 '''
4784 u'''Additional module docstring.'''
4785 '''Not a module docstring.'''
4786 "
4787 (python-tests-look-at "Module Docstring Django style.")
4788 (should (python-info-docstring-p))
4789 (python-tests-look-at "u'''Additional module docstring.'''")
4790 (should (python-info-docstring-p))
4791 (python-tests-look-at "'''Not a module docstring.'''")
4792 (should (not (python-info-docstring-p)))))
4793
4794 (ert-deftest python-info-docstring-p-2 ()
4795 "Test variable docstring detection."
4796 (python-tests-with-temp-buffer
4797 "
4798 variable = 42
4799 U'''Variable docstring.'''
4800 '''Additional variable docstring.'''
4801 '''Not a variable docstring.'''
4802 "
4803 (python-tests-look-at "Variable docstring.")
4804 (should (python-info-docstring-p))
4805 (python-tests-look-at "u'''Additional variable docstring.'''")
4806 (should (python-info-docstring-p))
4807 (python-tests-look-at "'''Not a variable docstring.'''")
4808 (should (not (python-info-docstring-p)))))
4809
4810 (ert-deftest python-info-docstring-p-3 ()
4811 "Test function docstring detection."
4812 (python-tests-with-temp-buffer
4813 "
4814 def func(a, b):
4815 r'''
4816 Function docstring.
4817
4818 onetwo style.
4819 '''
4820 R'''Additional function docstring.'''
4821 '''Not a function docstring.'''
4822 return a + b
4823 "
4824 (python-tests-look-at "Function docstring.")
4825 (should (python-info-docstring-p))
4826 (python-tests-look-at "R'''Additional function docstring.'''")
4827 (should (python-info-docstring-p))
4828 (python-tests-look-at "'''Not a function docstring.'''")
4829 (should (not (python-info-docstring-p)))))
4830
4831 (ert-deftest python-info-docstring-p-4 ()
4832 "Test class docstring detection."
4833 (python-tests-with-temp-buffer
4834 "
4835 class Class:
4836 ur'''
4837 Class docstring.
4838
4839 symmetric style.
4840 '''
4841 uR'''
4842 Additional class docstring.
4843 '''
4844 '''Not a class docstring.'''
4845 pass
4846 "
4847 (python-tests-look-at "Class docstring.")
4848 (should (python-info-docstring-p))
4849 (python-tests-look-at "uR'''") ;; Additional class docstring
4850 (should (python-info-docstring-p))
4851 (python-tests-look-at "'''Not a class docstring.'''")
4852 (should (not (python-info-docstring-p)))))
4853
4854 (ert-deftest python-info-docstring-p-5 ()
4855 "Test class attribute docstring detection."
4856 (python-tests-with-temp-buffer
4857 "
4858 class Class:
4859 attribute = 42
4860 Ur'''
4861 Class attribute docstring.
4862
4863 pep-257 style.
4864
4865 '''
4866 UR'''
4867 Additional class attribute docstring.
4868 '''
4869 '''Not a class attribute docstring.'''
4870 pass
4871 "
4872 (python-tests-look-at "Class attribute docstring.")
4873 (should (python-info-docstring-p))
4874 (python-tests-look-at "UR'''") ;; Additional class attr docstring
4875 (should (python-info-docstring-p))
4876 (python-tests-look-at "'''Not a class attribute docstring.'''")
4877 (should (not (python-info-docstring-p)))))
4878
4879 (ert-deftest python-info-docstring-p-6 ()
4880 "Test class method docstring detection."
4881 (python-tests-with-temp-buffer
4882 "
4883 class Class:
4884
4885 def __init__(self, a, b):
4886 self.a = a
4887 self.b = b
4888
4889 def __call__(self):
4890 '''Method docstring.
4891
4892 pep-257-nn style.
4893 '''
4894 '''Additional method docstring.'''
4895 '''Not a method docstring.'''
4896 return self.a + self.b
4897 "
4898 (python-tests-look-at "Method docstring.")
4899 (should (python-info-docstring-p))
4900 (python-tests-look-at "'''Additional method docstring.'''")
4901 (should (python-info-docstring-p))
4902 (python-tests-look-at "'''Not a method docstring.'''")
4903 (should (not (python-info-docstring-p)))))
4904
4905 (ert-deftest python-info-encoding-from-cookie-1 ()
4906 "Should detect it on first line."
4907 (python-tests-with-temp-buffer
4908 "# coding=latin-1
4909
4910 foo = True # another comment
4911 "
4912 (should (eq (python-info-encoding-from-cookie) 'latin-1))))
4913
4914 (ert-deftest python-info-encoding-from-cookie-2 ()
4915 "Should detect it on second line."
4916 (python-tests-with-temp-buffer
4917 "
4918 # coding=latin-1
4919
4920 foo = True # another comment
4921 "
4922 (should (eq (python-info-encoding-from-cookie) 'latin-1))))
4923
4924 (ert-deftest python-info-encoding-from-cookie-3 ()
4925 "Should not be detected on third line (and following ones)."
4926 (python-tests-with-temp-buffer
4927 "
4928
4929 # coding=latin-1
4930 foo = True # another comment
4931 "
4932 (should (not (python-info-encoding-from-cookie)))))
4933
4934 (ert-deftest python-info-encoding-from-cookie-4 ()
4935 "Should detect Emacs style."
4936 (python-tests-with-temp-buffer
4937 "# -*- coding: latin-1 -*-
4938
4939 foo = True # another comment"
4940 (should (eq (python-info-encoding-from-cookie) 'latin-1))))
4941
4942 (ert-deftest python-info-encoding-from-cookie-5 ()
4943 "Should detect Vim style."
4944 (python-tests-with-temp-buffer
4945 "# vim: set fileencoding=latin-1 :
4946
4947 foo = True # another comment"
4948 (should (eq (python-info-encoding-from-cookie) 'latin-1))))
4949
4950 (ert-deftest python-info-encoding-from-cookie-6 ()
4951 "First cookie wins."
4952 (python-tests-with-temp-buffer
4953 "# -*- coding: iso-8859-1 -*-
4954 # vim: set fileencoding=latin-1 :
4955
4956 foo = True # another comment"
4957 (should (eq (python-info-encoding-from-cookie) 'iso-8859-1))))
4958
4959 (ert-deftest python-info-encoding-from-cookie-7 ()
4960 "First cookie wins."
4961 (python-tests-with-temp-buffer
4962 "# vim: set fileencoding=latin-1 :
4963 # -*- coding: iso-8859-1 -*-
4964
4965 foo = True # another comment"
4966 (should (eq (python-info-encoding-from-cookie) 'latin-1))))
4967
4968 (ert-deftest python-info-encoding-1 ()
4969 "Should return the detected encoding from cookie."
4970 (python-tests-with-temp-buffer
4971 "# vim: set fileencoding=latin-1 :
4972
4973 foo = True # another comment"
4974 (should (eq (python-info-encoding) 'latin-1))))
4975
4976 (ert-deftest python-info-encoding-2 ()
4977 "Should default to utf-8."
4978 (python-tests-with-temp-buffer
4979 "# No encoding for you
4980
4981 foo = True # another comment"
4982 (should (eq (python-info-encoding) 'utf-8))))
4983
4984 \f
4985 ;;; Utility functions
4986
4987 (ert-deftest python-util-goto-line-1 ()
4988 (python-tests-with-temp-buffer
4989 (concat
4990 "# a comment
4991 # another comment
4992 def foo(a, b, c):
4993 pass" (make-string 20 ?\n))
4994 (python-util-goto-line 10)
4995 (should (= (line-number-at-pos) 10))
4996 (python-util-goto-line 20)
4997 (should (= (line-number-at-pos) 20))))
4998
4999 (ert-deftest python-util-clone-local-variables-1 ()
5000 (let ((buffer (generate-new-buffer
5001 "python-util-clone-local-variables-1"))
5002 (varcons
5003 '((python-fill-docstring-style . django)
5004 (python-shell-interpreter . "python")
5005 (python-shell-interpreter-args . "manage.py shell")
5006 (python-shell-prompt-regexp . "In \\[[0-9]+\\]: ")
5007 (python-shell-prompt-output-regexp . "Out\\[[0-9]+\\]: ")
5008 (python-shell-extra-pythonpaths "/home/user/pylib/")
5009 (python-shell-completion-setup-code
5010 . "from IPython.core.completerlib import module_completion")
5011 (python-shell-completion-string-code
5012 . "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
5013 (python-shell-virtualenv-root
5014 . "/home/user/.virtualenvs/project"))))
5015 (with-current-buffer buffer
5016 (kill-all-local-variables)
5017 (dolist (ccons varcons)
5018 (set (make-local-variable (car ccons)) (cdr ccons))))
5019 (python-tests-with-temp-buffer
5020 ""
5021 (python-util-clone-local-variables buffer)
5022 (dolist (ccons varcons)
5023 (should
5024 (equal (symbol-value (car ccons)) (cdr ccons)))))
5025 (kill-buffer buffer)))
5026
5027 (ert-deftest python-util-strip-string-1 ()
5028 (should (string= (python-util-strip-string "\t\r\n str") "str"))
5029 (should (string= (python-util-strip-string "str \n\r") "str"))
5030 (should (string= (python-util-strip-string "\t\r\n str \n\r ") "str"))
5031 (should
5032 (string= (python-util-strip-string "\n str \nin \tg \n\r") "str \nin \tg"))
5033 (should (string= (python-util-strip-string "\n \t \n\r ") ""))
5034 (should (string= (python-util-strip-string "") "")))
5035
5036 (ert-deftest python-util-forward-comment-1 ()
5037 (python-tests-with-temp-buffer
5038 (concat
5039 "# a comment
5040 # another comment
5041 # bad indented comment
5042 # more comments" (make-string 9999 ?\n))
5043 (python-util-forward-comment 1)
5044 (should (= (point) (point-max)))
5045 (python-util-forward-comment -1)
5046 (should (= (point) (point-min)))))
5047
5048 (ert-deftest python-util-valid-regexp-p-1 ()
5049 (should (python-util-valid-regexp-p ""))
5050 (should (python-util-valid-regexp-p python-shell-prompt-regexp))
5051 (should (not (python-util-valid-regexp-p "\\("))))
5052
5053 \f
5054 ;;; Electricity
5055
5056 (ert-deftest python-parens-electric-indent-1 ()
5057 (let ((eim electric-indent-mode))
5058 (unwind-protect
5059 (progn
5060 (python-tests-with-temp-buffer
5061 "
5062 from django.conf.urls import patterns, include, url
5063
5064 from django.contrib import admin
5065
5066 from myapp import views
5067
5068
5069 urlpatterns = patterns('',
5070 url(r'^$', views.index
5071 )
5072 "
5073 (electric-indent-mode 1)
5074 (python-tests-look-at "views.index")
5075 (end-of-line)
5076
5077 ;; Inserting commas within the same line should leave
5078 ;; indentation unchanged.
5079 (python-tests-self-insert ",")
5080 (should (= (current-indentation) 4))
5081
5082 ;; As well as any other input happening within the same
5083 ;; set of parens.
5084 (python-tests-self-insert " name='index')")
5085 (should (= (current-indentation) 4))
5086
5087 ;; But a comma outside it, should trigger indentation.
5088 (python-tests-self-insert ",")
5089 (should (= (current-indentation) 23))
5090
5091 ;; Newline indents to the first argument column
5092 (python-tests-self-insert "\n")
5093 (should (= (current-indentation) 23))
5094
5095 ;; All this input must not change indentation
5096 (indent-line-to 4)
5097 (python-tests-self-insert "url(r'^/login$', views.login)")
5098 (should (= (current-indentation) 4))
5099
5100 ;; But this comma does
5101 (python-tests-self-insert ",")
5102 (should (= (current-indentation) 23))))
5103 (or eim (electric-indent-mode -1)))))
5104
5105 (ert-deftest python-triple-quote-pairing ()
5106 (let ((epm electric-pair-mode))
5107 (unwind-protect
5108 (progn
5109 (python-tests-with-temp-buffer
5110 "\"\"\n"
5111 (or epm (electric-pair-mode 1))
5112 (goto-char (1- (point-max)))
5113 (python-tests-self-insert ?\")
5114 (should (string= (buffer-string)
5115 "\"\"\"\"\"\"\n"))
5116 (should (= (point) 4)))
5117 (python-tests-with-temp-buffer
5118 "\n"
5119 (python-tests-self-insert (list ?\" ?\" ?\"))
5120 (should (string= (buffer-string)
5121 "\"\"\"\"\"\"\n"))
5122 (should (= (point) 4)))
5123 (python-tests-with-temp-buffer
5124 "\"\n\"\"\n"
5125 (goto-char (1- (point-max)))
5126 (python-tests-self-insert ?\")
5127 (should (= (point) (1- (point-max))))
5128 (should (string= (buffer-string)
5129 "\"\n\"\"\"\n"))))
5130 (or epm (electric-pair-mode -1)))))
5131
5132 \f
5133 ;;; Hideshow support
5134
5135 (ert-deftest python-hideshow-hide-levels-1 ()
5136 "Should hide all methods when called after class start."
5137 (let ((enabled hs-minor-mode))
5138 (unwind-protect
5139 (progn
5140 (python-tests-with-temp-buffer
5141 "
5142 class SomeClass:
5143
5144 def __init__(self, arg, kwarg=1):
5145 self.arg = arg
5146 self.kwarg = kwarg
5147
5148 def filter(self, nums):
5149 def fn(item):
5150 return item in [self.arg, self.kwarg]
5151 return filter(fn, nums)
5152
5153 def __str__(self):
5154 return '%s-%s' % (self.arg, self.kwarg)
5155 "
5156 (hs-minor-mode 1)
5157 (python-tests-look-at "class SomeClass:")
5158 (forward-line)
5159 (hs-hide-level 1)
5160 (should
5161 (string=
5162 (python-tests-visible-string)
5163 "
5164 class SomeClass:
5165
5166 def __init__(self, arg, kwarg=1):
5167 def filter(self, nums):
5168 def __str__(self):"))))
5169 (or enabled (hs-minor-mode -1)))))
5170
5171 (ert-deftest python-hideshow-hide-levels-2 ()
5172 "Should hide nested methods and parens at end of defun."
5173 (let ((enabled hs-minor-mode))
5174 (unwind-protect
5175 (progn
5176 (python-tests-with-temp-buffer
5177 "
5178 class SomeClass:
5179
5180 def __init__(self, arg, kwarg=1):
5181 self.arg = arg
5182 self.kwarg = kwarg
5183
5184 def filter(self, nums):
5185 def fn(item):
5186 return item in [self.arg, self.kwarg]
5187 return filter(fn, nums)
5188
5189 def __str__(self):
5190 return '%s-%s' % (self.arg, self.kwarg)
5191 "
5192 (hs-minor-mode 1)
5193 (python-tests-look-at "def fn(item):")
5194 (hs-hide-block)
5195 (should
5196 (string=
5197 (python-tests-visible-string)
5198 "
5199 class SomeClass:
5200
5201 def __init__(self, arg, kwarg=1):
5202 self.arg = arg
5203 self.kwarg = kwarg
5204
5205 def filter(self, nums):
5206 def fn(item):
5207 return filter(fn, nums)
5208
5209 def __str__(self):
5210 return '%s-%s' % (self.arg, self.kwarg)
5211 "))))
5212 (or enabled (hs-minor-mode -1)))))
5213
5214
5215
5216 (provide 'python-tests)
5217
5218 ;; Local Variables:
5219 ;; indent-tabs-mode: nil
5220 ;; End:
5221
5222 ;;; python-tests.el ends here