Python indentation in Spacemacs with hard tabs is off - python

Let me preface by saying that I am a relatively new emacs/spacemacs convert from vim, so my my knowledge is still pretty basic.
I have spacemacs set up with the python layer, with the additional package of dtrt-indent listed in dotspacemacs-additional-packages. And setting
(dtrt-indent-mode t)
in the dotspacemacs/user-config. I need the dtrt-indent as I am working on a few projects (in python and lua) where I am not the one who sets the indentation rules.
This configuration works fine for python files with soft-tabs of varying length. This configuration also works for lua files that have hard tabs.
When I open a python file indented with hard tabs something seems to get messed up, it appears to think that the indentation is two hard tabs. Meaning, if I have code like this (pretend that the 4 spaces are tabs):
def func():| <--- Cursor
print 'line'
and press enter, I get:
def func():
| <--- Cursor
print 'line'
The status line prints dtrt-indent's message saying:
Note: indent-tabs-mode adjusted to t
Note: As stated I'm pretty new at this, and my spacemacs configuration is pretty sparse. There is nothing else in my user-config, I have not custom layers, I don't even have any additional packages other than dtrt-indent.
EDIT:
python-indent-offset is set to 8
indent-tabs-mode is set to t
tab-width is set to 4

Try M-x whitespace-mode and repeat this experiment. What do you see? Did you indent with spaces or with tabs?
I'm guessing you'll see something like this:
def·func():
········
» print·'line'
This would mean you have python-indent-offset set to 8, indent-tabs-mode set to nil (aka indent with spaces), and tab-width set to 4.
If that's not the case, what are the values of those variables (C-h v python-indent-offset, etc.)?
If that is the case, you can fix the problem by running
(setq-default python-indent-offset 4)

Related

why in the Python interpreter the first indentation level is set to 4 space, while the second to 8?

let's take the really simple case of two nested for loops
after pressing return and tab the first time, I get an indentation level where 1 tab equals 4 spaces
after pressing return and tab the second time, I get an indentation level where 1 tab equals 9 spaces
this is rather annoying when I want to copy a piece of code from a script and run it on the interpreter, as it returns the
TabError: inconsistent use of tabs and spaces in indentation
I did some googling but you can imagine what the keywords "python", "interpreter", "indentation" returns: nothing useful
Is there a way to correct this? Thanks
EDIT
just try yourselves:
open a terminal
run python command
then type for i in range(3):
press Enter
then press Tab once, to get to the right indentation level
then type for j in range(3):
press Enter again
then press Tab twice, to get to the (expected) indentation level
if, like me, you have a Mac, chances are that the second Tab hit in the last step above, will yield 8 spaces, instead of 4
This causes problems when copying lines of code written with an IDE
(I'm using Sublime 3, with the option translate_tabs_to_spaces set to True)
I was hoping someone could identify some flag/options/setting of my interpreter which could solve this issue
Title question :
Because you are at 2nd indentation level since you have a loop inside a loop.
Tabulation/space error :
Python uses only indentation to interpret which block belongs to the code. No "BEGIN...END" , no brackets. So indentation IS information.
The rule is "indentation must be uniform", so either everything is spaces (1,2,4.. as you want) or everything is tabulations.
For more information, refer to the Python style guideline (PEP8) here :
https://www.python.org/dev/peps/pep-0008/
By using an IDE ( such as Spyder, for example) tabs will automatically be replaced by spaces. I recommend you to use one, especially if you are a new to python.

VS Code Python autopep8 does not honor 2 spaces hanging indentation

I'm trying to get autopep8 work to properly indent Python code with 2 spaces instead of 4. I'm using VS Code with Python extension which uses autopep8 for formatting. I found here that autopep8 can be configured to use 2 spaces by
"python.formatting.autopep8Args": ["--indent-size=2"]
But it does not work for me.
My situation is like this. When I press enter, it correctly starts the next line with the same indentation as the previous line. Press enter after an open parenthesis, it correctly starts the new line with 2 more spaces. But when I paste or save (I have "editor.formatOnPaste" and "editor.formatOnSave" set to true), the annoying thing happened: all the 2-space indentation inside the parentheses became 4 (other 2-space indentation are unaffected). Why is it doing this and how can I make it 2 spaces everywhere?
====EDIT====
I found out that the pylint error Wrong hanging indentation (remove 2 spaces). [bad-continuation]. It's because my pylintrc has indent-after-paren=2. I'm wondering if autopep8 or other Python formatter can set this property?
I also had to include this in my array in settings.json, similar to yours.
"--ignore E121"
According to https://pypi.org/project/autopep8/, this setting ensures your indents are a multiple of 4. By not enforcing that, the configured tab size in VSCode is used.
E121 - Fix indentation to be a multiple of four.
That being said, your indentation is still "acceptable" according to pep8, so it actually will not change it to the 4 spaces you are expecting in your parens. I had to outdent mine one level, then when it ran again, it didn't change it.
Unfortunately this is actually just a workaround and it actually negatively affects other indention rules...
You can see in the code for pep8 that they hardcode the default tab size to be the "python way" (4 spaces) in:
https://github.com/hhatto/autopep8/blob/120537a051d7f3cbbb5c4ede19b9e515156bd3d1/autopep8.py#L104
That makes it look like the hanging indent is just not respecting the --indent-size option...
Adding --indent-size=2 --ignore=E121 worked for me.
had the same issue, here is the solution:
Navigate to library directory of your environment
Open autopep8.py
Search for "DEFAULT_INDENT_SIZE" and change it to 2

Indentation error in simple python

Update: The original question was posted using C-RET to run the lines, which produces the error. I get no such error using The menu Python > Eval region, which successfully evaluates the script.
However, using the menu for every execution is really annoying, and moreover I can't run the present line alone with that method. So my problem remains.
Forgive me if I'm missing something obvious, but I can't figure this out.
This code is giving me an IndentationError. I can't imagine what's going on.
for x in range(0, 3):
print "We're on time %d" % (x)
Here's everything related to python in my emacs.el
;; elpy
(add-to-list 'package-archives
'("elpy" . "http://jorgenschaefer.github.io/packages/"))
(package-initialize)
(elpy-enable)
You've mixed tabs and spaces. This can lead to some confusing errors.
I'd suggest using only tabs or only spaces for indentation.
Using only spaces is generally the easier choice. Most editors have an option for automatically converting tabs to spaces. If your editor has this option, turn it on.
You can paste your code in notepad to see.
All commands from menu have a command-name callable via M-x COMMAND RET.
In this case M-x python-send-region RET

indent python file (with pydev) in eclipse

I'm a newbie in eclipse. I want to indent all the lines of my code and formatting the open file by pressing a shortcut or something like that...
I know the CTRL+SHIFT+F (as it actually doesn't work in pydev!!)
I've been searching for hours with no success. Is there any way to do that in eclipse. kind of like CTRL+K,D in visual studio, which formats and indents all the source code lines automatically?
If you want to change from 2 space to 4 space indentation (for instance), use "Source->Convert space to tab" with 2 spaces, then "Soruce->Convert tab to space" with 4 spaces.
I ... don't think this question makes sense. Indentation is syntax in Python. It doesn't make sense to have your IDE auto-indent your code. If it's not indented properly already, it doesn't work, and the IDE can't know where your indentation blocks begin and end. Take, for example:
# Valid Code
for i in range(10):
b = i
for j in range(b):
c = j
# Also Valid Code.
for i in range(10):
b = i
for j in range(b):
c = j
There's no possible way that the IDE can know which of those is the correct version, or what your intent is. If you're going to write Python code, you're going to have to learn to manage the indentation. There's no way to avoid it, and expecting the IDE to magically clean it up and still get the desired result out of it is pretty much impossible.
Further example:
# Valid Code.
outputData = []
for i in range(100):
outputData.append(str(i))
print ''.join(outputData)
# Again, also valid code, wildly different behavior.
outputData = []
for i in range(100):
outputData.append(str(i))
print ''.join(outputData)
The first will produce a list of strings, then print the joined result to the console 1 time. The second will still produce a list of strings, but prints the cumulative joined result for each iteration of the loop - 100 print statements. The two are both 100% syntactically correct. There's no problem with them. Either of them could be what the developer wanted. An IDE can't "know" which is correct. It could, very easily incorrectly change the first version to the second version. Because the Language uses Indentation as Syntax, there is no way to configure an IDE to perform this kind of formatting for you.
Although auto-indentation is not a feature of PyDev because of the language design you should be able to indent with a simple tab. Just select the lines you want to indent and press Tab. If you want to unindent lines you have to press Shift+Tab.
Thats all.
It is much easier:
Select multiple lines
Press Tab to indent (move right), Shift + Tab to unindent (move left) all selected
lines.
Indentation is syntactically significant; consider the difference between
for i in range(5):
print i
print "done"
and
for i in range(5):
print i
print "done"
However, it certainly makes sense for the IDE to be able to normalize the existing indentation (e.g. apply a consistent number of spaces/tabs at each level).
Currently PyDev does not support such a feature; Pydev author Fabioz at one point expressed interest in adding it in the future and indicated that for now you can use the supplied reindent.py script to do it.
Obviously this is only for Pydev, but I've worked out that you can get the very useful functions "Shift Right" and "Shift Left" (mapped by default to CTRL + ALT + . and CTRL + ALT + ,) to become useful by changing their keybindings to "Pydev Editor Scope" from "Pydev View". This effectively indents/dedents all lines that you've selected as much as you'd like
I think that what you're looking for is some kind of shortcut in Eclipse/PyDev so that the selected code can be idented all at once. Just like when you create a new "if" or a "for" loop above a block of code and then need to rearrange the identation. The IDLE Editor has the "Ctrl + ]" shortcut that works exactly that way. It seems that the PyDev in Eclipse doesnt have something like that as far as I know.
One can also select the lines, right click, then shift right / shift left
It seems source formatting is still not available in PyDev.
For one off instances I found this web app does the job nicely.
http://pythoniter.appspot.com/
Like earlier said python requires to indent your code, so for other things like: space between variables passed as arguments to methods, etc., one can use ctrl+shift+f to format the code. This what is used for java, I tried for pydev and does some formatting.

Is there any way to format a complete python buffer in emacs with a key press?

I am looking for any way to have Emacs format a Python buffer by hitting a few keys. By format, I mean:
Replace tabs with 4 spaces
Wrap all long lines correctly at 79 chars. This includes wrapping & concatenating long strings, wrapping long comments, wrapping lists, function headers, etc.
Unrelated, but when I hit enter, it'd be nice if the cursor was tabbed in automatically.
In general I'd like to just format everything according to PEP 8.
I've looked for a pretty printer / code beautifier / code formatter for Python to run the buffer through, but can't find an open source one.
My .emacs is here.
For those who are going to answer "You don't need a formatter for Python, it's beautiful by the nature of the language," I say to you that this is not correct. In real software systems, comments should be auto-wrapped for you, strings are going to be longer than 79 characters, tab levels run 3+ deep. Please just help me solve my issue directly without some philosophical discussion about the merits of formatting Python source.
To change tabs into spaces and fill comments at the same time, you can use this command:
(defun my-format-python-text ()
"untabify and wrap python comments"
(interactive)
(untabify (point-min) (point-max))
(goto-char (point-min))
(while (re-search-forward comment-start nil t)
(call-interactively 'fill-paragraph)
(forward-line 1)))
Which you can bind to the key of your choice, presumably like so:
(eval-after-load "python"
'(progn
(define-key python-mode-map (kbd "RET") 'newline-and-indent)
(define-key python-mode-map (kbd "<f4>") 'my-format-python-text)))
Note the setting of the RET key to automatically indent.
If you wanted to all tabs with spaces with just built-in commands, this is a possible sequence:
C-x h ;; mark-whole-buffer
M-x untabify ;; tabs->spaces
To get the fill column and tab width to be what you want, add to your .emacs:
(setq fill-column 79)
(setq-default tab-width 4)
Arguably, the tab-width should be set to 8, depending on how other folks have indented their code in your environment (8 being a default that some other editors have). If that's the case, you could just set it to 4 in the 'python-mode-hook. It kind of depends on your environment.
About your point 3:
Unrelated, but when I hit enter, it'd
be nice if the cursor was tabbed in
automatically.
My emacs Python mode does this by default, apparently. It's simply called python-mode...
Using Spacemacs' Python layer with default bindings:
The sequence , = will run yapfify-buffer to impose PEP8 formatting on the entire buffer.
You can set
(setq-default dotspacemacs-configuration-layers '(
(python :variables python-enable-yapf-format-on-save t)))
to enable automating reformatting on save.
The best way to avoid tab characters in your file is to not insert them at all. The following statement will always insert the correct number of spaces, rather than inserting tab characters
;; Turn off tab insertion in favor of space insertion
(setq-default indent-tabs-mode nil)
I see you have this in your .emacs file already
The autopep8 and the emacs wrapper for it should fulfill your desire.. https://github.com/paetzke/py-autopep8.el

Categories

Resources