Subject: bug#24809: 25.1; Python.el improper indention after backslash-assignment-continuation

From: [email-masked]
Date: Mon, 22 May 2017 20:47:31 -0400

From: Jules Tamagnan <[email-masked]>

> an_overly_long_variable_name = some_object.some_method(some_argument_to_some_method)
>
> could be split like this:
>
> an_overly_long_variable_name = (
>     some_object.some_method(some_argument_to_some_method))
>
> or if someone wanted to use a backslash like this:
>
> an_overly_long_variable_name = \
>     some_object.some_method(some_argument_to_some_method)
>
> instead of like:
>
> an_overly_long_variable_name = \
>                                some_object.some_method(some_argument_to_some_method)
> ----------

Ah, I'd been looking at stuff from the test suite which looked like:

    an_overly_long_variable_name = something \
                                   another.thing(etc)

which seems a bit neater than

    an_overly_long_variable_name = something \
        another.thing(etc)

but I find your example convincing.  And we still have parens if the
first kind of indentation is preferred:

    an_overly_long_variable_name = (something 
                                    another.thing(etc))

I actually have the fix for the tests already written anyway.  I'll wait
a week or so before pushing, in case anyone else has some comments on
this.

>From 5476e881e1d302bcd40a407de0946d383012384f Mon Sep 17 00:00:00 2001
From: Jules Tamagnan <[email-masked]>
Date: Thu, 27 Oct 2016 15:03:31 -0700
Subject: [PATCH v2 1/3] Comply with pep 8 style guide for backslash in
 assignment (Bug#24809)

* lisp/progmodes/python.el (python-indent--calculate-indentation):
Increase indent by `python-indent-offset' after
`:after-backslash-assignment-continuation'.

Copyright-paperwork-exempt: yes
---
 lisp/progmodes/python.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 9cebc81bfc..02a2e4046d 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1054,13 +1054,13 @@ (defun python-indent--calculate-indentation ()
            (max line-indentation base-indent)))
         (`(,(or :after-block-start
                 :after-backslash-first-line
+                :after-backslash-assignment-continuation
                 :inside-paren-newline-start) . ,start)
          ;; Add one indentation level.
          (goto-char start)
          (+ (current-indentation) python-indent-offset))
         (`(,(or :inside-paren
                 :after-backslash-block-continuation
-                :after-backslash-assignment-continuation
                 :after-backslash-dotted-continuation) . ,start)
          ;; Use the column given by the context.
          (goto-char start)
-- 
2.11.1

>From e931c8bd772be41dc4b98bc2614eacff529af195 Mon Sep 17 00:00:00 2001
From: Noam Postavsky <[email-masked]>
Date: Mon, 22 May 2017 12:32:04 -0400
Subject: [PATCH v2 2/3] ; Update test for previous change

* test/lisp/progmodes/python-tests.el
(python-indent-after-backslash-4): Indent after backslash is now
python-indent-offset.
---
 test/lisp/progmodes/python-tests.el | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index cd05710000..cea597acea 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -753,8 +753,8 @@ (ert-deftest python-indent-after-backslash-4 ()
   (python-tests-with-temp-buffer
    "
 super_awful_assignment = some_calculation() and \\\\
-                         another_calculation() and \\\\
-                         some_final_calculation()
+    another_calculation() and \\\\
+    some_final_calculation()
 "
    (python-tests-look-at
     "super_awful_assignment = some_calculation() and \\\\")
@@ -763,10 +763,10 @@ (ert-deftest python-indent-after-backslash-4 ()
    (python-tests-look-at "another_calculation() and \\\\")
    (should (eq (car (python-indent-context))
                :after-backslash-assignment-continuation))
-   (should (= (python-indent-calculate-indentation) 25))
+   (should (= (python-indent-calculate-indentation) python-indent-offset))
    (python-tests-look-at "some_final_calculation()")
    (should (eq (car (python-indent-context)) :after-backslash))
-   (should (= (python-indent-calculate-indentation) 25))))
+   (should (= (python-indent-calculate-indentation) python-indent-offset))))
 
 (ert-deftest python-indent-after-backslash-5 ()
   "Dotted continuation bizarre example."
-- 
2.11.1

>From 711102160a678b4f9fb7042d8ae53cf7c740c309 Mon Sep 17 00:00:00 2001
From: Noam Postavsky <[email-masked]>
Date: Mon, 22 May 2017 12:36:20 -0400
Subject: [PATCH v2 3/3] ; Fix backslashes in python-tests

* test/lisp/progmodes/python-tests.el (python-indent-after-backslash-1)
(python-indent-after-backslash-2)
(python-indent-after-backslash-3)
(python-indent-after-backslash-4)
(python-indent-after-backslash-5)
(python-nav-beginning-of-statement-1)
(python-nav-end-of-statement-1)
(python-nav-forward-statement-1)
(python-nav-backward-statement-1)
(python-nav-backward-statement-2)
(python-info-statement-starts-block-p-2)
(python-info-statement-ends-block-p-2)
(python-info-beginning-of-statement-p-2)
(python-info-end-of-statement-p-2)
(python-info-beginning-of-block-p-2)
(python-info-end-of-block-p-2)
(python-info-line-ends-backslash-p-1)
(python-info-beginning-of-backslash-1)
(python-info-continuation-line-p-1)
(python-info-block-continuation-line-p-1)
(python-info-assignment-statement-p-1)
(python-info-assignment-continuation-line-p-1): Backslashes in
literals should be doubled only once to produce one backslash in the
buffer.  If there backslashes inside a Python string literal in a Lisp
literal, that would need to be doubled twice, but there are no such
cases.  Note that `python-tests-looking-at' takes a plain string, not
a regexp.
---
 test/lisp/progmodes/python-tests.el | 106 ++++++++++++++++++------------------
 1 file changed, 53 insertions(+), 53 deletions(-)

diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index cea597acea..7c274381cd 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -662,8 +662,8 @@ (ert-deftest python-indent-after-backslash-1 ()
   "The most common case."
   (python-tests-with-temp-buffer
    "
-from foo.bar.baz import something, something_1 \\\\
-    something_2 something_3, \\\\
+from foo.bar.baz import something, something_1 \\
+    something_2 something_3, \\
     something_4, something_5
 "
    (python-tests-look-at "from foo.bar.baz import something, something_1")
@@ -683,14 +683,14 @@ (ert-deftest python-indent-after-backslash-2 ()
   "A pretty extreme complicated case."
   (python-tests-with-temp-buffer
    "
-objects = Thing.objects.all() \\\\
+objects = Thing.objects.all() \\
                        .filter(
                            type='toy',
                            status='bought'
-                       ) \\\\
+                       ) \\
                        .aggregate(
                            Sum('amount')
-                       ) \\\\
+                       ) \\
                        .values_list()
 "
    (python-tests-look-at "objects = Thing.objects.all()")
@@ -706,7 +706,7 @@ (ert-deftest python-indent-after-backslash-2 ()
    (python-tests-look-at "status='bought'")
    (should (eq (car (python-indent-context)) :inside-paren-newline-start))
    (should (= (python-indent-calculate-indentation) 27))
-   (python-tests-look-at ") \\\\")
+   (python-tests-look-at ") \\")
    (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
    (should (= (python-indent-calculate-indentation) 23))
    (python-tests-look-at ".aggregate(")
@@ -716,7 +716,7 @@ (ert-deftest python-indent-after-backslash-2 ()
    (python-tests-look-at "Sum('amount')")
    (should (eq (car (python-indent-context)) :inside-paren-newline-start))
    (should (= (python-indent-calculate-indentation) 27))
-   (python-tests-look-at ") \\\\")
+   (python-tests-look-at ") \\")
    (should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
    (should (= (python-indent-calculate-indentation) 23))
    (python-tests-look-at ".values_list()")
@@ -731,12 +731,12 @@ (ert-deftest python-indent-after-backslash-3 ()
   "Backslash continuation from block start."
   (python-tests-with-temp-buffer
    "
-with open('/path/to/some/file/you/want/to/read') as file_1, \\\\
+with open('/path/to/some/file/you/want/to/read') as file_1, \\
      open('/path/to/some/file/being/written', 'w') as file_2:
     file_2.write(file_1.read())
 "
    (python-tests-look-at
-    "with open('/path/to/some/file/you/want/to/read') as file_1, \\\\")
+    "with open('/path/to/some/file/you/want/to/read') as file_1, \\")
    (should (eq (car (python-indent-context)) :no-indent))
    (should (= (python-indent-calculate-indentation) 0))
    (python-tests-look-at
@@ -752,15 +752,15 @@ (ert-deftest python-indent-after-backslash-4 ()
   "Backslash continuation from assignment."
   (python-tests-with-temp-buffer
    "
-super_awful_assignment = some_calculation() and \\\\
-    another_calculation() and \\\\
+super_awful_assignment = some_calculation() and \\
+    another_calculation() and \\
     some_final_calculation()
 "
    (python-tests-look-at
-    "super_awful_assignment = some_calculation() and \\\\")
+    "super_awful_assignment = some_calculation() and \\")
    (should (eq (car (python-indent-context)) :no-indent))
    (should (= (python-indent-calculate-indentation) 0))
-   (python-tests-look-at "another_calculation() and \\\\")
+   (python-tests-look-at "another_calculation() and \\")
    (should (eq (car (python-indent-context))
                :after-backslash-assignment-continuation))
    (should (= (python-indent-calculate-indentation) python-indent-offset))
@@ -773,14 +773,14 @@ (ert-deftest python-indent-after-backslash-5 ()
   (python-tests-with-temp-buffer
    "
 def delete_all_things():
-    Thing \\\\
-        .objects.all() \\\\
+    Thing \\
+        .objects.all() \\
                 .delete()
 "
-   (python-tests-look-at "Thing \\\\")
+   (python-tests-look-at "Thing \\")
    (should (eq (car (python-indent-context)) :after-block-start))
    (should (= (python-indent-calculate-indentation) 4))
-   (python-tests-look-at ".objects.all() \\\\")
+   (python-tests-look-at ".objects.all() \\")
    (should (eq (car (python-indent-context)) :after-backslash-first-line))
    (should (= (python-indent-calculate-indentation) 8))
    (python-tests-look-at ".delete()")
@@ -1882,8 +1882,8 @@ (ert-deftest python-nav-forward-defun-3 ()
 (ert-deftest python-nav-beginning-of-statement-1 ()
   (python-tests-with-temp-buffer
    "
-v1 = 123 + \
-     456 + \
+v1 = 123 + \\
+     456 + \\
      789
 v2 = (value1,
       value2,
@@ -1930,8 +1930,8 @@ (ert-deftest python-nav-beginning-of-statement-1 ()
 (ert-deftest python-nav-end-of-statement-1 ()
   (python-tests-with-temp-buffer
    "
-v1 = 123 + \
-     456 + \
+v1 = 123 + \\
+     456 + \\
      789
 v2 = (value1,
       value2,
@@ -1984,8 +1984,8 @@ (ert-deftest python-nav-end-of-statement-1 ()
 (ert-deftest python-nav-forward-statement-1 ()
   (python-tests-with-temp-buffer
    "
-v1 = 123 + \
-     456 + \
+v1 = 123 + \\
+     456 + \\
      789
 v2 = (value1,
       value2,
@@ -2025,8 +2025,8 @@ (ert-deftest python-nav-forward-statement-1 ()
 (ert-deftest python-nav-backward-statement-1 ()
   (python-tests-with-temp-buffer
    "
-v1 = 123 + \
-     456 + \
+v1 = 123 + \\
+     456 + \\
      789
 v2 = (value1,
       value2,
@@ -2067,8 +2067,8 @@ (ert-deftest python-nav-backward-statement-2 ()
   :expected-result :failed
   (python-tests-with-temp-buffer
    "
-v1 = 123 + \
-     456 + \
+v1 = 123 + \\
+     456 + \\
      789
 v2 = (value1,
       value2,
@@ -3962,8 +3962,8 @@ (ert-deftest python-info-statement-starts-block-p-1 ()
 (ert-deftest python-info-statement-starts-block-p-2 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError('sorry, you lose')
 "
@@ -3987,8 +3987,8 @@ (ert-deftest python-info-statement-ends-block-p-1 ()
 (ert-deftest python-info-statement-ends-block-p-2 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError(
 'sorry, you lose'
@@ -4018,8 +4018,8 @@ (ert-deftest python-info-beginning-of-statement-p-1 ()
 (ert-deftest python-info-beginning-of-statement-p-2 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError(
 'sorry, you lose'
@@ -4058,8 +4058,8 @@ (ert-deftest python-info-end-of-statement-p-1 ()
 (ert-deftest python-info-end-of-statement-p-2 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError(
 'sorry, you lose'
@@ -4099,8 +4099,8 @@ (ert-deftest python-info-beginning-of-block-p-1 ()
 (ert-deftest python-info-beginning-of-block-p-2 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError(
 'sorry, you lose'
@@ -4137,8 +4137,8 @@ (ert-deftest python-info-end-of-block-p-1 ()
 (ert-deftest python-info-end-of-block-p-2 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError(
 'sorry, you lose'
@@ -4645,14 +4645,14 @@ (ert-deftest python-info-dedenter-statement-p-5 ()
 (ert-deftest python-info-line-ends-backslash-p-1 ()
   (python-tests-with-temp-buffer
    "
-objects = Thing.objects.all() \\\\
+objects = Thing.objects.all() \\
                        .filter(
                            type='toy',
                            status='bought'
-                       ) \\\\
+                       ) \\
                        .aggregate(
                            Sum('amount')
-                       ) \\\\
+                       ) \\
                        .values_list()
 "
    (should (python-info-line-ends-backslash-p 2)) ; .filter(...
@@ -4668,14 +4668,14 @@ (ert-deftest python-info-line-ends-backslash-p-1 ()
 (ert-deftest python-info-beginning-of-backslash-1 ()
   (python-tests-with-temp-buffer
    "
-objects = Thing.objects.all() \\\\
+objects = Thing.objects.all() \\
                        .filter(
                            type='toy',
                            status='bought'
-                       ) \\\\
+                       ) \\
                        .aggregate(
                            Sum('amount')
-                       ) \\\\
+                       ) \\
                        .values_list()
 "
    (let ((first 2)
@@ -4694,8 +4694,8 @@ (ert-deftest python-info-beginning-of-backslash-1 ()
 (ert-deftest python-info-continuation-line-p-1 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError(
 'sorry, you lose'
@@ -4722,8 +4722,8 @@ (ert-deftest python-info-continuation-line-p-1 ()
 (ert-deftest python-info-block-continuation-line-p-1 ()
   (python-tests-with-temp-buffer
    "
-if width == 0 and height == 0 and \\\\
-   color == 'red' and emphasis == 'strong' or \\\\
+if width == 0 and height == 0 and \\
+   color == 'red' and emphasis == 'strong' or \\
    highlight > 100:
     raise ValueError(
 'sorry, you lose'
@@ -4757,8 +4757,8 @@ (ert-deftest python-info-block-continuation-line-p-2 ()
 (ert-deftest python-info-assignment-statement-p-1 ()
   (python-tests-with-temp-buffer
    "
-data = foo(), bar() \\\\
-       baz(), 4 \\\\
+data = foo(), bar() \\
+       baz(), 4 \\
        5, 6
 "
    (python-tests-look-at "data = foo(), bar()")
@@ -4800,8 +4800,8 @@ (ert-deftest python-info-assignment-statement-p-3 ()
 (ert-deftest python-info-assignment-continuation-line-p-1 ()
   (python-tests-with-temp-buffer
    "
-data = foo(), bar() \\\\
-       baz(), 4 \\\\
+data = foo(), bar() \\
+       baz(), 4 \\
        5, 6
 "
    (python-tests-look-at "data = foo(), bar()")
-- 
2.11.1