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