]> code.delx.au - gnu-emacs/blob - test/automated/python-tests.el
Merge from emacs-24; up to 2014-06-15T04:52:34Z!eli@barzilay.org
[gnu-emacs] / test / automated / python-tests.el
1 ;;; python-tests.el --- Test suite for python.el
2
3 ;; Copyright (C) 2013-2014 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 (defmacro python-tests-with-temp-buffer (contents &rest body)
28 "Create a `python-mode' enabled temp buffer with CONTENTS.
29 BODY is code to be executed within the temp buffer. Point is
30 always located at the beginning of buffer."
31 (declare (indent 1) (debug t))
32 `(with-temp-buffer
33 (python-mode)
34 (insert ,contents)
35 (goto-char (point-min))
36 ,@body))
37
38 (defmacro python-tests-with-temp-file (contents &rest body)
39 "Create a `python-mode' enabled file with CONTENTS.
40 BODY is code to be executed within the temp buffer. Point is
41 always located at the beginning of buffer."
42 (declare (indent 1) (debug t))
43 ;; temp-file never actually used for anything?
44 `(let* ((temp-file (make-temp-file "python-tests" nil ".py"))
45 (buffer (find-file-noselect temp-file)))
46 (unwind-protect
47 (with-current-buffer buffer
48 (python-mode)
49 (insert ,contents)
50 (goto-char (point-min))
51 ,@body)
52 (and buffer (kill-buffer buffer))
53 (delete-file temp-file))))
54
55 (defun python-tests-look-at (string &optional num restore-point)
56 "Move point at beginning of STRING in the current buffer.
57 Optional argument NUM defaults to 1 and is an integer indicating
58 how many occurrences must be found, when positive the search is
59 done forwards, otherwise backwards. When RESTORE-POINT is
60 non-nil the point is not moved but the position found is still
61 returned. When searching forward and point is already looking at
62 STRING, it is skipped so the next STRING occurrence is selected."
63 (let* ((num (or num 1))
64 (starting-point (point))
65 (string (regexp-quote string))
66 (search-fn (if (> num 0) #'re-search-forward #'re-search-backward))
67 (deinc-fn (if (> num 0) #'1- #'1+))
68 (found-point))
69 (prog2
70 (catch 'exit
71 (while (not (= num 0))
72 (when (and (> num 0)
73 (looking-at string))
74 ;; Moving forward and already looking at STRING, skip it.
75 (forward-char (length (match-string-no-properties 0))))
76 (and (not (funcall search-fn string nil t))
77 (throw 'exit t))
78 (when (> num 0)
79 ;; `re-search-forward' leaves point at the end of the
80 ;; occurrence, move back so point is at the beginning
81 ;; instead.
82 (forward-char (- (length (match-string-no-properties 0)))))
83 (setq
84 num (funcall deinc-fn num)
85 found-point (point))))
86 found-point
87 (and restore-point (goto-char starting-point)))))
88
89 (defun python-tests-self-insert (char-or-str)
90 "Call `self-insert-command' for chars in CHAR-OR-STR."
91 (let ((chars
92 (cond
93 ((characterp char-or-str)
94 (list char-or-str))
95 ((stringp char-or-str)
96 (string-to-list char-or-str))
97 ((not
98 (cl-remove-if #'characterp char-or-str))
99 char-or-str)
100 (t (error "CHAR-OR-STR must be a char, string, or list of char")))))
101 (mapc
102 (lambda (char)
103 (let ((last-command-event char))
104 (call-interactively 'self-insert-command)))
105 chars)))
106
107 \f
108 ;;; Tests for your tests, so you can test while you test.
109
110 (ert-deftest python-tests-look-at-1 ()
111 "Test forward movement."
112 (python-tests-with-temp-buffer
113 "Lorem ipsum dolor sit amet, consectetur adipisicing elit,
114 sed do eiusmod tempor incididunt ut labore et dolore magna
115 aliqua."
116 (let ((expected (save-excursion
117 (dotimes (i 3)
118 (re-search-forward "et" nil t))
119 (forward-char -2)
120 (point))))
121 (should (= (python-tests-look-at "et" 3 t) expected))
122 ;; Even if NUM is bigger than found occurrences the point of last
123 ;; one should be returned.
124 (should (= (python-tests-look-at "et" 6 t) expected))
125 ;; If already looking at STRING, it should skip it.
126 (dotimes (i 2) (re-search-forward "et"))
127 (forward-char -2)
128 (should (= (python-tests-look-at "et") expected)))))
129
130 (ert-deftest python-tests-look-at-2 ()
131 "Test backward movement."
132 (python-tests-with-temp-buffer
133 "Lorem ipsum dolor sit amet, consectetur adipisicing elit,
134 sed do eiusmod tempor incididunt ut labore et dolore magna
135 aliqua."
136 (let ((expected
137 (save-excursion
138 (re-search-forward "et" nil t)
139 (forward-char -2)
140 (point))))
141 (dotimes (i 3)
142 (re-search-forward "et" nil t))
143 (should (= (python-tests-look-at "et" -3 t) expected))
144 (should (= (python-tests-look-at "et" -6 t) expected)))))
145
146 \f
147 ;;; Bindings
148
149 \f
150 ;;; Python specialized rx
151
152 \f
153 ;;; Font-lock and syntax
154
155 (ert-deftest python-syntax-after-python-backspace ()
156 ;; `python-indent-dedent-line-backspace' garbles syntax
157 :expected-result :failed
158 (python-tests-with-temp-buffer
159 "\"\"\""
160 (goto-char (point-max))
161 (python-indent-dedent-line-backspace 1)
162 (should (string= (buffer-string) "\"\""))
163 (should (null (nth 3 (syntax-ppss))))))
164
165 \f
166 ;;; Indentation
167
168 ;; See: http://www.python.org/dev/peps/pep-0008/#indentation
169
170 (ert-deftest python-indent-pep8-1 ()
171 "First pep8 case."
172 (python-tests-with-temp-buffer
173 "# Aligned with opening delimiter
174 foo = long_function_name(var_one, var_two,
175 var_three, var_four)
176 "
177 (should (eq (car (python-indent-context)) 'no-indent))
178 (should (= (python-indent-calculate-indentation) 0))
179 (python-tests-look-at "foo = long_function_name(var_one, var_two,")
180 (should (eq (car (python-indent-context)) 'after-line))
181 (should (= (python-indent-calculate-indentation) 0))
182 (python-tests-look-at "var_three, var_four)")
183 (should (eq (car (python-indent-context)) 'inside-paren))
184 (should (= (python-indent-calculate-indentation) 25))))
185
186 (ert-deftest python-indent-pep8-2 ()
187 "Second pep8 case."
188 (python-tests-with-temp-buffer
189 "# More indentation included to distinguish this from the rest.
190 def long_function_name(
191 var_one, var_two, var_three,
192 var_four):
193 print (var_one)
194 "
195 (should (eq (car (python-indent-context)) 'no-indent))
196 (should (= (python-indent-calculate-indentation) 0))
197 (python-tests-look-at "def long_function_name(")
198 (should (eq (car (python-indent-context)) 'after-line))
199 (should (= (python-indent-calculate-indentation) 0))
200 (python-tests-look-at "var_one, var_two, var_three,")
201 (should (eq (car (python-indent-context)) 'inside-paren))
202 (should (= (python-indent-calculate-indentation) 8))
203 (python-tests-look-at "var_four):")
204 (should (eq (car (python-indent-context)) 'inside-paren))
205 (should (= (python-indent-calculate-indentation) 8))
206 (python-tests-look-at "print (var_one)")
207 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
208 (should (= (python-indent-calculate-indentation) 4))))
209
210 (ert-deftest python-indent-pep8-3 ()
211 "Third pep8 case."
212 (python-tests-with-temp-buffer
213 "# Extra indentation is not necessary.
214 foo = long_function_name(
215 var_one, var_two,
216 var_three, var_four)
217 "
218 (should (eq (car (python-indent-context)) 'no-indent))
219 (should (= (python-indent-calculate-indentation) 0))
220 (python-tests-look-at "foo = long_function_name(")
221 (should (eq (car (python-indent-context)) 'after-line))
222 (should (= (python-indent-calculate-indentation) 0))
223 (python-tests-look-at "var_one, var_two,")
224 (should (eq (car (python-indent-context)) 'inside-paren))
225 (should (= (python-indent-calculate-indentation) 4))
226 (python-tests-look-at "var_three, var_four)")
227 (should (eq (car (python-indent-context)) 'inside-paren))
228 (should (= (python-indent-calculate-indentation) 4))))
229
230 (ert-deftest python-indent-after-comment-1 ()
231 "The most simple after-comment case that shouldn't fail."
232 (python-tests-with-temp-buffer
233 "# Contents will be modified to correct indentation
234 class Blag(object):
235 def _on_child_complete(self, child_future):
236 if self.in_terminal_state():
237 pass
238 # We only complete when all our async children have entered a
239 # terminal state. At that point, if any child failed, we fail
240 # with the exception with which the first child failed.
241 "
242 (python-tests-look-at "# We only complete")
243 (should (eq (car (python-indent-context)) 'after-line))
244 (should (= (python-indent-calculate-indentation) 8))
245 (python-tests-look-at "# terminal state")
246 (should (eq (car (python-indent-context)) 'after-comment))
247 (should (= (python-indent-calculate-indentation) 8))
248 (python-tests-look-at "# with the exception")
249 (should (eq (car (python-indent-context)) 'after-comment))
250 ;; This one indents relative to previous block, even given the fact
251 ;; that it was under-indented.
252 (should (= (python-indent-calculate-indentation) 4))
253 (python-tests-look-at "# terminal state" -1)
254 ;; It doesn't hurt to check again.
255 (should (eq (car (python-indent-context)) 'after-comment))
256 (python-indent-line)
257 (should (= (current-indentation) 8))
258 (python-tests-look-at "# with the exception")
259 (should (eq (car (python-indent-context)) 'after-comment))
260 ;; Now everything should be lined up.
261 (should (= (python-indent-calculate-indentation) 8))))
262
263 (ert-deftest python-indent-after-comment-2 ()
264 "Test after-comment in weird cases."
265 (python-tests-with-temp-buffer
266 "# Contents will be modified to correct indentation
267 def func(arg):
268 # I don't do much
269 return arg
270 # This comment is badly indented just because.
271 # But we won't mess with the user in this line.
272
273 now_we_do_mess_cause_this_is_not_a_comment = 1
274
275 # yeah, that.
276 "
277 (python-tests-look-at "# I don't do much")
278 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
279 (should (= (python-indent-calculate-indentation) 4))
280 (python-tests-look-at "return arg")
281 ;; Comment here just gets ignored, this line is not a comment so
282 ;; the rules won't apply here.
283 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
284 (should (= (python-indent-calculate-indentation) 4))
285 (python-tests-look-at "# This comment is badly")
286 (should (eq (car (python-indent-context)) 'after-line))
287 ;; The return keyword moves indentation backwards 4 spaces, but
288 ;; let's assume this comment was placed there because the user
289 ;; wanted to (manually adding spaces or whatever).
290 (should (= (python-indent-calculate-indentation) 0))
291 (python-tests-look-at "# but we won't mess")
292 (should (eq (car (python-indent-context)) 'after-comment))
293 (should (= (python-indent-calculate-indentation) 4))
294 ;; Behave the same for blank lines: potentially a comment.
295 (forward-line 1)
296 (should (eq (car (python-indent-context)) 'after-comment))
297 (should (= (python-indent-calculate-indentation) 4))
298 (python-tests-look-at "now_we_do_mess")
299 ;; Here is where comment indentation starts to get ignored and
300 ;; where the user can't freely indent anymore.
301 (should (eq (car (python-indent-context)) 'after-line))
302 (should (= (python-indent-calculate-indentation) 0))
303 (python-tests-look-at "# yeah, that.")
304 (should (eq (car (python-indent-context)) 'after-line))
305 (should (= (python-indent-calculate-indentation) 0))))
306
307 (ert-deftest python-indent-inside-paren-1 ()
308 "The most simple inside-paren case that shouldn't fail."
309 (python-tests-with-temp-buffer
310 "
311 data = {
312 'key':
313 {
314 'objlist': [
315 {
316 'pk': 1,
317 'name': 'first',
318 },
319 {
320 'pk': 2,
321 'name': 'second',
322 }
323 ]
324 }
325 }
326 "
327 (python-tests-look-at "data = {")
328 (should (eq (car (python-indent-context)) 'after-line))
329 (should (= (python-indent-calculate-indentation) 0))
330 (python-tests-look-at "'key':")
331 (should (eq (car (python-indent-context)) 'inside-paren))
332 (should (= (python-indent-calculate-indentation) 4))
333 (python-tests-look-at "{")
334 (should (eq (car (python-indent-context)) 'inside-paren))
335 (should (= (python-indent-calculate-indentation) 4))
336 (python-tests-look-at "'objlist': [")
337 (should (eq (car (python-indent-context)) 'inside-paren))
338 (should (= (python-indent-calculate-indentation) 8))
339 (python-tests-look-at "{")
340 (should (eq (car (python-indent-context)) 'inside-paren))
341 (should (= (python-indent-calculate-indentation) 12))
342 (python-tests-look-at "'pk': 1,")
343 (should (eq (car (python-indent-context)) 'inside-paren))
344 (should (= (python-indent-calculate-indentation) 16))
345 (python-tests-look-at "'name': 'first',")
346 (should (eq (car (python-indent-context)) 'inside-paren))
347 (should (= (python-indent-calculate-indentation) 16))
348 (python-tests-look-at "},")
349 (should (eq (car (python-indent-context)) 'inside-paren))
350 (should (= (python-indent-calculate-indentation) 12))
351 (python-tests-look-at "{")
352 (should (eq (car (python-indent-context)) 'inside-paren))
353 (should (= (python-indent-calculate-indentation) 12))
354 (python-tests-look-at "'pk': 2,")
355 (should (eq (car (python-indent-context)) 'inside-paren))
356 (should (= (python-indent-calculate-indentation) 16))
357 (python-tests-look-at "'name': 'second',")
358 (should (eq (car (python-indent-context)) 'inside-paren))
359 (should (= (python-indent-calculate-indentation) 16))
360 (python-tests-look-at "}")
361 (should (eq (car (python-indent-context)) 'inside-paren))
362 (should (= (python-indent-calculate-indentation) 12))
363 (python-tests-look-at "]")
364 (should (eq (car (python-indent-context)) 'inside-paren))
365 (should (= (python-indent-calculate-indentation) 8))
366 (python-tests-look-at "}")
367 (should (eq (car (python-indent-context)) 'inside-paren))
368 (should (= (python-indent-calculate-indentation) 4))
369 (python-tests-look-at "}")
370 (should (eq (car (python-indent-context)) 'inside-paren))
371 (should (= (python-indent-calculate-indentation) 0))))
372
373 (ert-deftest python-indent-inside-paren-2 ()
374 "Another more compact paren group style."
375 (python-tests-with-temp-buffer
376 "
377 data = {'key': {
378 'objlist': [
379 {'pk': 1,
380 'name': 'first'},
381 {'pk': 2,
382 'name': 'second'}
383 ]
384 }}
385 "
386 (python-tests-look-at "data = {")
387 (should (eq (car (python-indent-context)) 'after-line))
388 (should (= (python-indent-calculate-indentation) 0))
389 (python-tests-look-at "'objlist': [")
390 (should (eq (car (python-indent-context)) 'inside-paren))
391 (should (= (python-indent-calculate-indentation) 4))
392 (python-tests-look-at "{'pk': 1,")
393 (should (eq (car (python-indent-context)) 'inside-paren))
394 (should (= (python-indent-calculate-indentation) 8))
395 (python-tests-look-at "'name': 'first'},")
396 (should (eq (car (python-indent-context)) 'inside-paren))
397 (should (= (python-indent-calculate-indentation) 9))
398 (python-tests-look-at "{'pk': 2,")
399 (should (eq (car (python-indent-context)) 'inside-paren))
400 (should (= (python-indent-calculate-indentation) 8))
401 (python-tests-look-at "'name': 'second'}")
402 (should (eq (car (python-indent-context)) 'inside-paren))
403 (should (= (python-indent-calculate-indentation) 9))
404 (python-tests-look-at "]")
405 (should (eq (car (python-indent-context)) 'inside-paren))
406 (should (= (python-indent-calculate-indentation) 4))
407 (python-tests-look-at "}}")
408 (should (eq (car (python-indent-context)) 'inside-paren))
409 (should (= (python-indent-calculate-indentation) 0))
410 (python-tests-look-at "}")
411 (should (eq (car (python-indent-context)) 'inside-paren))
412 (should (= (python-indent-calculate-indentation) 0))))
413
414 (ert-deftest python-indent-after-block-1 ()
415 "The most simple after-block case that shouldn't fail."
416 (python-tests-with-temp-buffer
417 "
418 def foo(a, b, c=True):
419 "
420 (should (eq (car (python-indent-context)) 'no-indent))
421 (should (= (python-indent-calculate-indentation) 0))
422 (goto-char (point-max))
423 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
424 (should (= (python-indent-calculate-indentation) 4))))
425
426 (ert-deftest python-indent-after-block-2 ()
427 "A weird (malformed) multiline block statement."
428 (python-tests-with-temp-buffer
429 "
430 def foo(a, b, c={
431 'a':
432 }):
433 "
434 (goto-char (point-max))
435 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
436 (should (= (python-indent-calculate-indentation) 4))))
437
438 (ert-deftest python-indent-dedenters-1 ()
439 "Check all dedenters."
440 (python-tests-with-temp-buffer
441 "
442 def foo(a, b, c):
443 if a:
444 print (a)
445 elif b:
446 print (b)
447 else:
448 try:
449 print (c.pop())
450 except (IndexError, AttributeError):
451 print (c)
452 finally:
453 print ('nor a, nor b are true')
454 "
455 (python-tests-look-at "if a:")
456 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
457 (should (= (python-indent-calculate-indentation) 4))
458 (python-tests-look-at "print (a)")
459 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
460 (should (= (python-indent-calculate-indentation) 8))
461 (python-tests-look-at "elif b:")
462 (should (eq (car (python-indent-context)) 'after-line))
463 (should (= (python-indent-calculate-indentation) 4))
464 (python-tests-look-at "print (b)")
465 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
466 (should (= (python-indent-calculate-indentation) 8))
467 (python-tests-look-at "else:")
468 (should (eq (car (python-indent-context)) 'after-line))
469 (should (= (python-indent-calculate-indentation) 4))
470 (python-tests-look-at "try:")
471 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
472 (should (= (python-indent-calculate-indentation) 8))
473 (python-tests-look-at "print (c.pop())")
474 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
475 (should (= (python-indent-calculate-indentation) 12))
476 (python-tests-look-at "except (IndexError, AttributeError):")
477 (should (eq (car (python-indent-context)) 'after-line))
478 (should (= (python-indent-calculate-indentation) 8))
479 (python-tests-look-at "print (c)")
480 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
481 (should (= (python-indent-calculate-indentation) 12))
482 (python-tests-look-at "finally:")
483 (should (eq (car (python-indent-context)) 'after-line))
484 (should (= (python-indent-calculate-indentation) 8))
485 (python-tests-look-at "print ('nor a, nor b are true')")
486 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
487 (should (= (python-indent-calculate-indentation) 12))))
488
489 (ert-deftest python-indent-dedenters-2 ()
490 "Check one-liner block special case.."
491 (python-tests-with-temp-buffer
492 "
493 cond = True
494 if cond:
495
496 if cond: print 'True'
497 else: print 'False'
498
499 else:
500 return
501 "
502 (python-tests-look-at "else: print 'False'")
503 ;; When a block has code after ":" it's just considered a simple
504 ;; line as that's a common thing to happen in one-liners.
505 (should (eq (car (python-indent-context)) 'after-line))
506 (should (= (python-indent-calculate-indentation) 4))
507 (python-tests-look-at "else:")
508 (should (eq (car (python-indent-context)) 'after-line))
509 (should (= (python-indent-calculate-indentation) 0))))
510
511 (ert-deftest python-indent-after-backslash-1 ()
512 "The most common case."
513 (python-tests-with-temp-buffer
514 "
515 from foo.bar.baz import something, something_1 \\\\
516 something_2 something_3, \\\\
517 something_4, something_5
518 "
519 (python-tests-look-at "from foo.bar.baz import something, something_1")
520 (should (eq (car (python-indent-context)) 'after-line))
521 (should (= (python-indent-calculate-indentation) 0))
522 (python-tests-look-at "something_2 something_3,")
523 (should (eq (car (python-indent-context)) 'after-backslash))
524 (should (= (python-indent-calculate-indentation) 4))
525 (python-tests-look-at "something_4, something_5")
526 (should (eq (car (python-indent-context)) 'after-backslash))
527 (should (= (python-indent-calculate-indentation) 4))
528 (goto-char (point-max))
529 (should (eq (car (python-indent-context)) 'after-line))
530 (should (= (python-indent-calculate-indentation) 0))))
531
532 (ert-deftest python-indent-after-backslash-2 ()
533 "A pretty extreme complicated case."
534 (python-tests-with-temp-buffer
535 "
536 objects = Thing.objects.all() \\\\
537 .filter(
538 type='toy',
539 status='bought'
540 ) \\\\
541 .aggregate(
542 Sum('amount')
543 ) \\\\
544 .values_list()
545 "
546 (python-tests-look-at "objects = Thing.objects.all()")
547 (should (eq (car (python-indent-context)) 'after-line))
548 (should (= (python-indent-calculate-indentation) 0))
549 (python-tests-look-at ".filter(")
550 (should (eq (car (python-indent-context)) 'after-backslash))
551 (should (= (python-indent-calculate-indentation) 23))
552 (python-tests-look-at "type='toy',")
553 (should (eq (car (python-indent-context)) 'inside-paren))
554 (should (= (python-indent-calculate-indentation) 27))
555 (python-tests-look-at "status='bought'")
556 (should (eq (car (python-indent-context)) 'inside-paren))
557 (should (= (python-indent-calculate-indentation) 27))
558 (python-tests-look-at ") \\\\")
559 (should (eq (car (python-indent-context)) 'inside-paren))
560 (should (= (python-indent-calculate-indentation) 23))
561 (python-tests-look-at ".aggregate(")
562 (should (eq (car (python-indent-context)) 'after-backslash))
563 (should (= (python-indent-calculate-indentation) 23))
564 (python-tests-look-at "Sum('amount')")
565 (should (eq (car (python-indent-context)) 'inside-paren))
566 (should (= (python-indent-calculate-indentation) 27))
567 (python-tests-look-at ") \\\\")
568 (should (eq (car (python-indent-context)) 'inside-paren))
569 (should (= (python-indent-calculate-indentation) 23))
570 (python-tests-look-at ".values_list()")
571 (should (eq (car (python-indent-context)) 'after-backslash))
572 (should (= (python-indent-calculate-indentation) 23))
573 (forward-line 1)
574 (should (eq (car (python-indent-context)) 'after-line))
575 (should (= (python-indent-calculate-indentation) 0))))
576
577 (ert-deftest python-indent-block-enders-1 ()
578 "Test `python-indent-block-enders' value honoring."
579 (python-tests-with-temp-buffer
580 "
581 Class foo(object):
582
583 def bar(self):
584 if self.baz:
585 return (1,
586 2,
587 3)
588
589 else:
590 pass
591 "
592 (python-tests-look-at "3)")
593 (forward-line 1)
594 (should (= (python-indent-calculate-indentation) 8))
595 (python-tests-look-at "pass")
596 (forward-line 1)
597 (should (= (python-indent-calculate-indentation) 8))))
598
599 (ert-deftest python-indent-block-enders-2 ()
600 "Test `python-indent-block-enders' value honoring."
601 (python-tests-with-temp-buffer
602 "
603 Class foo(object):
604 '''raise lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
605
606 eiusmod tempor incididunt ut labore et dolore magna aliqua.
607 '''
608 def bar(self):
609 \"return (1, 2, 3).\"
610 if self.baz:
611 return (1,
612 2,
613 3)
614 "
615 (python-tests-look-at "def")
616 (should (= (python-indent-calculate-indentation) 4))
617 (python-tests-look-at "if")
618 (should (= (python-indent-calculate-indentation) 8))))
619
620 \f
621 ;;; Navigation
622
623 (ert-deftest python-nav-beginning-of-defun-1 ()
624 (python-tests-with-temp-buffer
625 "
626 def decoratorFunctionWithArguments(arg1, arg2, arg3):
627 '''print decorated function call data to stdout.
628
629 Usage:
630
631 @decoratorFunctionWithArguments('arg1', 'arg2')
632 def func(a, b, c=True):
633 pass
634 '''
635
636 def wwrap(f):
637 print 'Inside wwrap()'
638 def wrapped_f(*args):
639 print 'Inside wrapped_f()'
640 print 'Decorator arguments:', arg1, arg2, arg3
641 f(*args)
642 print 'After f(*args)'
643 return wrapped_f
644 return wwrap
645 "
646 (python-tests-look-at "return wrap")
647 (should (= (save-excursion
648 (python-nav-beginning-of-defun)
649 (point))
650 (save-excursion
651 (python-tests-look-at "def wrapped_f(*args):" -1)
652 (beginning-of-line)
653 (point))))
654 (python-tests-look-at "def wrapped_f(*args):" -1)
655 (should (= (save-excursion
656 (python-nav-beginning-of-defun)
657 (point))
658 (save-excursion
659 (python-tests-look-at "def wwrap(f):" -1)
660 (beginning-of-line)
661 (point))))
662 (python-tests-look-at "def wwrap(f):" -1)
663 (should (= (save-excursion
664 (python-nav-beginning-of-defun)
665 (point))
666 (save-excursion
667 (python-tests-look-at "def decoratorFunctionWithArguments" -1)
668 (beginning-of-line)
669 (point))))))
670
671 (ert-deftest python-nav-beginning-of-defun-2 ()
672 (python-tests-with-temp-buffer
673 "
674 class C(object):
675
676 def m(self):
677 self.c()
678
679 def b():
680 pass
681
682 def a():
683 pass
684
685 def c(self):
686 pass
687 "
688 ;; Nested defuns, are handled with care.
689 (python-tests-look-at "def c(self):")
690 (should (= (save-excursion
691 (python-nav-beginning-of-defun)
692 (point))
693 (save-excursion
694 (python-tests-look-at "def m(self):" -1)
695 (beginning-of-line)
696 (point))))
697 ;; Defuns on same levels should be respected.
698 (python-tests-look-at "def a():" -1)
699 (should (= (save-excursion
700 (python-nav-beginning-of-defun)
701 (point))
702 (save-excursion
703 (python-tests-look-at "def b():" -1)
704 (beginning-of-line)
705 (point))))
706 ;; Jump to a top level defun.
707 (python-tests-look-at "def b():" -1)
708 (should (= (save-excursion
709 (python-nav-beginning-of-defun)
710 (point))
711 (save-excursion
712 (python-tests-look-at "def m(self):" -1)
713 (beginning-of-line)
714 (point))))
715 ;; Jump to a top level defun again.
716 (python-tests-look-at "def m(self):" -1)
717 (should (= (save-excursion
718 (python-nav-beginning-of-defun)
719 (point))
720 (save-excursion
721 (python-tests-look-at "class C(object):" -1)
722 (beginning-of-line)
723 (point))))))
724
725 (ert-deftest python-nav-end-of-defun-1 ()
726 (python-tests-with-temp-buffer
727 "
728 class C(object):
729
730 def m(self):
731 self.c()
732
733 def b():
734 pass
735
736 def a():
737 pass
738
739 def c(self):
740 pass
741 "
742 (should (= (save-excursion
743 (python-tests-look-at "class C(object):")
744 (python-nav-end-of-defun)
745 (point))
746 (save-excursion
747 (point-max))))
748 (should (= (save-excursion
749 (python-tests-look-at "def m(self):")
750 (python-nav-end-of-defun)
751 (point))
752 (save-excursion
753 (python-tests-look-at "def c(self):")
754 (forward-line -1)
755 (point))))
756 (should (= (save-excursion
757 (python-tests-look-at "def b():")
758 (python-nav-end-of-defun)
759 (point))
760 (save-excursion
761 (python-tests-look-at "def b():")
762 (forward-line 2)
763 (point))))
764 (should (= (save-excursion
765 (python-tests-look-at "def c(self):")
766 (python-nav-end-of-defun)
767 (point))
768 (save-excursion
769 (point-max))))))
770
771 (ert-deftest python-nav-end-of-defun-2 ()
772 (python-tests-with-temp-buffer
773 "
774 def decoratorFunctionWithArguments(arg1, arg2, arg3):
775 '''print decorated function call data to stdout.
776
777 Usage:
778
779 @decoratorFunctionWithArguments('arg1', 'arg2')
780 def func(a, b, c=True):
781 pass
782 '''
783
784 def wwrap(f):
785 print 'Inside wwrap()'
786 def wrapped_f(*args):
787 print 'Inside wrapped_f()'
788 print 'Decorator arguments:', arg1, arg2, arg3
789 f(*args)
790 print 'After f(*args)'
791 return wrapped_f
792 return wwrap
793 "
794 (should (= (save-excursion
795 (python-tests-look-at "def decoratorFunctionWithArguments")
796 (python-nav-end-of-defun)
797 (point))
798 (save-excursion
799 (point-max))))
800 (should (= (save-excursion
801 (python-tests-look-at "@decoratorFunctionWithArguments")
802 (python-nav-end-of-defun)
803 (point))
804 (save-excursion
805 (point-max))))
806 (should (= (save-excursion
807 (python-tests-look-at "def wwrap(f):")
808 (python-nav-end-of-defun)
809 (point))
810 (save-excursion
811 (python-tests-look-at "return wwrap")
812 (line-beginning-position))))
813 (should (= (save-excursion
814 (python-tests-look-at "def wrapped_f(*args):")
815 (python-nav-end-of-defun)
816 (point))
817 (save-excursion
818 (python-tests-look-at "return wrapped_f")
819 (line-beginning-position))))
820 (should (= (save-excursion
821 (python-tests-look-at "f(*args)")
822 (python-nav-end-of-defun)
823 (point))
824 (save-excursion
825 (python-tests-look-at "return wrapped_f")
826 (line-beginning-position))))))
827
828 (ert-deftest python-nav-backward-defun-1 ()
829 (python-tests-with-temp-buffer
830 "
831 class A(object): # A
832
833 def a(self): # a
834 pass
835
836 def b(self): # b
837 pass
838
839 class B(object): # B
840
841 class C(object): # C
842
843 def d(self): # d
844 pass
845
846 # def e(self): # e
847 # pass
848
849 def c(self): # c
850 pass
851
852 # def d(self): # d
853 # pass
854 "
855 (goto-char (point-max))
856 (should (= (save-excursion (python-nav-backward-defun))
857 (python-tests-look-at " def c(self): # c" -1)))
858 (should (= (save-excursion (python-nav-backward-defun))
859 (python-tests-look-at " def d(self): # d" -1)))
860 (should (= (save-excursion (python-nav-backward-defun))
861 (python-tests-look-at " class C(object): # C" -1)))
862 (should (= (save-excursion (python-nav-backward-defun))
863 (python-tests-look-at " class B(object): # B" -1)))
864 (should (= (save-excursion (python-nav-backward-defun))
865 (python-tests-look-at " def b(self): # b" -1)))
866 (should (= (save-excursion (python-nav-backward-defun))
867 (python-tests-look-at " def a(self): # a" -1)))
868 (should (= (save-excursion (python-nav-backward-defun))
869 (python-tests-look-at "class A(object): # A" -1)))
870 (should (not (python-nav-backward-defun)))))
871
872 (ert-deftest python-nav-backward-defun-2 ()
873 (python-tests-with-temp-buffer
874 "
875 def decoratorFunctionWithArguments(arg1, arg2, arg3):
876 '''print decorated function call data to stdout.
877
878 Usage:
879
880 @decoratorFunctionWithArguments('arg1', 'arg2')
881 def func(a, b, c=True):
882 pass
883 '''
884
885 def wwrap(f):
886 print 'Inside wwrap()'
887 def wrapped_f(*args):
888 print 'Inside wrapped_f()'
889 print 'Decorator arguments:', arg1, arg2, arg3
890 f(*args)
891 print 'After f(*args)'
892 return wrapped_f
893 return wwrap
894 "
895 (goto-char (point-max))
896 (should (= (save-excursion (python-nav-backward-defun))
897 (python-tests-look-at " def wrapped_f(*args):" -1)))
898 (should (= (save-excursion (python-nav-backward-defun))
899 (python-tests-look-at " def wwrap(f):" -1)))
900 (should (= (save-excursion (python-nav-backward-defun))
901 (python-tests-look-at "def decoratorFunctionWithArguments(arg1, arg2, arg3):" -1)))
902 (should (not (python-nav-backward-defun)))))
903
904 (ert-deftest python-nav-backward-defun-3 ()
905 (python-tests-with-temp-buffer
906 "
907 '''
908 def u(self):
909 pass
910
911 def v(self):
912 pass
913
914 def w(self):
915 pass
916 '''
917
918 class A(object):
919 pass
920 "
921 (goto-char (point-min))
922 (let ((point (python-tests-look-at "class A(object):")))
923 (should (not (python-nav-backward-defun)))
924 (should (= point (point))))))
925
926 (ert-deftest python-nav-forward-defun-1 ()
927 (python-tests-with-temp-buffer
928 "
929 class A(object): # A
930
931 def a(self): # a
932 pass
933
934 def b(self): # b
935 pass
936
937 class B(object): # B
938
939 class C(object): # C
940
941 def d(self): # d
942 pass
943
944 # def e(self): # e
945 # pass
946
947 def c(self): # c
948 pass
949
950 # def d(self): # d
951 # pass
952 "
953 (goto-char (point-min))
954 (should (= (save-excursion (python-nav-forward-defun))
955 (python-tests-look-at "(object): # A")))
956 (should (= (save-excursion (python-nav-forward-defun))
957 (python-tests-look-at "(self): # a")))
958 (should (= (save-excursion (python-nav-forward-defun))
959 (python-tests-look-at "(self): # b")))
960 (should (= (save-excursion (python-nav-forward-defun))
961 (python-tests-look-at "(object): # B")))
962 (should (= (save-excursion (python-nav-forward-defun))
963 (python-tests-look-at "(object): # C")))
964 (should (= (save-excursion (python-nav-forward-defun))
965 (python-tests-look-at "(self): # d")))
966 (should (= (save-excursion (python-nav-forward-defun))
967 (python-tests-look-at "(self): # c")))
968 (should (not (python-nav-forward-defun)))))
969
970 (ert-deftest python-nav-forward-defun-2 ()
971 (python-tests-with-temp-buffer
972 "
973 def decoratorFunctionWithArguments(arg1, arg2, arg3):
974 '''print decorated function call data to stdout.
975
976 Usage:
977
978 @decoratorFunctionWithArguments('arg1', 'arg2')
979 def func(a, b, c=True):
980 pass
981 '''
982
983 def wwrap(f):
984 print 'Inside wwrap()'
985 def wrapped_f(*args):
986 print 'Inside wrapped_f()'
987 print 'Decorator arguments:', arg1, arg2, arg3
988 f(*args)
989 print 'After f(*args)'
990 return wrapped_f
991 return wwrap
992 "
993 (goto-char (point-min))
994 (should (= (save-excursion (python-nav-forward-defun))
995 (python-tests-look-at "(arg1, arg2, arg3):")))
996 (should (= (save-excursion (python-nav-forward-defun))
997 (python-tests-look-at "(f):")))
998 (should (= (save-excursion (python-nav-forward-defun))
999 (python-tests-look-at "(*args):")))
1000 (should (not (python-nav-forward-defun)))))
1001
1002 (ert-deftest python-nav-forward-defun-3 ()
1003 (python-tests-with-temp-buffer
1004 "
1005 class A(object):
1006 pass
1007
1008 '''
1009 def u(self):
1010 pass
1011
1012 def v(self):
1013 pass
1014
1015 def w(self):
1016 pass
1017 '''
1018 "
1019 (goto-char (point-min))
1020 (let ((point (python-tests-look-at "(object):")))
1021 (should (not (python-nav-forward-defun)))
1022 (should (= point (point))))))
1023
1024 (ert-deftest python-nav-beginning-of-statement-1 ()
1025 (python-tests-with-temp-buffer
1026 "
1027 v1 = 123 + \
1028 456 + \
1029 789
1030 v2 = (value1,
1031 value2,
1032
1033 value3,
1034 value4)
1035 v3 = ('this is a string'
1036
1037 'that is continued'
1038 'between lines'
1039 'within a paren',
1040 # this is a comment, yo
1041 'continue previous line')
1042 v4 = '''
1043 a very long
1044 string
1045 '''
1046 "
1047 (python-tests-look-at "v2 =")
1048 (python-util-forward-comment -1)
1049 (should (= (save-excursion
1050 (python-nav-beginning-of-statement)
1051 (point))
1052 (python-tests-look-at "v1 =" -1 t)))
1053 (python-tests-look-at "v3 =")
1054 (python-util-forward-comment -1)
1055 (should (= (save-excursion
1056 (python-nav-beginning-of-statement)
1057 (point))
1058 (python-tests-look-at "v2 =" -1 t)))
1059 (python-tests-look-at "v4 =")
1060 (python-util-forward-comment -1)
1061 (should (= (save-excursion
1062 (python-nav-beginning-of-statement)
1063 (point))
1064 (python-tests-look-at "v3 =" -1 t)))
1065 (goto-char (point-max))
1066 (python-util-forward-comment -1)
1067 (should (= (save-excursion
1068 (python-nav-beginning-of-statement)
1069 (point))
1070 (python-tests-look-at "v4 =" -1 t)))))
1071
1072 (ert-deftest python-nav-end-of-statement-1 ()
1073 (python-tests-with-temp-buffer
1074 "
1075 v1 = 123 + \
1076 456 + \
1077 789
1078 v2 = (value1,
1079 value2,
1080
1081 value3,
1082 value4)
1083 v3 = ('this is a string'
1084
1085 'that is continued'
1086 'between lines'
1087 'within a paren',
1088 # this is a comment, yo
1089 'continue previous line')
1090 v4 = '''
1091 a very long
1092 string
1093 '''
1094 "
1095 (python-tests-look-at "v1 =")
1096 (should (= (save-excursion
1097 (python-nav-end-of-statement)
1098 (point))
1099 (save-excursion
1100 (python-tests-look-at "789")
1101 (line-end-position))))
1102 (python-tests-look-at "v2 =")
1103 (should (= (save-excursion
1104 (python-nav-end-of-statement)
1105 (point))
1106 (save-excursion
1107 (python-tests-look-at "value4)")
1108 (line-end-position))))
1109 (python-tests-look-at "v3 =")
1110 (should (= (save-excursion
1111 (python-nav-end-of-statement)
1112 (point))
1113 (save-excursion
1114 (python-tests-look-at
1115 "'continue previous line')")
1116 (line-end-position))))
1117 (python-tests-look-at "v4 =")
1118 (should (= (save-excursion
1119 (python-nav-end-of-statement)
1120 (point))
1121 (save-excursion
1122 (goto-char (point-max))
1123 (python-util-forward-comment -1)
1124 (point))))))
1125
1126 (ert-deftest python-nav-forward-statement-1 ()
1127 (python-tests-with-temp-buffer
1128 "
1129 v1 = 123 + \
1130 456 + \
1131 789
1132 v2 = (value1,
1133 value2,
1134
1135 value3,
1136 value4)
1137 v3 = ('this is a string'
1138
1139 'that is continued'
1140 'between lines'
1141 'within a paren',
1142 # this is a comment, yo
1143 'continue previous line')
1144 v4 = '''
1145 a very long
1146 string
1147 '''
1148 "
1149 (python-tests-look-at "v1 =")
1150 (should (= (save-excursion
1151 (python-nav-forward-statement)
1152 (point))
1153 (python-tests-look-at "v2 =")))
1154 (should (= (save-excursion
1155 (python-nav-forward-statement)
1156 (point))
1157 (python-tests-look-at "v3 =")))
1158 (should (= (save-excursion
1159 (python-nav-forward-statement)
1160 (point))
1161 (python-tests-look-at "v4 =")))
1162 (should (= (save-excursion
1163 (python-nav-forward-statement)
1164 (point))
1165 (point-max)))))
1166
1167 (ert-deftest python-nav-backward-statement-1 ()
1168 (python-tests-with-temp-buffer
1169 "
1170 v1 = 123 + \
1171 456 + \
1172 789
1173 v2 = (value1,
1174 value2,
1175
1176 value3,
1177 value4)
1178 v3 = ('this is a string'
1179
1180 'that is continued'
1181 'between lines'
1182 'within a paren',
1183 # this is a comment, yo
1184 'continue previous line')
1185 v4 = '''
1186 a very long
1187 string
1188 '''
1189 "
1190 (goto-char (point-max))
1191 (should (= (save-excursion
1192 (python-nav-backward-statement)
1193 (point))
1194 (python-tests-look-at "v4 =" -1)))
1195 (should (= (save-excursion
1196 (python-nav-backward-statement)
1197 (point))
1198 (python-tests-look-at "v3 =" -1)))
1199 (should (= (save-excursion
1200 (python-nav-backward-statement)
1201 (point))
1202 (python-tests-look-at "v2 =" -1)))
1203 (should (= (save-excursion
1204 (python-nav-backward-statement)
1205 (point))
1206 (python-tests-look-at "v1 =" -1)))))
1207
1208 (ert-deftest python-nav-backward-statement-2 ()
1209 :expected-result :failed
1210 (python-tests-with-temp-buffer
1211 "
1212 v1 = 123 + \
1213 456 + \
1214 789
1215 v2 = (value1,
1216 value2,
1217
1218 value3,
1219 value4)
1220 "
1221 ;; FIXME: For some reason `python-nav-backward-statement' is moving
1222 ;; back two sentences when starting from 'value4)'.
1223 (goto-char (point-max))
1224 (python-util-forward-comment -1)
1225 (should (= (save-excursion
1226 (python-nav-backward-statement)
1227 (point))
1228 (python-tests-look-at "v2 =" -1 t)))))
1229
1230 (ert-deftest python-nav-beginning-of-block-1 ()
1231 (python-tests-with-temp-buffer
1232 "
1233 def decoratorFunctionWithArguments(arg1, arg2, arg3):
1234 '''print decorated function call data to stdout.
1235
1236 Usage:
1237
1238 @decoratorFunctionWithArguments('arg1', 'arg2')
1239 def func(a, b, c=True):
1240 pass
1241 '''
1242
1243 def wwrap(f):
1244 print 'Inside wwrap()'
1245 def wrapped_f(*args):
1246 print 'Inside wrapped_f()'
1247 print 'Decorator arguments:', arg1, arg2, arg3
1248 f(*args)
1249 print 'After f(*args)'
1250 return wrapped_f
1251 return wwrap
1252 "
1253 (python-tests-look-at "return wwrap")
1254 (should (= (save-excursion
1255 (python-nav-beginning-of-block)
1256 (point))
1257 (python-tests-look-at "def decoratorFunctionWithArguments" -1)))
1258 (python-tests-look-at "print 'Inside wwrap()'")
1259 (should (= (save-excursion
1260 (python-nav-beginning-of-block)
1261 (point))
1262 (python-tests-look-at "def wwrap(f):" -1)))
1263 (python-tests-look-at "print 'After f(*args)'")
1264 (end-of-line)
1265 (should (= (save-excursion
1266 (python-nav-beginning-of-block)
1267 (point))
1268 (python-tests-look-at "def wrapped_f(*args):" -1)))
1269 (python-tests-look-at "return wrapped_f")
1270 (should (= (save-excursion
1271 (python-nav-beginning-of-block)
1272 (point))
1273 (python-tests-look-at "def wwrap(f):" -1)))))
1274
1275 (ert-deftest python-nav-end-of-block-1 ()
1276 (python-tests-with-temp-buffer
1277 "
1278 def decoratorFunctionWithArguments(arg1, arg2, arg3):
1279 '''print decorated function call data to stdout.
1280
1281 Usage:
1282
1283 @decoratorFunctionWithArguments('arg1', 'arg2')
1284 def func(a, b, c=True):
1285 pass
1286 '''
1287
1288 def wwrap(f):
1289 print 'Inside wwrap()'
1290 def wrapped_f(*args):
1291 print 'Inside wrapped_f()'
1292 print 'Decorator arguments:', arg1, arg2, arg3
1293 f(*args)
1294 print 'After f(*args)'
1295 return wrapped_f
1296 return wwrap
1297 "
1298 (python-tests-look-at "def decoratorFunctionWithArguments")
1299 (should (= (save-excursion
1300 (python-nav-end-of-block)
1301 (point))
1302 (save-excursion
1303 (goto-char (point-max))
1304 (python-util-forward-comment -1)
1305 (point))))
1306 (python-tests-look-at "def wwrap(f):")
1307 (should (= (save-excursion
1308 (python-nav-end-of-block)
1309 (point))
1310 (save-excursion
1311 (python-tests-look-at "return wrapped_f")
1312 (line-end-position))))
1313 (end-of-line)
1314 (should (= (save-excursion
1315 (python-nav-end-of-block)
1316 (point))
1317 (save-excursion
1318 (python-tests-look-at "return wrapped_f")
1319 (line-end-position))))
1320 (python-tests-look-at "f(*args)")
1321 (should (= (save-excursion
1322 (python-nav-end-of-block)
1323 (point))
1324 (save-excursion
1325 (python-tests-look-at "print 'After f(*args)'")
1326 (line-end-position))))))
1327
1328 (ert-deftest python-nav-forward-block-1 ()
1329 "This also accounts as a test for `python-nav-backward-block'."
1330 (python-tests-with-temp-buffer
1331 "
1332 if request.user.is_authenticated():
1333 # def block():
1334 # pass
1335 try:
1336 profile = request.user.get_profile()
1337 except Profile.DoesNotExist:
1338 profile = Profile.objects.create(user=request.user)
1339 else:
1340 if profile.stats:
1341 profile.recalculate_stats()
1342 else:
1343 profile.clear_stats()
1344 finally:
1345 profile.views += 1
1346 profile.save()
1347 "
1348 (should (= (save-excursion (python-nav-forward-block))
1349 (python-tests-look-at "if request.user.is_authenticated():")))
1350 (should (= (save-excursion (python-nav-forward-block))
1351 (python-tests-look-at "try:")))
1352 (should (= (save-excursion (python-nav-forward-block))
1353 (python-tests-look-at "except Profile.DoesNotExist:")))
1354 (should (= (save-excursion (python-nav-forward-block))
1355 (python-tests-look-at "else:")))
1356 (should (= (save-excursion (python-nav-forward-block))
1357 (python-tests-look-at "if profile.stats:")))
1358 (should (= (save-excursion (python-nav-forward-block))
1359 (python-tests-look-at "else:")))
1360 (should (= (save-excursion (python-nav-forward-block))
1361 (python-tests-look-at "finally:")))
1362 ;; When point is at the last block, leave it there and return nil
1363 (should (not (save-excursion (python-nav-forward-block))))
1364 ;; Move backwards, and even if the number of moves is less than the
1365 ;; provided argument return the point.
1366 (should (= (save-excursion (python-nav-forward-block -10))
1367 (python-tests-look-at
1368 "if request.user.is_authenticated():" -1)))))
1369
1370 (ert-deftest python-nav-forward-sexp-1 ()
1371 (python-tests-with-temp-buffer
1372 "
1373 a()
1374 b()
1375 c()
1376 "
1377 (python-tests-look-at "a()")
1378 (python-nav-forward-sexp)
1379 (should (looking-at "$"))
1380 (should (save-excursion
1381 (beginning-of-line)
1382 (looking-at "a()")))
1383 (python-nav-forward-sexp)
1384 (should (looking-at "$"))
1385 (should (save-excursion
1386 (beginning-of-line)
1387 (looking-at "b()")))
1388 (python-nav-forward-sexp)
1389 (should (looking-at "$"))
1390 (should (save-excursion
1391 (beginning-of-line)
1392 (looking-at "c()")))
1393 ;; Movement next to a paren should do what lisp does and
1394 ;; unfortunately It can't change, because otherwise
1395 ;; `blink-matching-open' breaks.
1396 (python-nav-forward-sexp -1)
1397 (should (looking-at "()"))
1398 (should (save-excursion
1399 (beginning-of-line)
1400 (looking-at "c()")))
1401 (python-nav-forward-sexp -1)
1402 (should (looking-at "c()"))
1403 (python-nav-forward-sexp -1)
1404 (should (looking-at "b()"))
1405 (python-nav-forward-sexp -1)
1406 (should (looking-at "a()"))))
1407
1408 (ert-deftest python-nav-forward-sexp-2 ()
1409 (python-tests-with-temp-buffer
1410 "
1411 def func():
1412 if True:
1413 aaa = bbb
1414 ccc = ddd
1415 eee = fff
1416 return ggg
1417 "
1418 (python-tests-look-at "aa =")
1419 (python-nav-forward-sexp)
1420 (should (looking-at " = bbb"))
1421 (python-nav-forward-sexp)
1422 (should (looking-at "$"))
1423 (should (save-excursion
1424 (back-to-indentation)
1425 (looking-at "aaa = bbb")))
1426 (python-nav-forward-sexp)
1427 (should (looking-at "$"))
1428 (should (save-excursion
1429 (back-to-indentation)
1430 (looking-at "ccc = ddd")))
1431 (python-nav-forward-sexp)
1432 (should (looking-at "$"))
1433 (should (save-excursion
1434 (back-to-indentation)
1435 (looking-at "eee = fff")))
1436 (python-nav-forward-sexp)
1437 (should (looking-at "$"))
1438 (should (save-excursion
1439 (back-to-indentation)
1440 (looking-at "return ggg")))
1441 (python-nav-forward-sexp -1)
1442 (should (looking-at "def func():"))))
1443
1444 (ert-deftest python-nav-forward-sexp-3 ()
1445 (python-tests-with-temp-buffer
1446 "
1447 from some_module import some_sub_module
1448 from another_module import another_sub_module
1449
1450 def another_statement():
1451 pass
1452 "
1453 (python-tests-look-at "some_module")
1454 (python-nav-forward-sexp)
1455 (should (looking-at " import"))
1456 (python-nav-forward-sexp)
1457 (should (looking-at " some_sub_module"))
1458 (python-nav-forward-sexp)
1459 (should (looking-at "$"))
1460 (should
1461 (save-excursion
1462 (back-to-indentation)
1463 (looking-at
1464 "from some_module import some_sub_module")))
1465 (python-nav-forward-sexp)
1466 (should (looking-at "$"))
1467 (should
1468 (save-excursion
1469 (back-to-indentation)
1470 (looking-at
1471 "from another_module import another_sub_module")))
1472 (python-nav-forward-sexp)
1473 (should (looking-at "$"))
1474 (should
1475 (save-excursion
1476 (back-to-indentation)
1477 (looking-at
1478 "pass")))
1479 (python-nav-forward-sexp -1)
1480 (should (looking-at "def another_statement():"))
1481 (python-nav-forward-sexp -1)
1482 (should (looking-at "from another_module import another_sub_module"))
1483 (python-nav-forward-sexp -1)
1484 (should (looking-at "from some_module import some_sub_module"))))
1485
1486 (ert-deftest python-nav-forward-sexp-safe-1 ()
1487 (python-tests-with-temp-buffer
1488 "
1489 profile = Profile.objects.create(user=request.user)
1490 profile.notify()
1491 "
1492 (python-tests-look-at "profile =")
1493 (python-nav-forward-sexp-safe 1)
1494 (should (looking-at "$"))
1495 (beginning-of-line 1)
1496 (python-tests-look-at "user=request.user")
1497 (python-nav-forward-sexp-safe -1)
1498 (should (looking-at "(user=request.user)"))
1499 (python-nav-forward-sexp-safe -4)
1500 (should (looking-at "profile ="))
1501 (python-tests-look-at "user=request.user")
1502 (python-nav-forward-sexp-safe 3)
1503 (should (looking-at ")"))
1504 (python-nav-forward-sexp-safe 1)
1505 (should (looking-at "$"))
1506 (python-nav-forward-sexp-safe 1)
1507 (should (looking-at "$"))))
1508
1509 (ert-deftest python-nav-up-list-1 ()
1510 (python-tests-with-temp-buffer
1511 "
1512 def f():
1513 if True:
1514 return [i for i in range(3)]
1515 "
1516 (python-tests-look-at "3)]")
1517 (python-nav-up-list)
1518 (should (looking-at "]"))
1519 (python-nav-up-list)
1520 (should (looking-at "$"))))
1521
1522 (ert-deftest python-nav-backward-up-list-1 ()
1523 :expected-result :failed
1524 (python-tests-with-temp-buffer
1525 "
1526 def f():
1527 if True:
1528 return [i for i in range(3)]
1529 "
1530 (python-tests-look-at "3)]")
1531 (python-nav-backward-up-list)
1532 (should (looking-at "(3)\\]"))
1533 (python-nav-backward-up-list)
1534 (should (looking-at
1535 "\\[i for i in range(3)\\]"))
1536 ;; FIXME: Need to move to beginning-of-statement.
1537 (python-nav-backward-up-list)
1538 (should (looking-at
1539 "return \\[i for i in range(3)\\]"))
1540 (python-nav-backward-up-list)
1541 (should (looking-at "if True:"))
1542 (python-nav-backward-up-list)
1543 (should (looking-at "def f():"))))
1544
1545 \f
1546 ;;; Shell integration
1547
1548 (defvar python-tests-shell-interpreter "python")
1549
1550 (ert-deftest python-shell-get-process-name-1 ()
1551 "Check process name calculation on different scenarios."
1552 (python-tests-with-temp-buffer
1553 ""
1554 (should (string= (python-shell-get-process-name nil)
1555 python-shell-buffer-name))
1556 ;; When the `current-buffer' doesn't have `buffer-file-name', even
1557 ;; if dedicated flag is non-nil should not include its name.
1558 (should (string= (python-shell-get-process-name t)
1559 python-shell-buffer-name)))
1560 (python-tests-with-temp-file
1561 ""
1562 ;; `buffer-file-name' is non-nil but the dedicated flag is nil and
1563 ;; should be respected.
1564 (should (string= (python-shell-get-process-name nil)
1565 python-shell-buffer-name))
1566 (should (string=
1567 (python-shell-get-process-name t)
1568 (format "%s[%s]" python-shell-buffer-name buffer-file-name)))))
1569
1570 (ert-deftest python-shell-internal-get-process-name-1 ()
1571 "Check the internal process name is config-unique."
1572 (let* ((python-shell-interpreter python-tests-shell-interpreter)
1573 (python-shell-interpreter-args "")
1574 (python-shell-prompt-regexp ">>> ")
1575 (python-shell-prompt-block-regexp "[.][.][.] ")
1576 (python-shell-setup-codes "")
1577 (python-shell-process-environment "")
1578 (python-shell-extra-pythonpaths "")
1579 (python-shell-exec-path "")
1580 (python-shell-virtualenv-path "")
1581 (expected (python-tests-with-temp-buffer
1582 "" (python-shell-internal-get-process-name))))
1583 ;; Same configurations should match.
1584 (should
1585 (string= expected
1586 (python-tests-with-temp-buffer
1587 "" (python-shell-internal-get-process-name))))
1588 (let ((python-shell-interpreter-args "-B"))
1589 ;; A minimal change should generate different names.
1590 (should
1591 (not (string=
1592 expected
1593 (python-tests-with-temp-buffer
1594 "" (python-shell-internal-get-process-name))))))))
1595
1596 (ert-deftest python-shell-parse-command-1 ()
1597 "Check the command to execute is calculated correctly.
1598 Using `python-shell-interpreter' and
1599 `python-shell-interpreter-args'."
1600 (skip-unless (executable-find python-tests-shell-interpreter))
1601 (let ((python-shell-interpreter (executable-find
1602 python-tests-shell-interpreter))
1603 (python-shell-interpreter-args "-B"))
1604 (should (string=
1605 (format "%s %s"
1606 python-shell-interpreter
1607 python-shell-interpreter-args)
1608 (python-shell-parse-command)))))
1609
1610 (ert-deftest python-shell-calculate-process-environment-1 ()
1611 "Test `python-shell-process-environment' modification."
1612 (let* ((original-process-environment process-environment)
1613 (python-shell-process-environment
1614 '("TESTVAR1=value1" "TESTVAR2=value2"))
1615 (process-environment
1616 (python-shell-calculate-process-environment)))
1617 (should (equal (getenv "TESTVAR1") "value1"))
1618 (should (equal (getenv "TESTVAR2") "value2"))))
1619
1620 (ert-deftest python-shell-calculate-process-environment-2 ()
1621 "Test `python-shell-extra-pythonpaths' modification."
1622 (let* ((original-process-environment process-environment)
1623 (original-pythonpath (getenv "PYTHONPATH"))
1624 (paths '("path1" "path2"))
1625 (python-shell-extra-pythonpaths paths)
1626 (process-environment
1627 (python-shell-calculate-process-environment)))
1628 (should (equal (getenv "PYTHONPATH")
1629 (concat
1630 (mapconcat 'identity paths path-separator)
1631 path-separator original-pythonpath)))))
1632
1633 (ert-deftest python-shell-calculate-process-environment-3 ()
1634 "Test `python-shell-virtualenv-path' modification."
1635 (let* ((original-process-environment process-environment)
1636 (original-path (or (getenv "PATH") ""))
1637 (python-shell-virtualenv-path
1638 (directory-file-name user-emacs-directory))
1639 (process-environment
1640 (python-shell-calculate-process-environment)))
1641 (should (not (getenv "PYTHONHOME")))
1642 (should (string= (getenv "VIRTUAL_ENV") python-shell-virtualenv-path))
1643 (should (equal (getenv "PATH")
1644 (format "%s/bin%s%s"
1645 python-shell-virtualenv-path
1646 path-separator original-path)))))
1647
1648 (ert-deftest python-shell-calculate-exec-path-1 ()
1649 "Test `python-shell-exec-path' modification."
1650 (let* ((original-exec-path exec-path)
1651 (python-shell-exec-path '("path1" "path2"))
1652 (exec-path (python-shell-calculate-exec-path)))
1653 (should (equal
1654 exec-path
1655 (append python-shell-exec-path
1656 original-exec-path)))))
1657
1658 (ert-deftest python-shell-calculate-exec-path-2 ()
1659 "Test `python-shell-exec-path' modification."
1660 (let* ((original-exec-path exec-path)
1661 (python-shell-virtualenv-path
1662 (directory-file-name user-emacs-directory))
1663 (exec-path (python-shell-calculate-exec-path)))
1664 (should (equal
1665 exec-path
1666 (append (cons
1667 (format "%s/bin" python-shell-virtualenv-path)
1668 original-exec-path))))))
1669
1670 (ert-deftest python-shell-make-comint-1 ()
1671 "Check comint creation for global shell buffer."
1672 (skip-unless (executable-find python-tests-shell-interpreter))
1673 ;; The interpreter can get killed too quickly to allow it to clean
1674 ;; up the tempfiles that the default python-shell-setup-codes create,
1675 ;; so it leaves tempfiles behind, which is a minor irritation.
1676 (let* ((python-shell-setup-codes nil)
1677 (python-shell-interpreter
1678 (executable-find python-tests-shell-interpreter))
1679 (proc-name (python-shell-get-process-name nil))
1680 (shell-buffer
1681 (python-tests-with-temp-buffer
1682 "" (python-shell-make-comint
1683 (python-shell-parse-command) proc-name)))
1684 (process (get-buffer-process shell-buffer)))
1685 (unwind-protect
1686 (progn
1687 (set-process-query-on-exit-flag process nil)
1688 (should (process-live-p process))
1689 (with-current-buffer shell-buffer
1690 (should (eq major-mode 'inferior-python-mode))
1691 (should (string= (buffer-name) (format "*%s*" proc-name)))))
1692 (kill-buffer shell-buffer))))
1693
1694 (ert-deftest python-shell-make-comint-2 ()
1695 "Check comint creation for internal shell buffer."
1696 (skip-unless (executable-find python-tests-shell-interpreter))
1697 (let* ((python-shell-setup-codes nil)
1698 (python-shell-interpreter
1699 (executable-find python-tests-shell-interpreter))
1700 (proc-name (python-shell-internal-get-process-name))
1701 (shell-buffer
1702 (python-tests-with-temp-buffer
1703 "" (python-shell-make-comint
1704 (python-shell-parse-command) proc-name nil t)))
1705 (process (get-buffer-process shell-buffer)))
1706 (unwind-protect
1707 (progn
1708 (set-process-query-on-exit-flag process nil)
1709 (should (process-live-p process))
1710 (with-current-buffer shell-buffer
1711 (should (eq major-mode 'inferior-python-mode))
1712 (should (string= (buffer-name) (format " *%s*" proc-name)))))
1713 (kill-buffer shell-buffer))))
1714
1715 (ert-deftest python-shell-get-process-1 ()
1716 "Check dedicated shell process preference over global."
1717 (skip-unless (executable-find python-tests-shell-interpreter))
1718 (python-tests-with-temp-file
1719 ""
1720 (let* ((python-shell-setup-codes nil)
1721 (python-shell-interpreter
1722 (executable-find python-tests-shell-interpreter))
1723 (global-proc-name (python-shell-get-process-name nil))
1724 (dedicated-proc-name (python-shell-get-process-name t))
1725 (global-shell-buffer
1726 (python-shell-make-comint
1727 (python-shell-parse-command) global-proc-name))
1728 (dedicated-shell-buffer
1729 (python-shell-make-comint
1730 (python-shell-parse-command) dedicated-proc-name))
1731 (global-process (get-buffer-process global-shell-buffer))
1732 (dedicated-process (get-buffer-process dedicated-shell-buffer)))
1733 (unwind-protect
1734 (progn
1735 (set-process-query-on-exit-flag global-process nil)
1736 (set-process-query-on-exit-flag dedicated-process nil)
1737 ;; Prefer dedicated if global also exists.
1738 (should (equal (python-shell-get-process) dedicated-process))
1739 (kill-buffer dedicated-shell-buffer)
1740 ;; If there's only global, use it.
1741 (should (equal (python-shell-get-process) global-process))
1742 (kill-buffer global-shell-buffer)
1743 ;; No buffer available.
1744 (should (not (python-shell-get-process))))
1745 (ignore-errors (kill-buffer global-shell-buffer))
1746 (ignore-errors (kill-buffer dedicated-shell-buffer))))))
1747
1748 (ert-deftest python-shell-get-or-create-process-1 ()
1749 "Check shell process creation fallback."
1750 :expected-result :failed
1751 (python-tests-with-temp-file
1752 ""
1753 ;; XXX: Break early until we can skip stuff. We need to mimic
1754 ;; user interaction because `python-shell-get-or-create-process'
1755 ;; asks for all arguments interactively when a shell process
1756 ;; doesn't exist.
1757 (should nil)
1758 (let* ((python-shell-interpreter
1759 (executable-find python-tests-shell-interpreter))
1760 (use-dialog-box)
1761 (dedicated-process-name (python-shell-get-process-name t))
1762 (dedicated-process (python-shell-get-or-create-process))
1763 (dedicated-shell-buffer (process-buffer dedicated-process)))
1764 (unwind-protect
1765 (progn
1766 (set-process-query-on-exit-flag dedicated-process nil)
1767 ;; Prefer dedicated if not buffer exist.
1768 (should (equal (process-name dedicated-process)
1769 dedicated-process-name))
1770 (kill-buffer dedicated-shell-buffer)
1771 ;; No buffer available.
1772 (should (not (python-shell-get-process))))
1773 (ignore-errors (kill-buffer dedicated-shell-buffer))))))
1774
1775 (ert-deftest python-shell-internal-get-or-create-process-1 ()
1776 "Check internal shell process creation fallback."
1777 (skip-unless (executable-find python-tests-shell-interpreter))
1778 (python-tests-with-temp-file
1779 ""
1780 (should (not (process-live-p (python-shell-internal-get-process-name))))
1781 (let* ((python-shell-interpreter
1782 (executable-find python-tests-shell-interpreter))
1783 (internal-process-name (python-shell-internal-get-process-name))
1784 (internal-process (python-shell-internal-get-or-create-process))
1785 (internal-shell-buffer (process-buffer internal-process)))
1786 (unwind-protect
1787 (progn
1788 (set-process-query-on-exit-flag internal-process nil)
1789 (should (equal (process-name internal-process)
1790 internal-process-name))
1791 (should (equal internal-process
1792 (python-shell-internal-get-or-create-process)))
1793 ;; No user buffer available.
1794 (should (not (python-shell-get-process)))
1795 (kill-buffer internal-shell-buffer))
1796 (ignore-errors (kill-buffer internal-shell-buffer))))))
1797
1798 \f
1799 ;;; Shell completion
1800
1801 \f
1802 ;;; PDB Track integration
1803
1804 \f
1805 ;;; Symbol completion
1806
1807 \f
1808 ;;; Fill paragraph
1809
1810 \f
1811 ;;; Skeletons
1812
1813 \f
1814 ;;; FFAP
1815
1816 \f
1817 ;;; Code check
1818
1819 \f
1820 ;;; Eldoc
1821
1822 \f
1823 ;;; Imenu
1824
1825 (ert-deftest python-imenu-create-index-1 ()
1826 (python-tests-with-temp-buffer
1827 "
1828 class Foo(models.Model):
1829 pass
1830
1831
1832 class Bar(models.Model):
1833 pass
1834
1835
1836 def decorator(arg1, arg2, arg3):
1837 '''print decorated function call data to stdout.
1838
1839 Usage:
1840
1841 @decorator('arg1', 'arg2')
1842 def func(a, b, c=True):
1843 pass
1844 '''
1845
1846 def wrap(f):
1847 print ('wrap')
1848 def wrapped_f(*args):
1849 print ('wrapped_f')
1850 print ('Decorator arguments:', arg1, arg2, arg3)
1851 f(*args)
1852 print ('called f(*args)')
1853 return wrapped_f
1854 return wrap
1855
1856
1857 class Baz(object):
1858
1859 def a(self):
1860 pass
1861
1862 def b(self):
1863 pass
1864
1865 class Frob(object):
1866
1867 def c(self):
1868 pass
1869 "
1870 (goto-char (point-max))
1871 (should (equal
1872 (list
1873 (cons "Foo (class)" (copy-marker 2))
1874 (cons "Bar (class)" (copy-marker 38))
1875 (list
1876 "decorator (def)"
1877 (cons "*function definition*" (copy-marker 74))
1878 (list
1879 "wrap (def)"
1880 (cons "*function definition*" (copy-marker 254))
1881 (cons "wrapped_f (def)" (copy-marker 294))))
1882 (list
1883 "Baz (class)"
1884 (cons "*class definition*" (copy-marker 519))
1885 (cons "a (def)" (copy-marker 539))
1886 (cons "b (def)" (copy-marker 570))
1887 (list
1888 "Frob (class)"
1889 (cons "*class definition*" (copy-marker 601))
1890 (cons "c (def)" (copy-marker 626)))))
1891 (python-imenu-create-index)))))
1892
1893 (ert-deftest python-imenu-create-index-2 ()
1894 (python-tests-with-temp-buffer
1895 "
1896 class Foo(object):
1897 def foo(self):
1898 def foo1():
1899 pass
1900
1901 def foobar(self):
1902 pass
1903 "
1904 (goto-char (point-max))
1905 (should (equal
1906 (list
1907 (list
1908 "Foo (class)"
1909 (cons "*class definition*" (copy-marker 2))
1910 (list
1911 "foo (def)"
1912 (cons "*function definition*" (copy-marker 21))
1913 (cons "foo1 (def)" (copy-marker 40)))
1914 (cons "foobar (def)" (copy-marker 78))))
1915 (python-imenu-create-index)))))
1916
1917 (ert-deftest python-imenu-create-index-3 ()
1918 (python-tests-with-temp-buffer
1919 "
1920 class Foo(object):
1921 def foo(self):
1922 def foo1():
1923 pass
1924 def foo2():
1925 pass
1926 "
1927 (goto-char (point-max))
1928 (should (equal
1929 (list
1930 (list
1931 "Foo (class)"
1932 (cons "*class definition*" (copy-marker 2))
1933 (list
1934 "foo (def)"
1935 (cons "*function definition*" (copy-marker 21))
1936 (cons "foo1 (def)" (copy-marker 40))
1937 (cons "foo2 (def)" (copy-marker 77)))))
1938 (python-imenu-create-index)))))
1939
1940 (ert-deftest python-imenu-create-index-4 ()
1941 (python-tests-with-temp-buffer
1942 "
1943 class Foo(object):
1944 class Bar(object):
1945 def __init__(self):
1946 pass
1947
1948 def __str__(self):
1949 pass
1950
1951 def __init__(self):
1952 pass
1953 "
1954 (goto-char (point-max))
1955 (should (equal
1956 (list
1957 (list
1958 "Foo (class)"
1959 (cons "*class definition*" (copy-marker 2))
1960 (list
1961 "Bar (class)"
1962 (cons "*class definition*" (copy-marker 21))
1963 (cons "__init__ (def)" (copy-marker 44))
1964 (cons "__str__ (def)" (copy-marker 90)))
1965 (cons "__init__ (def)" (copy-marker 135))))
1966 (python-imenu-create-index)))))
1967
1968 (ert-deftest python-imenu-create-flat-index-1 ()
1969 (python-tests-with-temp-buffer
1970 "
1971 class Foo(models.Model):
1972 pass
1973
1974
1975 class Bar(models.Model):
1976 pass
1977
1978
1979 def decorator(arg1, arg2, arg3):
1980 '''print decorated function call data to stdout.
1981
1982 Usage:
1983
1984 @decorator('arg1', 'arg2')
1985 def func(a, b, c=True):
1986 pass
1987 '''
1988
1989 def wrap(f):
1990 print ('wrap')
1991 def wrapped_f(*args):
1992 print ('wrapped_f')
1993 print ('Decorator arguments:', arg1, arg2, arg3)
1994 f(*args)
1995 print ('called f(*args)')
1996 return wrapped_f
1997 return wrap
1998
1999
2000 class Baz(object):
2001
2002 def a(self):
2003 pass
2004
2005 def b(self):
2006 pass
2007
2008 class Frob(object):
2009
2010 def c(self):
2011 pass
2012 "
2013 (goto-char (point-max))
2014 (should (equal
2015 (list (cons "Foo" (copy-marker 2))
2016 (cons "Bar" (copy-marker 38))
2017 (cons "decorator" (copy-marker 74))
2018 (cons "decorator.wrap" (copy-marker 254))
2019 (cons "decorator.wrap.wrapped_f" (copy-marker 294))
2020 (cons "Baz" (copy-marker 519))
2021 (cons "Baz.a" (copy-marker 539))
2022 (cons "Baz.b" (copy-marker 570))
2023 (cons "Baz.Frob" (copy-marker 601))
2024 (cons "Baz.Frob.c" (copy-marker 626)))
2025 (python-imenu-create-flat-index)))))
2026
2027 (ert-deftest python-imenu-create-flat-index-2 ()
2028 (python-tests-with-temp-buffer
2029 "
2030 class Foo(object):
2031 class Bar(object):
2032 def __init__(self):
2033 pass
2034
2035 def __str__(self):
2036 pass
2037
2038 def __init__(self):
2039 pass
2040 "
2041 (goto-char (point-max))
2042 (should (equal
2043 (list
2044 (cons "Foo" (copy-marker 2))
2045 (cons "Foo.Bar" (copy-marker 21))
2046 (cons "Foo.Bar.__init__" (copy-marker 44))
2047 (cons "Foo.Bar.__str__" (copy-marker 90))
2048 (cons "Foo.__init__" (copy-marker 135)))
2049 (python-imenu-create-flat-index)))))
2050
2051 \f
2052 ;;; Misc helpers
2053
2054 (ert-deftest python-info-current-defun-1 ()
2055 (python-tests-with-temp-buffer
2056 "
2057 def foo(a, b):
2058 "
2059 (forward-line 1)
2060 (should (string= "foo" (python-info-current-defun)))
2061 (should (string= "def foo" (python-info-current-defun t)))
2062 (forward-line 1)
2063 (should (not (python-info-current-defun)))
2064 (indent-for-tab-command)
2065 (should (string= "foo" (python-info-current-defun)))
2066 (should (string= "def foo" (python-info-current-defun t)))))
2067
2068 (ert-deftest python-info-current-defun-2 ()
2069 (python-tests-with-temp-buffer
2070 "
2071 class C(object):
2072
2073 def m(self):
2074 if True:
2075 return [i for i in range(3)]
2076 else:
2077 return []
2078
2079 def b():
2080 do_b()
2081
2082 def a():
2083 do_a()
2084
2085 def c(self):
2086 do_c()
2087 "
2088 (forward-line 1)
2089 (should (string= "C" (python-info-current-defun)))
2090 (should (string= "class C" (python-info-current-defun t)))
2091 (python-tests-look-at "return [i for ")
2092 (should (string= "C.m" (python-info-current-defun)))
2093 (should (string= "def C.m" (python-info-current-defun t)))
2094 (python-tests-look-at "def b():")
2095 (should (string= "C.m.b" (python-info-current-defun)))
2096 (should (string= "def C.m.b" (python-info-current-defun t)))
2097 (forward-line 2)
2098 (indent-for-tab-command)
2099 (python-indent-dedent-line-backspace 1)
2100 (should (string= "C.m" (python-info-current-defun)))
2101 (should (string= "def C.m" (python-info-current-defun t)))
2102 (python-tests-look-at "def c(self):")
2103 (forward-line -1)
2104 (indent-for-tab-command)
2105 (should (string= "C.m.a" (python-info-current-defun)))
2106 (should (string= "def C.m.a" (python-info-current-defun t)))
2107 (python-indent-dedent-line-backspace 1)
2108 (should (string= "C.m" (python-info-current-defun)))
2109 (should (string= "def C.m" (python-info-current-defun t)))
2110 (python-indent-dedent-line-backspace 1)
2111 (should (string= "C" (python-info-current-defun)))
2112 (should (string= "class C" (python-info-current-defun t)))
2113 (python-tests-look-at "def c(self):")
2114 (should (string= "C.c" (python-info-current-defun)))
2115 (should (string= "def C.c" (python-info-current-defun t)))
2116 (python-tests-look-at "do_c()")
2117 (should (string= "C.c" (python-info-current-defun)))
2118 (should (string= "def C.c" (python-info-current-defun t)))))
2119
2120 (ert-deftest python-info-current-defun-3 ()
2121 (python-tests-with-temp-buffer
2122 "
2123 def decoratorFunctionWithArguments(arg1, arg2, arg3):
2124 '''print decorated function call data to stdout.
2125
2126 Usage:
2127
2128 @decoratorFunctionWithArguments('arg1', 'arg2')
2129 def func(a, b, c=True):
2130 pass
2131 '''
2132
2133 def wwrap(f):
2134 print 'Inside wwrap()'
2135 def wrapped_f(*args):
2136 print 'Inside wrapped_f()'
2137 print 'Decorator arguments:', arg1, arg2, arg3
2138 f(*args)
2139 print 'After f(*args)'
2140 return wrapped_f
2141 return wwrap
2142 "
2143 (python-tests-look-at "def wwrap(f):")
2144 (forward-line -1)
2145 (should (not (python-info-current-defun)))
2146 (indent-for-tab-command 1)
2147 (should (string= (python-info-current-defun)
2148 "decoratorFunctionWithArguments"))
2149 (should (string= (python-info-current-defun t)
2150 "def decoratorFunctionWithArguments"))
2151 (python-tests-look-at "def wrapped_f(*args):")
2152 (should (string= (python-info-current-defun)
2153 "decoratorFunctionWithArguments.wwrap.wrapped_f"))
2154 (should (string= (python-info-current-defun t)
2155 "def decoratorFunctionWithArguments.wwrap.wrapped_f"))
2156 (python-tests-look-at "return wrapped_f")
2157 (should (string= (python-info-current-defun)
2158 "decoratorFunctionWithArguments.wwrap"))
2159 (should (string= (python-info-current-defun t)
2160 "def decoratorFunctionWithArguments.wwrap"))
2161 (end-of-line 1)
2162 (python-tests-look-at "return wwrap")
2163 (should (string= (python-info-current-defun)
2164 "decoratorFunctionWithArguments"))
2165 (should (string= (python-info-current-defun t)
2166 "def decoratorFunctionWithArguments"))))
2167
2168 (ert-deftest python-info-current-symbol-1 ()
2169 (python-tests-with-temp-buffer
2170 "
2171 class C(object):
2172
2173 def m(self):
2174 self.c()
2175
2176 def c(self):
2177 print ('a')
2178 "
2179 (python-tests-look-at "self.c()")
2180 (should (string= "self.c" (python-info-current-symbol)))
2181 (should (string= "C.c" (python-info-current-symbol t)))))
2182
2183 (ert-deftest python-info-current-symbol-2 ()
2184 (python-tests-with-temp-buffer
2185 "
2186 class C(object):
2187
2188 class M(object):
2189
2190 def a(self):
2191 self.c()
2192
2193 def c(self):
2194 pass
2195 "
2196 (python-tests-look-at "self.c()")
2197 (should (string= "self.c" (python-info-current-symbol)))
2198 (should (string= "C.M.c" (python-info-current-symbol t)))))
2199
2200 (ert-deftest python-info-current-symbol-3 ()
2201 "Keywords should not be considered symbols."
2202 :expected-result :failed
2203 (python-tests-with-temp-buffer
2204 "
2205 class C(object):
2206 pass
2207 "
2208 ;; FIXME: keywords are not symbols.
2209 (python-tests-look-at "class C")
2210 (should (not (python-info-current-symbol)))
2211 (should (not (python-info-current-symbol t)))
2212 (python-tests-look-at "C(object)")
2213 (should (string= "C" (python-info-current-symbol)))
2214 (should (string= "class C" (python-info-current-symbol t)))))
2215
2216 (ert-deftest python-info-statement-starts-block-p-1 ()
2217 (python-tests-with-temp-buffer
2218 "
2219 def long_function_name(
2220 var_one, var_two, var_three,
2221 var_four):
2222 print (var_one)
2223 "
2224 (python-tests-look-at "def long_function_name")
2225 (should (python-info-statement-starts-block-p))
2226 (python-tests-look-at "print (var_one)")
2227 (python-util-forward-comment -1)
2228 (should (python-info-statement-starts-block-p))))
2229
2230 (ert-deftest python-info-statement-starts-block-p-2 ()
2231 (python-tests-with-temp-buffer
2232 "
2233 if width == 0 and height == 0 and \\\\
2234 color == 'red' and emphasis == 'strong' or \\\\
2235 highlight > 100:
2236 raise ValueError('sorry, you lose')
2237 "
2238 (python-tests-look-at "if width == 0 and")
2239 (should (python-info-statement-starts-block-p))
2240 (python-tests-look-at "raise ValueError(")
2241 (python-util-forward-comment -1)
2242 (should (python-info-statement-starts-block-p))))
2243
2244 (ert-deftest python-info-statement-ends-block-p-1 ()
2245 (python-tests-with-temp-buffer
2246 "
2247 def long_function_name(
2248 var_one, var_two, var_three,
2249 var_four):
2250 print (var_one)
2251 "
2252 (python-tests-look-at "print (var_one)")
2253 (should (python-info-statement-ends-block-p))))
2254
2255 (ert-deftest python-info-statement-ends-block-p-2 ()
2256 (python-tests-with-temp-buffer
2257 "
2258 if width == 0 and height == 0 and \\\\
2259 color == 'red' and emphasis == 'strong' or \\\\
2260 highlight > 100:
2261 raise ValueError(
2262 'sorry, you lose'
2263
2264 )
2265 "
2266 (python-tests-look-at "raise ValueError(")
2267 (should (python-info-statement-ends-block-p))))
2268
2269 (ert-deftest python-info-beginning-of-statement-p-1 ()
2270 (python-tests-with-temp-buffer
2271 "
2272 def long_function_name(
2273 var_one, var_two, var_three,
2274 var_four):
2275 print (var_one)
2276 "
2277 (python-tests-look-at "def long_function_name")
2278 (should (python-info-beginning-of-statement-p))
2279 (forward-char 10)
2280 (should (not (python-info-beginning-of-statement-p)))
2281 (python-tests-look-at "print (var_one)")
2282 (should (python-info-beginning-of-statement-p))
2283 (goto-char (line-beginning-position))
2284 (should (not (python-info-beginning-of-statement-p)))))
2285
2286 (ert-deftest python-info-beginning-of-statement-p-2 ()
2287 (python-tests-with-temp-buffer
2288 "
2289 if width == 0 and height == 0 and \\\\
2290 color == 'red' and emphasis == 'strong' or \\\\
2291 highlight > 100:
2292 raise ValueError(
2293 'sorry, you lose'
2294
2295 )
2296 "
2297 (python-tests-look-at "if width == 0 and")
2298 (should (python-info-beginning-of-statement-p))
2299 (forward-char 10)
2300 (should (not (python-info-beginning-of-statement-p)))
2301 (python-tests-look-at "raise ValueError(")
2302 (should (python-info-beginning-of-statement-p))
2303 (goto-char (line-beginning-position))
2304 (should (not (python-info-beginning-of-statement-p)))))
2305
2306 (ert-deftest python-info-end-of-statement-p-1 ()
2307 (python-tests-with-temp-buffer
2308 "
2309 def long_function_name(
2310 var_one, var_two, var_three,
2311 var_four):
2312 print (var_one)
2313 "
2314 (python-tests-look-at "def long_function_name")
2315 (should (not (python-info-end-of-statement-p)))
2316 (end-of-line)
2317 (should (not (python-info-end-of-statement-p)))
2318 (python-tests-look-at "print (var_one)")
2319 (python-util-forward-comment -1)
2320 (should (python-info-end-of-statement-p))
2321 (python-tests-look-at "print (var_one)")
2322 (should (not (python-info-end-of-statement-p)))
2323 (end-of-line)
2324 (should (python-info-end-of-statement-p))))
2325
2326 (ert-deftest python-info-end-of-statement-p-2 ()
2327 (python-tests-with-temp-buffer
2328 "
2329 if width == 0 and height == 0 and \\\\
2330 color == 'red' and emphasis == 'strong' or \\\\
2331 highlight > 100:
2332 raise ValueError(
2333 'sorry, you lose'
2334
2335 )
2336 "
2337 (python-tests-look-at "if width == 0 and")
2338 (should (not (python-info-end-of-statement-p)))
2339 (end-of-line)
2340 (should (not (python-info-end-of-statement-p)))
2341 (python-tests-look-at "raise ValueError(")
2342 (python-util-forward-comment -1)
2343 (should (python-info-end-of-statement-p))
2344 (python-tests-look-at "raise ValueError(")
2345 (should (not (python-info-end-of-statement-p)))
2346 (end-of-line)
2347 (should (not (python-info-end-of-statement-p)))
2348 (goto-char (point-max))
2349 (python-util-forward-comment -1)
2350 (should (python-info-end-of-statement-p))))
2351
2352 (ert-deftest python-info-beginning-of-block-p-1 ()
2353 (python-tests-with-temp-buffer
2354 "
2355 def long_function_name(
2356 var_one, var_two, var_three,
2357 var_four):
2358 print (var_one)
2359 "
2360 (python-tests-look-at "def long_function_name")
2361 (should (python-info-beginning-of-block-p))
2362 (python-tests-look-at "var_one, var_two, var_three,")
2363 (should (not (python-info-beginning-of-block-p)))
2364 (python-tests-look-at "print (var_one)")
2365 (should (not (python-info-beginning-of-block-p)))))
2366
2367 (ert-deftest python-info-beginning-of-block-p-2 ()
2368 (python-tests-with-temp-buffer
2369 "
2370 if width == 0 and height == 0 and \\\\
2371 color == 'red' and emphasis == 'strong' or \\\\
2372 highlight > 100:
2373 raise ValueError(
2374 'sorry, you lose'
2375
2376 )
2377 "
2378 (python-tests-look-at "if width == 0 and")
2379 (should (python-info-beginning-of-block-p))
2380 (python-tests-look-at "color == 'red' and emphasis")
2381 (should (not (python-info-beginning-of-block-p)))
2382 (python-tests-look-at "raise ValueError(")
2383 (should (not (python-info-beginning-of-block-p)))))
2384
2385 (ert-deftest python-info-end-of-block-p-1 ()
2386 (python-tests-with-temp-buffer
2387 "
2388 def long_function_name(
2389 var_one, var_two, var_three,
2390 var_four):
2391 print (var_one)
2392 "
2393 (python-tests-look-at "def long_function_name")
2394 (should (not (python-info-end-of-block-p)))
2395 (python-tests-look-at "var_one, var_two, var_three,")
2396 (should (not (python-info-end-of-block-p)))
2397 (python-tests-look-at "var_four):")
2398 (end-of-line)
2399 (should (not (python-info-end-of-block-p)))
2400 (python-tests-look-at "print (var_one)")
2401 (should (not (python-info-end-of-block-p)))
2402 (end-of-line 1)
2403 (should (python-info-end-of-block-p))))
2404
2405 (ert-deftest python-info-end-of-block-p-2 ()
2406 (python-tests-with-temp-buffer
2407 "
2408 if width == 0 and height == 0 and \\\\
2409 color == 'red' and emphasis == 'strong' or \\\\
2410 highlight > 100:
2411 raise ValueError(
2412 'sorry, you lose'
2413
2414 )
2415 "
2416 (python-tests-look-at "if width == 0 and")
2417 (should (not (python-info-end-of-block-p)))
2418 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
2419 (should (not (python-info-end-of-block-p)))
2420 (python-tests-look-at "highlight > 100:")
2421 (end-of-line)
2422 (should (not (python-info-end-of-block-p)))
2423 (python-tests-look-at "raise ValueError(")
2424 (should (not (python-info-end-of-block-p)))
2425 (end-of-line 1)
2426 (should (not (python-info-end-of-block-p)))
2427 (goto-char (point-max))
2428 (python-util-forward-comment -1)
2429 (should (python-info-end-of-block-p))))
2430
2431 (ert-deftest python-info-closing-block-1 ()
2432 (python-tests-with-temp-buffer
2433 "
2434 if request.user.is_authenticated():
2435 try:
2436 profile = request.user.get_profile()
2437 except Profile.DoesNotExist:
2438 profile = Profile.objects.create(user=request.user)
2439 else:
2440 if profile.stats:
2441 profile.recalculate_stats()
2442 else:
2443 profile.clear_stats()
2444 finally:
2445 profile.views += 1
2446 profile.save()
2447 "
2448 (python-tests-look-at "try:")
2449 (should (not (python-info-closing-block)))
2450 (python-tests-look-at "except Profile.DoesNotExist:")
2451 (should (= (python-tests-look-at "try:" -1 t)
2452 (python-info-closing-block)))
2453 (python-tests-look-at "else:")
2454 (should (= (python-tests-look-at "except Profile.DoesNotExist:" -1 t)
2455 (python-info-closing-block)))
2456 (python-tests-look-at "if profile.stats:")
2457 (should (not (python-info-closing-block)))
2458 (python-tests-look-at "else:")
2459 (should (= (python-tests-look-at "if profile.stats:" -1 t)
2460 (python-info-closing-block)))
2461 (python-tests-look-at "finally:")
2462 (should (= (python-tests-look-at "else:" -2 t)
2463 (python-info-closing-block)))))
2464
2465 (ert-deftest python-info-closing-block-2 ()
2466 (python-tests-with-temp-buffer
2467 "
2468 if request.user.is_authenticated():
2469 profile = Profile.objects.get_or_create(user=request.user)
2470 if profile.stats:
2471 profile.recalculate_stats()
2472
2473 data = {
2474 'else': 'do it'
2475 }
2476 'else'
2477 "
2478 (python-tests-look-at "'else': 'do it'")
2479 (should (not (python-info-closing-block)))
2480 (python-tests-look-at "'else'")
2481 (should (not (python-info-closing-block)))))
2482
2483 (ert-deftest python-info-line-ends-backslash-p-1 ()
2484 (python-tests-with-temp-buffer
2485 "
2486 objects = Thing.objects.all() \\\\
2487 .filter(
2488 type='toy',
2489 status='bought'
2490 ) \\\\
2491 .aggregate(
2492 Sum('amount')
2493 ) \\\\
2494 .values_list()
2495 "
2496 (should (python-info-line-ends-backslash-p 2)) ; .filter(...
2497 (should (python-info-line-ends-backslash-p 3))
2498 (should (python-info-line-ends-backslash-p 4))
2499 (should (python-info-line-ends-backslash-p 5))
2500 (should (python-info-line-ends-backslash-p 6)) ; ) \...
2501 (should (python-info-line-ends-backslash-p 7))
2502 (should (python-info-line-ends-backslash-p 8))
2503 (should (python-info-line-ends-backslash-p 9))
2504 (should (not (python-info-line-ends-backslash-p 10))))) ; .values_list()...
2505
2506 (ert-deftest python-info-beginning-of-backslash-1 ()
2507 (python-tests-with-temp-buffer
2508 "
2509 objects = Thing.objects.all() \\\\
2510 .filter(
2511 type='toy',
2512 status='bought'
2513 ) \\\\
2514 .aggregate(
2515 Sum('amount')
2516 ) \\\\
2517 .values_list()
2518 "
2519 (let ((first 2)
2520 (second (python-tests-look-at ".filter("))
2521 (third (python-tests-look-at ".aggregate(")))
2522 (should (= first (python-info-beginning-of-backslash 2)))
2523 (should (= second (python-info-beginning-of-backslash 3)))
2524 (should (= second (python-info-beginning-of-backslash 4)))
2525 (should (= second (python-info-beginning-of-backslash 5)))
2526 (should (= second (python-info-beginning-of-backslash 6)))
2527 (should (= third (python-info-beginning-of-backslash 7)))
2528 (should (= third (python-info-beginning-of-backslash 8)))
2529 (should (= third (python-info-beginning-of-backslash 9)))
2530 (should (not (python-info-beginning-of-backslash 10))))))
2531
2532 (ert-deftest python-info-continuation-line-p-1 ()
2533 (python-tests-with-temp-buffer
2534 "
2535 if width == 0 and height == 0 and \\\\
2536 color == 'red' and emphasis == 'strong' or \\\\
2537 highlight > 100:
2538 raise ValueError(
2539 'sorry, you lose'
2540
2541 )
2542 "
2543 (python-tests-look-at "if width == 0 and height == 0 and")
2544 (should (not (python-info-continuation-line-p)))
2545 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
2546 (should (python-info-continuation-line-p))
2547 (python-tests-look-at "highlight > 100:")
2548 (should (python-info-continuation-line-p))
2549 (python-tests-look-at "raise ValueError(")
2550 (should (not (python-info-continuation-line-p)))
2551 (python-tests-look-at "'sorry, you lose'")
2552 (should (python-info-continuation-line-p))
2553 (forward-line 1)
2554 (should (python-info-continuation-line-p))
2555 (python-tests-look-at ")")
2556 (should (python-info-continuation-line-p))
2557 (forward-line 1)
2558 (should (not (python-info-continuation-line-p)))))
2559
2560 (ert-deftest python-info-block-continuation-line-p-1 ()
2561 (python-tests-with-temp-buffer
2562 "
2563 if width == 0 and height == 0 and \\\\
2564 color == 'red' and emphasis == 'strong' or \\\\
2565 highlight > 100:
2566 raise ValueError(
2567 'sorry, you lose'
2568
2569 )
2570 "
2571 (python-tests-look-at "if width == 0 and")
2572 (should (not (python-info-block-continuation-line-p)))
2573 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
2574 (should (= (python-info-block-continuation-line-p)
2575 (python-tests-look-at "if width == 0 and" -1 t)))
2576 (python-tests-look-at "highlight > 100:")
2577 (should (not (python-info-block-continuation-line-p)))))
2578
2579 (ert-deftest python-info-block-continuation-line-p-2 ()
2580 (python-tests-with-temp-buffer
2581 "
2582 def foo(a,
2583 b,
2584 c):
2585 pass
2586 "
2587 (python-tests-look-at "def foo(a,")
2588 (should (not (python-info-block-continuation-line-p)))
2589 (python-tests-look-at "b,")
2590 (should (= (python-info-block-continuation-line-p)
2591 (python-tests-look-at "def foo(a," -1 t)))
2592 (python-tests-look-at "c):")
2593 (should (not (python-info-block-continuation-line-p)))))
2594
2595 (ert-deftest python-info-assignment-continuation-line-p-1 ()
2596 (python-tests-with-temp-buffer
2597 "
2598 data = foo(), bar() \\\\
2599 baz(), 4 \\\\
2600 5, 6
2601 "
2602 (python-tests-look-at "data = foo(), bar()")
2603 (should (not (python-info-assignment-continuation-line-p)))
2604 (python-tests-look-at "baz(), 4")
2605 (should (= (python-info-assignment-continuation-line-p)
2606 (python-tests-look-at "foo()," -1 t)))
2607 (python-tests-look-at "5, 6")
2608 (should (not (python-info-assignment-continuation-line-p)))))
2609
2610 (ert-deftest python-info-assignment-continuation-line-p-2 ()
2611 (python-tests-with-temp-buffer
2612 "
2613 data = (foo(), bar()
2614 baz(), 4
2615 5, 6)
2616 "
2617 (python-tests-look-at "data = (foo(), bar()")
2618 (should (not (python-info-assignment-continuation-line-p)))
2619 (python-tests-look-at "baz(), 4")
2620 (should (= (python-info-assignment-continuation-line-p)
2621 (python-tests-look-at "(foo()," -1 t)))
2622 (python-tests-look-at "5, 6)")
2623 (should (not (python-info-assignment-continuation-line-p)))))
2624
2625 (ert-deftest python-info-looking-at-beginning-of-defun-1 ()
2626 (python-tests-with-temp-buffer
2627 "
2628 def decorat0r(deff):
2629 '''decorates stuff.
2630
2631 @decorat0r
2632 def foo(arg):
2633 ...
2634 '''
2635 def wrap():
2636 deff()
2637 return wwrap
2638 "
2639 (python-tests-look-at "def decorat0r(deff):")
2640 (should (python-info-looking-at-beginning-of-defun))
2641 (python-tests-look-at "def foo(arg):")
2642 (should (not (python-info-looking-at-beginning-of-defun)))
2643 (python-tests-look-at "def wrap():")
2644 (should (python-info-looking-at-beginning-of-defun))
2645 (python-tests-look-at "deff()")
2646 (should (not (python-info-looking-at-beginning-of-defun)))))
2647
2648 (ert-deftest python-info-current-line-comment-p-1 ()
2649 (python-tests-with-temp-buffer
2650 "
2651 # this is a comment
2652 foo = True # another comment
2653 '#this is a string'
2654 if foo:
2655 # more comments
2656 print ('bar') # print bar
2657 "
2658 (python-tests-look-at "# this is a comment")
2659 (should (python-info-current-line-comment-p))
2660 (python-tests-look-at "foo = True # another comment")
2661 (should (not (python-info-current-line-comment-p)))
2662 (python-tests-look-at "'#this is a string'")
2663 (should (not (python-info-current-line-comment-p)))
2664 (python-tests-look-at "# more comments")
2665 (should (python-info-current-line-comment-p))
2666 (python-tests-look-at "print ('bar') # print bar")
2667 (should (not (python-info-current-line-comment-p)))))
2668
2669 (ert-deftest python-info-current-line-empty-p ()
2670 (python-tests-with-temp-buffer
2671 "
2672 # this is a comment
2673
2674 foo = True # another comment
2675 "
2676 (should (python-info-current-line-empty-p))
2677 (python-tests-look-at "# this is a comment")
2678 (should (not (python-info-current-line-empty-p)))
2679 (forward-line 1)
2680 (should (python-info-current-line-empty-p))))
2681
2682 \f
2683 ;;; Utility functions
2684
2685 (ert-deftest python-util-goto-line-1 ()
2686 (python-tests-with-temp-buffer
2687 (concat
2688 "# a comment
2689 # another comment
2690 def foo(a, b, c):
2691 pass" (make-string 20 ?\n))
2692 (python-util-goto-line 10)
2693 (should (= (line-number-at-pos) 10))
2694 (python-util-goto-line 20)
2695 (should (= (line-number-at-pos) 20))))
2696
2697 (ert-deftest python-util-clone-local-variables-1 ()
2698 (let ((buffer (generate-new-buffer
2699 "python-util-clone-local-variables-1"))
2700 (varcons
2701 '((python-fill-docstring-style . django)
2702 (python-shell-interpreter . "python")
2703 (python-shell-interpreter-args . "manage.py shell")
2704 (python-shell-prompt-regexp . "In \\[[0-9]+\\]: ")
2705 (python-shell-prompt-output-regexp . "Out\\[[0-9]+\\]: ")
2706 (python-shell-extra-pythonpaths "/home/user/pylib/")
2707 (python-shell-completion-setup-code
2708 . "from IPython.core.completerlib import module_completion")
2709 (python-shell-completion-module-string-code
2710 . "';'.join(module_completion('''%s'''))\n")
2711 (python-shell-completion-string-code
2712 . "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
2713 (python-shell-virtualenv-path
2714 . "/home/user/.virtualenvs/project"))))
2715 (with-current-buffer buffer
2716 (kill-all-local-variables)
2717 (dolist (ccons varcons)
2718 (set (make-local-variable (car ccons)) (cdr ccons))))
2719 (python-tests-with-temp-buffer
2720 ""
2721 (python-util-clone-local-variables buffer)
2722 (dolist (ccons varcons)
2723 (should
2724 (equal (symbol-value (car ccons)) (cdr ccons)))))
2725 (kill-buffer buffer)))
2726
2727 (ert-deftest python-util-strip-string-1 ()
2728 (should (string= (python-util-strip-string "\t\r\n str") "str"))
2729 (should (string= (python-util-strip-string "str \n\r") "str"))
2730 (should (string= (python-util-strip-string "\t\r\n str \n\r ") "str"))
2731 (should
2732 (string= (python-util-strip-string "\n str \nin \tg \n\r") "str \nin \tg"))
2733 (should (string= (python-util-strip-string "\n \t \n\r ") ""))
2734 (should (string= (python-util-strip-string "") "")))
2735
2736 (ert-deftest python-util-forward-comment-1 ()
2737 (python-tests-with-temp-buffer
2738 (concat
2739 "# a comment
2740 # another comment
2741 # bad indented comment
2742 # more comments" (make-string 9999 ?\n))
2743 (python-util-forward-comment 1)
2744 (should (= (point) (point-max)))
2745 (python-util-forward-comment -1)
2746 (should (= (point) (point-min)))))
2747
2748 \f
2749 ;;; Electricity
2750
2751 (ert-deftest python-parens-electric-indent-1 ()
2752 (require 'electric)
2753 (let ((eim electric-indent-mode))
2754 (unwind-protect
2755 (progn
2756 (python-tests-with-temp-buffer
2757 "
2758 from django.conf.urls import patterns, include, url
2759
2760 from django.contrib import admin
2761
2762 from myapp import views
2763
2764
2765 urlpatterns = patterns('',
2766 url(r'^$', views.index
2767 )
2768 "
2769 (electric-indent-mode 1)
2770 (python-tests-look-at "views.index")
2771 (end-of-line)
2772
2773 ;; Inserting commas within the same line should leave
2774 ;; indentation unchanged.
2775 (python-tests-self-insert ",")
2776 (should (= (current-indentation) 4))
2777
2778 ;; As well as any other input happening within the same
2779 ;; set of parens.
2780 (python-tests-self-insert " name='index')")
2781 (should (= (current-indentation) 4))
2782
2783 ;; But a comma outside it, should trigger indentation.
2784 (python-tests-self-insert ",")
2785 (should (= (current-indentation) 23))
2786
2787 ;; Newline indents to the first argument column
2788 (python-tests-self-insert "\n")
2789 (should (= (current-indentation) 23))
2790
2791 ;; All this input must not change indentation
2792 (indent-line-to 4)
2793 (python-tests-self-insert "url(r'^/login$', views.login)")
2794 (should (= (current-indentation) 4))
2795
2796 ;; But this comma does
2797 (python-tests-self-insert ",")
2798 (should (= (current-indentation) 23))))
2799 (or eim (electric-indent-mode -1)))))
2800
2801 (ert-deftest python-triple-quote-pairing ()
2802 (require 'electric)
2803 (let ((epm electric-pair-mode))
2804 (unwind-protect
2805 (progn
2806 (python-tests-with-temp-buffer
2807 "\"\"\n"
2808 (or epm (electric-pair-mode 1))
2809 (goto-char (1- (point-max)))
2810 (python-tests-self-insert ?\")
2811 (should (string= (buffer-string)
2812 "\"\"\"\"\"\"\n"))
2813 (should (= (point) 4)))
2814 (python-tests-with-temp-buffer
2815 "\n"
2816 (python-tests-self-insert (list ?\" ?\" ?\"))
2817 (should (string= (buffer-string)
2818 "\"\"\"\"\"\"\n"))
2819 (should (= (point) 4)))
2820 (python-tests-with-temp-buffer
2821 "\"\n\"\"\n"
2822 (goto-char (1- (point-max)))
2823 (python-tests-self-insert ?\")
2824 (should (= (point) (1- (point-max))))
2825 (should (string= (buffer-string)
2826 "\"\n\"\"\"\n"))))
2827 (or epm (electric-pair-mode -1)))))
2828
2829
2830 (provide 'python-tests)
2831
2832 ;; Local Variables:
2833 ;; coding: utf-8
2834 ;; indent-tabs-mode: nil
2835 ;; End:
2836
2837 ;;; python-tests.el ends here