;;; python-tests.el --- Test suite for python.el
-;; Copyright (C) 2013 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2014 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
(should (eq (car (python-indent-context)) 'inside-paren))
(should (= (python-indent-calculate-indentation) 4))))
+(ert-deftest python-indent-after-comment-1 ()
+ "The most simple after-comment case that shouldn't fail."
+ (python-tests-with-temp-buffer
+ "# Contents will be modified to correct indentation
+class Blag(object):
+ def _on_child_complete(self, child_future):
+ if self.in_terminal_state():
+ pass
+ # We only complete when all our async children have entered a
+ # terminal state. At that point, if any child failed, we fail
+# with the exception with which the first child failed.
+"
+ (python-tests-look-at "# We only complete")
+ (should (eq (car (python-indent-context)) 'after-line))
+ (should (= (python-indent-calculate-indentation) 8))
+ (python-tests-look-at "# terminal state")
+ (should (eq (car (python-indent-context)) 'after-comment))
+ (should (= (python-indent-calculate-indentation) 8))
+ (python-tests-look-at "# with the exception")
+ (should (eq (car (python-indent-context)) 'after-comment))
+ ;; This one indents relative to previous block, even given the fact
+ ;; that it was under-indented.
+ (should (= (python-indent-calculate-indentation) 4))
+ (python-tests-look-at "# terminal state" -1)
+ ;; It doesn't hurt to check again.
+ (should (eq (car (python-indent-context)) 'after-comment))
+ (python-indent-line)
+ (should (= (current-indentation) 8))
+ (python-tests-look-at "# with the exception")
+ (should (eq (car (python-indent-context)) 'after-comment))
+ ;; Now everything should be lined up.
+ (should (= (python-indent-calculate-indentation) 8))))
+
+(ert-deftest python-indent-after-comment-2 ()
+ "Test after-comment in weird cases."
+ (python-tests-with-temp-buffer
+ "# Contents will be modified to correct indentation
+def func(arg):
+ # I don't do much
+ return arg
+ # This comment is badly indented just because.
+ # But we won't mess with the user in this line.
+
+now_we_do_mess_cause_this_is_not_a_comment = 1
+
+# yeah, that.
+"
+ (python-tests-look-at "# I don't do much")
+ (should (eq (car (python-indent-context)) 'after-beginning-of-block))
+ (should (= (python-indent-calculate-indentation) 4))
+ (python-tests-look-at "return arg")
+ ;; Comment here just gets ignored, this line is not a comment so
+ ;; the rules won't apply here.
+ (should (eq (car (python-indent-context)) 'after-beginning-of-block))
+ (should (= (python-indent-calculate-indentation) 4))
+ (python-tests-look-at "# This comment is badly")
+ (should (eq (car (python-indent-context)) 'after-line))
+ ;; The return keyword moves indentation backwards 4 spaces, but
+ ;; let's assume this comment was placed there because the user
+ ;; wanted to (manually adding spaces or whatever).
+ (should (= (python-indent-calculate-indentation) 0))
+ (python-tests-look-at "# but we won't mess")
+ (should (eq (car (python-indent-context)) 'after-comment))
+ (should (= (python-indent-calculate-indentation) 4))
+ ;; Behave the same for blank lines: potentially a comment.
+ (forward-line 1)
+ (should (eq (car (python-indent-context)) 'after-comment))
+ (should (= (python-indent-calculate-indentation) 4))
+ (python-tests-look-at "now_we_do_mess")
+ ;; Here is where comment indentation starts to get ignored and
+ ;; where the user can't freely indent anymore.
+ (should (eq (car (python-indent-context)) 'after-line))
+ (should (= (python-indent-calculate-indentation) 0))
+ (python-tests-look-at "# yeah, that.")
+ (should (eq (car (python-indent-context)) 'after-line))
+ (should (= (python-indent-calculate-indentation) 0))))
+
(ert-deftest python-indent-inside-paren-1 ()
"The most simple inside-paren case that shouldn't fail."
(python-tests-with-temp-buffer
(should (eq (car (python-indent-context)) 'after-beginning-of-block))
(should (= (python-indent-calculate-indentation) 12))))
+(ert-deftest python-indent-dedenters-2 ()
+ "Check one-liner block special case.."
+ (python-tests-with-temp-buffer
+ "
+cond = True
+if cond:
+
+ if cond: print 'True'
+else: print 'False'
+
+else:
+ return
+"
+ (python-tests-look-at "else: print 'False'")
+ ;; When a block has code after ":" it's just considered a simple
+ ;; line as that's a common thing to happen in one-liners.
+ (should (eq (car (python-indent-context)) 'after-line))
+ (should (= (python-indent-calculate-indentation) 4))
+ (python-tests-look-at "else:")
+ (should (eq (car (python-indent-context)) 'after-line))
+ (should (= (python-indent-calculate-indentation) 0))))
+
(ert-deftest python-indent-after-backslash-1 ()
"The most common case."
(python-tests-with-temp-buffer
(should (eq (car (python-indent-context)) 'after-line))
(should (= (python-indent-calculate-indentation) 0))))
-(ert-deftest python-indent-block-enders ()
+(ert-deftest python-indent-block-enders-1 ()
"Test `python-indent-block-enders' value honoring."
(python-tests-with-temp-buffer
"
"
(python-tests-look-at "3)")
(forward-line 1)
- (= (python-indent-calculate-indentation) 12)
+ (should (= (python-indent-calculate-indentation) 8))
(python-tests-look-at "pass")
(forward-line 1)
- (= (python-indent-calculate-indentation) 8)))
+ (should (= (python-indent-calculate-indentation) 8))))
+
+(ert-deftest python-indent-block-enders-2 ()
+ "Test `python-indent-block-enders' value honoring."
+ (python-tests-with-temp-buffer
+ "
+Class foo(object):
+ '''raise lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
+
+ eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ '''
+ def bar(self):
+ \"return (1, 2, 3).\"
+ if self.baz:
+ return (1,
+ 2,
+ 3)
+"
+ (python-tests-look-at "def")
+ (should (= (python-indent-calculate-indentation) 4))
+ (python-tests-look-at "if")
+ (should (= (python-indent-calculate-indentation) 8))))
\f
;;; Navigation
(python-tests-look-at
"if request.user.is_authenticated():" -1)))))
-(ert-deftest python-nav-lisp-forward-sexp-safe-1 ()
- (python-tests-with-temp-buffer
- "
-profile = Profile.objects.create(user=request.user)
-profile.notify()
-"
- (python-tests-look-at "profile =")
- (python-nav-lisp-forward-sexp-safe 4)
- (should (looking-at "(user=request.user)"))
- (python-tests-look-at "user=request.user")
- (python-nav-lisp-forward-sexp-safe -1)
- (should (looking-at "(user=request.user)"))
- (python-nav-lisp-forward-sexp-safe -4)
- (should (looking-at "profile ="))
- (python-tests-look-at "user=request.user")
- (python-nav-lisp-forward-sexp-safe 3)
- (should (looking-at ")"))
- (python-nav-lisp-forward-sexp-safe 1)
- (should (looking-at "$"))
- (python-nav-lisp-forward-sexp-safe 1)
- (should (looking-at ".notify()"))))
-
(ert-deftest python-nav-forward-sexp-1 ()
(python-tests-with-temp-buffer
"
(python-nav-forward-sexp -1)
(should (looking-at "from some_module import some_sub_module"))))
+(ert-deftest python-nav-forward-sexp-safe-1 ()
+ (python-tests-with-temp-buffer
+ "
+profile = Profile.objects.create(user=request.user)
+profile.notify()
+"
+ (python-tests-look-at "profile =")
+ (python-nav-forward-sexp-safe 1)
+ (should (looking-at "$"))
+ (beginning-of-line 1)
+ (python-tests-look-at "user=request.user")
+ (python-nav-forward-sexp-safe -1)
+ (should (looking-at "(user=request.user)"))
+ (python-nav-forward-sexp-safe -4)
+ (should (looking-at "profile ="))
+ (python-tests-look-at "user=request.user")
+ (python-nav-forward-sexp-safe 3)
+ (should (looking-at ")"))
+ (python-nav-forward-sexp-safe 1)
+ (should (looking-at "$"))
+ (python-nav-forward-sexp-safe 1)
+ (should (looking-at "$"))))
+
(ert-deftest python-nav-up-list-1 ()
(python-tests-with-temp-buffer
"
"Check the command to execute is calculated correctly.
Using `python-shell-interpreter' and
`python-shell-interpreter-args'."
- :expected-result (if (executable-find python-tests-shell-interpreter)
- :passed
- :failed)
+ (skip-unless (executable-find python-tests-shell-interpreter))
(let ((python-shell-interpreter (executable-find
python-tests-shell-interpreter))
(python-shell-interpreter-args "-B"))
(ert-deftest python-shell-make-comint-1 ()
"Check comint creation for global shell buffer."
- :expected-result (if (executable-find python-tests-shell-interpreter)
- :passed
- :failed)
- (let* ((python-shell-interpreter
+ (skip-unless (executable-find python-tests-shell-interpreter))
+ ;; The interpreter can get killed too quickly to allow it to clean
+ ;; up the tempfiles that the default python-shell-setup-codes create,
+ ;; so it leaves tempfiles behind, which is a minor irritation.
+ (let* ((python-shell-setup-codes nil)
+ (python-shell-interpreter
(executable-find python-tests-shell-interpreter))
(proc-name (python-shell-get-process-name nil))
(shell-buffer
(ert-deftest python-shell-make-comint-2 ()
"Check comint creation for internal shell buffer."
- :expected-result (if (executable-find python-tests-shell-interpreter)
- :passed
- :failed)
- (let* ((python-shell-interpreter
+ (skip-unless (executable-find python-tests-shell-interpreter))
+ (let* ((python-shell-setup-codes nil)
+ (python-shell-interpreter
(executable-find python-tests-shell-interpreter))
(proc-name (python-shell-internal-get-process-name))
(shell-buffer
(ert-deftest python-shell-get-process-1 ()
"Check dedicated shell process preference over global."
- :expected-result (if (executable-find python-tests-shell-interpreter)
- :passed
- :failed)
+ (skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-file
""
- (let* ((python-shell-interpreter
+ (let* ((python-shell-setup-codes nil)
+ (python-shell-interpreter
(executable-find python-tests-shell-interpreter))
(global-proc-name (python-shell-get-process-name nil))
(dedicated-proc-name (python-shell-get-process-name t))
(ert-deftest python-shell-internal-get-or-create-process-1 ()
"Check internal shell process creation fallback."
- :expected-result (if (executable-find python-tests-shell-interpreter)
- :passed
- :failed)
+ (skip-unless (executable-find python-tests-shell-interpreter))
(python-tests-with-temp-file
""
(should (not (process-live-p (python-shell-internal-get-process-name))))
(cons "c (def)" (copy-marker 626)))))
(python-imenu-create-index)))))
+(ert-deftest python-imenu-create-index-2 ()
+ (python-tests-with-temp-buffer
+ "
+class Foo(object):
+ def foo(self):
+ def foo1():
+ pass
+
+ def foobar(self):
+ pass
+"
+ (goto-char (point-max))
+ (should (equal
+ (list
+ (list
+ "Foo (class)"
+ (cons "*class definition*" (copy-marker 2))
+ (list
+ "foo (def)"
+ (cons "*function definition*" (copy-marker 21))
+ (cons "foo1 (def)" (copy-marker 40)))
+ (cons "foobar (def)" (copy-marker 78))))
+ (python-imenu-create-index)))))
+
+(ert-deftest python-imenu-create-index-3 ()
+ (python-tests-with-temp-buffer
+ "
+class Foo(object):
+ def foo(self):
+ def foo1():
+ pass
+ def foo2():
+ pass
+"
+ (goto-char (point-max))
+ (should (equal
+ (list
+ (list
+ "Foo (class)"
+ (cons "*class definition*" (copy-marker 2))
+ (list
+ "foo (def)"
+ (cons "*function definition*" (copy-marker 21))
+ (cons "foo1 (def)" (copy-marker 40))
+ (cons "foo2 (def)" (copy-marker 77)))))
+ (python-imenu-create-index)))))
+
+(ert-deftest python-imenu-create-index-4 ()
+ (python-tests-with-temp-buffer
+ "
+class Foo(object):
+ class Bar(object):
+ def __init__(self):
+ pass
+
+ def __str__(self):
+ pass
+
+ def __init__(self):
+ pass
+"
+ (goto-char (point-max))
+ (should (equal
+ (list
+ (list
+ "Foo (class)"
+ (cons "*class definition*" (copy-marker 2))
+ (list
+ "Bar (class)"
+ (cons "*class definition*" (copy-marker 21))
+ (cons "__init__ (def)" (copy-marker 44))
+ (cons "__str__ (def)" (copy-marker 90)))
+ (cons "__init__ (def)" (copy-marker 135))))
+ (python-imenu-create-index)))))
+
(ert-deftest python-imenu-create-flat-index-1 ()
(python-tests-with-temp-buffer
"
(cons "Baz.Frob.c" (copy-marker 626)))
(python-imenu-create-flat-index)))))
+(ert-deftest python-imenu-create-flat-index-2 ()
+ (python-tests-with-temp-buffer
+ "
+class Foo(object):
+ class Bar(object):
+ def __init__(self):
+ pass
+
+ def __str__(self):
+ pass
+
+ def __init__(self):
+ pass
+"
+ (goto-char (point-max))
+ (should (equal
+ (list
+ (cons "Foo" (copy-marker 2))
+ (cons "Foo.Bar" (copy-marker 21))
+ (cons "Foo.Bar.__init__" (copy-marker 44))
+ (cons "Foo.Bar.__str__" (copy-marker 90))
+ (cons "Foo.__init__" (copy-marker 135)))
+ (python-imenu-create-flat-index)))))
+
\f
;;; Misc helpers