internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: psf/black

Issue:
cannot parse assignment expression in preview style since 23.1
Hello,

I seem to have found a bug in black's preview style regarding assignment expressions, that has been present since version 23.1.0.

**Describe the bug**

When using an assignment expression in my code example, black with preview=true complains it cannot parse the line. Black preview=false accepts the code happily and leaves no changes. 

**To Reproduce**

Here's my code example:

```python
# file.py
from pydriller import Commit

commits: list[Commit] = []
update_hashes: list[str] = []
upstream_messages: list[str] = []
parsed = [
    {
        "hash": commit.hash,
        "author": f"{commit.author.name} <{commit.author.email}>",
        # black 23.1 --preview can't parse the following line:
        "is_update": (up := commit.hash in update_hashes),
        "is_upstream": up and commit.msg in upstream_messages,
    }
    for commit in commits
]
```

And run it with these arguments:

```sh
$ black file.py --target-version py311 --preview
```

The resulting error is:

> `cannot format file.py: Cannot parse: 12:24:         "is_update": up := commit.hash in update_hashes,`

**Expected behavior**

It should parse the line like it does with preview=false.

Also, look at the error above. The line of code shown doesn't include the parentheses like it does in my source. Without the parens, cpython can't parse it either!

**Environment**

- Black's version: 23.3, also tested on main branch at g839ef35.
- OS and Python version: Linux/Python 3.11.4

**Additional context**

I love you lots <3



Discussion:
Thanks for reporting! I'm guessing we incorrectly remove the parentheses here. Should be an easy fix.
Bisects to 658c8d8d96047c5ba77be4aecc2545a22d5e35b9 (#3440), cc @yilei 

Resolving patch:
diff --git a/src/black/linegen.py b/src/black/linegen.py
--- a/src/black/linegen.py
+++ b/src/black/linegen.py
@@ -242,7 +242,11 @@ def visit_dictsetmaker(self, node: Node) -> Iterator[Line]:
                 if i == 0:
                     continue
                 if node.children[i - 1].type == token.COLON:
-                    if child.type == syms.atom and child.children[0].type == token.LPAR:
+                    if (
+                        child.type == syms.atom
+                        and child.children[0].type == token.LPAR
+                        and not is_walrus_assignment(child)
+                    ):
                         if maybe_make_parens_invisible_in_atom(
                             child,
                             parent=node,


Test patch:
diff --git a/tests/data/cases/walrus_in_dict.py b/tests/data/cases/walrus_in_dict.py
new file mode 100644
--- /dev/null
+++ b/tests/data/cases/walrus_in_dict.py
@@ -0,0 +1,7 @@
+# flags: --preview
+{
+    "is_update": (up := commit.hash in update_hashes)
+}
+
+# output
+{"is_update": (up := commit.hash in update_hashes)}
Repository: psf/black

Issue:
Error on invalid configuration
Currently if you make a typo when configuring Black you don't get an error


Discussion:

Resolving patch:
diff --git a/src/black/__init__.py b/src/black/__init__.py
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -142,6 +142,7 @@ def read_pyproject_toml(
     if not config:
         return None
     else:
+        spellcheck_pyproject_toml_keys(ctx, list(config), value)
         # Sanitize the values to be Click friendly. For more information please see:
         # https://github.com/psf/black/issues/1458
         # https://github.com/pallets/click/issues/1567
@@ -181,6 +182,22 @@ def read_pyproject_toml(
     return value
 
 
+def spellcheck_pyproject_toml_keys(
+    ctx: click.Context, config_keys: List[str], config_file_path: str
+) -> None:
+    invalid_keys: List[str] = []
+    available_config_options = {param.name for param in ctx.command.params}
+    for key in config_keys:
+        if key not in available_config_options:
+            invalid_keys.append(key)
+    if invalid_keys:
+        keys_str = ", ".join(map(repr, invalid_keys))
+        out(
+            f"Invalid config keys detected: {keys_str} (in {config_file_path})",
+            fg="red",
+        )
+
+
 def target_version_option_callback(
     c: click.Context, p: Union[click.Option, click.Parameter], v: Tuple[str, ...]
 ) -> List[TargetVersion]:


Test patch:
diff --git a/tests/data/incorrect_spelling.toml b/tests/data/incorrect_spelling.toml
new file mode 100644
--- /dev/null
+++ b/tests/data/incorrect_spelling.toml
@@ -0,0 +1,5 @@
+[tool.black]
+ine_length = 50
+target-ersion = ['py37']
+exclude='\.pyi?$'
+include='\.py?$'
\ No newline at end of file
diff --git a/tests/test_black.py b/tests/test_black.py
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -106,6 +106,7 @@ class FakeContext(click.Context):
     def __init__(self) -> None:
         self.default_map: Dict[str, Any] = {}
         self.params: Dict[str, Any] = {}
+        self.command: click.Command = black.main
         # Dummy root, since most of the tests don't care about it
         self.obj: Dict[str, Any] = {"root": PROJECT_ROOT}
 
@@ -1538,6 +1539,22 @@ def test_parse_pyproject_toml(self) -> None:
         self.assertEqual(config["exclude"], r"\.pyi?$")
         self.assertEqual(config["include"], r"\.py?$")
 
+    def test_spellcheck_pyproject_toml(self) -> None:
+        test_toml_file = THIS_DIR / "data" / "incorrect_spelling.toml"
+        result = BlackRunner().invoke(
+            black.main,
+            [
+                "--code=print('hello world')",
+                "--verbose",
+                f"--config={str(test_toml_file)}",
+            ],
+        )
+
+        assert (
+            r"Invalid config keys detected: 'ine_length', 'target_ersion' (in"
+            rf" {test_toml_file})" in result.stderr
+        )
+
     def test_parse_pyproject_toml_project_metadata(self) -> None:
         for test_toml, expected in [
             ("only_black_pyproject.toml", ["py310"]),
Repository: psf/black

Issue:
assertion with multi-line string needlessly spans multiple lines
**Describe the bug**

When an `assert` statement has a multi-line string, the condition is split across 3 lines for no reason.

**To Reproduce**

For example, take this code:

```python
assert some_var == expected_result, f"""
expected: {expected_result}
actual: {some_var}"""
```

And run it with these arguments:

```sh
$ black file.py
```

The resulting output is:

```py
assert (
    some_var == expected_result
), f"""
expected: {expected_result}
actual: {some_var}"""
```

**Expected behavior**

The condition should remain as a single line.

**Environment**

- Black's version: [@ed770b](https://github.com/psf/black/commit/ed770b)
- OS and Python version: Whatever https://black.vercel.app uses



Discussion:
Would not be marginally cleaner to re-format it to:

```
assert (
    some_var == expected_result,
    f"""expected: {expected_result}
    actual: {some_var}"""
)
> Would not be marginally cleaner to re-format it to:
> 
> ```
> assert (
>     some_var == expected_result,
>     f"""expected: {expected_result}
>     actual: {some_var}"""
> )
> ```

No, because that would change the meaning of the code (and make the assertion useless).

Resolving patch:
diff --git a/src/black/lines.py b/src/black/lines.py
--- a/src/black/lines.py
+++ b/src/black/lines.py
@@ -858,11 +858,13 @@ def is_line_short_enough(  # noqa: C901
                     return False
 
         if leaf.bracket_depth <= max_level_to_update and leaf.type == token.COMMA:
-            # Ignore non-nested trailing comma
+            # Inside brackets, ignore trailing comma
             # directly after MLS/MLS-containing expression
             ignore_ctxs: List[Optional[LN]] = [None]
             ignore_ctxs += multiline_string_contexts
-            if not (leaf.prev_sibling in ignore_ctxs and i == len(line.leaves) - 1):
+            if (line.inside_brackets or leaf.bracket_depth > 0) and (
+                i != len(line.leaves) - 1 or leaf.prev_sibling not in ignore_ctxs
+            ):
                 commas[leaf.bracket_depth] += 1
         if max_level_to_update != math.inf:
             max_level_to_update = min(max_level_to_update, leaf.bracket_depth)


Test patch:
diff --git a/tests/data/cases/preview_multiline_strings.py b/tests/data/cases/preview_multiline_strings.py
--- a/tests/data/cases/preview_multiline_strings.py
+++ b/tests/data/cases/preview_multiline_strings.py
@@ -175,6 +175,13 @@ def dastardly_default_value(
     "c"
 )
 
+assert some_var == expected_result, """
+test
+"""
+assert some_var == expected_result, f"""
+expected: {expected_result}
+actual: {some_var}"""
+
 # output
 """cow
 say""",
@@ -385,3 +392,10 @@ def dastardly_default_value(
 )
 
 this_will_also_become_one_line = "abc"  # comment
+
+assert some_var == expected_result, """
+test
+"""
+assert some_var == expected_result, f"""
+expected: {expected_result}
+actual: {some_var}"""
Repository: psf/black

Issue:
Fix AST safety check false negative
Fixes #4268

Previously we would allow whitespace changes in all strings, now
only in docstrings.



Discussion:
**diff-shades** reports zero changes comparing this PR (2a6507797132d0bfa16de632fc0048f281a41dc8) to main (f03ee113c9f3dfeb477f2d4247bfb7de2e5f465c).

---

[**What is this?**](https://black.readthedocs.io/en/latest/contributing/gauging_changes.html#diff-shades) | [Workflow run](https://github.com/psf/black/actions/runs/8218647963) | [diff-shades documentation](https://github.com/ichard26/diff-shades#readme)
Seems like we got unlucky and someone added 3.12+ syntax to a diff-shades project just two hours ago (https://github.com/koaning/scikit-lego/commit/64485a9d99a24267a25a57dbd66214796d80b70a#diff-db41f509a7991f7b7579a72fe7bdba315b5ab82bdde2f237c6a53d03396c0081R97 line 97).

Resolving patch:
diff --git a/src/black/parsing.py b/src/black/parsing.py
--- a/src/black/parsing.py
+++ b/src/black/parsing.py
@@ -223,11 +223,9 @@ def _stringify_ast(node: ast.AST, parent_stack: List[ast.AST]) -> Iterator[str]:
                 and field == "value"
                 and isinstance(value, str)
                 and len(parent_stack) >= 2
+                # Any standalone string, ideally this would
+                # exactly match black.nodes.is_docstring
                 and isinstance(parent_stack[-1], ast.Expr)
-                and isinstance(
-                    parent_stack[-2],
-                    (ast.FunctionDef, ast.AsyncFunctionDef, ast.Module, ast.ClassDef),
-                )
             ):
                 # Constant strings may be indented across newlines, if they are
                 # docstrings; fold spaces after newlines when comparing. Similarly,


Test patch:
diff --git a/tests/test_black.py b/tests/test_black.py
--- a/tests/test_black.py
+++ b/tests/test_black.py
@@ -2908,6 +2908,22 @@ async def f():
                 """docstring"""
             ''',
         )
+        self.check_ast_equivalence(
+            """
+            if __name__ == "__main__":
+                "  docstring-like  "
+            """,
+            '''
+            if __name__ == "__main__":
+                """docstring-like"""
+            ''',
+        )
+        self.check_ast_equivalence(r'def f(): r" \n "', r'def f(): "\\n"')
+        self.check_ast_equivalence('try: pass\nexcept: " x "', 'try: pass\nexcept: "x"')
+
+        self.check_ast_equivalence(
+            'def foo(): return " x "', 'def foo(): return "x"', should_fail=True
+        )
 
     def test_assert_equivalent_fstring(self) -> None:
         major, minor = sys.version_info[:2]
Repository: psf/black

Issue:
Create URL links to actual PRs rather than simply referencing the PR number
The change log is immensely useful, however it makes reference to specific Github PRs and only mentions the PR number without actually linking to the issue.

I would like for the changelog to actually include links to the issue. It would be of great help to readers to be able to see the contextual discussion for a change, particularly for style changes.

https://black.readthedocs.io/en/stable/change_log.html



Discussion:
That would be very useful; there's probably something we can do in Sphinx to transform the references to links. Contributions welcome!

Note the links are to PRs, not issues.
I've implemented this, but it requires https://github.com/executablebooks/MyST-Parser/pull/887, so waiting on that.

Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,10 +13,13 @@
 #
 
 import os
+import re
 import string
 from importlib.metadata import version
 from pathlib import Path
 
+from sphinx.application import Sphinx
+
 CURRENT_DIR = Path(__file__).parent
 
 
@@ -29,6 +32,36 @@ def make_pypi_svg(version: str) -> None:
         f.write(svg)
 
 
+def replace_pr_numbers_with_links(content: str) -> str:
+    """Replaces all PR numbers with the corresponding GitHub link."""
+
+    base_url = "https://github.com/psf/black/pull/"
+    pr_num_regex = re.compile(r"\(#(\d+)\)")
+
+    def num_to_link(match: re.Match[str]) -> str:
+        number = match.group(1)
+        url = f"{base_url}{number}"
+        return f"([#{number}]({url}))"
+
+    return pr_num_regex.sub(num_to_link, content)
+
+
+def handle_include_read(
+    app: Sphinx,
+    relative_path: Path,
+    parent_docname: str,
+    content: list[str],
+) -> None:
+    """Handler for the include-read sphinx event."""
+    if parent_docname == "change_log":
+        content[0] = replace_pr_numbers_with_links(content[0])
+
+
+def setup(app: Sphinx) -> None:
+    """Sets up a minimal sphinx extension."""
+    app.connect("include-read", handle_include_read)
+
+
 # Necessary so Click doesn't hit an encode error when called by
 # sphinxcontrib-programoutput on Windows.
 os.putenv("pythonioencoding", "utf-8")


Test patch:
Repository: napari/napari

Issue:
cmap vs colormap on a layer
## ❓ Questions and Help

As initially posed in #89 - both `cmap` and `colormap` exist as properties on a layer, but have slightly different setters. It's not clear to me what the difference is or why we need both. If possible it would be nice to eliminate one. Maybe @kne42 has the answer?


Discussion:
`colormap` is simply an alias to `cmap` – since I'd assume that this is a pretty standard abbreviation we can just get rid of `colormap`
i'm fine to get rid of `colormap` and just have `cmap`, can you make a PR @kne42? 
Do we also want to rename `colormaps` to `cmaps` to be more consistent or is that fine?
I would rename too

Resolving patch:
diff --git a/napari/layers/_image_layer/model.py b/napari/layers/_image_layer/model.py
--- a/napari/layers/_image_layer/model.py
+++ b/napari/layers/_image_layer/model.py
@@ -78,7 +78,7 @@ class Image(Layer):
     """
     _colormaps = AVAILABLE_COLORMAPS
 
-    default_cmap = 'magma'
+    default_colormap = 'magma'
     default_interpolation = 'nearest'
 
     def __init__(self, image, meta=None, multichannel=None, *, name=None, **kwargs):
@@ -97,8 +97,8 @@ def __init__(self, image, meta=None, multichannel=None, *, name=None, **kwargs):
 
         self._image = image
         self._meta = meta
-        self.cmap = Image.default_cmap
-        self.interpolation = Image.default_interpolation
+        self.colormap = self.default_colormap
+        self.interpolation = self.default_interpolation
         self._interpolation_names = interpolation_names
 
         # update flags
@@ -247,18 +247,23 @@ def interpolation_index(self, interpolation_index):
     def colormap(self):
         """string or ColorMap: Colormap to use for luminance images.
         """
-        return self.cmap
+        return self._node.cmap
 
     @colormap.setter
     def colormap(self, colormap):
-        self.cmap = colormap
+        try:
+            cmap = self._colormaps[colormap]
+        except KeyError:
+            pass
+
+        self._node.cmap = cmap
         self.events.colormap()
 
     @property
     def colormaps(self):
         """tuple of str: names of available colormaps.
         """
-        return tuple(AVAILABLE_COLORMAPS.keys())
+        return tuple(self._colormaps.keys())
 
     # wrap visual properties:
     @property
@@ -275,21 +280,6 @@ def clim(self, clim):
         self._node.clim = clim
         self.events.clim()
 
-    @property
-    def cmap(self):
-        """string or ColorMap: Colormap to use for luminance images.
-        """
-        return self._node.cmap
-
-    @cmap.setter
-    def cmap(self, cmap):
-        try:
-            cmap = Image._colormaps[cmap]
-        except KeyError:
-            pass
-
-        self._node.cmap = cmap
-
     @property
     def method(self):
         """string: Selects method of rendering image in case of non-linear


Test patch:
Repository: napari/napari

Issue:
Default layer selection logic
## ❓ Questions and Help

By default, as far as I can tell, all layers are selected as they are added to the viewer. In all of the examples, whenever there is more than one layer, they all appear selected. I think this is unintuitive, and it particular it means that layer reordering feels broken by default (because we need to click to select first, and only then can we reorder).

I think the selection should be *empty* before any clicks. Does anyone feel differently? Was this a conscious design choice? Sorry if I am behind the curve here.


Discussion:
Agreed, wasn't really a conscious design choice, was just sort of the way it worked out and we havn't fixed.

How about when you add a new layer that layer is selected and all the others become unselected. That seems most intuitive to me.

Resolving patch:
diff --git a/napari/components/_viewer/model.py b/napari/components/_viewer/model.py
--- a/napari/components/_viewer/model.py
+++ b/napari/components/_viewer/model.py
@@ -287,6 +287,8 @@ def add_layer(self, layer):
         if len(self.layers) == 1:
             self.reset_view()
 
+        self.layers.unselect_all(ignore=layer)
+
     def _new_markers(self):
         if self.dims.ndim == 0:
             empty_markers = np.empty((0, 2))


Test patch:
Repository: napari/napari

Issue:
blending mode update error
## 🐛 Bug

When viewing multiple layers with blending, I am experiencing a bug whereby changing the blending mode doesn't result in an immediate update. The update does occur when I change the opacity (at which point is happens immediately). 

![bug](https://user-images.githubusercontent.com/3387500/55253093-aa80cc00-5211-11e9-828c-686595346b86.gif)


## To Reproduce

Steps to reproduce the behavior:

1. Open the viewer with multiple layers (e.g. `examples/layers.py`)
2. Reduce the opacity of the top most layer to 0.5
3. Change the blending mode (e.g. `translucent` -> `opaque`)

## Expected behavior

The update to what is rendered should happen immediately upon updating the blending mode.

## Environment

 - napari 0.18
 - OS X 10.14.3
 - Python version: 3.7.2



Discussion:

Resolving patch:
diff --git a/napari/layers/_base_layer/_visual_wrapper.py b/napari/layers/_base_layer/_visual_wrapper.py
--- a/napari/layers/_base_layer/_visual_wrapper.py
+++ b/napari/layers/_base_layer/_visual_wrapper.py
@@ -124,6 +124,7 @@ def blending(self, blending):
                              f'got {blending}')
         self._node.set_gl_state(blending)
         self._blending = blending
+        self._node.update()
         self.events.blending()
 
     @property


Test patch:
Repository: napari/napari

Issue:
Clims cannot be set to integer values
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->

Clims cannot be set to integer values

## To Reproduce

Steps to reproduce the behavior:

```python
from napari import Window, Viewer
viewer = Viewer()
window = Window(viewer)
viewer.add_image(data.camera())
viewer.layers[0].clim = [0, 255]

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-4d36bc0c2b58> in <module>()
----> 1 viewer.layers[0].clim = [0, 255]

~/Github/napari/napari/layers/_image_layer/model.py in clim(self, clim)
    265     @clim.setter
    266     def clim(self, clim):
--> 267         self._clim_msg = f'{clim[0]: 0.3}, {clim[1]: 0.3}'
    268         self.status = self._clim_msg
    269         self._node.clim = clim

ValueError: Precision not allowed in integer format specifier
```

## Expected behavior

This should be allowed. The problem is due to how we print the status bar, see #93 for a discussion around that. Resolving #93 should resolve this bug too.

## Environment

 - napari Version (e.g., 1.0): master
 - OS (e.g., Linux): OSX
 - Python version: 3.6.5
 - Any other relevant information:

## Additional context

<!-- Add any other context about the problem here. -->



Discussion:
Yeah I guess we need a function here rather than relying on format strings.

Resolving patch:
diff --git a/examples/add_image.py b/examples/add_image.py
--- a/examples/add_image.py
+++ b/examples/add_image.py
@@ -40,7 +40,7 @@
 
     # change the layer colormap and color limits
     layer.colormap = 'gray'
-    layer.clim = (0.1, 0.9)
+    layer.clim = (0, 0.9)
 
     # change the layer interpolation mode
     layer.interpolation = 'bicubic'
diff --git a/napari/layers/_image_layer/model.py b/napari/layers/_image_layer/model.py
--- a/napari/layers/_image_layer/model.py
+++ b/napari/layers/_image_layer/model.py
@@ -275,7 +275,7 @@ def clim(self):
 
     @clim.setter
     def clim(self, clim):
-        self._clim_msg = f'{clim[0]: 0.3}, {clim[1]: 0.3}'
+        self._clim_msg = f'{float(clim[0]): 0.3}, {float(clim[1]): 0.3}'
         self.status = self._clim_msg
         self._node.clim = clim
         self.events.clim()


Test patch: