]> code.delx.au - gnu-emacs/blobdiff - test/automated/python-tests.el
Merge branch 'master' into xwidget
[gnu-emacs] / test / automated / python-tests.el
index a60da31e44c3ad4a8dc825d1d9d0809d1fd1618e..e989ccb6792f26c3eaa8620c5b4fe7275c844602 100644 (file)
@@ -1,6 +1,6 @@
 ;;; python-tests.el --- Test suite for python.el
 
-;; Copyright (C) 2013-2014 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
 
 ;; This file is part of GNU Emacs.
 
@@ -711,6 +711,172 @@ if a:
     (should (= (python-indent-calculate-indentation) 0))
     (should (equal (python-indent-calculate-levels) '(0)))))
 
+(ert-deftest python-indent-dedenters-8 ()
+  "Test indentation for Bug#18432."
+  (python-tests-with-temp-buffer
+   "
+if (a == 1 or
+    a == 2):
+    pass
+elif (a == 3 or
+a == 4):
+"
+   (python-tests-look-at "a == 4):\n")
+   (should (eq (car (python-indent-context)) 'inside-paren))
+   (should (= (python-indent-calculate-indentation) 6))
+   (should (equal (python-indent-calculate-levels) '(0 4 6)))))
+
+(ert-deftest python-indent-electric-colon-1 ()
+  "Test indentation case from Bug#18228."
+  (python-tests-with-temp-buffer
+   "
+def a():
+    pass
+
+def b()
+"
+   (python-tests-look-at "def b()")
+   (goto-char (line-end-position))
+   (python-tests-self-insert ":")
+   (should (= (current-indentation) 0))))
+
+(ert-deftest python-indent-electric-colon-2 ()
+  "Test indentation case for dedenter."
+  (python-tests-with-temp-buffer
+   "
+if do:
+    something()
+    else
+"
+   (python-tests-look-at "else")
+   (goto-char (line-end-position))
+   (python-tests-self-insert ":")
+   (should (= (current-indentation) 0))))
+
+(ert-deftest python-indent-electric-colon-3 ()
+  "Test indentation case for multi-line dedenter."
+  (python-tests-with-temp-buffer
+   "
+if do:
+    something()
+    elif (this
+          and
+          that)
+"
+   (python-tests-look-at "that)")
+   (goto-char (line-end-position))
+   (python-tests-self-insert ":")
+   (python-tests-look-at "elif" -1)
+   (should (= (current-indentation) 0))
+   (python-tests-look-at "and")
+   (should (= (current-indentation) 6))
+   (python-tests-look-at "that)")
+   (should (= (current-indentation) 6))))
+
+(ert-deftest python-indent-region-1 ()
+  "Test indentation case from Bug#18843."
+  (let ((contents "
+def foo ():
+    try:
+        pass
+    except:
+        pass
+"))
+    (python-tests-with-temp-buffer
+     contents
+     (python-indent-region (point-min) (point-max))
+     (should (string= (buffer-substring-no-properties (point-min) (point-max))
+                      contents)))))
+
+(ert-deftest python-indent-region-2 ()
+  "Test region indentation on comments."
+  (let ((contents "
+def f():
+    if True:
+        pass
+
+# This is
+# some multiline
+# comment
+"))
+    (python-tests-with-temp-buffer
+     contents
+     (python-indent-region (point-min) (point-max))
+     (should (string= (buffer-substring-no-properties (point-min) (point-max))
+                      contents)))))
+
+(ert-deftest python-indent-region-3 ()
+  "Test region indentation on comments."
+  (let ((contents "
+def f():
+    if True:
+        pass
+# This is
+# some multiline
+# comment
+")
+        (expected "
+def f():
+    if True:
+        pass
+    # This is
+    # some multiline
+    # comment
+"))
+    (python-tests-with-temp-buffer
+     contents
+     (python-indent-region (point-min) (point-max))
+     (should (string= (buffer-substring-no-properties (point-min) (point-max))
+                      expected)))))
+
+(ert-deftest python-indent-region-4 ()
+  "Test region indentation block starts, dedenters and enders."
+  (let ((contents "
+def f():
+    if True:
+a  = 5
+    else:
+            a = 10
+    return a
+")
+        (expected "
+def f():
+    if True:
+        a  = 5
+    else:
+        a = 10
+    return a
+"))
+    (python-tests-with-temp-buffer
+     contents
+     (python-indent-region (point-min) (point-max))
+     (should (string= (buffer-substring-no-properties (point-min) (point-max))
+                      expected)))))
+
+(ert-deftest python-indent-region-5 ()
+  "Test region indentation leaves strings untouched (start delimiter)."
+  (let ((contents "
+def f():
+'''
+this is
+a multiline
+string
+'''
+")
+        (expected "
+def f():
+    '''
+this is
+a multiline
+string
+'''
+"))
+    (python-tests-with-temp-buffer
+     contents
+     (python-indent-region (point-min) (point-max))
+     (should (string= (buffer-substring-no-properties (point-min) (point-max))
+                      expected)))))
+
 \f
 ;;; Navigation
 
@@ -1642,52 +1808,41 @@ def f():
 (defvar python-tests-shell-interpreter "python")
 
 (ert-deftest python-shell-get-process-name-1 ()
-  "Check process name calculation on different scenarios."
+  "Check process name calculation sans `buffer-file-name'."
   (python-tests-with-temp-buffer
-      ""
-    (should (string= (python-shell-get-process-name nil)
-                     python-shell-buffer-name))
-    ;; When the `current-buffer' doesn't have `buffer-file-name', even
-    ;; if dedicated flag is non-nil should not include its name.
-    (should (string= (python-shell-get-process-name t)
-                     python-shell-buffer-name)))
+   ""
+   (should (string= (python-shell-get-process-name nil)
+                    python-shell-buffer-name))
+   (should (string= (python-shell-get-process-name t)
+                    (format "%s[%s]" python-shell-buffer-name (buffer-name))))))
+
+(ert-deftest python-shell-get-process-name-2 ()
+  "Check process name calculation with `buffer-file-name'."
   (python-tests-with-temp-file
-      ""
-    ;; `buffer-file-name' is non-nil but the dedicated flag is nil and
-    ;; should be respected.
-    (should (string= (python-shell-get-process-name nil)
-                     python-shell-buffer-name))
-    (should (string=
-             (python-shell-get-process-name t)
-             (format "%s[%s]" python-shell-buffer-name buffer-file-name)))))
+   ""
+   ;; `buffer-file-name' is non-nil but the dedicated flag is nil and
+   ;; should be respected.
+   (should (string= (python-shell-get-process-name nil)
+                    python-shell-buffer-name))
+   (should (string=
+            (python-shell-get-process-name t)
+            (format "%s[%s]" python-shell-buffer-name (buffer-name))))))
 
 (ert-deftest python-shell-internal-get-process-name-1 ()
-  "Check the internal process name is config-unique."
-  (let* ((python-shell-interpreter python-tests-shell-interpreter)
-         (python-shell-interpreter-args "")
-         (python-shell-prompt-regexp ">>> ")
-         (python-shell-prompt-block-regexp "[.][.][.] ")
-         (python-shell-setup-codes "")
-         (python-shell-process-environment "")
-         (python-shell-extra-pythonpaths "")
-         (python-shell-exec-path "")
-         (python-shell-virtualenv-path "")
-         (expected (python-tests-with-temp-buffer
-                       "" (python-shell-internal-get-process-name))))
-    ;; Same configurations should match.
-    (should
-     (string= expected
-              (python-tests-with-temp-buffer
-                  "" (python-shell-internal-get-process-name))))
-    (let ((python-shell-interpreter-args "-B"))
-      ;; A minimal change should generate different names.
-      (should
-       (not (string=
-             expected
-             (python-tests-with-temp-buffer
-                 "" (python-shell-internal-get-process-name))))))))
-
-(ert-deftest python-shell-parse-command-1 ()
+  "Check the internal process name is buffer-unique sans `buffer-file-name'."
+  (python-tests-with-temp-buffer
+   ""
+   (should (string= (python-shell-internal-get-process-name)
+                    (format "%s[%s]" python-shell-internal-buffer-name (buffer-name))))))
+
+(ert-deftest python-shell-internal-get-process-name-2 ()
+  "Check the internal process name is buffer-unique with `buffer-file-name'."
+  (python-tests-with-temp-file
+   ""
+   (should (string= (python-shell-internal-get-process-name)
+                    (format "%s[%s]" python-shell-internal-buffer-name (buffer-name))))))
+
+(ert-deftest python-shell-calculate-command-1 ()
   "Check the command to execute is calculated correctly.
 Using `python-shell-interpreter' and
 `python-shell-interpreter-args'."
@@ -1699,12 +1854,11 @@ Using `python-shell-interpreter' and
              (format "%s %s"
                      python-shell-interpreter
                      python-shell-interpreter-args)
-             (python-shell-parse-command)))))
+             (python-shell-calculate-command)))))
 
 (ert-deftest python-shell-calculate-process-environment-1 ()
   "Test `python-shell-process-environment' modification."
-  (let* ((original-process-environment process-environment)
-         (python-shell-process-environment
+  (let* ((python-shell-process-environment
           '("TESTVAR1=value1" "TESTVAR2=value2"))
          (process-environment
           (python-shell-calculate-process-environment)))
@@ -1713,8 +1867,8 @@ Using `python-shell-interpreter' and
 
 (ert-deftest python-shell-calculate-process-environment-2 ()
   "Test `python-shell-extra-pythonpaths' modification."
-  (let* ((original-process-environment process-environment)
-         (original-pythonpath (getenv "PYTHONPATH"))
+  (let* ((process-environment process-environment)
+         (original-pythonpath (setenv "PYTHONPATH" "path3"))
          (paths '("path1" "path2"))
          (python-shell-extra-pythonpaths paths)
          (process-environment
@@ -1725,20 +1879,36 @@ Using `python-shell-interpreter' and
                     path-separator original-pythonpath)))))
 
 (ert-deftest python-shell-calculate-process-environment-3 ()
-  "Test `python-shell-virtualenv-path' modification."
-  (let* ((original-process-environment process-environment)
-         (original-path (or (getenv "PATH") ""))
-         (python-shell-virtualenv-path
+  "Test `python-shell-virtualenv-root' modification."
+  (let* ((original-path (or (getenv "PATH") ""))
+         (python-shell-virtualenv-root
           (directory-file-name user-emacs-directory))
          (process-environment
           (python-shell-calculate-process-environment)))
     (should (not (getenv "PYTHONHOME")))
-    (should (string= (getenv "VIRTUAL_ENV") python-shell-virtualenv-path))
+    (should (string= (getenv "VIRTUAL_ENV") python-shell-virtualenv-root))
     (should (equal (getenv "PATH")
                    (format "%s/bin%s%s"
-                           python-shell-virtualenv-path
+                           python-shell-virtualenv-root
                            path-separator original-path)))))
 
+(ert-deftest python-shell-calculate-process-environment-4 ()
+  "Test `python-shell-unbuffered' modification."
+  (setenv "PYTHONUNBUFFERED")
+  (let* ((process-environment
+          (python-shell-calculate-process-environment)))
+    ;; Defaults to t
+    (should python-shell-unbuffered)
+    (should (string= (getenv "PYTHONUNBUFFERED") "1"))))
+
+(ert-deftest python-shell-calculate-process-environment-5 ()
+  (setenv "PYTHONUNBUFFERED")
+  "Test `python-shell-unbuffered' modification."
+  (let* ((python-shell-unbuffered nil)
+         (process-environment
+          (python-shell-calculate-process-environment)))
+    (should (not (getenv "PYTHONUNBUFFERED")))))
+
 (ert-deftest python-shell-calculate-exec-path-1 ()
   "Test `python-shell-exec-path' modification."
   (let* ((original-exec-path exec-path)
@@ -1752,13 +1922,13 @@ Using `python-shell-interpreter' and
 (ert-deftest python-shell-calculate-exec-path-2 ()
   "Test `python-shell-exec-path' modification."
   (let* ((original-exec-path exec-path)
-         (python-shell-virtualenv-path
-          (directory-file-name user-emacs-directory))
+         (python-shell-virtualenv-root
+          (directory-file-name (expand-file-name user-emacs-directory)))
          (exec-path (python-shell-calculate-exec-path)))
     (should (equal
              exec-path
              (append (cons
-                      (format "%s/bin" python-shell-virtualenv-path)
+                      (format "%s/bin" python-shell-virtualenv-root)
                       original-exec-path))))))
 
 (ert-deftest python-shell-make-comint-1 ()
@@ -1774,7 +1944,7 @@ Using `python-shell-interpreter' and
          (shell-buffer
           (python-tests-with-temp-buffer
            "" (python-shell-make-comint
-               (python-shell-parse-command) proc-name)))
+               (python-shell-calculate-command) proc-name)))
          (process (get-buffer-process shell-buffer)))
     (unwind-protect
         (progn
@@ -1795,7 +1965,7 @@ Using `python-shell-interpreter' and
          (shell-buffer
           (python-tests-with-temp-buffer
            "" (python-shell-make-comint
-               (python-shell-parse-command) proc-name nil t)))
+               (python-shell-calculate-command) proc-name nil t)))
          (process (get-buffer-process shell-buffer)))
     (unwind-protect
         (progn
@@ -1807,7 +1977,7 @@ Using `python-shell-interpreter' and
       (kill-buffer shell-buffer))))
 
 (ert-deftest python-shell-make-comint-3 ()
-  "Check comint creation with overriden python interpreter and args.
+  "Check comint creation with overridden python interpreter and args.
 The command passed to `python-shell-make-comint' as argument must
 locally override global values set in `python-shell-interpreter'
 and `python-shell-interpreter-args' in the new shell buffer."
@@ -1828,8 +1998,9 @@ and `python-shell-interpreter-args' in the new shell buffer."
           (should (process-live-p process))
           (with-current-buffer shell-buffer
             (should (eq major-mode 'inferior-python-mode))
-            (should (string= python-shell-interpreter
-                             (executable-find python-tests-shell-interpreter)))
+            (should (file-equal-p
+                     python-shell-interpreter
+                     (executable-find python-tests-shell-interpreter)))
             (should (string= python-shell-interpreter-args "-i"))))
       (kill-buffer shell-buffer))))
 
@@ -1861,7 +2032,7 @@ and `python-shell-interpreter-args' in the new shell buffer."
             (setenv "PYTHONSTARTUP" startup-file)
             (python-tests-with-temp-buffer
              "" (python-shell-make-comint
-                 (python-shell-parse-command) proc-name nil))))
+                 (python-shell-calculate-command) proc-name nil))))
          (process (get-buffer-process shell-buffer)))
     (unwind-protect
         (progn
@@ -1891,10 +2062,10 @@ and `python-shell-interpreter-args' in the new shell buffer."
            (dedicated-proc-name (python-shell-get-process-name t))
            (global-shell-buffer
             (python-shell-make-comint
-             (python-shell-parse-command) global-proc-name))
+             (python-shell-calculate-command) global-proc-name))
            (dedicated-shell-buffer
             (python-shell-make-comint
-             (python-shell-parse-command) dedicated-proc-name))
+             (python-shell-calculate-command) dedicated-proc-name))
            (global-process (get-buffer-process global-shell-buffer))
            (dedicated-process (get-buffer-process dedicated-shell-buffer)))
       (unwind-protect
@@ -1912,87 +2083,6 @@ and `python-shell-interpreter-args' in the new shell buffer."
         (ignore-errors (kill-buffer global-shell-buffer))
         (ignore-errors (kill-buffer dedicated-shell-buffer))))))
 
-(ert-deftest python-shell-get-or-create-process-1 ()
-  "Check shell dedicated process creation."
-  (skip-unless (executable-find python-tests-shell-interpreter))
-  (python-tests-with-temp-file
-   ""
-   (let* ((python-shell-interpreter
-           (executable-find python-tests-shell-interpreter))
-          (use-dialog-box)
-          (dedicated-process-name (python-shell-get-process-name t))
-          (dedicated-process
-           (python-shell-get-or-create-process python-shell-interpreter t))
-          (dedicated-shell-buffer (process-buffer dedicated-process)))
-     (unwind-protect
-         (progn
-           (set-process-query-on-exit-flag dedicated-process nil)
-           ;; should be dedicated.
-           (should (equal (process-name dedicated-process)
-                          dedicated-process-name))
-           (kill-buffer dedicated-shell-buffer)
-           ;; Check there are no processes for current buffer.
-           (should (not (python-shell-get-process))))
-       (ignore-errors (kill-buffer dedicated-shell-buffer))))))
-
-(ert-deftest python-shell-get-or-create-process-2 ()
-  "Check shell global process creation."
-  (skip-unless (executable-find python-tests-shell-interpreter))
-  (python-tests-with-temp-file
-   ""
-   (let* ((python-shell-interpreter
-           (executable-find python-tests-shell-interpreter))
-          (use-dialog-box)
-          (process-name (python-shell-get-process-name nil))
-          (process
-           (python-shell-get-or-create-process python-shell-interpreter))
-          (shell-buffer (process-buffer process)))
-     (unwind-protect
-         (progn
-           (set-process-query-on-exit-flag process nil)
-           ;; should be global.
-           (should (equal (process-name process) process-name))
-           (kill-buffer shell-buffer)
-           ;; Check there are no processes for current buffer.
-           (should (not (python-shell-get-process))))
-       (ignore-errors (kill-buffer dedicated-shell-buffer))))))
-
-(ert-deftest python-shell-get-or-create-process-3 ()
-  "Check shell dedicated/global process preference."
-  (skip-unless (executable-find python-tests-shell-interpreter))
-  (python-tests-with-temp-file
-   ""
-   (let* ((python-shell-interpreter
-           (executable-find python-tests-shell-interpreter))
-          (use-dialog-box)
-          (dedicated-process-name (python-shell-get-process-name t))
-          (global-process)
-          (dedicated-process))
-     (unwind-protect
-         (progn
-           ;; Create global process
-           (run-python python-shell-interpreter nil)
-           (setq global-process (get-buffer-process "*Python*"))
-           (should global-process)
-           (set-process-query-on-exit-flag global-process nil)
-           ;; Create dedicated process
-           (run-python python-shell-interpreter t)
-           (setq dedicated-process (get-process dedicated-process-name))
-           (should dedicated-process)
-           (set-process-query-on-exit-flag dedicated-process nil)
-           ;; Prefer dedicated.
-           (should (equal (python-shell-get-or-create-process)
-                          dedicated-process))
-           ;; Kill the dedicated so the global takes over.
-           (kill-buffer (process-buffer dedicated-process))
-           ;; Detect global.
-           (should (equal (python-shell-get-or-create-process) global-process))
-           ;; Kill the global.
-           (kill-buffer (process-buffer global-process))
-           ;; Check there are no processes for current buffer.
-           (should (not (python-shell-get-process))))
-       (ignore-errors (kill-buffer dedicated-shell-buffer))))))
-
 (ert-deftest python-shell-internal-get-or-create-process-1 ()
   "Check internal shell process creation fallback."
   (skip-unless (executable-find python-tests-shell-interpreter))
@@ -2278,9 +2368,229 @@ and `python-shell-interpreter-args' in the new shell buffer."
                            "^\\(o\\.t \\|\\)")))
       (ignore-errors (delete-file startup-file)))))
 
+(ert-deftest python-shell-buffer-substring-1 ()
+  "Selecting a substring of the whole buffer must match its contents."
+  (python-tests-with-temp-buffer
+   "
+class Foo(models.Model):
+    pass
+
+
+class Bar(models.Model):
+    pass
+"
+   (should (string= (buffer-string)
+                    (python-shell-buffer-substring (point-min) (point-max))))))
+
+(ert-deftest python-shell-buffer-substring-2 ()
+  "Main block should be removed if NOMAIN is non-nil."
+  (python-tests-with-temp-buffer
+   "
+class Foo(models.Model):
+    pass
+
+class Bar(models.Model):
+    pass
+
+if __name__ == \"__main__\":
+    foo = Foo()
+    print (foo)
+"
+   (should (string= (python-shell-buffer-substring (point-min) (point-max) t)
+                    "
+class Foo(models.Model):
+    pass
+
+class Bar(models.Model):
+    pass
+
+
+
+
+"))))
+
+(ert-deftest python-shell-buffer-substring-3 ()
+  "Main block should be removed if NOMAIN is non-nil."
+  (python-tests-with-temp-buffer
+   "
+class Foo(models.Model):
+    pass
+
+if __name__ == \"__main__\":
+    foo = Foo()
+    print (foo)
+
+class Bar(models.Model):
+    pass
+"
+   (should (string= (python-shell-buffer-substring (point-min) (point-max) t)
+                    "
+class Foo(models.Model):
+    pass
+
+
+
+
+
+class Bar(models.Model):
+    pass
+"))))
+
+(ert-deftest python-shell-buffer-substring-4 ()
+  "Coding cookie should be added for substrings."
+  (python-tests-with-temp-buffer
+   "# coding: latin-1
+
+class Foo(models.Model):
+    pass
+
+if __name__ == \"__main__\":
+    foo = Foo()
+    print (foo)
+
+class Bar(models.Model):
+    pass
+"
+   (should (string= (python-shell-buffer-substring
+                     (python-tests-look-at "class Foo(models.Model):")
+                     (progn (python-nav-forward-sexp) (point)))
+                    "# -*- coding: latin-1 -*-
+
+class Foo(models.Model):
+    pass"))))
+
+(ert-deftest python-shell-buffer-substring-5 ()
+  "The proper amount of blank lines is added for a substring."
+  (python-tests-with-temp-buffer
+   "# coding: latin-1
+
+class Foo(models.Model):
+    pass
+
+if __name__ == \"__main__\":
+    foo = Foo()
+    print (foo)
+
+class Bar(models.Model):
+    pass
+"
+   (should (string= (python-shell-buffer-substring
+                     (python-tests-look-at "class Bar(models.Model):")
+                     (progn (python-nav-forward-sexp) (point)))
+                    "# -*- coding: latin-1 -*-
+
+
+
+
+
+
+
+
+class Bar(models.Model):
+    pass"))))
+
+(ert-deftest python-shell-buffer-substring-6 ()
+  "Handle substring with coding cookie in the second line."
+  (python-tests-with-temp-buffer
+   "
+# coding: latin-1
+
+class Foo(models.Model):
+    pass
+
+if __name__ == \"__main__\":
+    foo = Foo()
+    print (foo)
+
+class Bar(models.Model):
+    pass
+"
+   (should (string= (python-shell-buffer-substring
+                     (python-tests-look-at "# coding: latin-1")
+                     (python-tests-look-at "if __name__ == \"__main__\":"))
+                    "# -*- coding: latin-1 -*-
+
+
+class Foo(models.Model):
+    pass
+
+"))))
+
+(ert-deftest python-shell-buffer-substring-7 ()
+  "Ensure first coding cookie gets precedence."
+  (python-tests-with-temp-buffer
+   "# coding: utf-8
+# coding: latin-1
+
+class Foo(models.Model):
+    pass
+
+if __name__ == \"__main__\":
+    foo = Foo()
+    print (foo)
+
+class Bar(models.Model):
+    pass
+"
+   (should (string= (python-shell-buffer-substring
+                     (python-tests-look-at "# coding: latin-1")
+                     (python-tests-look-at "if __name__ == \"__main__\":"))
+                    "# -*- coding: utf-8 -*-
+
+
+class Foo(models.Model):
+    pass
+
+"))))
+
+(ert-deftest python-shell-buffer-substring-8 ()
+  "Ensure first coding cookie gets precedence when sending whole buffer."
+  (python-tests-with-temp-buffer
+   "# coding: utf-8
+# coding: latin-1
+
+class Foo(models.Model):
+    pass
+"
+   (should (string= (python-shell-buffer-substring (point-min) (point-max))
+                    "# coding: utf-8
+
+
+class Foo(models.Model):
+    pass
+"))))
+
+(ert-deftest python-shell-buffer-substring-9 ()
+  "Check substring starting from `point-min'."
+  (python-tests-with-temp-buffer
+   "# coding: utf-8
+
+class Foo(models.Model):
+    pass
+
+class Bar(models.Model):
+    pass
+"
+   (should (string= (python-shell-buffer-substring
+                     (point-min)
+                     (python-tests-look-at "class Bar(models.Model):"))
+                    "# coding: utf-8
+
+class Foo(models.Model):
+    pass
+
+"))))
+
 \f
 ;;; Shell completion
 
+(ert-deftest python-shell-completion-native-interpreter-disabled-p-1 ()
+  (let* ((python-shell-completion-native-disabled-interpreters (list "pypy"))
+         (python-shell-interpreter "/some/path/to/bin/pypy"))
+    (should (python-shell-completion-native-interpreter-disabled-p))))
+
+
+
 \f
 ;;; PDB Track integration
 
@@ -3592,6 +3902,85 @@ foo = True  # another comment
    (forward-line 1)
    (should (python-info-current-line-empty-p))))
 
+(ert-deftest python-info-encoding-from-cookie-1 ()
+  "Should detect it on first line."
+  (python-tests-with-temp-buffer
+   "# coding=latin-1
+
+foo = True  # another comment
+"
+   (should (eq (python-info-encoding-from-cookie) 'latin-1))))
+
+(ert-deftest python-info-encoding-from-cookie-2 ()
+  "Should detect it on second line."
+  (python-tests-with-temp-buffer
+   "
+# coding=latin-1
+
+foo = True  # another comment
+"
+   (should (eq (python-info-encoding-from-cookie) 'latin-1))))
+
+(ert-deftest python-info-encoding-from-cookie-3 ()
+  "Should not be detected on third line (and following ones)."
+  (python-tests-with-temp-buffer
+   "
+
+# coding=latin-1
+foo = True  # another comment
+"
+   (should (not (python-info-encoding-from-cookie)))))
+
+(ert-deftest python-info-encoding-from-cookie-4 ()
+  "Should detect Emacs style."
+  (python-tests-with-temp-buffer
+   "# -*- coding: latin-1 -*-
+
+foo = True  # another comment"
+   (should (eq (python-info-encoding-from-cookie) 'latin-1))))
+
+(ert-deftest python-info-encoding-from-cookie-5 ()
+  "Should detect Vim style."
+  (python-tests-with-temp-buffer
+   "# vim: set fileencoding=latin-1 :
+
+foo = True  # another comment"
+   (should (eq (python-info-encoding-from-cookie) 'latin-1))))
+
+(ert-deftest python-info-encoding-from-cookie-6 ()
+  "First cookie wins."
+  (python-tests-with-temp-buffer
+   "# -*- coding: iso-8859-1 -*-
+# vim: set fileencoding=latin-1 :
+
+foo = True  # another comment"
+   (should (eq (python-info-encoding-from-cookie) 'iso-8859-1))))
+
+(ert-deftest python-info-encoding-from-cookie-7 ()
+  "First cookie wins."
+  (python-tests-with-temp-buffer
+   "# vim: set fileencoding=latin-1 :
+# -*- coding: iso-8859-1 -*-
+
+foo = True  # another comment"
+   (should (eq (python-info-encoding-from-cookie) 'latin-1))))
+
+(ert-deftest python-info-encoding-1 ()
+  "Should return the detected encoding from cookie."
+  (python-tests-with-temp-buffer
+   "# vim: set fileencoding=latin-1 :
+
+foo = True  # another comment"
+   (should (eq (python-info-encoding) 'latin-1))))
+
+(ert-deftest python-info-encoding-2 ()
+  "Should default to utf-8."
+  (python-tests-with-temp-buffer
+   "# No encoding for you
+
+foo = True  # another comment"
+   (should (eq (python-info-encoding) 'utf-8))))
+
 \f
 ;;; Utility functions
 
@@ -3619,11 +4008,9 @@ def foo(a, b, c):
            (python-shell-extra-pythonpaths "/home/user/pylib/")
            (python-shell-completion-setup-code
             . "from IPython.core.completerlib import module_completion")
-           (python-shell-completion-module-string-code
-            . "';'.join(module_completion('''%s'''))\n")
            (python-shell-completion-string-code
             . "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
-           (python-shell-virtualenv-path
+           (python-shell-virtualenv-root
             . "/home/user/.virtualenvs/project"))))
     (with-current-buffer buffer
       (kill-all-local-variables)