Skip to content

Commit

Permalink
Merge pull request #747 from hhatto/fix-e501-experimental-fstring
Browse files Browse the repository at this point in the history
Fix e501 experimental fstring case in Python3.12+
  • Loading branch information
hhatto committed May 28, 2024
2 parents afd79c2 + 6f5f04d commit 7316aac
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
26 changes: 24 additions & 2 deletions autopep8.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ class documentation for more information.

MAX_PYTHON_FILE_DETECTION_BYTES = 1024

IS_SUPPORT_TOKEN_FSTRING = False
if sys.version_info >= (3, 12): # pgrama: no cover
IS_SUPPORT_TOKEN_FSTRING = True


def open_with_encoding(filename, mode='r', encoding=None, limit_byte_check=-1):
"""Return opened file with a specific encoding."""
Expand Down Expand Up @@ -2045,6 +2049,7 @@ def __init__(self, max_line_length):
self._bracket_depth = 0
self._prev_item = None
self._prev_prev_item = None
self._in_fstring = False

def __repr__(self):
return self.emit()
Expand Down Expand Up @@ -2172,6 +2177,11 @@ def _add_item(self, item, indent_amt):
inserted inside of a container or not.
"""
if item.is_fstring_start:
self._in_fstring = True
elif self._prev_item and self._prev_item.is_fstring_end:
self._in_fstring = False

if self._prev_item and self._prev_item.is_string and item.is_string:
# Place consecutive string literals on separate lines.
self._lines.append(self._LineBreak())
Expand All @@ -2198,10 +2208,10 @@ def _add_item(self, item, indent_amt):
self._lines.append(item)
self._prev_item, self._prev_prev_item = item, self._prev_item

if item_text in '([{':
if item_text in '([{' and not self._in_fstring:
self._bracket_depth += 1

elif item_text in '}])':
elif item_text in '}])' and not self._in_fstring:
self._bracket_depth -= 1
assert self._bracket_depth >= 0

Expand Down Expand Up @@ -2400,6 +2410,18 @@ def is_keyword(self):
def is_string(self):
return self._atom.token_type == tokenize.STRING

@property
def is_fstring_start(self):
if not IS_SUPPORT_TOKEN_FSTRING:
return False
return self._atom.token_type == tokenize.FSTRING_START

@property
def is_fstring_end(self):
if not IS_SUPPORT_TOKEN_FSTRING:
return False
return self._atom.token_type == tokenize.FSTRING_END

@property
def is_name(self):
return self._atom.token_type == tokenize.NAME
Expand Down
18 changes: 13 additions & 5 deletions test/test_autopep8.py
Original file line number Diff line number Diff line change
Expand Up @@ -3948,7 +3948,7 @@ def test_e701_with_escaped_newline(self):
with autopep8_context(line) as result:
self.assertEqual(fixed, result)

@unittest.skipIf(sys.version_info >= (3, 12), 'not detech in Python3.12+')
@unittest.skipIf(sys.version_info >= (3, 12), 'not detect in Python3.12+')
def test_e701_with_escaped_newline_and_spaces(self):
line = 'if True: \\ \nprint(True)\n'
fixed = 'if True:\n print(True)\n'
Expand Down Expand Up @@ -4446,7 +4446,7 @@ def test_e731_with_default_arguments(self):
with autopep8_context(line, options=['--select=E731']) as result:
self.assertEqual(fixed, result)

@unittest.skipIf(sys.version_info >= (3, 12), 'not detech in Python3.12+')
@unittest.skipIf(sys.version_info >= (3, 12), 'not detect in Python3.12+')
def test_e901_should_cause_indentation_screw_up(self):
line = """\
def tmp(g):
Expand Down Expand Up @@ -5495,7 +5495,7 @@ def test_help(self):
stdout=PIPE)
self.assertIn('usage:', p.communicate()[0].decode('utf-8').lower())

@unittest.skipIf(sys.version_info >= (3, 12), 'not detech in Python3.12+')
@unittest.skipIf(sys.version_info >= (3, 12), 'not detect in Python3.12+')
def test_verbose(self):
line = 'bad_syntax)'
with temporary_file_context(line) as filename:
Expand Down Expand Up @@ -7236,7 +7236,7 @@ def f(self):
with autopep8_context(line, options=['--experimental']) as result:
self.assertEqual(fixed, result)

@unittest.skipIf(sys.version_info >= (3, 12), 'not detech in Python3.12+')
@unittest.skipIf(sys.version_info >= (3, 12), 'not detect in Python3.12+')
def test_e501_experimental_parsing_dict_with_comments(self):
line = """\
self.display['xxxxxxxxxxxx'] = [{'title': _('Library'), #. This is the first comment.
Expand All @@ -7260,7 +7260,7 @@ def test_e501_experimental_parsing_dict_with_comments(self):
with autopep8_context(line, options=['--experimental']) as result:
self.assertEqual(fixed, result)

@unittest.skipIf(sys.version_info >= (3, 12), 'not detech in Python3.12+')
@unittest.skipIf(sys.version_info >= (3, 12), 'not detect in Python3.12+')
def test_e501_experimental_if_line_over_limit(self):
line = """\
if not xxxxxxxxxxxx(aaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccc, dddddddddddddddddddddd):
Expand Down Expand Up @@ -7333,6 +7333,14 @@ def test_e501_experimental_with_in(self):
with autopep8_context(line, options=['--experimental']) as result:
self.assertEqual(fixed, result)

@unittest.skipIf(sys.version_info < (3, 12), 'not support in Python3.11 and lower version')
def test_e501_experimental_not_effect_with_fstring(self):
line = """\
fstring = {"some_key": f"There is a string value inside of an f string, which itself is a dictionary value {s})"}
"""
with autopep8_context(line, options=['--experimental']) as result:
self.assertEqual(line, result)


def fix_e266(source):
with autopep8_context(source, options=['--select=E266']) as result:
Expand Down

0 comments on commit 7316aac

Please sign in to comment.