diff options
| author | Fabián Ezequiel Gallina | 2014-12-27 01:30:21 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2014-12-27 01:30:21 -0300 |
| commit | 2dd5163d764f395eb31a2306dba385d123af4aba (patch) | |
| tree | 27b1ade1b6af5e984040a8acc840f81ee4f5adaa | |
| parent | 7aa506eed8881788485a9774165454404bac2623 (diff) | |
| download | emacs-2dd5163d764f395eb31a2306dba385d123af4aba.tar.gz emacs-2dd5163d764f395eb31a2306dba385d123af4aba.zip | |
python.el: Handle file encoding for shell.
* lisp/progmodes/python.el (python-rx-constituents): Add coding-cookie.
(python-shell--save-temp-file): Write file with proper encoding.
(python-shell-buffer-substring): Add coding cookie for detected
encoding to generated content. Fix blank lines when removing
if-name-main block.
(python-shell-send-file): Handle file encoding.
(python-info-encoding-from-cookie)
(python-info-encoding): New functions.
* test/automated/python-tests.el (python-shell-buffer-substring-1)
(python-shell-buffer-substring-2, python-shell-buffer-substring-3)
(python-shell-buffer-substring-4, python-shell-buffer-substring-5)
(python-shell-buffer-substring-6, python-shell-buffer-substring-7)
(python-shell-buffer-substring-8)
(python-info-encoding-from-cookie-1)
(python-info-encoding-from-cookie-2)
(python-info-encoding-from-cookie-3)
(python-info-encoding-from-cookie-4)
(python-info-encoding-from-cookie-5)
(python-info-encoding-from-cookie-6)
(python-info-encoding-from-cookie-7, python-info-encoding-1)
(python-info-encoding-2): New tests.
| -rw-r--r-- | lisp/ChangeLog | 13 | ||||
| -rw-r--r-- | lisp/progmodes/python.el | 110 | ||||
| -rw-r--r-- | test/ChangeLog | 16 | ||||
| -rw-r--r-- | test/automated/python-tests.el | 271 |
4 files changed, 385 insertions, 25 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 22728121a15..b73732a1a7e 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,16 @@ | |||
| 1 | 2014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org> | ||
| 2 | |||
| 3 | python.el: Handle file encoding for shell. | ||
| 4 | |||
| 5 | * progmodes/python.el (python-rx-constituents): Add coding-cookie. | ||
| 6 | (python-shell--save-temp-file): Write file with proper encoding. | ||
| 7 | (python-shell-buffer-substring): Add coding cookie for detected | ||
| 8 | encoding to generated content. Fix blank lines when removing | ||
| 9 | if-name-main block. | ||
| 10 | (python-shell-send-file): Handle file encoding. | ||
| 11 | (python-info-encoding-from-cookie) | ||
| 12 | (python-info-encoding): New functions. | ||
| 13 | |||
| 1 | 2014-12-24 Michael Albinus <michael.albinus@gmx.de> | 14 | 2014-12-24 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 15 | ||
| 3 | * net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band): | 16 | * net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band): |
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 632659c28bb..02d0cbef262 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -386,7 +386,18 @@ | |||
| 386 | (* ?\\ ?\\) (any ?\' ?\"))) | 386 | (* ?\\ ?\\) (any ?\' ?\"))) |
| 387 | (* ?\\ ?\\) | 387 | (* ?\\ ?\\) |
| 388 | ;; Match single or triple quotes of any kind. | 388 | ;; Match single or triple quotes of any kind. |
| 389 | (group (or "\"" "\"\"\"" "'" "'''")))))) | 389 | (group (or "\"" "\"\"\"" "'" "'''"))))) |
| 390 | (coding-cookie . ,(rx line-start ?# (* space) | ||
| 391 | (or | ||
| 392 | ;; # coding=<encoding name> | ||
| 393 | (: "coding" (or ?: ?=) (* space) (group-n 1 (+ (or word ?-)))) | ||
| 394 | ;; # -*- coding: <encoding name> -*- | ||
| 395 | (: "-*-" (* space) "coding:" (* space) | ||
| 396 | (group-n 1 (+ (or word ?-))) (* space) "-*-") | ||
| 397 | ;; # vim: set fileencoding=<encoding name> : | ||
| 398 | (: "vim:" (* space) "set" (+ space) | ||
| 399 | "fileencoding" (* space) ?= (* space) | ||
| 400 | (group-n 1 (+ (or word ?-))) (* space) ":"))))) | ||
| 390 | "Additional Python specific sexps for `python-rx'") | 401 | "Additional Python specific sexps for `python-rx'") |
| 391 | 402 | ||
| 392 | (defmacro python-rx (&rest regexps) | 403 | (defmacro python-rx (&rest regexps) |
| @@ -2400,11 +2411,7 @@ there for compatibility with CEDET.") | |||
| 2400 | (concat (file-remote-p default-directory) "/tmp") | 2411 | (concat (file-remote-p default-directory) "/tmp") |
| 2401 | temporary-file-directory)) | 2412 | temporary-file-directory)) |
| 2402 | (temp-file-name (make-temp-file "py")) | 2413 | (temp-file-name (make-temp-file "py")) |
| 2403 | ;; XXX: Python's built-in compile function accepts utf-8 as | 2414 | (coding-system-for-write (python-info-encoding))) |
| 2404 | ;; input so there's no need to enforce a coding cookie. In | ||
| 2405 | ;; the future making `coding-system-for-write' match the | ||
| 2406 | ;; current buffer's coding may be a good idea. | ||
| 2407 | (coding-system-for-write 'utf-8)) | ||
| 2408 | (with-temp-file temp-file-name | 2415 | (with-temp-file temp-file-name |
| 2409 | (insert string) | 2416 | (insert string) |
| 2410 | (delete-trailing-whitespace)) | 2417 | (delete-trailing-whitespace)) |
| @@ -2511,16 +2518,28 @@ the python shell: | |||
| 2511 | \"if __name__ == '__main__'\" block will be removed. | 2518 | \"if __name__ == '__main__'\" block will be removed. |
| 2512 | 2. When a subregion of the buffer is sent, it takes care of | 2519 | 2. When a subregion of the buffer is sent, it takes care of |
| 2513 | appending extra empty lines so tracebacks are correct. | 2520 | appending extra empty lines so tracebacks are correct. |
| 2514 | 3. Wraps indented regions under an \"if True:\" block so the | 2521 | 3. When the region sent is a substring of the current buffer, a |
| 2522 | coding cookie is added. | ||
| 2523 | 4. Wraps indented regions under an \"if True:\" block so the | ||
| 2515 | interpreter evaluates them correctly." | 2524 | interpreter evaluates them correctly." |
| 2516 | (let ((substring (buffer-substring-no-properties start end)) | 2525 | (let* ((substring (buffer-substring-no-properties start end)) |
| 2517 | (fillstr (make-string (1- (line-number-at-pos start)) ?\n)) | 2526 | (buffer-substring-p (save-restriction |
| 2518 | (toplevel-block-p (save-excursion | 2527 | (widen) |
| 2519 | (goto-char start) | 2528 | (not (equal (list (point-min) (point-max)) |
| 2520 | (or (zerop (line-number-at-pos start)) | 2529 | (list start end))))) |
| 2521 | (progn | 2530 | (encoding (python-info-encoding)) |
| 2522 | (python-util-forward-comment 1) | 2531 | (fillstr (concat |
| 2523 | (zerop (current-indentation))))))) | 2532 | (when buffer-substring-p |
| 2533 | (format "# -*- coding: %s -*-\n" encoding)) | ||
| 2534 | (make-string | ||
| 2535 | (- (line-number-at-pos start) | ||
| 2536 | (if buffer-substring-p 2 1)) ?\n))) | ||
| 2537 | (toplevel-block-p (save-excursion | ||
| 2538 | (goto-char start) | ||
| 2539 | (or (zerop (line-number-at-pos start)) | ||
| 2540 | (progn | ||
| 2541 | (python-util-forward-comment 1) | ||
| 2542 | (zerop (current-indentation))))))) | ||
| 2524 | (with-temp-buffer | 2543 | (with-temp-buffer |
| 2525 | (python-mode) | 2544 | (python-mode) |
| 2526 | (if fillstr (insert fillstr)) | 2545 | (if fillstr (insert fillstr)) |
| @@ -2536,17 +2555,26 @@ the python shell: | |||
| 2536 | (when (python-nav-if-name-main) | 2555 | (when (python-nav-if-name-main) |
| 2537 | (cons (point) | 2556 | (cons (point) |
| 2538 | (progn (python-nav-forward-sexp-safe) | 2557 | (progn (python-nav-forward-sexp-safe) |
| 2558 | ;; Include ending newline | ||
| 2559 | (forward-line 1) | ||
| 2539 | (point))))))) | 2560 | (point))))))) |
| 2540 | ;; Oh destructuring bind, how I miss you. | 2561 | ;; Oh destructuring bind, how I miss you. |
| 2541 | (if-name-main-start (car if-name-main-start-end)) | 2562 | (if-name-main-start (car if-name-main-start-end)) |
| 2542 | (if-name-main-end (cdr if-name-main-start-end))) | 2563 | (if-name-main-end (cdr if-name-main-start-end)) |
| 2564 | (fillstr (make-string | ||
| 2565 | (- (line-number-at-pos if-name-main-end) | ||
| 2566 | (line-number-at-pos if-name-main-start)) ?\n))) | ||
| 2543 | (when if-name-main-start-end | 2567 | (when if-name-main-start-end |
| 2544 | (goto-char if-name-main-start) | 2568 | (goto-char if-name-main-start) |
| 2545 | (delete-region if-name-main-start if-name-main-end) | 2569 | (delete-region if-name-main-start if-name-main-end) |
| 2546 | (insert | 2570 | (insert fillstr)))) |
| 2547 | (make-string | 2571 | ;; Ensure there's only one coding cookie in the generated string. |
| 2548 | (- (line-number-at-pos if-name-main-end) | 2572 | (goto-char (point-min)) |
| 2549 | (line-number-at-pos if-name-main-start)) ?\n))))) | 2573 | (when (looking-at-p (python-rx coding-cookie)) |
| 2574 | (forward-line 1) | ||
| 2575 | (when (looking-at-p (python-rx coding-cookie)) | ||
| 2576 | (delete-region | ||
| 2577 | (line-beginning-position) (line-end-position)))) | ||
| 2550 | (buffer-substring-no-properties (point-min) (point-max))))) | 2578 | (buffer-substring-no-properties (point-min) (point-max))))) |
| 2551 | 2579 | ||
| 2552 | (defun python-shell-send-region (start end &optional nomain) | 2580 | (defun python-shell-send-region (start end &optional nomain) |
| @@ -2604,15 +2632,21 @@ If DELETE is non-nil, delete the file afterwards." | |||
| 2604 | (expand-file-name | 2632 | (expand-file-name |
| 2605 | (or (file-remote-p file-name 'localname) | 2633 | (or (file-remote-p file-name 'localname) |
| 2606 | file-name))) | 2634 | file-name))) |
| 2607 | temp-file-name))) | 2635 | temp-file-name)) |
| 2636 | (encoding | ||
| 2637 | (with-temp-buffer | ||
| 2638 | (insert-file-contents | ||
| 2639 | (or temp-file-name file-name)) | ||
| 2640 | (python-info-encoding)))) | ||
| 2608 | (when (not file-name) | 2641 | (when (not file-name) |
| 2609 | (error "If FILE-NAME is nil then TEMP-FILE-NAME must be non-nil")) | 2642 | (error "If FILE-NAME is nil then TEMP-FILE-NAME must be non-nil")) |
| 2610 | (python-shell-send-string | 2643 | (python-shell-send-string |
| 2611 | (format | 2644 | (format |
| 2612 | (concat "__pyfile = open('''%s''');" | 2645 | (concat |
| 2613 | "exec(compile(__pyfile.read(), '''%s''', 'exec'));" | 2646 | "import codecs; __pyfile = codecs.open('''%s''', encoding='''%s''');" |
| 2614 | "__pyfile.close()%s") | 2647 | "exec(compile(__pyfile.read().encode('''%s'''), '''%s''', 'exec'));" |
| 2615 | (or temp-file-name file-name) file-name | 2648 | "__pyfile.close()%s") |
| 2649 | (or temp-file-name file-name) encoding encoding file-name | ||
| 2616 | (if delete (format "; import os; os.remove('''%s''')" | 2650 | (if delete (format "; import os; os.remove('''%s''')" |
| 2617 | (or temp-file-name file-name)) | 2651 | (or temp-file-name file-name)) |
| 2618 | "")) | 2652 | "")) |
| @@ -3912,6 +3946,32 @@ operator." | |||
| 3912 | (* whitespace) line-end)) | 3946 | (* whitespace) line-end)) |
| 3913 | (string-equal "" (match-string-no-properties 1)))) | 3947 | (string-equal "" (match-string-no-properties 1)))) |
| 3914 | 3948 | ||
| 3949 | (defun python-info-encoding-from-cookie () | ||
| 3950 | "Detect current buffer's encoding from its coding cookie. | ||
| 3951 | Returns the enconding as a symbol." | ||
| 3952 | (let ((first-two-lines | ||
| 3953 | (save-excursion | ||
| 3954 | (save-restriction | ||
| 3955 | (widen) | ||
| 3956 | (goto-char (point-min)) | ||
| 3957 | (forward-line 2) | ||
| 3958 | (buffer-substring-no-properties | ||
| 3959 | (point) | ||
| 3960 | (point-min)))))) | ||
| 3961 | (when (string-match (python-rx coding-cookie) first-two-lines) | ||
| 3962 | (intern (match-string-no-properties 1 first-two-lines))))) | ||
| 3963 | |||
| 3964 | (defun python-info-encoding () | ||
| 3965 | "Return encoding for file. | ||
| 3966 | Try `python-info-encoding-from-cookie', if none is found then | ||
| 3967 | default to utf-8." | ||
| 3968 | ;; If no enconding is defined, then it's safe to use UTF-8: Python 2 | ||
| 3969 | ;; uses ASCII as default while Python 3 uses UTF-8. This means that | ||
| 3970 | ;; in the worst case escenario python.el will make things work for | ||
| 3971 | ;; Python 2 files with unicode data and no encoding defined. | ||
| 3972 | (or (python-info-encoding-from-cookie) | ||
| 3973 | 'utf-8)) | ||
| 3974 | |||
| 3915 | 3975 | ||
| 3916 | ;;; Utility functions | 3976 | ;;; Utility functions |
| 3917 | 3977 | ||
diff --git a/test/ChangeLog b/test/ChangeLog index 14780c09e6f..101e9d9caa7 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | 2014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org> | ||
| 2 | |||
| 3 | * automated/python-tests.el (python-shell-buffer-substring-1) | ||
| 4 | (python-shell-buffer-substring-2, python-shell-buffer-substring-3) | ||
| 5 | (python-shell-buffer-substring-4, python-shell-buffer-substring-5) | ||
| 6 | (python-shell-buffer-substring-6, python-shell-buffer-substring-7) | ||
| 7 | (python-shell-buffer-substring-8) | ||
| 8 | (python-info-encoding-from-cookie-1) | ||
| 9 | (python-info-encoding-from-cookie-2) | ||
| 10 | (python-info-encoding-from-cookie-3) | ||
| 11 | (python-info-encoding-from-cookie-4) | ||
| 12 | (python-info-encoding-from-cookie-5) | ||
| 13 | (python-info-encoding-from-cookie-6) | ||
| 14 | (python-info-encoding-from-cookie-7, python-info-encoding-1) | ||
| 15 | (python-info-encoding-2): New tests. | ||
| 16 | |||
| 1 | 2014-12-25 Michael Albinus <michael.albinus@gmx.de> | 17 | 2014-12-25 Michael Albinus <michael.albinus@gmx.de> |
| 2 | 18 | ||
| 3 | * automated/tramp-tests.el (tramp-test17-insert-directory): Do not | 19 | * automated/tramp-tests.el (tramp-test17-insert-directory): Do not |
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el index d1713ac1851..8fcda58e1e0 100644 --- a/test/automated/python-tests.el +++ b/test/automated/python-tests.el | |||
| @@ -2459,6 +2459,198 @@ and `python-shell-interpreter-args' in the new shell buffer." | |||
| 2459 | "^\\(o\\.t \\|\\)"))) | 2459 | "^\\(o\\.t \\|\\)"))) |
| 2460 | (ignore-errors (delete-file startup-file))))) | 2460 | (ignore-errors (delete-file startup-file))))) |
| 2461 | 2461 | ||
| 2462 | (ert-deftest python-shell-buffer-substring-1 () | ||
| 2463 | "Selecting a substring of the whole buffer must match its contents." | ||
| 2464 | (python-tests-with-temp-buffer | ||
| 2465 | " | ||
| 2466 | class Foo(models.Model): | ||
| 2467 | pass | ||
| 2468 | |||
| 2469 | |||
| 2470 | class Bar(models.Model): | ||
| 2471 | pass | ||
| 2472 | " | ||
| 2473 | (should (string= (buffer-string) | ||
| 2474 | (python-shell-buffer-substring (point-min) (point-max)))))) | ||
| 2475 | |||
| 2476 | (ert-deftest python-shell-buffer-substring-2 () | ||
| 2477 | "Main block should be removed if NOMAIN is non-nil." | ||
| 2478 | (python-tests-with-temp-buffer | ||
| 2479 | " | ||
| 2480 | class Foo(models.Model): | ||
| 2481 | pass | ||
| 2482 | |||
| 2483 | class Bar(models.Model): | ||
| 2484 | pass | ||
| 2485 | |||
| 2486 | if __name__ == \"__main__\": | ||
| 2487 | foo = Foo() | ||
| 2488 | print (foo) | ||
| 2489 | " | ||
| 2490 | (should (string= (python-shell-buffer-substring (point-min) (point-max) t) | ||
| 2491 | " | ||
| 2492 | class Foo(models.Model): | ||
| 2493 | pass | ||
| 2494 | |||
| 2495 | class Bar(models.Model): | ||
| 2496 | pass | ||
| 2497 | |||
| 2498 | |||
| 2499 | |||
| 2500 | |||
| 2501 | ")))) | ||
| 2502 | |||
| 2503 | (ert-deftest python-shell-buffer-substring-3 () | ||
| 2504 | "Main block should be removed if NOMAIN is non-nil." | ||
| 2505 | (python-tests-with-temp-buffer | ||
| 2506 | " | ||
| 2507 | class Foo(models.Model): | ||
| 2508 | pass | ||
| 2509 | |||
| 2510 | if __name__ == \"__main__\": | ||
| 2511 | foo = Foo() | ||
| 2512 | print (foo) | ||
| 2513 | |||
| 2514 | class Bar(models.Model): | ||
| 2515 | pass | ||
| 2516 | " | ||
| 2517 | (should (string= (python-shell-buffer-substring (point-min) (point-max) t) | ||
| 2518 | " | ||
| 2519 | class Foo(models.Model): | ||
| 2520 | pass | ||
| 2521 | |||
| 2522 | |||
| 2523 | |||
| 2524 | |||
| 2525 | |||
| 2526 | class Bar(models.Model): | ||
| 2527 | pass | ||
| 2528 | ")))) | ||
| 2529 | |||
| 2530 | (ert-deftest python-shell-buffer-substring-4 () | ||
| 2531 | "Coding cookie should be added for substrings." | ||
| 2532 | (python-tests-with-temp-buffer | ||
| 2533 | "# coding: latin-1 | ||
| 2534 | |||
| 2535 | class Foo(models.Model): | ||
| 2536 | pass | ||
| 2537 | |||
| 2538 | if __name__ == \"__main__\": | ||
| 2539 | foo = Foo() | ||
| 2540 | print (foo) | ||
| 2541 | |||
| 2542 | class Bar(models.Model): | ||
| 2543 | pass | ||
| 2544 | " | ||
| 2545 | (should (string= (python-shell-buffer-substring | ||
| 2546 | (python-tests-look-at "class Foo(models.Model):") | ||
| 2547 | (progn (python-nav-forward-sexp) (point))) | ||
| 2548 | "# -*- coding: latin-1 -*- | ||
| 2549 | |||
| 2550 | class Foo(models.Model): | ||
| 2551 | pass")))) | ||
| 2552 | |||
| 2553 | (ert-deftest python-shell-buffer-substring-5 () | ||
| 2554 | "The proper amount of blank lines is added for a substring." | ||
| 2555 | (python-tests-with-temp-buffer | ||
| 2556 | "# coding: latin-1 | ||
| 2557 | |||
| 2558 | class Foo(models.Model): | ||
| 2559 | pass | ||
| 2560 | |||
| 2561 | if __name__ == \"__main__\": | ||
| 2562 | foo = Foo() | ||
| 2563 | print (foo) | ||
| 2564 | |||
| 2565 | class Bar(models.Model): | ||
| 2566 | pass | ||
| 2567 | " | ||
| 2568 | (should (string= (python-shell-buffer-substring | ||
| 2569 | (python-tests-look-at "class Bar(models.Model):") | ||
| 2570 | (progn (python-nav-forward-sexp) (point))) | ||
| 2571 | "# -*- coding: latin-1 -*- | ||
| 2572 | |||
| 2573 | |||
| 2574 | |||
| 2575 | |||
| 2576 | |||
| 2577 | |||
| 2578 | |||
| 2579 | |||
| 2580 | class Bar(models.Model): | ||
| 2581 | pass")))) | ||
| 2582 | |||
| 2583 | (ert-deftest python-shell-buffer-substring-6 () | ||
| 2584 | "Handle substring with coding cookie in the second line." | ||
| 2585 | (python-tests-with-temp-buffer | ||
| 2586 | " | ||
| 2587 | # coding: latin-1 | ||
| 2588 | |||
| 2589 | class Foo(models.Model): | ||
| 2590 | pass | ||
| 2591 | |||
| 2592 | if __name__ == \"__main__\": | ||
| 2593 | foo = Foo() | ||
| 2594 | print (foo) | ||
| 2595 | |||
| 2596 | class Bar(models.Model): | ||
| 2597 | pass | ||
| 2598 | " | ||
| 2599 | (should (string= (python-shell-buffer-substring | ||
| 2600 | (python-tests-look-at "# coding: latin-1") | ||
| 2601 | (python-tests-look-at "if __name__ == \"__main__\":")) | ||
| 2602 | "# -*- coding: latin-1 -*- | ||
| 2603 | |||
| 2604 | |||
| 2605 | class Foo(models.Model): | ||
| 2606 | pass | ||
| 2607 | |||
| 2608 | ")))) | ||
| 2609 | |||
| 2610 | (ert-deftest python-shell-buffer-substring-7 () | ||
| 2611 | "Ensure first coding cookie gets precedence." | ||
| 2612 | (python-tests-with-temp-buffer | ||
| 2613 | "# coding: utf-8 | ||
| 2614 | # coding: latin-1 | ||
| 2615 | |||
| 2616 | class Foo(models.Model): | ||
| 2617 | pass | ||
| 2618 | |||
| 2619 | if __name__ == \"__main__\": | ||
| 2620 | foo = Foo() | ||
| 2621 | print (foo) | ||
| 2622 | |||
| 2623 | class Bar(models.Model): | ||
| 2624 | pass | ||
| 2625 | " | ||
| 2626 | (should (string= (python-shell-buffer-substring | ||
| 2627 | (python-tests-look-at "# coding: latin-1") | ||
| 2628 | (python-tests-look-at "if __name__ == \"__main__\":")) | ||
| 2629 | "# -*- coding: utf-8 -*- | ||
| 2630 | |||
| 2631 | |||
| 2632 | class Foo(models.Model): | ||
| 2633 | pass | ||
| 2634 | |||
| 2635 | ")))) | ||
| 2636 | |||
| 2637 | (ert-deftest python-shell-buffer-substring-8 () | ||
| 2638 | "Ensure first coding cookie gets precedence when sending whole buffer." | ||
| 2639 | (python-tests-with-temp-buffer | ||
| 2640 | "# coding: utf-8 | ||
| 2641 | # coding: latin-1 | ||
| 2642 | |||
| 2643 | class Foo(models.Model): | ||
| 2644 | pass | ||
| 2645 | " | ||
| 2646 | (should (string= (python-shell-buffer-substring (point-min) (point-max)) | ||
| 2647 | "# coding: utf-8 | ||
| 2648 | |||
| 2649 | |||
| 2650 | class Foo(models.Model): | ||
| 2651 | pass | ||
| 2652 | ")))) | ||
| 2653 | |||
| 2462 | 2654 | ||
| 2463 | ;;; Shell completion | 2655 | ;;; Shell completion |
| 2464 | 2656 | ||
| @@ -3773,6 +3965,85 @@ foo = True # another comment | |||
| 3773 | (forward-line 1) | 3965 | (forward-line 1) |
| 3774 | (should (python-info-current-line-empty-p)))) | 3966 | (should (python-info-current-line-empty-p)))) |
| 3775 | 3967 | ||
| 3968 | (ert-deftest python-info-encoding-from-cookie-1 () | ||
| 3969 | "Should detect it on first line." | ||
| 3970 | (python-tests-with-temp-buffer | ||
| 3971 | "# coding=latin-1 | ||
| 3972 | |||
| 3973 | foo = True # another comment | ||
| 3974 | " | ||
| 3975 | (should (eq (python-info-encoding-from-cookie) 'latin-1)))) | ||
| 3976 | |||
| 3977 | (ert-deftest python-info-encoding-from-cookie-2 () | ||
| 3978 | "Should detect it on second line." | ||
| 3979 | (python-tests-with-temp-buffer | ||
| 3980 | " | ||
| 3981 | # coding=latin-1 | ||
| 3982 | |||
| 3983 | foo = True # another comment | ||
| 3984 | " | ||
| 3985 | (should (eq (python-info-encoding-from-cookie) 'latin-1)))) | ||
| 3986 | |||
| 3987 | (ert-deftest python-info-encoding-from-cookie-3 () | ||
| 3988 | "Should not be detected on third line (and following ones)." | ||
| 3989 | (python-tests-with-temp-buffer | ||
| 3990 | " | ||
| 3991 | |||
| 3992 | # coding=latin-1 | ||
| 3993 | foo = True # another comment | ||
| 3994 | " | ||
| 3995 | (should (not (python-info-encoding-from-cookie))))) | ||
| 3996 | |||
| 3997 | (ert-deftest python-info-encoding-from-cookie-4 () | ||
| 3998 | "Should detect Emacs style." | ||
| 3999 | (python-tests-with-temp-buffer | ||
| 4000 | "# -*- coding: latin-1 -*- | ||
| 4001 | |||
| 4002 | foo = True # another comment" | ||
| 4003 | (should (eq (python-info-encoding-from-cookie) 'latin-1)))) | ||
| 4004 | |||
| 4005 | (ert-deftest python-info-encoding-from-cookie-5 () | ||
| 4006 | "Should detect Vim style." | ||
| 4007 | (python-tests-with-temp-buffer | ||
| 4008 | "# vim: set fileencoding=latin-1 : | ||
| 4009 | |||
| 4010 | foo = True # another comment" | ||
| 4011 | (should (eq (python-info-encoding-from-cookie) 'latin-1)))) | ||
| 4012 | |||
| 4013 | (ert-deftest python-info-encoding-from-cookie-6 () | ||
| 4014 | "First cookie wins." | ||
| 4015 | (python-tests-with-temp-buffer | ||
| 4016 | "# -*- coding: iso-8859-1 -*- | ||
| 4017 | # vim: set fileencoding=latin-1 : | ||
| 4018 | |||
| 4019 | foo = True # another comment" | ||
| 4020 | (should (eq (python-info-encoding-from-cookie) 'iso-8859-1)))) | ||
| 4021 | |||
| 4022 | (ert-deftest python-info-encoding-from-cookie-7 () | ||
| 4023 | "First cookie wins." | ||
| 4024 | (python-tests-with-temp-buffer | ||
| 4025 | "# vim: set fileencoding=latin-1 : | ||
| 4026 | # -*- coding: iso-8859-1 -*- | ||
| 4027 | |||
| 4028 | foo = True # another comment" | ||
| 4029 | (should (eq (python-info-encoding-from-cookie) 'latin-1)))) | ||
| 4030 | |||
| 4031 | (ert-deftest python-info-encoding-1 () | ||
| 4032 | "Should return the detected encoding from cookie." | ||
| 4033 | (python-tests-with-temp-buffer | ||
| 4034 | "# vim: set fileencoding=latin-1 : | ||
| 4035 | |||
| 4036 | foo = True # another comment" | ||
| 4037 | (should (eq (python-info-encoding) 'latin-1)))) | ||
| 4038 | |||
| 4039 | (ert-deftest python-info-encoding-2 () | ||
| 4040 | "Should default to utf-8." | ||
| 4041 | (python-tests-with-temp-buffer | ||
| 4042 | "# No encoding for you | ||
| 4043 | |||
| 4044 | foo = True # another comment" | ||
| 4045 | (should (eq (python-info-encoding) 'utf-8)))) | ||
| 4046 | |||
| 3776 | 4047 | ||
| 3777 | ;;; Utility functions | 4048 | ;;; Utility functions |
| 3778 | 4049 | ||