Repository: PyCQA/isort

Issue:
isort introduces SyntaxError with multiline "from a import b as c" plus a comment ending in a parenthesis
```
% cat frimp.py 
from a import (
    b as c,  # comment that is long enough that this import doesn't fit in one line (parens)
)
% isort --diff frimp.py --profile=black
--- /Users/jelle/py/tmp/frimp.py:before	2023-07-09 09:06:19.191799
+++ /Users/jelle/py/tmp/frimp.py:after	2023-07-09 09:08:40.508309
@@ -1,3 +1,3 @@
 from a import (
-    b as c,  # comment that is long enough that this import doesn't fit in one line (parens)
+    b as c,)  # comment that is long enough that this import doesn't fit in one line (parens
 )
```
It incorrectly moves the parenthesis at the end of the comment into the code.

Reproduced on isort 5.12.0. Came up in pycqa/flake8-pyi#411.

Discussion:
staticdev: @bp72 LGTM, do you mind rebasing to current code so we can see checks/pipelines run?
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PyCQA/isort/pull/2184?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PyCQA) Report
> Merging [#2184](https://app.codecov.io/gh/PyCQA/isort/pull/2184?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PyCQA) (5b7d64e) into [main](https://app.codecov.io/gh/PyCQA/isort/commit/9255bcae69aef671f281aa29a7159dd7b840b3d5?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PyCQA) (9255bca) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #2184   +/-   ##
=======================================
  Coverage   99.15%   99.15%           
=======================================
  Files          39       39           
  Lines        3090     3091    +1     
  Branches      748      748           
=======================================
+ Hits         3064     3065    +1     
  Misses         15       15           
  Partials       11       11           
```

</details>

Patch:
diff --git a/isort/parse.py b/isort/parse.py
index 7dfd7cef..2c3c41ef 100644
--- a/isort/parse.py
+++ b/isort/parse.py
@@ -519,7 +519,11 @@ def file_contents(contents: str, config: Config = DEFAULT_CONFIG) -> ParsedConte
                 if comments and attach_comments_to is not None:
                     attach_comments_to.extend(comments)
 
-                if "," in import_string.split(just_imports[-1])[-1]:
+                if (
+                    just_imports
+                    and just_imports[-1]
+                    and "," in import_string.split(just_imports[-1])[-1]
+                ):
                     trailing_commas.add(import_from)
             else:
                 if comments and attach_comments_to is not None:
diff --git a/isort/wrap.py b/isort/wrap.py
index 8904d0ed..119531ad 100644
--- a/isort/wrap.py
+++ b/isort/wrap.py
@@ -122,20 +122,21 @@ def line(content: str, line_separator: str, config: Config = DEFAULT_CONFIG) ->
                             _separator = line_separator
                         else:
                             _separator = ""
-                        _comment = ""
+                        noqa_comment = ""
                         if comment and "noqa" in comment:
-                            _comment = f"{config.comment_prefix}{comment}"
+                            noqa_comment = f"{config.comment_prefix}{comment}"
                             cont_line = cont_line.rstrip()
                             _comma = "," if config.include_trailing_comma else ""
                         output = (
-                            f"{content}{splitter}({_comment}"
+                            f"{content}{splitter}({noqa_comment}"
                             f"{line_separator}{cont_line}{_comma}{_separator})"
                         )
-                    lines = output.split(line_separator)
-                    if config.comment_prefix in lines[-1] and lines[-1].endswith(")"):
-                        content, comment = lines[-1].split(config.comment_prefix, 1)
-                        lines[-1] = content + ")" + config.comment_prefix + comment[:-1]
-                    return line_separator.join(lines)
+                        lines = output.split(line_separator)
+                        if config.comment_prefix in lines[-1] and lines[-1].endswith(")"):
+                            content, comment = lines[-1].split(config.comment_prefix, 1)
+                            lines[-1] = content + ")" + config.comment_prefix + comment[:-1]
+                        output = line_separator.join(lines)
+                    return output
                 return f"{content}{splitter}\\{line_separator}{cont_line}"
     elif len(content) > config.line_length and wrap_mode == Modes.NOQA and "# NOQA" not in content:  # type: ignore
         return f"{content}{config.comment_prefix} NOQA"


Test patch:
diff --git a/tests/unit/test_wrap.py b/tests/unit/test_wrap.py
index 2e35951f..ba378884 100644
--- a/tests/unit/test_wrap.py
+++ b/tests/unit/test_wrap.py
@@ -1,5 +1,8 @@
+import pytest
+
 from isort import wrap
 from isort.settings import Config
+from isort.wrap_modes import WrapModes
 
 
 def test_import_statement():
@@ -16,3 +19,32 @@ def test_import_statement():
     assert wrap.import_statement("from x import ", ["y", "z"], [], explode=True) == (
         "from x import (\n    y,\n    z,\n)"
     )
+
+
+@pytest.mark.parametrize(
+    "multi_line_output, expected",
+    (
+        (
+            WrapModes.VERTICAL_HANGING_INDENT,  # type: ignore
+            """from a import (
+    b as c  # comment that is long enough that this import doesn't fit in one line (parens)
+)""",
+        ),
+        (
+            WrapModes.VERTICAL,  # type: ignore
+            """from a import (
+    b as c)  # comment that is long enough that this import doesn't fit in one line (parens)""",
+        ),
+    ),
+)
+def test_line__comment_with_brackets__expects_unchanged_comment(multi_line_output, expected):
+    content = (
+        "from a import b as c  "
+        "# comment that is long enough that this import doesn't fit in one line (parens)"
+    )
+    config = Config(
+        multi_line_output=multi_line_output,
+        use_parentheses=True,
+    )
+
+    assert wrap.line(content=content, line_separator="\n", config=config) == expected