| # -*- coding: utf-8 -*- |
| # Copyright 2015 Google Inc. All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| """Tests for yapf.style.""" |
| |
| import os |
| import shutil |
| import tempfile |
| import textwrap |
| import unittest |
| |
| from yapf.yapflib import style |
| |
| from yapftests import utils |
| from yapftests import yapf_test_helper |
| |
| |
| class UtilsTest(yapf_test_helper.YAPFTest): |
| |
| def testContinuationAlignStyleStringConverter(self): |
| for cont_align_space in ('', 'space', '"space"', '\'space\''): |
| self.assertEqual( |
| style._ContinuationAlignStyleStringConverter(cont_align_space), |
| 'SPACE') |
| for cont_align_fixed in ('fixed', '"fixed"', '\'fixed\''): |
| self.assertEqual( |
| style._ContinuationAlignStyleStringConverter(cont_align_fixed), |
| 'FIXED') |
| for cont_align_valignright in ( |
| 'valign-right', |
| '"valign-right"', |
| '\'valign-right\'', |
| 'valign_right', |
| '"valign_right"', |
| '\'valign_right\'', |
| ): |
| self.assertEqual( |
| style._ContinuationAlignStyleStringConverter(cont_align_valignright), |
| 'VALIGN-RIGHT') |
| with self.assertRaises(ValueError) as ctx: |
| style._ContinuationAlignStyleStringConverter('blahblah') |
| self.assertIn("unknown continuation align style: 'blahblah'", |
| str(ctx.exception)) |
| |
| def testStringListConverter(self): |
| self.assertEqual(style._StringListConverter('foo, bar'), ['foo', 'bar']) |
| self.assertEqual(style._StringListConverter('foo,bar'), ['foo', 'bar']) |
| self.assertEqual(style._StringListConverter(' foo'), ['foo']) |
| self.assertEqual( |
| style._StringListConverter('joe ,foo, bar'), ['joe', 'foo', 'bar']) |
| |
| def testBoolConverter(self): |
| self.assertEqual(style._BoolConverter('true'), True) |
| self.assertEqual(style._BoolConverter('1'), True) |
| self.assertEqual(style._BoolConverter('false'), False) |
| self.assertEqual(style._BoolConverter('0'), False) |
| |
| def testIntListConverter(self): |
| self.assertEqual(style._IntListConverter('1, 2, 3'), [1, 2, 3]) |
| self.assertEqual(style._IntListConverter('[ 1, 2, 3 ]'), [1, 2, 3]) |
| self.assertEqual(style._IntListConverter('[ 1, 2, 3, ]'), [1, 2, 3]) |
| |
| def testIntOrIntListConverter(self): |
| self.assertEqual(style._IntOrIntListConverter('10'), 10) |
| self.assertEqual(style._IntOrIntListConverter('1, 2, 3'), [1, 2, 3]) |
| |
| |
| def _LooksLikeGoogleStyle(cfg): |
| return cfg['COLUMN_LIMIT'] == 80 and cfg['SPLIT_COMPLEX_COMPREHENSION'] |
| |
| |
| def _LooksLikePEP8Style(cfg): |
| return cfg['COLUMN_LIMIT'] == 79 |
| |
| |
| def _LooksLikeFacebookStyle(cfg): |
| return cfg['DEDENT_CLOSING_BRACKETS'] |
| |
| |
| def _LooksLikeYapfStyle(cfg): |
| return cfg['SPLIT_BEFORE_DOT'] |
| |
| |
| class PredefinedStylesByNameTest(yapf_test_helper.YAPFTest): |
| |
| @classmethod |
| def setUpClass(cls): # pylint: disable=g-missing-super-call |
| style.SetGlobalStyle(style.CreatePEP8Style()) |
| |
| def testDefault(self): |
| # default is PEP8 |
| cfg = style.CreateStyleFromConfig(None) |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| |
| def testPEP8ByName(self): |
| for pep8_name in ('PEP8', 'pep8', 'Pep8'): |
| cfg = style.CreateStyleFromConfig(pep8_name) |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| |
| def testGoogleByName(self): |
| for google_name in ('google', 'Google', 'GOOGLE'): |
| cfg = style.CreateStyleFromConfig(google_name) |
| self.assertTrue(_LooksLikeGoogleStyle(cfg)) |
| |
| def testYapfByName(self): |
| for yapf_name in ('yapf', 'YAPF'): |
| cfg = style.CreateStyleFromConfig(yapf_name) |
| self.assertTrue(_LooksLikeYapfStyle(cfg)) |
| |
| def testFacebookByName(self): |
| for fb_name in ('facebook', 'FACEBOOK', 'Facebook'): |
| cfg = style.CreateStyleFromConfig(fb_name) |
| self.assertTrue(_LooksLikeFacebookStyle(cfg)) |
| |
| |
| class StyleFromFileTest(yapf_test_helper.YAPFTest): |
| |
| @classmethod |
| def setUpClass(cls): # pylint: disable=g-missing-super-call |
| cls.test_tmpdir = tempfile.mkdtemp() |
| style.SetGlobalStyle(style.CreatePEP8Style()) |
| |
| @classmethod |
| def tearDownClass(cls): # pylint: disable=g-missing-super-call |
| shutil.rmtree(cls.test_tmpdir) |
| |
| def testDefaultBasedOnStyle(self): |
| cfg = textwrap.dedent("""\ |
| [style] |
| continuation_indent_width = 20 |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| cfg = style.CreateStyleFromConfig(filepath) |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 20) |
| |
| def testDefaultBasedOnPEP8Style(self): |
| cfg = textwrap.dedent("""\ |
| [style] |
| based_on_style = pep8 |
| continuation_indent_width = 40 |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| cfg = style.CreateStyleFromConfig(filepath) |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 40) |
| |
| def testDefaultBasedOnGoogleStyle(self): |
| cfg = textwrap.dedent("""\ |
| [style] |
| based_on_style = google |
| continuation_indent_width = 20 |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| cfg = style.CreateStyleFromConfig(filepath) |
| self.assertTrue(_LooksLikeGoogleStyle(cfg)) |
| self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 20) |
| |
| def testDefaultBasedOnFacebookStyle(self): |
| cfg = textwrap.dedent("""\ |
| [style] |
| based_on_style = facebook |
| continuation_indent_width = 20 |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| cfg = style.CreateStyleFromConfig(filepath) |
| self.assertTrue(_LooksLikeFacebookStyle(cfg)) |
| self.assertEqual(cfg['CONTINUATION_INDENT_WIDTH'], 20) |
| |
| def testBoolOptionValue(self): |
| cfg = textwrap.dedent("""\ |
| [style] |
| based_on_style = pep8 |
| SPLIT_BEFORE_NAMED_ASSIGNS=False |
| split_before_logical_operator = true |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| cfg = style.CreateStyleFromConfig(filepath) |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| self.assertEqual(cfg['SPLIT_BEFORE_NAMED_ASSIGNS'], False) |
| self.assertEqual(cfg['SPLIT_BEFORE_LOGICAL_OPERATOR'], True) |
| |
| def testStringListOptionValue(self): |
| cfg = textwrap.dedent("""\ |
| [style] |
| based_on_style = pep8 |
| I18N_FUNCTION_CALL = N_, V_, T_ |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| cfg = style.CreateStyleFromConfig(filepath) |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| self.assertEqual(cfg['I18N_FUNCTION_CALL'], ['N_', 'V_', 'T_']) |
| |
| def testErrorNoStyleFile(self): |
| with self.assertRaisesRegex(style.StyleConfigError, |
| 'is not a valid style or file path'): |
| style.CreateStyleFromConfig('/8822/xyznosuchfile') |
| |
| def testErrorNoStyleSection(self): |
| cfg = textwrap.dedent("""\ |
| [s] |
| indent_width=2 |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| with self.assertRaisesRegex(style.StyleConfigError, |
| 'Unable to find section'): |
| style.CreateStyleFromConfig(filepath) |
| |
| def testErrorUnknownStyleOption(self): |
| cfg = textwrap.dedent("""\ |
| [style] |
| indent_width=2 |
| hummus=2 |
| """) |
| with utils.TempFileContents(self.test_tmpdir, cfg) as filepath: |
| with self.assertRaisesRegex(style.StyleConfigError, |
| 'Unknown style option'): |
| style.CreateStyleFromConfig(filepath) |
| |
| def testPyprojectTomlNoYapfSection(self): |
| filepath = os.path.join(self.test_tmpdir, 'pyproject.toml') |
| _ = open(filepath, 'w') |
| with self.assertRaisesRegex(style.StyleConfigError, |
| 'Unable to find section'): |
| style.CreateStyleFromConfig(filepath) |
| |
| def testPyprojectTomlParseYapfSection(self): |
| |
| cfg = textwrap.dedent("""\ |
| [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(yapf_test_helper.YAPFTest): |
| |
| @classmethod |
| def setUpClass(cls): # pylint: disable=g-missing-super-call |
| style.SetGlobalStyle(style.CreatePEP8Style()) |
| |
| def testDefaultBasedOnStyle(self): |
| config_dict = { |
| 'based_on_style': 'pep8', |
| 'indent_width': 2, |
| 'blank_line_before_nested_class_or_def': True |
| } |
| cfg = style.CreateStyleFromConfig(config_dict) |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| self.assertEqual(cfg['INDENT_WIDTH'], 2) |
| |
| def testDefaultBasedOnStyleBadDict(self): |
| self.assertRaisesRegex(style.StyleConfigError, 'Unknown style option', |
| style.CreateStyleFromConfig, |
| {'based_on_styl': 'pep8'}) |
| self.assertRaisesRegex(style.StyleConfigError, 'not a valid', |
| style.CreateStyleFromConfig, |
| {'INDENT_WIDTH': 'FOUR'}) |
| |
| |
| class StyleFromCommandLine(yapf_test_helper.YAPFTest): |
| |
| @classmethod |
| def setUpClass(cls): # pylint: disable=g-missing-super-call |
| style.SetGlobalStyle(style.CreatePEP8Style()) |
| |
| def testDefaultBasedOnStyle(self): |
| cfg = style.CreateStyleFromConfig( |
| '{based_on_style: pep8,' |
| ' indent_width: 2,' |
| ' blank_line_before_nested_class_or_def: True}') |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| self.assertEqual(cfg['INDENT_WIDTH'], 2) |
| |
| def testDefaultBasedOnStyleNotStrict(self): |
| cfg = style.CreateStyleFromConfig( |
| '{based_on_style : pep8,' |
| ' indent_width=2' |
| ' blank_line_before_nested_class_or_def:True}') |
| self.assertTrue(_LooksLikePEP8Style(cfg)) |
| self.assertEqual(cfg['INDENT_WIDTH'], 2) |
| |
| def testDefaultBasedOnExplicitlyUnicodeTypeString(self): |
| cfg = style.CreateStyleFromConfig('{}') |
| self.assertIsInstance(cfg, dict) |
| |
| def testDefaultBasedOnDetaultTypeString(self): |
| cfg = style.CreateStyleFromConfig('{}') |
| self.assertIsInstance(cfg, dict) |
| |
| def testDefaultBasedOnStyleBadString(self): |
| self.assertRaisesRegex(style.StyleConfigError, 'Unknown style option', |
| style.CreateStyleFromConfig, '{based_on_styl: pep8}') |
| self.assertRaisesRegex(style.StyleConfigError, 'not a valid', |
| style.CreateStyleFromConfig, '{INDENT_WIDTH: FOUR}') |
| self.assertRaisesRegex(style.StyleConfigError, 'Invalid style dict', |
| style.CreateStyleFromConfig, '{based_on_style: pep8') |
| |
| |
| class StyleHelp(yapf_test_helper.YAPFTest): |
| |
| def testHelpKeys(self): |
| settings = sorted(style.Help()) |
| expected = sorted(style._style) |
| self.assertListEqual(settings, expected) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |