Repository: google/yapf
Pull request #837 (2020-05-05 08:35:08)

Reformatted source

coveralls: 
[![Coverage Status](https://coveralls.io/builds/30562501/badge)](https://coveralls.io/builds/30562501)

Coverage decreased (-0.05%) to 96.266% when pulling **3c4b9fc078e3cfe25a9c195a917a29a99fe3d2d8 on keshavgbpecdelhi:patch-1** into **51ffe2d07930a509ecb2ef454a7b251eeeac0a59 on google:master**.


Patch:
diff --git a/CHANGELOG b/CHANGELOG
index 6b10382..afe8718 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,12 +2,19 @@
 # All notable changes to this project will be documented in this file.
 # This project adheres to [Semantic Versioning](http://semver.org/).
 
-## [0.31.0] UNRELEASED
+## [0.31.0] 2021-03-14
 ### Added
+- Renamed 'master' brannch to 'main'.
 - Add 'BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES' to support setting
   a custom number of blank lines between top-level imports and variable
   definitions.
 - Ignore end of line `# copybara:` directives when checking line length.
+- Look at the 'pyproject.toml' file to see if it contains style information for
+  YAPF.
+### Changed
+- Do not scan exlcuded directories. Prior versions would scan an exluded
+  folder then exclude its contents on a file by file basis. Preventing the
+  folder being scanned is faster.
 ### Fixed
 - Exclude directories on Windows.
 
diff --git a/README.rst b/README.rst
index e013c52..5a099cb 100644
--- a/README.rst
+++ b/README.rst
@@ -6,12 +6,12 @@ YAPF
     :target: https://badge.fury.io/py/yapf
     :alt: PyPI version
 
-.. image:: https://travis-ci.org/google/yapf.svg?branch=master
+.. image:: https://travis-ci.org/google/yapf.svg?branch=main
     :target: https://travis-ci.org/google/yapf
     :alt: Build status
 
-.. image:: https://coveralls.io/repos/google/yapf/badge.svg?branch=master
-    :target: https://coveralls.io/r/google/yapf?branch=master
+.. image:: https://coveralls.io/repos/google/yapf/badge.svg?branch=main
+    :target: https://coveralls.io/r/google/yapf?branch=main
     :alt: Coverage status
 
 
@@ -113,10 +113,10 @@ Options::
       --style STYLE         specify formatting style: either a style name (for
                             example "pep8" or "google"), or the name of a file
                             with style settings. The default is pep8 unless a
-                            .style.yapf or setup.cfg file located in the same
-                            directory as the source or one of its parent
-                            directories (for stdin, the current directory is
-                            used).
+                            .style.yapf or setup.cfg or pyproject.toml file
+                            located in the same directory as the source or one of
+                            its parent directories (for stdin, the current
+                            directory is used).
       --style-help          show style settings and exit; this output can be saved
                             to .style.yapf to make your settings permanent
       --no-local-style      don't search for local style definition
@@ -176,10 +176,18 @@ with a ``[yapf]`` heading. For example:
 
 The ``based_on_style`` setting determines which of the predefined styles this
 custom style is based on (think of it like subclassing). Four
-styles are predefined: ``pep8`` (default), ``google``, ``yapf``, and ``facebook``
-(see ``_STYLE_NAME_TO_FACTORY`` in style.py_).
+styles are predefined:
 
-.. _style.py: https://github.com/google/yapf/blob/master/yapf/yapflib/style.py#L445
+- ``pep8`` (default)
+- ``google`` (based off of the `Google Python Style Guide`_)
+- ``yapf`` (for use with Google open source projects)
+- ``facebook``
+
+.. _`Google Python Style Guide`: https://github.com/google/styleguide/blob/gh-pages/pyguide.md
+
+See ``_STYLE_NAME_TO_FACTORY`` in style.py_ for details.
+
+.. _style.py: https://github.com/google/yapf/blob/main/yapf/yapflib/style.py
 
 It's also possible to do the same on the command line with a dictionary. For
 example:
@@ -198,7 +206,9 @@ YAPF will search for the formatting style in the following manner:
    directory or one of its parent directories.
 3. In the ``[yapf]`` section of a ``setup.cfg`` file in either the current
    directory or one of its parent directories.
-4. In the ``[style]`` section of a ``~/.config/yapf/style`` file in your home
+4. In the ``[tool.yapf]`` section of a ``pyproject.toml`` file in either the current
+   directory or one of its parent directories.
+5. In the ``[style]`` section of a ``~/.config/yapf/style`` file in your home
    directory.
 
 If none of those files are found, the default style is used (PEP8).
@@ -283,7 +293,7 @@ than a whole file.
     'def g():\n    a = 1\n    b = 2\n    return a==b\n'
 
 A ``print_diff`` (bool): Instead of returning the reformatted source, return a
-diff that turns the formatted source into reformatter source.
+diff that turns the formatted source into reformatted source.
 
 .. code-block:: python
 
@@ -351,9 +361,10 @@ Options::
       --style STYLE         specify formatting style: either a style name (for
                             example "pep8" or "google"), or the name of a file
                             with style settings. The default is pep8 unless a
-                            .style.yapf or setup.cfg file located in one of the
-                            parent directories of the source file (or current
-                            directory for stdin)
+                            .style.yapf or setup.cfg or pyproject.toml file
+                            located in the same directory as the source or one of
+                            its parent directories (for stdin, the current
+                            directory is used).
       --binary BINARY       location of binary to use for yapf
 
 Knobs
diff --git a/plugins/README.rst b/plugins/README.rst
index f7657cc..b87bb2d 100644
--- a/plugins/README.rst
+++ b/plugins/README.rst
@@ -65,7 +65,7 @@ directory:
 .. code-block:: bash
 
     # From the root of your git project.
-    curl -o pre-commit.sh https://raw.githubusercontent.com/google/yapf/master/plugins/pre-commit.sh
+    curl -o pre-commit.sh https://raw.githubusercontent.com/google/yapf/main/plugins/pre-commit.sh
     chmod a+x pre-commit.sh
     mv pre-commit.sh .git/hooks/pre-commit
 
diff --git a/setup.py b/setup.py
index fe2a046..70e57da 100644
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@ import codecs
 import sys
 import unittest
 
-from setuptools import setup, Command
+from setuptools import find_packages, setup, Command
 
 import yapf
 
@@ -49,7 +49,7 @@ with codecs.open('README.rst', 'r', 'utf-8') as fd:
       author='Google Inc.',
       maintainer='Bill Wendling',
       maintainer_email='morbo@google.com',
-      packages=['yapf', 'yapf.yapflib', 'yapftests'],
+      packages=find_packages('.'),
       classifiers=[
           'Development Status :: 4 - Beta',
           'Environment :: Console',
diff --git a/yapf/__init__.py b/yapf/__init__.py
index 3aca8bd..a70db84 100644
--- a/yapf/__init__.py
+++ b/yapf/__init__.py
@@ -40,7 +40,7 @@ from yapf.yapflib import py3compat
 from yapf.yapflib import style
 from yapf.yapflib import yapf_api
 
-__version__ = '0.30.0'
+__version__ = '0.31.0'
 
 
 def main(argv):
@@ -325,10 +325,10 @@ def _BuildParser():
       action='store',
       help=('specify formatting style: either a style name (for example "pep8" '
             'or "google"), or the name of a file with style settings. The '
-            'default is pep8 unless a %s or %s file located in the same '
+            'default is pep8 unless a %s or %s or %s file located in the same '
             'directory as the source or one of its parent directories '
             '(for stdin, the current directory is used).' %
-            (style.LOCAL_STYLE, style.SETUP_CONFIG)))
+            (style.LOCAL_STYLE, style.SETUP_CONFIG, style.PYPROJECT_TOML)))
   parser.add_argument(
       '--style-help',
       action='store_true',
diff --git a/yapf/yapflib/file_resources.py b/yapf/yapflib/file_resources.py
index 4c6bf38..84a8a54 100644
--- a/yapf/yapflib/file_resources.py
+++ b/yapf/yapflib/file_resources.py
@@ -67,7 +67,7 @@ def GetExcludePatternsForDir(dirname):
 def GetDefaultStyleForDir(dirname, default_style=style.DEFAULT_STYLE):
   """Return default style name for a given directory.
 
-  Looks for .style.yapf or setup.cfg in the parent directories.
+  Looks for .style.yapf or setup.cfg or pyproject.toml in the parent directories.
 
   Arguments:
     dirname: (unicode) The name of the directory.
@@ -97,6 +97,26 @@ def GetDefaultStyleForDir(dirname, default_style=style.DEFAULT_STYLE):
         if config.has_section('yapf'):
           return config_file
 
+    # See if we have a pyproject.toml file with a '[tool.yapf]'  section.
+    config_file = os.path.join(dirname, style.PYPROJECT_TOML)
+    try:
+      fd = open(config_file)
+    except IOError:
+      pass  # It's okay if it's not there.
+    else:
+      with fd:
+        try:
+          import toml
+        except ImportError:
+          raise errors.YapfError(
+              "toml package is needed for using pyproject.toml as a configuration file"
+          )
+
+        pyproject_toml = toml.load(config_file)
+        style_dict = pyproject_toml.get('tool', {}).get('yapf', None)
+        if style_dict is not None:
+          return config_file
+
     if (not dirname or not os.path.basename(dirname) or
         dirname == os.path.abspath(os.path.sep)):
       break
@@ -167,7 +187,7 @@ def _FindPythonFiles(filenames, recursive, exclude):
 
       # TODO(morbo): Look into a version of os.walk that can handle recursion.
       excluded_dirs = []
-      for dirpath, _, filelist in os.walk(filename):
+      for dirpath, dirnames, filelist in os.walk(filename):
         if dirpath != '.' and exclude and IsIgnored(dirpath, exclude):
           excluded_dirs.append(dirpath)
           continue
@@ -179,6 +199,19 @@ def _FindPythonFiles(filenames, recursive, exclude):
             continue
           if IsPythonFile(filepath):
             python_files.append(filepath)
+        # To prevent it from scanning the contents excluded folders, os.walk()
+        # lets you amend its list of child dirs `dirnames`. These edits must be
+        # made in-place instead of creating a modified copy of `dirnames`.
+        # list.remove() is slow and list.pop() is a headache. Instead clear
+        # `dirnames` then repopulate it.
+        dirnames_ = [dirnames.pop(0) for i in range(len(dirnames))]
+        for dirname in dirnames_:
+          dir_ = os.path.join(dirpath, dirname)
+          if IsIgnored(dir_, exclude):
+            excluded_dirs.append(dir_)
+          else:
+            dirnames.append(dirname)
+
     elif os.path.isfile(filename):
       python_files.append(filename)
 
@@ -187,6 +220,8 @@ def _FindPythonFiles(filenames, recursive, exclude):
 
 def IsIgnored(path, exclude):
   """Return True if filename matches any patterns in exclude."""
+  if exclude is None:
+    return False
   path = path.lstrip(os.path.sep)
   while path.startswith('.' + os.path.sep):
     path = path[2:]
diff --git a/yapf/yapflib/format_decision_state.py b/yapf/yapflib/format_decision_state.py
index dbe3d81..164818e 100644
--- a/yapf/yapflib/format_decision_state.py
+++ b/yapf/yapflib/format_decision_state.py
@@ -741,8 +741,8 @@ class FormatDecisionState(object):
 
     # Calculate the penalty for overflowing the column limit.
     penalty = 0
-    if (not current.is_pylint_comment and not current.is_pytype_comment
-        and not current.is_copybara_comment and self.column > self.column_limit):
+    if (not current.is_pylint_comment and not current.is_pytype_comment and
+        not current.is_copybara_comment and self.column > self.column_limit):
       excess_characters = self.column - self.column_limit
       penalty += style.Get('SPLIT_PENALTY_EXCESS_CHARACTER') * excess_characters
 
diff --git a/yapf/yapflib/reformatter.py b/yapf/yapflib/reformatter.py
index cd940bb..d07be84 100644
--- a/yapf/yapflib/reformatter.py
+++ b/yapf/yapflib/reformatter.py
@@ -119,14 +119,14 @@ def _RetainRequiredVerticalSpacing(cur_uwline, prev_uwline, lines):
   if prev_uwline is not None:
     prev_tok = prev_uwline.last
 
+  if cur_uwline.disable:
+    # After the first token we are acting on a single line. So if it is
+    # disabled we must not reformat.
+    lines = set()
+
   for cur_tok in cur_uwline.tokens:
     _RetainRequiredVerticalSpacingBetweenTokens(cur_tok, prev_tok, lines)
-
     prev_tok = cur_tok
-    if cur_uwline.disable:
-      # After the first token we are acting on a single line. So if it is
-      # disabled we must not reformat.
-      lines = set()
 
 
 def _RetainRequiredVerticalSpacingBetweenTokens(cur_tok, prev_tok, lines):
@@ -259,8 +259,8 @@ def _CanPlaceOnSingleLine(uwline):
   indent_amt = style.Get('INDENT_WIDTH') * uwline.depth
   last = uwline.last
   last_index = -1
-  if (last.is_pylint_comment or last.is_pytype_comment
-      or last.is_copybara_comment):
+  if (last.is_pylint_comment or last.is_pytype_comment or
+      last.is_copybara_comment):
     last = last.previous_token
     last_index = -2
   if last is None:
@@ -491,10 +491,13 @@ def _AnalyzeSolutionSpace(initial_state):
     if count > 10000:
       node.state.ignore_stack_for_comparison = True
 
-    if node.state in seen:
-      continue
-
+    # Unconditionally add the state and check if it was present to avoid having to
+    # hash it twice in the common case (state hashing is expensive).
+    before_seen_count = len(seen)
     seen.add(node.state)
+    # If seen didn't change size, the state was already present.
+    if before_seen_count == len(seen):
+      continue
 
     # FIXME(morbo): Add a 'decision' element?
 
diff --git a/yapf/yapflib/style.py b/yapf/yapflib/style.py
index b01c231..6bd2372 100644
--- a/yapf/yapflib/style.py
+++ b/yapf/yapflib/style.py
@@ -742,19 +742,40 @@ def _CreateConfigParserFromConfigFile(config_filename):
         '"{0}" is not a valid style or file path'.format(config_filename))
   with open(config_filename) as style_file:
     config = py3compat.ConfigParser()
+    if config_filename.endswith(PYPROJECT_TOML):
+      try:
+        import toml
+      except ImportError:
+        raise errors.YapfError(
+            "toml package is needed for using pyproject.toml as a configuration file"
+        )
+
+      pyproject_toml = toml.load(style_file)
+      style_dict = pyproject_toml.get("tool", {}).get("yapf", None)
+      if style_dict is None:
+        raise StyleConfigError(
+            'Unable to find section [tool.yapf] in {0}'.format(config_filename))
+      config.add_section('style')
+      for k, v in style_dict.items():
+        config.set('style', k, str(v))
+      return config
+
     config.read_file(style_file)
     if config_filename.endswith(SETUP_CONFIG):
       if not config.has_section('yapf'):
         raise StyleConfigError(
             'Unable to find section [yapf] in {0}'.format(config_filename))
-    elif config_filename.endswith(LOCAL_STYLE):
-      if not config.has_section('style'):
-        raise StyleConfigError(
-            'Unable to find section [style] in {0}'.format(config_filename))
-    else:
+      return config
+
+    if config_filename.endswith(LOCAL_STYLE):
       if not config.has_section('style'):
         raise StyleConfigError(
             'Unable to find section [style] in {0}'.format(config_filename))
+      return config
+
+    if not config.has_section('style'):
+      raise StyleConfigError(
+          'Unable to find section [style] in {0}'.format(config_filename))
     return config
 
 
@@ -817,6 +838,10 @@ LOCAL_STYLE = '.style.yapf'
 # specified in the '[yapf]' section.
 SETUP_CONFIG = 'setup.cfg'
 
+# Style definition by local pyproject.toml file. Style should be specified
+# in the '[tool.yapf]' section.
+PYPROJECT_TOML = 'pyproject.toml'
+
 # TODO(eliben): For now we're preserving the global presence of a style dict.
 # Refactor this so that the style is passed around through yapf rather than
 # being global.
diff --git a/yapf/yapflib/unwrapped_line.py b/yapf/yapflib/unwrapped_line.py
index 475bd6e..0986314 100644
--- a/yapf/yapflib/unwrapped_line.py
+++ b/yapf/yapflib/unwrapped_line.py
@@ -323,6 +323,9 @@ def _SpaceRequiredBetween(left, right, is_line_disabled):
       format_token.Subtype.DEFAULT_OR_NAMED_ASSIGN not in left.subtypes):
     # Space between equal and '.' as in "X = ...".
     return True
+  if lval == ':' and rval == '.':
+    # Space between : and ...
+    return True
   if ((right.is_keyword or right.is_name) and
       (left.is_keyword or left.is_name)):
     # Don't merge two keywords/identifiers.
diff --git a/yapf/yapflib/yapf_api.py b/yapf/yapflib/yapf_api.py
index dde1df9..fdcce30 100644
--- a/yapf/yapflib/yapf_api.py
+++ b/yapf/yapflib/yapf_api.py
@@ -269,10 +269,9 @@ def _MarkLinesToFormat(uwlines, lines):
         index += 1
         while index < len(uwlines):
           uwline = uwlines[index]
-          if uwline.is_comment and _EnableYAPF(uwline.first.value.strip()):
-            if not re.search(DISABLE_PATTERN,
-                             uwline.first.value.strip().split('\n')[-1].strip(),
-                             re.IGNORECASE):
+          line = uwline.first.value.strip()
+          if uwline.is_comment and _EnableYAPF(line):
+            if not _DisableYAPF(line):
               break
           uwline.disable = True
           index += 1


Test patch:
diff --git a/yapftests/blank_line_calculator_test.py b/yapftests/blank_line_calculator_test.py
index 1ec0a5e..193f419 100644
--- a/yapftests/blank_line_calculator_test.py
+++ b/yapftests/blank_line_calculator_test.py
@@ -300,15 +300,12 @@ class BasicBlankLineCalculatorTest(yapf_test_helper.YAPFTest):
         def B():  # 4
           pass  # 5
 
-
         def C():
           pass
 
 
         def D():  # 9
           pass  # 10
-
-
         def E():
           pass
         """)
@@ -375,6 +372,8 @@ class BasicBlankLineCalculatorTest(yapf_test_helper.YAPFTest):
           pass  # 7
 
 
+
+
         def C():
           pass
         """)
@@ -410,6 +409,7 @@ class BasicBlankLineCalculatorTest(yapf_test_helper.YAPFTest):
 
 
 
+
         def C():
           pass
         """)
diff --git a/yapftests/file_resources_test.py b/yapftests/file_resources_test.py
index 2bf68ab..a4b1230 100644
--- a/yapftests/file_resources_test.py
+++ b/yapftests/file_resources_test.py
@@ -117,6 +117,26 @@ class GetDefaultStyleForDirTest(unittest.TestCase):
     self.assertEqual(setup_config,
                      file_resources.GetDefaultStyleForDir(test_dir))
 
+  def test_pyproject_toml(self):
+    # An empty pyproject.toml file should not be used
+    try:
+      import toml
+    except ImportError:
+      return
+
+    pyproject_toml = os.path.join(self.test_tmpdir, 'pyproject.toml')
+    open(pyproject_toml, 'w').close()
+
+    test_dir = os.path.join(self.test_tmpdir, 'dir1')
+    style_name = file_resources.GetDefaultStyleForDir(test_dir)
+    self.assertEqual(style_name, 'pep8')
+
+    # One with a '[tool.yapf]' section should be used
+    with open(pyproject_toml, 'w') as f:
+      f.write('[tool.yapf]\n')
+    self.assertEqual(pyproject_toml,
+                     file_resources.GetDefaultStyleForDir(test_dir))
+
   def test_local_style_at_root(self):
     # Test behavior of files located on the root, and under root.
     rootdir = os.path.abspath(os.path.sep)
diff --git a/yapftests/reformatter_pep8_test.py b/yapftests/reformatter_pep8_test.py
index bdd074a..a5301f1 100644
--- a/yapftests/reformatter_pep8_test.py
+++ b/yapftests/reformatter_pep8_test.py
@@ -698,6 +698,17 @@ class _():
     reformatted_code = reformatter.Reformat(uwlines)
     self.assertCodeEqual(expected_formatted_code, reformatted_code)
 
+  @unittest.skipUnless(py3compat.PY36, 'Requires Python 3.6')
+  def testSpaceBetweenColonAndElipses(self):
+    style.SetGlobalStyle(style.CreatePEP8Style())
+    code = textwrap.dedent("""\
+      class MyClass(ABC):
+
+          place: ...
+    """)
+    uwlines = yapf_test_helper.ParseAndUnwrap(code)
+    self.assertCodeEqual(code, reformatter.Reformat(uwlines, verify=False))
+
 
 class TestsForSpacesInsideBrackets(yapf_test_helper.YAPFTest):
   """Test the SPACE_INSIDE_BRACKETS style option."""
diff --git a/yapftests/style_test.py b/yapftests/style_test.py
index a9c478d..2fd3f2d 100644
--- a/yapftests/style_test.py
+++ b/yapftests/style_test.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 """Tests for yapf.style."""
 
+import os
 import shutil
 import tempfile
 import textwrap
@@ -226,6 +227,36 @@ class StyleFromFileTest(unittest.TestCase):
                                    'Unknown style option'):
         style.CreateStyleFromConfig(filepath)
 
+  def testPyprojectTomlNoYapfSection(self):
+    try:
+      import toml
+    except ImportError:
+      return
+
+    filepath = os.path.join(self.test_tmpdir, 'pyproject.toml')
+    _ = open(filepath, 'w')
+    with self.assertRaisesRegexp(style.StyleConfigError,
+                                 'Unable to find section'):
+      style.CreateStyleFromConfig(filepath)
+
+  def testPyprojectTomlParseYapfSection(self):
+    try:
+      import toml
+    except ImportError:
+      return
+
+    cfg = textwrap.dedent(u'''\
+        [tool.yapf]
+        based_on_style = "pep8"
+        continuation_indent_width = 40
+        ''')
+    filepath = os.path.join(self.test_tmpdir, 'pyproject.toml')
+    with open(filepath, 'w') as f:
+      f.write(cfg)
+    cfg = style.CreateStyleFromConfig(filepath)
+    self.assertTrue(_LooksLikePEP8Style(cfg))
+    self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 40)
+
 
 class StyleFromDict(unittest.TestCase):
 
diff --git a/yapftests/yapf_test.py b/yapftests/yapf_test.py
index e3e3df3..dc0d0a5 100644
--- a/yapftests/yapf_test.py
+++ b/yapftests/yapf_test.py
@@ -881,8 +881,6 @@ x = {
         """)
     expected_formatted_code = textwrap.dedent("""\
         a = line_to_format
-
-
         def f():
             x = y + 42; z = n * 42
             if True: a += 1 ; b += 1 ; c += 1
@@ -905,8 +903,6 @@ x = {
         ''')
     expected_formatted_code = textwrap.dedent('''\
         foo = 42
-
-
         def f():
             email_text += """<html>This is a really long docstring that goes over the column limit and is multi-line.<br><br>
         <b>Czar: </b>"""+despot["Nicholas"]+"""<br>
@@ -1031,6 +1027,7 @@ x = {
             def aaaaaaaaaaaaa(self):
                 pass
 
+
             def bbbbbbbbbbbbb(self):  # 5
                 pass
         """)
@@ -1170,13 +1167,12 @@ x = {
 
   def testPseudoParenSpaces(self):
     unformatted_code = textwrap.dedent("""\
-        def foo():
+        def   foo():
           def bar():
             return {msg_id: author for author, msg_id in reader}
         """)
     expected_formatted_code = textwrap.dedent("""\
         def foo():
-
           def bar():
             return {msg_id: author for author, msg_id in reader}
         """)
@@ -1482,6 +1478,30 @@ CONTINUATION_ALIGN_STYLE = valign-right
         expected_formatted_code,
         extra_options=['--style', 'yapf', '--lines', '1-1'])
 
+  def testDisableWithLinesOption(self):
+    unformatted_code = textwrap.dedent("""\
+        # yapf_lines_bug.py
+        # yapf: disable
+        def outer_func():
+            def inner_func():
+                return
+            return
+        # yapf: enable
+        """)
+    expected_formatted_code = textwrap.dedent("""\
+        # yapf_lines_bug.py
+        # yapf: disable
+        def outer_func():
+            def inner_func():
+                return
+            return
+        # yapf: enable
+        """)
+    self.assertYapfReformats(
+        unformatted_code,
+        expected_formatted_code,
+        extra_options=['--lines', '1-8'])
+
   @unittest.skipUnless(py3compat.PY36, 'Requires Python 3.6')
   def testNoSpacesAroundBinaryOperators(self):
     unformatted_code = """\