aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhirosassa <hiro.sassa@gmail.com>2021-07-13 10:00:32 +0900
committerGitHub <noreply@github.com>2021-07-12 18:00:32 -0700
commitf16340e99a2dbd2187a0e547256296717d1196d6 (patch)
treef8bb4ed7631be6eaeda6568c2bf4db966373ba64
parent618c2a0e60f3fc0477856076fcd8a5cc4fc403ee (diff)
downloadyapf-f16340e99a2dbd2187a0e547256296717d1196d6.tar.gz
support ignore config in pyproject.toml (#937)
* support ignore config in pyproject.toml * add doc in readme * add tests * changelog
-rw-r--r--CHANGELOG5
-rw-r--r--README.rst15
-rw-r--r--yapf/yapflib/file_resources.py44
-rw-r--r--yapftests/file_resources_test.py81
4 files changed, 132 insertions, 13 deletions
diff --git a/CHANGELOG b/CHANGELOG
index afe8718..a35ce68 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,11 @@
# All notable changes to this project will be documented in this file.
# This project adheres to [Semantic Versioning](http://semver.org/).
+## [0.32.0] UNRELEASED
+### Added
+- Look at the 'pyproject.toml' file to see if it contains ignore file information
+ for YAPF.
+
## [0.31.0] 2021-03-14
### Added
- Renamed 'master' brannch to 'main'.
diff --git a/README.rst b/README.rst
index 1bc7b58..b381c4d 100644
--- a/README.rst
+++ b/README.rst
@@ -136,12 +136,12 @@ otherwise (including program error). You can use this in a CI workflow to test t
has been YAPF-formatted.
---------------------------------------------
-Excluding files from formatting (.yapfignore)
+Excluding files from formatting (.yapfignore or pyproject.toml)
---------------------------------------------
In addition to exclude patterns provided on commandline, YAPF looks for additional
-patterns specified in a file named ``.yapfignore`` located in the working directory from
-which YAPF is invoked.
+patterns specified in a file named ``.yapfignore`` or ``pyproject.toml`` located in the
+working directory from which YAPF is invoked.
``.yapfignore``'s syntax is similar to UNIX's filename pattern matching::
@@ -152,6 +152,15 @@ which YAPF is invoked.
Note that no entry should begin with `./`.
+If you use ``pyproject.toml``, exclude patterns are specified by ``ignore_pattens`` key
+in ``[tool.yapfignore]`` section. For example:
+
+.. code-block:: ini
+ [tool.yapfignore]
+ ignore_patterns="""
+ temp/**/*.py
+ temp2/*.py
+ """
Formatting style
================
diff --git a/yapf/yapflib/file_resources.py b/yapf/yapflib/file_resources.py
index 84a8a54..4c0fbf2 100644
--- a/yapf/yapflib/file_resources.py
+++ b/yapf/yapflib/file_resources.py
@@ -32,10 +32,9 @@ LF = '\n'
CRLF = '\r\n'
-def _GetExcludePatternsFromFile(filename):
- """Get a list of file patterns to ignore."""
+def _GetExcludePatternsFromYapfIgnore(filename):
+ """Get a list of file patterns to ignore from .yapfignore."""
ignore_patterns = []
- # See if we have a .yapfignore file.
if os.path.isfile(filename) and os.access(filename, os.R_OK):
with open(filename, 'r') as fd:
for line in fd:
@@ -48,6 +47,33 @@ def _GetExcludePatternsFromFile(filename):
return ignore_patterns
+def _GetExcludePatternsFromPyprojectToml(filename):
+ """Get a list of file patterns to ignore from pyproject.toml."""
+ ignore_patterns = []
+ try:
+ import toml
+ except ImportError:
+ raise errors.YapfError(
+ "toml package is needed for using pyproject.toml as a configuration file"
+ )
+
+ pyproject_toml = toml.load(filename)
+ if os.path.isfile(filename) and os.access(filename, os.R_OK):
+ excludes = pyproject_toml.get('tool',
+ {}).get('yapfignore',
+ {}).get('ignore_patterns', None)
+ if excludes is None:
+ return []
+
+ for line in excludes.split('\n'):
+ if line.strip() and not line.startswith('#'):
+ ignore_patterns.append(line.strip())
+ if any(e.startswith('./') for e in ignore_patterns):
+ raise errors.YapfError('path in pyproject.toml should not start with ./')
+
+ return ignore_patterns
+
+
def GetExcludePatternsForDir(dirname):
"""Return patterns of files to exclude from ignorefile in a given directory.
@@ -60,8 +86,16 @@ def GetExcludePatternsForDir(dirname):
A List of file patterns to exclude if ignore file is found, otherwise empty
List.
"""
- ignore_file = os.path.join(dirname, '.yapfignore')
- return _GetExcludePatternsFromFile(ignore_file)
+ ignore_patterns = []
+
+ yapfignore_file = os.path.join(dirname, '.yapfignore')
+ if os.path.exists(yapfignore_file):
+ ignore_patterns += _GetExcludePatternsFromYapfIgnore(yapfignore_file)
+
+ pyproject_toml_file = os.path.join(dirname, 'pyproject.toml')
+ if os.path.exists(pyproject_toml_file):
+ ignore_patterns += _GetExcludePatternsFromPyprojectToml(pyproject_toml_file)
+ return ignore_patterns
def GetDefaultStyleForDir(dirname, default_style=style.DEFAULT_STYLE):
diff --git a/yapftests/file_resources_test.py b/yapftests/file_resources_test.py
index a4b1230..6afd8a4 100644
--- a/yapftests/file_resources_test.py
+++ b/yapftests/file_resources_test.py
@@ -54,16 +54,87 @@ class GetExcludePatternsForDir(unittest.TestCase):
def tearDown(self): # pylint: disable=g-missing-super-call
shutil.rmtree(self.test_tmpdir)
- def _make_test_dir(self, name):
- fullpath = os.path.normpath(os.path.join(self.test_tmpdir, name))
- os.makedirs(fullpath)
- return fullpath
+ def test_get_exclude_file_patterns_from_yapfignore(self):
+ local_ignore_file = os.path.join(self.test_tmpdir, '.yapfignore')
+ ignore_patterns = ['temp/**/*.py', 'temp2/*.py']
+ with open(local_ignore_file, 'w') as f:
+ f.writelines('\n'.join(ignore_patterns))
- def test_get_exclude_file_patterns(self):
+ self.assertEqual(
+ sorted(file_resources.GetExcludePatternsForDir(self.test_tmpdir)),
+ sorted(ignore_patterns))
+
+ def test_get_exclude_file_patterns_from_yapfignore_with_wrong_syntax(self):
local_ignore_file = os.path.join(self.test_tmpdir, '.yapfignore')
+ ignore_patterns = ['temp/**/*.py', './wrong/syntax/*.py']
+ with open(local_ignore_file, 'w') as f:
+ f.writelines('\n'.join(ignore_patterns))
+
+ with self.assertRaises(errors.YapfError):
+ file_resources.GetExcludePatternsForDir(self.test_tmpdir)
+
+ def test_get_exclude_file_patterns_from_pyproject(self):
+ try:
+ import toml
+ except ImportError:
+ return
+ local_ignore_file = os.path.join(self.test_tmpdir, 'pyproject.toml')
ignore_patterns = ['temp/**/*.py', 'temp2/*.py']
with open(local_ignore_file, 'w') as f:
+ f.write('[tool.yapfignore]\n')
+ f.write('ignore_patterns="""')
+ f.writelines('\n'.join(ignore_patterns))
+ f.write('"""')
+
+ self.assertEqual(
+ sorted(file_resources.GetExcludePatternsForDir(self.test_tmpdir)),
+ sorted(ignore_patterns))
+
+ def test_get_exclude_file_patterns_from_pyproject_with_wrong_syntax(self):
+ try:
+ import toml
+ except ImportError:
+ return
+ local_ignore_file = os.path.join(self.test_tmpdir, 'pyproject.toml')
+ ignore_patterns = ['temp/**/*.py', './wrong/syntax/*.py']
+ with open(local_ignore_file, 'w') as f:
+ f.write('[tool.yapfignore]\n')
+ f.write('ignore_patterns="""')
f.writelines('\n'.join(ignore_patterns))
+ f.write('"""')
+
+ with self.assertRaises(errors.YapfError):
+ file_resources.GetExcludePatternsForDir(self.test_tmpdir)
+
+ def test_get_exclude_file_patterns_from_pyproject_no_ignore_section(self):
+ try:
+ import toml
+ except ImportError:
+ return
+ local_ignore_file = os.path.join(self.test_tmpdir, 'pyproject.toml')
+ ignore_patterns = []
+ open(local_ignore_file, 'w').close()
+
+ self.assertEqual(
+ sorted(file_resources.GetExcludePatternsForDir(self.test_tmpdir)),
+ sorted(ignore_patterns))
+
+ def test_get_exclude_file_patterns_from_pyproject_ignore_section_empty(self):
+ try:
+ import toml
+ except ImportError:
+ return
+ local_ignore_file = os.path.join(self.test_tmpdir, 'pyproject.toml')
+ ignore_patterns = []
+ with open(local_ignore_file, 'w') as f:
+ f.write('[tool.yapfignore]\n')
+
+ self.assertEqual(
+ sorted(file_resources.GetExcludePatternsForDir(self.test_tmpdir)),
+ sorted(ignore_patterns))
+
+ def test_get_exclude_file_patterns_with_no_config_files(self):
+ ignore_patterns = []
self.assertEqual(
sorted(file_resources.GetExcludePatternsForDir(self.test_tmpdir)),