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