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