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