Repository: google/yapf
Pull request #1134 (2023-09-04 03:44:32)

pyproject.toml updates to HACKING.md
* Setup module is missing, use build instead.
* Run tests with tox.


Patch:
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..5bb982c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,1 @@
+.python-version eol=lf
diff --git a/.python-version b/.python-version
new file mode 100644
index 0000000..f4bd916
--- /dev/null
+++ b/.python-version
@@ -0,0 +1,5 @@
+3.7.9
+3.8.10
+3.9.13
+3.10.11
+3.11.5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb5df20..9beed29 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,9 @@
   by removing the "verify" parameter.
 - Changed FORCE_MULTILINE_DICT to override SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES.
 - Adopt pyproject.toml (PEP 517) for build system
+### Fixed
+- Do not treat variables named `match` as the match keyword
+- Fix SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED for one-item argument lists.
 
 ## [0.40.1] 2023-06-20
 ### Fixed
diff --git a/EDITOR SUPPORT.md b/EDITOR SUPPORT.md
new file mode 100644
index 0000000..b6f7acb
--- /dev/null
+++ b/EDITOR SUPPORT.md
@@ -0,0 +1,82 @@
+# Using YAPF with your editor
+
+YAPF is supported by multiple editors via community extensions or plugins.
+
+- [IntelliJ/PyCharm](#intellijpycharm)
+- [IPython](#ipython)
+- [VSCode](#vscode)
+
+## IntelliJ/PyCharm
+
+Use the `File Watchers` plugin to run YAPF against a file when you perform a save.
+
+1.  Install the [File Watchers](https://www.jetbrains.com/help/idea/using-file-watchers.html) Plugin
+1.  Add the following `.idea/watcherTasks.xml` to your project. If you already have this file just add the `TaskOptions` section from below. This example uses Windows and a virtual environment, modify the `program` option as appropriate.
+    ```xml
+    <?xml version="1.0" encoding="UTF-8"?>
+    <project version="4">
+        <component name="ProjectTasksOptions">
+            <TaskOptions isEnabled="true">
+                <option name="arguments" value="-i $FilePathRelativeToProjectRoot$" />
+                <option name="checkSyntaxErrors" value="true" />
+                <option name="description" />
+                <option name="exitCodeBehavior" value="ERROR" />
+                <option name="fileExtension" value="py" />
+                <option name="immediateSync" value="true" />
+                <option name="name" value="yapf" />
+                <option name="output" value="" />
+                <option name="outputFilters">
+                    <array />
+                </option>
+                <option name="outputFromStdout" value="false" />
+                <option name="program" value="$PROJECT_DIR$/.venv/Scripts/yapf.exe" />
+                <option name="runOnExternalChanges" value="true" />
+                <option name="scopeName" value="Project Files" />
+                <option name="trackOnlyRoot" value="false" />
+                <option name="workingDir" value="$Projectpath$" />
+                <envs />
+            </TaskOptions>
+        </component>
+    </project>
+    ```
+
+## IPython
+
+IPython supports formatting lines automatically when you press the `<Enter>` button to submit the current code block.
+
+Make sure that the YAPF module is available to the IPython runtime:
+
+```shell
+pip install ipython yapf
+```
+
+pipx example:
+
+```shell
+pipx install ipython
+pipx inject ipython yapf
+```
+
+Add following to `~/.ipython/profile_default/ipython_config.py`:
+
+```python
+c.TerminalInteractiveShell.autoformatter = 'yapf'
+```
+
+## VSCode
+
+VSCode has deprecated support for YAPF in its official Python extension [in favor of dedicated formatter extensions](https://github.com/microsoft/vscode-python/wiki/Migration-to-Python-Tools-Extensions).
+
+1. Install EeyoreLee's [yapf](https://marketplace.visualstudio.com/items?itemName=eeyore.yapf) extension.
+1. Install the yapf package from pip.
+   ```
+   pip install yapf
+   ```
+1. Add the following to VSCode's `settings.json`:
+   ```jsonc
+   "[python]": {
+       "editor.formatOnSaveMode": "file",
+       "editor.formatOnSave": true,
+       "editor.defaultFormatter": "eeyore.yapf"  # choose this extension
+   },
+   ```
diff --git a/HACKING.md b/HACKING.md
index 7499c86..c970d3c 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -12,45 +12,64 @@ $ PYTHONPATH=$PWD/yapf python -m yapf -i -r .
 $ PYTHONPATH=$PWD/yapf python -m yapf -i $(git diff --name-only @{upstream})
 ```
 
-## Releasing a new version
+## Testing and building redistributables locally
+
+YAPF uses tox 3 to test against multiple python versions and to build redistributables.
 
-- Run tests with Python 3.7 and 3.11:
+Tox will opportunistically use pyenv environments when available.
+To configure pyenv run the following in bash:
 
 ```bash
-$ python setup.py test
+$ xargs -t -n1 pyenv install  < .python-version
 ```
 
-- Bump version in `setup.py`.
-
-- Build source distribution:
+Test against all supported Python versions that are currently installed:
+```bash
+$ pipx run --spec='tox<4' tox
+```
 
+Build and test the sdist and wheel against your default Python environment. The redistributables will be in the `dist` directory.
 ```bash
-$ python setup.py sdist
+$ tox -e bdist_wheel -e sdist
 ```
 
-- Check that it looks OK.
-  - Install it onto a virtualenv,
-  - run tests, and
-  - run yapf as a tool.
+## Releasing a new version
 
-- Build release:
+1. Install all expected pyenv environements
+    ```bash
+    $ xargs -t -n1 pyenv install  < .python-version
+    ```
 
-```bash
-$ python setup.py sdist bdist_wheel
-```
+1. Run tests against Python 3.7 - 3.11 with
+    ```bash
+    $ pipx run --spec='tox<4' tox
+    ```
 
-- Push to PyPI:
+1. Bump version in `pyproject.toml`.
 
-```bash
-$ twine upload dist/*
-```
+1. Build and test redistributables
+
+    ```bash
+    $ pipx run --spec='tox<4' tox -e bdist_wheel -e sdist
+    ```
+
+1. Check that it looks OK.
+   1. Install it onto a virtualenv,
+   1. run tests, and
+   1. run yapf as a tool.
 
-- Test in a clean virtualenv that 'pip install yapf' works with the new
+1. Push to PyPI:
+
+    ```bash
+    $ pipx run twine upload dist/*
+    ```
+
+1. Test in a clean virtualenv that 'pip install yapf' works with the new
   version.
 
-- Commit the version bump and add tag with:
+1. Commit the version bump and add tag with:
 
-```bash
-$ git tag v$(VERSION_NUM)
-$ git push --tags
-```
+    ```bash
+    $ git tag v$(VERSION_NUM)
+    $ git push --tags
+    ```
diff --git a/README.md b/README.md
index bd03fd2..34ee8b0 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,9 @@ optional arguments:
   -vv, --verbose        print out file names while processing
 ```
 
+### Using YAPF within your favorite editor
+YAPF is supported by multiple editors via community extensions or plugins. See [Editor Support](EDITOR%20SUPPORT.md) for more info.
+
 ### Return Codes
 
 Normally YAPF returns zero on successful program termination and non-zero
diff --git a/tox.ini b/tox.ini
index 3fcea7e..ebf2d03 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,19 @@
 [tox]
-envlist=py37,py38,py39,py310
+requires =
+    tox<4
+    tox-pyenv
+    tox-wheel
+envlist = py37,py38,py39,py310,py311
+# tox-wheel alias for `wheel_pep517 = true`
+isolated_build = True
+distshare = ./dist
 
 [testenv]
-commands=
-    python -m unittest discover -p '*_test.py' yapftests/
+wheel = True
+wheel_build_env = bdist_wheel
+commands = python -m unittest discover -p '*_test.py' yapftests/
+
+[testenv:bdist_wheel]
+
+[testenv:sdist]
+wheel = False
diff --git a/yapf/yapflib/format_decision_state.py b/yapf/yapflib/format_decision_state.py
index a0d7033..bc7f977 100644
--- a/yapf/yapflib/format_decision_state.py
+++ b/yapf/yapflib/format_decision_state.py
@@ -27,6 +27,7 @@ through the code to commit the whitespace formatting.
 """
 
 from yapf.pytree import split_penalty
+from yapf.pytree.pytree_utils import NodeName
 from yapf.yapflib import logical_line
 from yapf.yapflib import object_state
 from yapf.yapflib import style
@@ -1101,15 +1102,26 @@ class FormatDecisionState(object):
 
 
 _COMPOUND_STMTS = frozenset({
-    'for', 'while', 'if', 'elif', 'with', 'except', 'def', 'class', 'match',
-    'case'
+    'for',
+    'while',
+    'if',
+    'elif',
+    'with',
+    'except',
+    'def',
+    'class',
 })
 
 
 def _IsCompoundStatement(token):
-  if token.value == 'async':
+  value = token.value
+  if value == 'async':
     token = token.next_token
-  return token.value in _COMPOUND_STMTS
+  if token.value in _COMPOUND_STMTS:
+    return True
+  parent_name = NodeName(token.node.parent)
+  return value == 'match' and parent_name == 'match_stmt' or \
+    value == 'case' and parent_name == 'case_stmt'
 
 
 def _IsFunctionDef(token):
diff --git a/yapf/yapflib/reformatter.py b/yapf/yapflib/reformatter.py
index 319fc9c..ff09525 100644
--- a/yapf/yapflib/reformatter.py
+++ b/yapf/yapflib/reformatter.py
@@ -245,8 +245,13 @@ def _CanPlaceOnSingleLine(line):
   Returns:
     True if the line can or should be added to a single line. False otherwise.
   """
-  token_names = [x.name for x in line.tokens]
-  if (style.Get('FORCE_MULTILINE_DICT') and 'LBRACE' in token_names):
+  token_types = [x.type for x in line.tokens]
+  if (style.Get('SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED') and
+      any(token_types[token_index - 1] == token.COMMA
+          for token_index, token_type in enumerate(token_types[1:], start=1)
+          if token_type == token.RPAR)):
+    return False
+  if (style.Get('FORCE_MULTILINE_DICT') and token.LBRACE in token_types):
     return False
   indent_amt = style.Get('INDENT_WIDTH') * line.depth
   last = line.last


Test patch:
diff --git a/yapftests/reformatter_basic_test.py b/yapftests/reformatter_basic_test.py
index aae46d6..c2200a9 100644
--- a/yapftests/reformatter_basic_test.py
+++ b/yapftests/reformatter_basic_test.py
@@ -2275,6 +2275,8 @@ xxxxxxxxxxx, yyyyyyyyyyyy, vvvvvvvvv)
         a_very_long_function_name(long_argument_name_1, long_argument_name_2, long_argument_name_3, long_argument_name_4,)
 
         r =f0 (1,  2,3,)
+
+        r =f0 (1,)
     """)  # noqa
     expected_formatted_code = textwrap.dedent("""\
         function_name(argument_name_1=1, argument_name_2=2, argument_name_3=3)
@@ -2303,6 +2305,10 @@ xxxxxxxxxxx, yyyyyyyyyyyy, vvvvvvvvv)
             2,
             3,
         )
+
+        r = f0(
+            1,
+        )
     """)
 
     try: