Repository: google/yapf
Pull request #1140 (2023-09-11 03:24:22)

fix trailing backslash stripped cause windows linesep
Fix related issue https://github.com/google/yapf/issues/1139

google-cla[bot]: Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this [failed invocation](https://github.com/google/yapf/pull/1140/checks?check_run_id=16661970932) of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

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/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e3707b0..ed99c16 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,7 +15,7 @@ jobs:
         python-version: ["3.7", "3.8", "3.11"]  # no particular need for 3.9 or 3.10
         os: [macos-latest, ubuntu-latest, windows-latest]
     steps:
-    - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744  # v3.6.0
+    - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac  # v4.0.0
     - name: Set up Python ${{ matrix.python-version }}
       uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1  # v4.6.0
       with:
diff --git a/.github/workflows/pre-commit-autoupdate.yml b/.github/workflows/pre-commit-autoupdate.yml
index 205e782..23eeed1 100644
--- a/.github/workflows/pre-commit-autoupdate.yml
+++ b/.github/workflows/pre-commit-autoupdate.yml
@@ -19,7 +19,7 @@ jobs:
     name: Detect outdated pre-commit hooks
     runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744  # v3.6.0
+      - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac  # v4.0.0
 
       - name: Set up Python 3.11
         uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1  # v4.7.0
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index ed0d802..22097c6 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -19,7 +19,7 @@ jobs:
     name: Run pre-commit
     runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744  # v3.6.0
+      - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac  # v4.0.0
 
       - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1  # v4.7.0
         with:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3248079..53ddc16 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -16,7 +16,7 @@ repos:
         args: [-i]
         types: [python]
   - repo: https://github.com/pycqa/flake8
-    rev: 6.0.0
+    rev: 6.1.0
     hooks:
       - id: flake8
   - repo: https://github.com/pre-commit/pre-commit-hooks
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 73911fb..9beed29 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +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/third_party/yapf_third_party/_ylib2to3/pytree.py b/third_party/yapf_third_party/_ylib2to3/pytree.py
index 0fcdf4b..ea9767b 100644
--- a/third_party/yapf_third_party/_ylib2to3/pytree.py
+++ b/third_party/yapf_third_party/_ylib2to3/pytree.py
@@ -32,7 +32,7 @@ def type_repr(type_num):
     # printing tokens is possible but not as useful
     # from .pgen2 import token // token.__dict__.items():
     for name, val in python_symbols.__dict__.items():
-      if type(val) == int:
+      if isinstance(val, int):
         _type_reprs[val] = name
   return _type_reprs.setdefault(type_num, type_num)
 
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/__init__.py b/yapf/__init__.py
index d6cde95..ebbc758 100644
--- a/yapf/__init__.py
+++ b/yapf/__init__.py
@@ -114,7 +114,7 @@ def main(argv):
 
     try:
       reformatted_source, _ = yapf_api.FormatCode(
-          str('\n'.join(source) + '\n'),
+          str('\n'.join(source).replace('\r\n', '\n') + '\n'),
           filename='<stdin>',
           style_config=style_config,
           lines=lines)
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: