autopep8
autopep8 copied to clipboard
KeyError in function continued_indentation
I ran into this issue when building formatting server (over Language server protocol) using autopep8 as a formatter. see here https://github.com/hhatto/autopep8/issues/624
Python Code
Let's call this autopep8_test.py
import contextlib
import io
import runpy
import sys
class redirect_io(contextlib.AbstractContextManager):
def __init__(self, stream, new_target):
self._stream = stream
self._new_target = new_target
# We use a list of old targets to make this CM re-entrant
self._old_targets = []
def __enter__(self):
self._old_targets.append(getattr(sys, self._stream))
setattr(sys, self._stream, self._new_target)
return self._new_target
def __exit__(self, exctype, excinst, exctb):
setattr(sys, self._stream, self._old_targets.pop())
class formatter_result(object):
def __init__(self):
self.stdout = None
self.stderr = None
class custom_io(io.TextIOWrapper):
name = None
def __init__(self, name, encoding="utf-8", newline=None):
super().__init__(io.BytesIO(), encoding=encoding)
self.name = name
def close(self):
pass
def _format_using_module(content):
str_output = custom_io("<stdout>")
str_error = custom_io("<stderr>")
run_args = ['autopep8', "-"]
original_argv = sys.argv[:]
try:
sys.argv = run_args
with redirect_io("stdout", str_output):
with redirect_io("stderr", str_error):
str_input = custom_io("<input>")
with redirect_io("stdin", str_input):
# Force line endings to be `\n`, this makes the diff
# easier to work with
str_input.write(content.replace("\r\n", "\n"))
str_input.flush()
str_input.seek(0)
runpy.run_module(
'autopep8', run_name="__main__", alter_sys=True
)
except SystemExit:
pass
finally:
sys.argv = original_argv
contents = "import sys;print(sys.argv)"
_format_using_module(contents) # Runs fine
_format_using_module(contents) # This one fails
Command Line and Configuration
None
Command Line
> python autopep8_test.py
Traceback (most recent call last):
File "c:/GIT/repro/tpi1/conda1/autopep8_test.py", line 72, in <module>
_format_using_module(contents) # This one fails
File "c:/GIT/repro/tpi1/conda1/autopep8_test.py", line 61, in _format_using_module
'autopep8', run_name="__main__", alter_sys=True
File "c:\GIT\repro\tpi1\conda1\.myenv1\lib\runpy.py", line 205, in run_module
return _run_module_code(code, init_globals, run_name, mod_spec)
File "c:\GIT\repro\tpi1\conda1\.myenv1\lib\runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "c:\GIT\repro\tpi1\conda1\.myenv1\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "c:\GIT\repro\tpi1\conda1\.myenv1\lib\site-packages\autopep8.py", line 430, in <module>
del pycodestyle._checks['logical_line'][pycodestyle.continued_indentation]
KeyError: <function continued_indentation at 0x000001FB175E0828>
Your Environment
- Python version: 3.10
- autopep8 version: 1.6.0
- Platform: windows
@karthiknadig
autopep8
calls pycodestyle.register_check
internally, but since pycodestyle.register_check
is a destructive function, calling it multiple times as a module results in unexpected behavior.
You can work around this problem by running importlib.reload(autopep8)
. Specifically, in this case, it is to call importlib.reload()
between the first and second _format_using_modules
.
$ diff -u example.py example_fix.py
--- example.py 2022-02-27 20:14:46.000000000 +0900
+++ example_fix.py 2022-02-27 20:15:23.000000000 +0900
@@ -1,8 +1,11 @@
import contextlib
import io
+import importlib
import runpy
import sys
+import autopep8
+
class redirect_io(contextlib.AbstractContextManager):
def __init__(self, stream, new_target):
@@ -69,4 +72,5 @@
contents = "import sys;print(sys.argv)"
_format_using_module(contents) # Runs fine
+importlib.reload(autopep8)
_format_using_module(contents) # This one fails
@hhatto Sorry for the delayed response on this. I finally got to working on this. with the latest version of autopep8 running to above code leads to:
Traceback (most recent call last):
File "c:/GIT/formatters/vscode-autopep8/src/test/python_tests/autopep8_test.py", line 74, in <module>
_format_using_module(contents) # Runs fine
File "c:/GIT/formatters/vscode-autopep8/src/test/python_tests/autopep8_test.py", line 64, in _format_using_module
'autopep8', run_name="__main__", alter_sys=True
File "C:\all_pys\Python37\lib\runpy.py", line 205, in run_module
return _run_module_code(code, init_globals, run_name, mod_spec)
File "C:\all_pys\Python37\lib\runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "C:\all_pys\Python37\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "c:\GIT\formatters\vscode-autopep8\.venv\lib\site-packages\autopep8.py", line 419, in <module>
del pycodestyle._checks['logical_line'][pycodestyle.continued_indentation]
KeyError: <function continued_indentation at 0x000002113C4178B8>
I ran into the same issue, had to restart, delete cache and reload many times but sometimes it doesn't work, is there any alternative solution for this?
@hhatto This is now hitting more frequently. The reload
mitigation does not help in some cases (I am still investigating the reason).
+1 on this issue, happens on a specific file. Any updates on having a fix for this issue, @karthiknadig?
@agherasim I am not the owner of this repo. @hhatto should provide more details.