dyyyyyyyy/swe-rebench-filtered-1150 huggingface dataset:
task: metadata: install: pip install -e .[dev]
patch: diff --git a/add_trailing_comma/_plugins/literals.py b/add_trailing_comma/_plugins/literals.py
index c5771be..53bdcf6 100644
--- a/add_trailing_comma/_plugins/literals.py
+++ b/add_trailing_comma/_plugins/literals.py
@@ -26,12 +26,11 @@ def _fix_literal(
         *,
         one_el_tuple: bool,
 ) -> None:
-    if tokens[i].src in START_BRACES:  # pragma: no branch (<py38)
-        fix_brace(
-            tokens, find_simple(i, tokens),
-            add_comma=True,
-            remove_comma=not one_el_tuple,
-        )
+    fix_brace(
+        tokens, find_simple(i, tokens),
+        add_comma=True,
+        remove_comma=not one_el_tuple,
+    )
 
 
 @register(ast.Set)
@@ -90,6 +89,27 @@ def _fix_tuple(
     )
 
 
+def _fix_tuple_py38(
+        i: int,
+        tokens: List[Token],
+        *,
+        one_el_tuple: bool,
+) -> None:  # pragma: no cover (<py38)
+    if tokens[i].src in START_BRACES:
+        fix = find_simple(i, tokens)
+
+        # for tuples we *must* find a comma, otherwise it is not a tuple
+        if fix is None or not fix.multi_arg:
+            return
+
+        fix_brace(
+            tokens,
+            fix,
+            add_comma=True,
+            remove_comma=not one_el_tuple,
+        )
+
+
 @register(ast.Tuple)
 def visit_Tuple(
         state: State,
@@ -105,5 +125,5 @@ def visit_Tuple(
             func = functools.partial(_fix_tuple, one_el_tuple=is_one_el)
             yield ast_to_offset(node), func
         else:  # pragma: no cover (py38+)
-            func = functools.partial(_fix_literal, one_el_tuple=is_one_el)
+            func = functools.partial(_fix_tuple_py38, one_el_tuple=is_one_el)
             yield ast_to_offset(node), func

problem_statement: Tool may change variables from type `T` to `tuple[T]`
Hey, I found this while using this as a pre-commit hook (big fan of the the project & your tools btw! :)).

It seems the tool may change turn a type into a tuple[type] in a situation like this;
```py
x = (
    object  # < comma is added here
), object
```
repo: asottile/add-trailing-comma
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/features/literals_test.py b/tests/features/literals_test.py
index 74f543e..f5dda44 100644
--- a/tests/features/literals_test.py
+++ b/tests/features/literals_test.py
@@ -15,6 +15,12 @@ from add_trailing_comma._main import _fix_src
         '    pass\n'
         '[x] = {y}',
         pytest.param('x[1, 2, 3, 4]', id='multi-slice'),
+        pytest.param(
+            'x = (\n'
+            '    object\n'
+            '), object\n',
+            id='regression test for #153',
+        ),
     ),
 )
 def test_noop_literals(src):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/add_trailing_comma.py b/add_trailing_comma.py
index 0f86212..2884adf 100644
--- a/add_trailing_comma.py
+++ b/add_trailing_comma.py
@@ -271,7 +271,7 @@ def _fix_brace(fix_data, add_comma, tokens):
         indents = []
         insert_indents = []
         for i in range(first_brace + 3, last_brace):
-            if tokens[i - 1].name == 'NL':
+            if tokens[i - 1].name == 'NL' and tokens[i].name != 'NL':
                 if tokens[i].name != UNIMPORTANT_WS:
                     min_indent = 0
                     insert_indents.append(i)

problem_statement: Blank lines may be considered as "minimum" indentation while unhugging
They should be ignored, this currently introduces trailing whitespace:

```python
x('foo', (
    'bar',

    'baz',
))
```
repo: asottile/add-trailing-comma
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/add_trailing_comma_test.py b/tests/add_trailing_comma_test.py
index b8b6f73..1cd26c9 100644
--- a/tests/add_trailing_comma_test.py
+++ b/tests/add_trailing_comma_test.py
@@ -473,6 +473,22 @@ def test_noop_unhugs(src):
             '    "bar"\n'
             ')',
         ),
+        # Regression test for #17
+        (
+            'x("foo", (\n'
+            '    "bar",\n'
+            '\n'
+            '    "baz",\n'
+            '))',
+
+            'x(\n'
+            '    "foo", (\n'
+            '        "bar",\n'
+            '\n'
+            '        "baz",\n'
+            '    ),\n'
+            ')',
+        ),
     ),
 )
 def test_fix_unhugs(src, expected):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/all_repos/list_repos.py b/all_repos/list_repos.py
index 470c4f7..f365192 100644
--- a/all_repos/list_repos.py
+++ b/all_repos/list_repos.py
@@ -1,4 +1,5 @@
 import argparse
+import os
 from typing import Optional
 from typing import Sequence
 
@@ -12,11 +13,15 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
         usage='all-repos-list-repos [options]',
     )
     cli.add_common_args(parser)
+    cli.add_output_paths_arg(parser)
     args = parser.parse_args(argv)
 
     config = load_config(args.config_filename)
     for repo in config.get_cloned_repos():
-        print(repo)
+        if args.output_paths:
+            print(os.path.join(config.output_dir, repo))
+        else:
+            print(repo)
     return 0
 
 

problem_statement: `all-repos-list-repos`: add `--output-paths`
The current output is a little clunky when trying to chain with xargs:

```console
$ all-repos-list-repos | tail -5
Yelp/docker-push-latest-if-changed
Yelp/requirements-tools
Yelp/venv-update
Yelp/wsgi-mod-rpaf
Yelp/yelp_cheetah
```

For instance:

```console
$ all-repos-list-repos | tail -5 | xargs --replace bash -c 'echo -n {}" " && git -C repos-asottile/{} rev-parse HEAD'
Yelp/docker-push-latest-if-changed 1d481bbbb30f1aa164bd965ba33ef61cbb11981c
Yelp/requirements-tools f94e0eb774bb4e37a58e98d5adbbe65a5520b8ef
Yelp/venv-update 02860446c983f8df10db221d66e22a7a912a550c
Yelp/wsgi-mod-rpaf d28a42fff8c77e5480bd6c166e4e53c2d308e81b
Yelp/yelp_cheetah 61ff00fd8944f19bc81b3f03801c322fc339ffeb
```

It would be nicer if there were this output:

```console
$ all-repos-list-repos --output-paths | tail -5
repos-asottile/Yelp/docker-push-latest-if-changed
repos-asottile/Yelp/requirements-tools
repos-asottile/Yelp/venv-update
repos-asottile/Yelp/wsgi-mod-rpaf
repos-asottile/Yelp/yelp_cheetah
```
repo: asottile/all-repos
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/list_repos_test.py b/tests/list_repos_test.py
index bb97023..87d5a81 100644
--- a/tests/list_repos_test.py
+++ b/tests/list_repos_test.py
@@ -5,3 +5,15 @@ def test_list_repos_main(file_config_files, capsys):
     assert not main(('--config-filename', str(file_config_files.cfg)))
     out, _ = capsys.readouterr()
     assert out == 'repo1\nrepo2\n'
+
+
+def test_list_repos_with_output_paths(file_config_files, capsys):
+    assert not main((
+        '--config-filename', str(file_config_files.cfg),
+        '--output-paths',
+    ))
+    out, _ = capsys.readouterr()
+    assert out == '{}\n{}\n'.format(
+        file_config_files.output_dir.join('repo1'),
+        file_config_files.output_dir.join('repo2'),
+    )
task: metadata: install: pip install -e .[dev]
patch: diff --git a/babi/linters/pre_commit.py b/babi/linters/pre_commit.py
index d5ffc5c..380608b 100644
--- a/babi/linters/pre_commit.py
+++ b/babi/linters/pre_commit.py
@@ -63,10 +63,16 @@ class PreCommit:
             return None  # not in a git repo!
 
         # no pre-commit config!
-        if not os.path.exists(os.path.join(root, '.pre-commit-config.yaml')):
+        cfg = os.path.join(root, '.pre-commit-config.yaml')
+        if not os.path.exists(cfg):
             return None
 
-        return ('pre-commit', 'run', '--color=never', '--files', filename)
+        return (
+            'pre-commit', 'run',
+            '--color=never',
+            '--config', cfg,
+            '--files', filename,
+        )
 
     def parse(self, filename: str, output: str) -> tuple[linting.Error, ...]:
         root = self._root(filename)

problem_statement: pre-commit runs with the wrong configuration when accessing a file in a different repository
went through all the trouble to check the right config exists here: https://github.com/asottile/babi/blob/5cf5f2501c90274e7f640ff0ad4dfb355631b960/babi/linters/pre_commit.py#L66

but then didn't bother actually using it here: https://github.com/asottile/babi/blob/5cf5f2501c90274e7f640ff0ad4dfb355631b960/babi/linters/pre_commit.py#L69
repo: asottile/babi
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/linters/pre_commit_test.py b/tests/linters/pre_commit_test.py
index 6fdf20a..7fa7781 100644
--- a/tests/linters/pre_commit_test.py
+++ b/tests/linters/pre_commit_test.py
@@ -96,10 +96,16 @@ def test_command_returns_none_no_pre_commit_config(tmpdir_git):
 
 
 def test_command_returns_when_config_exists(tmpdir_git):
-    tmpdir_git.join('.pre-commit-config.yaml').write('{}\n')
+    cfg = tmpdir_git.join('.pre-commit-config.yaml')
+    cfg.write('{}\n')
     path = str(tmpdir_git.join('t.py'))
     ret = PreCommit().command(path, 'source.python')
-    assert ret == ('pre-commit', 'run', '--color=never', '--files', path)
+    assert ret == (
+        'pre-commit', 'run',
+        '--color=never',
+        '--config', str(cfg),
+        '--files', path,
+    )
 
 
 def test_filters_file_paths_to_actual_file(tmpdir_git):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/dead.py b/dead.py
index 5464817..17fb034 100644
--- a/dead.py
+++ b/dead.py
@@ -72,6 +72,17 @@ class Visitor(ast.NodeVisitor):
         finally:
             self.previous_scopes.append(self.scopes.pop())
 
+    @contextlib.contextmanager
+    def root_scope_for_class_body(self) -> Generator[None]:
+        # classes "sort of" have a scope -- but more commonly they will be
+        # returned outside of their current scope and have their attributes
+        # referenced rather than have their attributes referenced inline
+        self.scopes.append(self.scopes[0])
+        try:
+            yield
+        finally:
+            self.scopes.pop()
+
     def _file_line(self, filename: str, line: int) -> FileLine:
         return FileLine(f'{filename}:{line}')
 
@@ -104,7 +115,10 @@ class Visitor(ast.NodeVisitor):
 
     def visit_ClassDef(self, node: ast.ClassDef) -> None:
         self.define(node.name, node)
-        self.generic_visit(node)
+
+        with self.root_scope_for_class_body():
+            self.generic_visit(node)
+
         # this is a bad middle ground to handle TypedDict and related classes
         # simply mark any annotated assignment directly in a class body as
         # "used"

problem_statement: does not understand methods of returned classes
a bit trickier since the scope target isn't quite right here?

```python
def f():
    class C:
        def handle(self): ...
    return C

f().handle()
```

```console
$ dead
handle is never read, defined in t.py:3
```
repo: asottile/dead
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/dead_test.py b/tests/dead_test.py
index 48c292d..96cee8f 100644
--- a/tests/dead_test.py
+++ b/tests/dead_test.py
@@ -340,6 +340,20 @@ f()
     assert not dead.main(())
 
 
+def test_class_methods_in_closure(git_dir):
+    src = '''\
+def f():
+    class C:
+        def handle(self): ...
+    return C
+
+f().handle()
+'''
+    git_dir.join('f.py').write(src)
+    subprocess.check_call(('git', 'add', '.'))
+    assert not dead.main(())
+
+
 def test_allowed_symbols_file(git_dir, tmp_path, capsys):
     allowed = tmp_path.joinpath('allowed')
     allowed.write_text('unused_function\n')
task: metadata: install: pip install -e .[dev]
patch: diff --git a/pyupgrade.py b/pyupgrade.py
index b67cbf7..b53cf3d 100644
--- a/pyupgrade.py
+++ b/pyupgrade.py
@@ -551,8 +551,8 @@ def _fix_extraneous_parens(tokens, i):
     depth = 1
     while depth:
         i += 1
-        # found comma at depth 1: this is a tuple
-        if depth == 1 and tokens[i].src == ',':
+        # found comma or yield at depth 1: this is a tuple / coroutine
+        if depth == 1 and tokens[i].src in {',', 'yield'}:
             return
         elif tokens[i].src in OPENING:
             depth += 1

problem_statement: Remove necessary extra parens from coroutine yield expression
Currently this is happening, but it causes a `SyntaxError` -- the extra set of parens is necessary here:

```diff
 def run_tests():
     url = options.url + '/getCaseCount'
     control_ws = yield websocket_connect(url, None)
-    num_tests = int((yield control_ws.read_message()))
+    num_tests = int(yield control_ws.read_message())
```
repo: asottile/pyupgrade
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/pyupgrade_test.py b/tests/pyupgrade_test.py
index 9ab97d3..be62291 100644
--- a/tests/pyupgrade_test.py
+++ b/tests/pyupgrade_test.py
@@ -513,6 +513,9 @@ def test_fix_octal_literal(s, expected):
         'print((\n))',
         # don't touch parenthesized generators
         'sum((block.code for block in blocks), [])',
+        # don't touch coroutine yields
+        'def f():\n'
+        '    x = int((yield 1))\n',
     ),
 )
 def test_fix_extra_parens_noop(s):
@@ -545,6 +548,15 @@ def test_fix_extra_parens_noop(s):
             '        "foo"\n'
             ')\n',
         ),
+        pytest.param(
+            'def f():\n'
+            '    x = int(((yield 1)))\n',
+
+            'def f():\n'
+            '    x = int((yield 1))\n',
+
+            id='extra parens on coroutines are instead reduced to 2',
+        ),
     ),
 )
 def test_fix_extra_parens(s, expected):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/README.md b/README.md
index eeb1a5f..7a7a469 100644
--- a/README.md
+++ b/README.md
@@ -331,6 +331,11 @@ six.get_function_globals(fn)            # fn.__globals__
 six.assertCountEqual(self, a1, a2)      # self.assertCountEqual(a1, a2)
 six.assertRaisesRegex(self, e, r, fn)   # self.assertRaisesRegex(e, r, fn)
 six.assertRegex(self, s, r)             # self.assertRegex(s, r)
+
+# note: only for *literals*
+six.ensure_binary('...')                # b'...'
+six.ensure_str('...')                   # '...'
+six.ensure_text('...')                  # '...'
 ```
 
 ### `open` alias
diff --git a/pyupgrade.py b/pyupgrade.py
index 07ed723..d110895 100644
--- a/pyupgrade.py
+++ b/pyupgrade.py
@@ -1420,7 +1420,7 @@ class FindPy3Plus(ast.NodeVisitor):
             # _is_six() enforces this
             assert isinstance(arg, (ast.Name, ast.Attribute))
             self.six_type_ctx[_ast_to_offset(node.args[1])] = arg
-        elif self._is_six(node.func, ('b',)):
+        elif self._is_six(node.func, ('b', 'ensure_binary')):
             self.six_b.add(_ast_to_offset(node))
         elif self._is_six(node.func, SIX_CALLS) and not _starargs(node):
             self.six_calls[_ast_to_offset(node)] = node
@@ -1457,8 +1457,10 @@ class FindPy3Plus(ast.NodeVisitor):
         ):
             self.super_calls[_ast_to_offset(node)] = node
         elif (
-                isinstance(node.func, ast.Name) and
-                node.func.id == 'str' and
+                (
+                    self._is_six(node.func, ('ensure_str', 'ensure_text')) or
+                    isinstance(node.func, ast.Name) and node.func.id == 'str'
+                ) and
                 not node.keywords and
                 not _starargs(node) and
                 (

problem_statement: six: ensure_str / ensure_binary / ensure_text of a literal string
while we generally can't fix the ensure_* variants, we can for string literals (as we're already doing for `str('...')` for example)
repo: asottile/pyupgrade
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/native_literals_test.py b/tests/native_literals_test.py
index a82820a..7b6c8f0 100644
--- a/tests/native_literals_test.py
+++ b/tests/native_literals_test.py
@@ -27,6 +27,8 @@ def test_fix_native_literals_noop(s):
         ('str()', "''"),
         ('str("foo")', '"foo"'),
         ('str("""\nfoo""")', '"""\nfoo"""'),
+        ('six.ensure_str("foo")', '"foo"'),
+        ('six.ensure_text("foo")', '"foo"'),
     ),
 )
 def test_fix_native_literals(s, expected):
diff --git a/tests/six_test.py b/tests/six_test.py
index f840c3f..83ce558 100644
--- a/tests/six_test.py
+++ b/tests/six_test.py
@@ -98,6 +98,10 @@ def test_fix_six_noop(s):
             r'six.b("\x12\xef")',
             r'b"\x12\xef"',
         ),
+        (
+            'six.ensure_binary("foo")',
+            'b"foo"',
+        ),
         (
             'from six import b\n\n' r'b("\x12\xef")',
             'from six import b\n\n' r'b"\x12\xef"',
task: metadata: install: pip install -e .[dev]
patch: diff --git a/pyupgrade.py b/pyupgrade.py
index c463fcf..54bbe0d 100644
--- a/pyupgrade.py
+++ b/pyupgrade.py
@@ -587,6 +587,11 @@ def _fix_format_literal(tokens: List[Token], end: int) -> None:
     parsed_parts = []
     last_int = -1
     for i in parts:
+        # f'foo {0}'.format(...) would get turned into a SyntaxError
+        prefix, _ = parse_string_literal(tokens[i].src)
+        if 'f' in prefix.lower():
+            return
+
         try:
             parsed = parse_format(tokens[i].src)
         except ValueError:

problem_statement: pyupgrade on f-strings with .format() results in invalid f-string
I understand that this is an edge-case because the input was buggy, but it _does_ convert running code into non-running code.

```
$ cat a.py
print(f"foo {0}".format("bar"))
$ python a.py
foo 0
$ pyupgrade a.py
Rewriting a.py
$ cat a.py
print(f"foo {}".format("bar"))
$ python a.py
  File "a.py", line 1
    print(f"foo {}".format("bar"))
         ^
SyntaxError: f-string: empty expression not allowed
```

```
$ pip freeze | grep pyupgrade
pyupgrade==2.7.0
```

I'm not sure what the right behavior is in this case; maybe just don't touch numbered args inside an f-string?
repo: asottile/pyupgrade
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/format_literals_test.py b/tests/format_literals_test.py
index f3610a1..0719138 100644
--- a/tests/format_literals_test.py
+++ b/tests/format_literals_test.py
@@ -51,6 +51,8 @@ def test_intentionally_not_round_trip(s, expected):
         '("{0}" # {1}\n"{2}").format(1, 2, 3)',
         # TODO: this works by accident (extended escape treated as placeholder)
         r'"\N{snowman} {}".format(1)',
+        # don't touch f-strings (these are wrong but don't make it worse)
+        'f"{0}".format(a)',
     ),
 )
 def test_format_literals_noop(s):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/pyupgrade/_plugins/typing_pep604.py b/pyupgrade/_plugins/typing_pep604.py
index 6ffcc20..8d55009 100644
--- a/pyupgrade/_plugins/typing_pep604.py
+++ b/pyupgrade/_plugins/typing_pep604.py
@@ -126,6 +126,15 @@ def _supported_version(state: State) -> bool:
     )
 
 
+def _any_arg_is_str(node_slice: ast.expr) -> bool:
+    return (
+        isinstance(node_slice, ast.Str) or (
+            isinstance(node_slice, ast.Tuple) and
+            any(isinstance(elt, ast.Str) for elt in node_slice.elts)
+        )
+    )
+
+
 @register(ast.Subscript)
 def visit_Subscript(
         state: State,
@@ -135,6 +144,17 @@ def visit_Subscript(
     if not _supported_version(state):
         return
 
+    # prevent rewriting forward annotations
+    if (
+            (sys.version_info >= (3, 9) and _any_arg_is_str(node.slice)) or
+            (
+                sys.version_info < (3, 9) and
+                isinstance(node.slice, ast.Index) and
+                _any_arg_is_str(node.slice.value)
+            )
+    ):
+        return
+
     if is_name_attr(node.value, state.from_imports, 'typing', ('Optional',)):
         yield ast_to_offset(node), _fix_optional
     elif is_name_attr(node.value, state.from_imports, 'typing', ('Union',)):

problem_statement: Do not upgrade string annotations types wrapped in `Optional` to new Union | formatting
Simplistic python code:

```python
qqq: "int" | None = 0
```

Output:

```
python qqq.py
Traceback (most recent call last):
  File "qqq.py", line 2, in <module>
    qqq: "int" | None = 0
TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'
```

When running pyupgrade a segment of code was updated to use the `|` notation and caused this explosion. I worked around it, but I am sure others might run into similar issues. 

repo: asottile/pyupgrade
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/features/typing_pep604_test.py b/tests/features/typing_pep604_test.py
index 503bc2a..7b734e9 100644
--- a/tests/features/typing_pep604_test.py
+++ b/tests/features/typing_pep604_test.py
@@ -41,6 +41,19 @@ from pyupgrade._main import _fix_plugins
             (3, 10),
             id='3.10+ empty Union',
         ),
+        # https://github.com/asottile/pyupgrade/issues/567
+        pytest.param(
+            'from typing import Optional\n'
+            'def f() -> Optional["str"]: ...\n',
+            (3, 10),
+            id='3.10+ Optional of forward reference',
+        ),
+        pytest.param(
+            'from typing import Union\n'
+            'def f() -> Union[int, "str"]: ...\n',
+            (3, 10),
+            id='3.10+ Union of forward reference',
+        ),
     ),
 )
 def test_fix_pep604_types_noop(s, version):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/pyupgrade/_plugins/six_calls.py b/pyupgrade/_plugins/six_calls.py
index 90c4ee3..ac58fd5 100644
--- a/pyupgrade/_plugins/six_calls.py
+++ b/pyupgrade/_plugins/six_calls.py
@@ -172,13 +172,21 @@ def visit_Call(
                 ('reraise',),
             )
     ):
-        if len(node.args) == 2 and not has_starargs(node):
+        if (
+                len(node.args) == 2 and
+                not node.keywords and
+                not has_starargs(node)
+        ):
             func = functools.partial(
                 find_and_replace_call,
                 template=RERAISE_2_TMPL,
             )
             yield ast_to_offset(node), func
-        elif len(node.args) == 3 and not has_starargs(node):
+        elif (
+                len(node.args) == 3 and
+                not node.keywords and
+                not has_starargs(node)
+        ):
             func = functools.partial(
                 find_and_replace_call,
                 template=RERAISE_3_TMPL,
@@ -186,6 +194,7 @@ def visit_Call(
             yield ast_to_offset(node), func
         elif (
                 len(node.args) == 1 and
+                not node.keywords and
                 isinstance(node.args[0], ast.Starred) and
                 isinstance(node.args[0].value, ast.Call) and
                 is_name_attr(

problem_statement: Incorrect rewrite of six.reraise with traceback as keyword argument
Reduced from real code in Launchpad:

```
$ cat t.py
import sys

from six import reraise

exc_info = sys.exc_info()
reraise(exc_info[0], exc_info[1], tb=exc_info[2])
$ pyupgrade --py3-plus t.py
Rewriting t.py
$ cat t.py
import sys

from six import reraise

exc_info = sys.exc_info()
raise exc_info[1].with_traceback(None)
```

pyupgrade has missed the keyword argument here; this should instead be rewritten to `raise exc_info[1].with_traceback(exc_info[2])`.

(In fact in Python 3 this can end up just being a plain `raise`: the original code was more complicated and had a second possible exception being raised and handled between `sys.exc_info()` and `reraise()`, which in Python 2 would have caused plain `raise` to raise the second exception, but the exception scoping changes in Python 3 mean that a plain `raise` will do the right thing.  I don't expect pyupgrade to do that sort of analysis, though.)
repo: asottile/pyupgrade
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/features/six_test.py b/tests/features/six_test.py
index e1f6cd8..4ea3f5b 100644
--- a/tests/features/six_test.py
+++ b/tests/features/six_test.py
@@ -24,6 +24,7 @@ from pyupgrade._main import _fix_plugins
         'class C(six.with_metaclass(Meta, B), D): pass',
         # cannot determine args to rewrite them
         'six.reraise(*err)', 'six.u(*a)',
+        'six.reraise(a, b, tb=c)',
         'class C(six.with_metaclass(*a)): pass',
         '@six.add_metaclass(*a)\n'
         'class C: pass\n',
task: metadata: install: pip install -e .[dev]
patch: diff --git a/pyupgrade.py b/pyupgrade.py
index d6a196c..928b97e 100644
--- a/pyupgrade.py
+++ b/pyupgrade.py
@@ -437,7 +437,7 @@ def _fix_unicode_literals(contents_text, py3_plus):
 
 # https://docs.python.org/3/reference/lexical_analysis.html
 ESCAPE_STARTS = frozenset((
-    '\n', '\\', "'", '"', 'a', 'b', 'f', 'n', 'r', 't', 'v',
+    '\n', '\r', '\\', "'", '"', 'a', 'b', 'f', 'n', 'r', 't', 'v',
     '0', '1', '2', '3', '4', '5', '6', '7',  # octal escapes
     'x',  # hex escapes
     # only valid in non-bytestrings

problem_statement: pyupgrade is introducing a raw string where a line continuation is being used.
Hi.

The pyupgrade tool is introducing a raw string where a line continuation is being used.

Check this example below:
```python
import textwrap


def test_importerror(tmpdir):
    print(tmpdir)
    p1 = tmpdir.join("test1.txt")
    p2 = tmpdir.join("test2.txt")
    p1.write(
        textwrap.dedent(
            """\
        import doesnotexist

        x = 1
        """
        )
    )
    p2.write(
        textwrap.dedent(
            """
        import doesnotexist

        x = 2
        """
        )
    )

```

after running pyupgrade on this file, a `r"""` is introduced as it's demonstrated above.

```python
def test_importerror(tmpdir):
    print(tmpdir)
    p1 = tmpdir.join("test1.txt")
    p2 = tmpdir.join("test2.txt")
    p1.write(
        textwrap.dedent(
            r"""\
        import doesnotexist

        x = 1
        """
        )
    )
    p2.write(
        textwrap.dedent(
            """
        import doesnotexist

        x = 2
        """
        )
    )
```

I'm running `pyupgrade (1.10.0)` with `python Python 3.6.2` on `Windows 10, version 1709`
repo: asottile/pyupgrade
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/pyupgrade_test.py b/tests/pyupgrade_test.py
index 82acd34..c571357 100644
--- a/tests/pyupgrade_test.py
+++ b/tests/pyupgrade_test.py
@@ -343,6 +343,8 @@ def test_unicode_literals(s, py3_plus, expected):
         '"\\u2603"',
         # don't touch already valid escapes
         r'"\r\n"',
+        # don't touch escaped newlines
+        '"""\\\n"""', '"""\\\r\n"""', '"""\\\r"""',
     ),
 )
 def test_fix_escape_sequences_noop(s):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/setup_cfg_fmt.py b/setup_cfg_fmt.py
index b1967b2..d541a70 100644
--- a/setup_cfg_fmt.py
+++ b/setup_cfg_fmt.py
@@ -398,11 +398,11 @@ def format_file(
         if section not in cfg:
             continue
 
-        new_section = {
-            k: cfg[section].pop(k) for k in key_order if k in cfg[section]
-        }
+        entries = {k.replace('-', '_'): v for k, v in cfg[section].items()}
+
+        new_section = {k: entries.pop(k) for k in key_order if k in entries}
         # sort any remaining keys
-        new_section.update(sorted(cfg[section].items()))
+        new_section.update(sorted(entries.items()))
 
         sections[section] = new_section
         cfg.pop(section)

problem_statement: normalize dashed-keys to underscored_keys
setuptools apparently allows both, but canonically spells them with underscores

found in https://github.com/pfmoore/editables/pull/2
repo: asottile/setup-cfg-fmt
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/setup_cfg_fmt_test.py b/tests/setup_cfg_fmt_test.py
index 6558886..677291b 100644
--- a/tests/setup_cfg_fmt_test.py
+++ b/tests/setup_cfg_fmt_test.py
@@ -192,6 +192,19 @@ def test_rewrite_requires(which, input_tpl, expected_tpl, tmpdir):
 
             id='orders authors and maintainers',
         ),
+        pytest.param(
+            '[metadata]\n'
+            'name = pkg\n'
+            'author-email = john@example.com\n'
+            'maintainer-email = jane@example.com\n',
+
+            '[metadata]\n'
+            'name = pkg\n'
+            'author_email = john@example.com\n'
+            'maintainer_email = jane@example.com\n',
+
+            id='normalize dashes to underscores in keys',
+        ),
     ),
 )
 def test_rewrite(input_s, expected, tmpdir):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/yesqa.py b/yesqa.py
index 008dc57..40cf153 100644
--- a/yesqa.py
+++ b/yesqa.py
@@ -43,14 +43,28 @@ def _remove_comments(tokens):
 
 
 def _rewrite_noqa_comment(tokens, i, flake8_results):
+    # find logical lines that this noqa comment may affect
+    lines = set()
+    j = i
+    while j >= 0 and tokens[j].name not in {'NL', 'NEWLINE'}:
+        t = tokens[j]
+        if t.line is not None:
+            lines.update(range(t.line, t.line + t.src.count('\n') + 1))
+        j -= 1
+
+    lints = set()
+    for line in lines:
+        lints.update(flake8_results[line])
+
     token = tokens[i]
     match = NOQA_RE.match(token.src)
+
     # exclude all lints on the line but no lints
-    if token.line not in flake8_results:
+    if not lints:
         _remove_comment(tokens, i)
     elif match.group().lower() != '# noqa':
         codes = set(SEP_RE.split(match.group(1)[2:]))
-        expected_codes = codes & flake8_results[token.line]
+        expected_codes = codes & lints
         if expected_codes != codes:
             comment = '# noqa: {}'.format(','.join(sorted(expected_codes)))
             tokens[i] = token._replace(src=NOQA_RE.sub(comment, token.src))

problem_statement: False positive: removes `noqa` on multi-line string
```python
"""
aaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
"""  # noqa
```

```console
$ flake8 test.py
$ yesqa test.py
Rewriting test.py
$ flake8 test.py
test.py:2:80: E501 line too long (82 > 79 characters)
```
repo: asottile/yesqa
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/yesqa_test.py b/tests/yesqa_test.py
index e0225c8..9043a86 100644
--- a/tests/yesqa_test.py
+++ b/tests/yesqa_test.py
@@ -32,9 +32,11 @@ def test_non_utf8_bytes(tmpdir, capsys):
     (
         '',  # noop
         '# hello\n',  # comment at beginning of file
-        'import os  # noqa\n',  # still needed
-        'import os  # NOQA\n',  # still needed
-        'import os  # noqa: F401\n',  # still needed
+        # still needed
+        'import os  # noqa\n',
+        'import os  # NOQA\n',
+        'import os  # noqa: F401\n',
+        '"""\n' + 'a' * 40 + ' ' + 'b' * 60 + '\n""" # noqa\n',
     ),
 )
 def test_ok(assert_rewrite, src):
task: metadata: install: pip install -e .[dev]
patch: diff --git a/yesqa.py b/yesqa.py
index 18ad40f..a0a49eb 100644
--- a/yesqa.py
+++ b/yesqa.py
@@ -7,6 +7,7 @@ import sys
 import tempfile
 from typing import Dict
 from typing import List
+from typing import Match
 from typing import Optional
 from typing import Sequence
 from typing import Set
@@ -49,12 +50,24 @@ def _remove_comments(tokens: Tokens) -> Tokens:
     for i, token in tokenize_rt.reversed_enumerate(tokens):
         if token.name == 'COMMENT':
             if NOQA_RE.search(token.src):
-                _rewrite_noqa_comment(tokens, i, collections.defaultdict(set))
+                _mask_noqa_comment(tokens, i)
             elif NOQA_FILE_RE.search(token.src):
                 _remove_comment(tokens, i)
     return tokens
 
 
+def _mask_noqa_comment(tokens: Tokens, i: int) -> None:
+    token = tokens[i]
+    match = NOQA_RE.search(token.src)
+    assert match is not None
+
+    def _sub(match: Match[str]) -> str:
+        return f'# {"."*(len(match.group())-2)}'
+
+    src = NOQA_RE.sub(_sub, token.src)
+    tokens[i] = token._replace(src=src)
+
+
 def _rewrite_noqa_comment(
         tokens: Tokens,
         i: int,

problem_statement: yesqa turns `# noqa: F821,E501` into `# noqa: F821`, but then flake8 reports it
Here's an example:
```console
$ cat t.py 
def foo(w: Sequence[int], x: Sequence[int], y: int, z: int) -> bar: ...  # noqa: F821,E501
$ yesqa t.py 
Rewriting t.py
$ cat t.py 
def foo(w: Sequence[int], x: Sequence[int], y: int, z: int) -> bar: ...  # noqa: F821
$ flake8 t.py 
t.py:1:80: E501 line too long (85 > 79 characters)
```
repo: asottile/yesqa
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/yesqa_test.py b/tests/yesqa_test.py
index 75d1081..b1cb7ef 100644
--- a/tests/yesqa_test.py
+++ b/tests/yesqa_test.py
@@ -45,6 +45,8 @@ def test_non_utf8_bytes(tmpdir, capsys):
         'def f():\n'
         '    # type: () -> ' + 'A' * 65 + '  # noqa\n'
         '    pass\n',
+        'def foo(w: Sequence[int], x: Sequence[int], y: int, z: int) -> bar: ...  # noqa: E501, F821\n',
+        'def foo(w: Sequence[int]) -> bar:  # foobarfoobarfoobarfoobarfoobarfoo   # noqa: E501, F821\n',
     ),
 )
 def test_ok(assert_rewrite, src):
task: metadata: install: pip install -e .[dev_all]
patch: diff --git a/astropy/utils/data.py b/astropy/utils/data.py
index 7473a7157d..8ca7fce2c7 100644
--- a/astropy/utils/data.py
+++ b/astropy/utils/data.py
@@ -384,7 +384,7 @@ def get_readable_fileobj(
             fileobj = io.BytesIO(fileobj.read())
 
     # Now read enough bytes to look at signature
-    signature = fileobj.read(4)
+    signature = fileobj.read(6)
     fileobj.seek(0)
 
     if signature[:3] == b"\x1f\x8b\x08":  # gzip
@@ -426,7 +426,7 @@ def get_readable_fileobj(
             fileobj_new.seek(0)
             close_fds.append(fileobj_new)
             fileobj = fileobj_new
-    elif signature[:3] == b"\xfd7z":  # xz
+    elif signature[:6] == b"\xfd7zXZ\x00":  # xz
         if not HAS_LZMA:
             for fd in close_fds:
                 fd.close()
@@ -438,7 +438,7 @@ def get_readable_fileobj(
         try:
             fileobj_new = lzma.LZMAFile(fileobj, mode="rb")
             fileobj_new.read(1)  # need to check that the file is really xz
-        except (OSError, EOFError):  # invalid xz file
+        except lzma.LZMAError:  # invalid xz file
             fileobj.seek(0)
             fileobj_new.close()
             # should we propagate this to the caller to signal bad content?
diff --git a/docs/changes/utils/17984.bugfix.rst b/docs/changes/utils/17984.bugfix.rst
new file mode 100644
index 0000000000..df606dbeaa
--- /dev/null
+++ b/docs/changes/utils/17984.bugfix.rst
@@ -0,0 +1,1 @@
+Properly detect invalid LZMA files in ``utils.data``.

problem_statement: Invalid LZMA files are not properly checked on utils.data
### Description

While working on #17960 I've noticed the test case for invalid LZMA files is not being done properly. I will provide a PR for this
repo: astropy/astropy
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/astropy/utils/tests/test_data.py b/astropy/utils/tests/test_data.py
index b10a392dc4..3809282697 100644
--- a/astropy/utils/tests/test_data.py
+++ b/astropy/utils/tests/test_data.py
@@ -971,12 +971,13 @@ def test_local_data_obj(filename):
             assert f.read().rstrip() == b"CONTENT"
 
 
-@pytest.fixture(params=["invalid.dat.bz2", "invalid.dat.gz"])
+@pytest.fixture(params=["invalid.dat.bz2", "invalid.dat.xz", "invalid.dat.gz"])
 def bad_compressed(request, tmp_path):
     # These contents have valid headers for their respective file formats, but
     # are otherwise malformed and invalid.
     bz_content = b"BZhinvalid"
     gz_content = b"\x1f\x8b\x08invalid"
+    xz_content = b"\xfd7zXZ\x00invalid"
 
     datafile = tmp_path / request.param
     filename = str(datafile)
@@ -985,6 +986,8 @@ def bad_compressed(request, tmp_path):
         contents = bz_content
     elif filename.endswith(".gz"):
         contents = gz_content
+    elif filename.endswith(".xz"):
+        contents = xz_content
     else:
         contents = "invalid"
task: metadata: install: pip install -e .[all]
patch: diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 7ea20a8..1dab8f1 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,7 @@ Next
 ====
 
 - Fix unneeded error when an operators is not supported by adapter (#378)
+- Fix comparison to empty strings in GSheets (#379)
 
 Version 1.2.6 - 2023-07-20
 ==========================
diff --git a/src/shillelagh/adapters/api/gsheets/fields.py b/src/shillelagh/adapters/api/gsheets/fields.py
index 7db343d..1f24b96 100644
--- a/src/shillelagh/adapters/api/gsheets/fields.py
+++ b/src/shillelagh/adapters/api/gsheets/fields.py
@@ -328,7 +328,7 @@ class GSheetsString(GSheetsField[str, str]):
         return "" if value is None else value
 
     def quote(self, value: Optional[str]) -> str:
-        if value == "" or value is None:
+        if value is None:
             return "null"
 
         return f"'{value}'"

problem_statement: Comparison with empty string throws Invalid query: NO_COLUMN: null
**Describe the bug**
Comparison with empty string throws Invalid query: NO_COLUMN: null (at least for Google Sheets sources)

**To Reproduce**
Take the query from the README:

```
SELECT country, SUM(cnt)
FROM "https://docs.google.com/spreadsheets/d/1_rN3lm0R_bU3NemO0s9pbFkY5LQPcuy1pscv8ZXPtg8/edit#gid=0"
WHERE cnt > 0
GROUP BY country
```

Add a comparison with empty string:

```
SELECT country, SUM(cnt)
FROM "https://docs.google.com/spreadsheets/d/1_rN3lm0R_bU3NemO0s9pbFkY5LQPcuy1pscv8ZXPtg8/edit#gid=0"
WHERE cnt > 0 AND country != ''
GROUP BY country
```

Raises:

```
ProgrammingError: (shillelagh.exceptions.ProgrammingError) Invalid query: NO_COLUMN: null
```
repo: betodealmeida/shillelagh
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/adapters/api/gsheets/fields_test.py b/tests/adapters/api/gsheets/fields_test.py
index d6a041f..0c9efd3 100644
--- a/tests/adapters/api/gsheets/fields_test.py
+++ b/tests/adapters/api/gsheets/fields_test.py
@@ -217,5 +217,5 @@ def test_GSheetsString() -> None:
     assert GSheetsString().format("test") == "test"
 
     assert GSheetsString().quote(None) == "null"
-    assert GSheetsString().quote("") == "null"
+    assert GSheetsString().quote("") == "''"
     assert GSheetsString().quote("test") == "'test'"
task: metadata: install: pip install -e .[dev]
patch: diff --git a/bmt/toolkit.py b/bmt/toolkit.py
index 4c08077..c43fae1 100644
--- a/bmt/toolkit.py
+++ b/bmt/toolkit.py
@@ -398,10 +398,12 @@ class Toolkit(object):
         """
         parsed_name = parse_name(name)
         element = self.generator.obj_for(parsed_name)
-        if element is None and name in self.generator.aliases:
-            element = self.get_element(self.generator.aliases[name])
-        if element and '_' in name:
-            element = self.get_element(name.replace('_', ' '))
+        if element is None:
+            if name in self.generator.aliases:
+                element = self.get_element(self.generator.aliases[name])
+        if element is None:
+            if '_' in name:
+                element = self.get_element(name.replace('_', ' '))
         return element
 
     def get_slot_domain(self,
@@ -810,7 +812,6 @@ class Toolkit(object):
         annotation_tags = []
         if element:
             for annotation in element.annotations:
-                print(annotation)
                 annotation_tags.append(annotation)
         is_canonical = True if element is not None and 'biolink:canonical_predicate' in annotation_tags else False
         return True if RELATED_TO in self.get_ancestors(name, mixin) and is_canonical else False

problem_statement: fix get_element() method for use in KGX
repo: biolink/biolink-model-toolkit
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/unit/test_toolkit.py b/tests/unit/test_toolkit.py
index b81fa75..983212d 100644
--- a/tests/unit/test_toolkit.py
+++ b/tests/unit/test_toolkit.py
@@ -115,6 +115,12 @@ def test_get_element(toolkit):
     o = toolkit.get_element('molecular function')
     assert o and o.name == MOLECULAR_ACTIVITY
 
+    o = toolkit.get_element('molecular_function')
+    assert o and o.name == MOLECULAR_ACTIVITY
+
+    o = toolkit.get_element('cellular_component')
+    assert o and o.name == 'cellular component'
+
     o = toolkit.get_element('RNA Product')
     assert o and o.name == 'RNA product'
task: metadata: install: pip install -e .[dev]
patch: diff --git a/bmt/utils.py b/bmt/utils.py
index f2ac488..e9a1d7c 100644
--- a/bmt/utils.py
+++ b/bmt/utils.py
@@ -4,6 +4,18 @@ import stringcase
 from linkml_runtime.linkml_model.meta import ClassDefinition, SlotDefinition, Element, ClassDefinitionName, \
     SlotDefinitionName, ElementName, TypeDefinition
 
+lowercase_pattern = re.compile(r"[a-zA-Z]*[a-z][a-zA-Z]*")
+underscore_pattern = re.compile(r"(?<!^)(?=[A-Z][a-z])")
+
+
+def from_camel(s: str, sep: str = " ") -> str:
+    underscored = underscore_pattern.sub(sep, s)
+    lowercased = lowercase_pattern.sub(
+        lambda match: match.group(0).lower(),
+        underscored,
+    )
+    return lowercased
+
 
 def camelcase_to_sentencecase(s: str) -> str:
     """
@@ -18,7 +30,7 @@ def camelcase_to_sentencecase(s: str) -> str:
     str
         string in sentence case form
     """
-    return stringcase.sentencecase(s).lower()
+    return from_camel(s, sep=" ")
 
 
 def snakecase_to_sentencecase(s: str) -> str:

problem_statement: Camel-case names with acronyms are not parsed well
Classes like "RNA product", etc. behave in strange ways.

```python
>>> print(tk.get_element("RNA product").class_uri)
biolink:RNAProduct
>>> print(tk.get_element("biolink:RNAProduct"))
None
```

I suspect that we are failing to convert "RNAProduct" to the expected sentence-case representation.
repo: biolink/biolink-model-toolkit
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py
index 3a7203f..a72f7fa 100644
--- a/tests/unit/test_utils.py
+++ b/tests/unit/test_utils.py
@@ -18,6 +18,7 @@ from bmt.utils import parse_name
     ('RNA product', 'RNA product'),
     ('RNA Product', 'RNA Product'),
     ('Rna Product', 'Rna Product'),
+    ('biolink:RNAProduct', 'RNA product'),
 ])
 def test_parse_name(query):
     n = parse_name(query[0])
task: metadata: install: pip install -e .
patch: diff --git a/sgp4/exporter.py b/sgp4/exporter.py
index 759c034..32d6baf 100644
--- a/sgp4/exporter.py
+++ b/sgp4/exporter.py
@@ -30,7 +30,10 @@ def export_tle(satrec):
     append(satrec.intldesg.ljust(8, " ") + " ")
 
     # Add epoch year and days in YYDDD.DDDDDDDD format
-    append(str(satrec.epochyr).zfill(2) + "{:012.8f}".format(satrec.epochdays) + " ")
+    epochyr = satrec.epochyr
+    # Undo non-standard 4-digit year for old satrec objects
+    epochyr %= 100
+    append(str(epochyr).zfill(2) + "{:012.8f}".format(satrec.epochdays) + " ")
 
     # Add First Time Derivative of the Mean Motion (don't use "+")
     append("{0: 8.8f}".format(satrec.ndot * (_xpdotp * 1440.0)).replace("0", "", 1) + " ")

problem_statement: export_tle roundtrip issues
While studying #70, I discovered a roundtrip problem with `export_tle`:

```
>>> lines = """1 46272U 20061A   20311.82207422  .00000083  00000-0  68546-5 0  9999
... 2 46272  97.3995  23.7575 0006827 352.5560   7.5569 15.20743438  9810"""
>>> print(lines)
1 46272U 20061A   20311.82207422  .00000083  00000-0  68546-5 0  9999
2 46272  97.3995  23.7575 0006827 352.5560   7.5569 15.20743438  9810
>>> sat = twoline2rv(*lines.splitlines(), wgs84)
>>> print("\n".join(export_tle(sat)))
1 46272U 20061A   2020311.82207422  .00000083  00000-0  68546-5 0  9993
2 46272  97.3995  23.7575 0006827 352.5560   7.5569 15.20743438  9810
```

And I think it also happens with other examples in https://github.com/brandon-rhodes/python-sgp4/blob/master/sgp4/SGP4-VER.TLE.
repo: brandon-rhodes/python-sgp4
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/sgp4/tests.py b/sgp4/tests.py
index ba63b1d..3fb6d41 100644
--- a/sgp4/tests.py
+++ b/sgp4/tests.py
@@ -198,14 +198,18 @@ def test_tle_export():
         line1 = line1[:69]
         line2 = line2[:69]
         satrec = Satrec.twoline2rv(line1, line2)
+        satrec_old = io.twoline2rv(line1, line2, wgs72)
 
         # Generate TLE from satrec
         out_line1, out_line2 = export_tle(satrec)
+        out_line1_old, out_line2_old = export_tle(satrec_old)
 
         if satrec.satnum not in expected_errs_line1:
             assertEqual(out_line1, line1)
+            assertEqual(out_line1_old, line1)
         if satrec.satnum not in expected_errs_line2:
             assertEqual(out_line2, line2)
+            assertEqual(out_line2_old, line2)
 
 def test_export_tle_raises_error_for_out_of_range_angles():
     # See https://github.com/brandon-rhodes/python-sgp4/issues/70
task: metadata: install: pip3 install -e .
patch: diff --git a/checkov/terraform/checks/resource/azure/AppServiceDotnetFrameworkVersion.py b/checkov/terraform/checks/resource/azure/AppServiceDotnetFrameworkVersion.py
index e4fd2f461..8aa662203 100644
--- a/checkov/terraform/checks/resource/azure/AppServiceDotnetFrameworkVersion.py
+++ b/checkov/terraform/checks/resource/azure/AppServiceDotnetFrameworkVersion.py
@@ -14,7 +14,7 @@ class AppServiceDotnetFrameworkVersion(BaseResourceValueCheck):
         return "site_config/0/dotnet_framework_version"
 
     def get_expected_value(self):
-        return "v5.0"
+        return "v6.0"
 
 
 check = AppServiceDotnetFrameworkVersion()

problem_statement: CKV_AZURE_80 - dotnet_framework_version with v6.0 fails
**Describe the issue**
Currently .NET 6.0 is the latest LTS version. However, CKV_AZURE_80 expects that latest version is v5.0.

**Examples**
```
resource "azurerm_app_service" "searchApi" {
  ...
  site_config {
    dotnet_framework_version = "v6.0"
  }
}
```
There should be no warning for CKV_AZURE_80 with the above configuration.

**Version (please complete the following information):**
 - Checkov Version 2.0.717

repo: bridgecrewio/checkov
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/tests/terraform/checks/resource/azure/test_AppServiceDotnetFrameworkVersion.py b/tests/terraform/checks/resource/azure/test_AppServiceDotnetFrameworkVersion.py
index d392d226e..e7c140a41 100644
--- a/tests/terraform/checks/resource/azure/test_AppServiceDotnetFrameworkVersion.py
+++ b/tests/terraform/checks/resource/azure/test_AppServiceDotnetFrameworkVersion.py
@@ -17,7 +17,7 @@ class TestAppServiceDotnetFrameworkVersion(unittest.TestCase):
               app_service_plan_id = azurerm_app_service_plan.example.id
               https_only          = true
               site_config {
-                dotnet_framework_version = "v4.0"
+                dotnet_framework_version = "v5.0"
                 scm_type                 = "someValue"
                 }
               }
@@ -52,7 +52,7 @@ class TestAppServiceDotnetFrameworkVersion(unittest.TestCase):
               app_service_plan_id = azurerm_app_service_plan.example.id
               https_only          = true
               site_config {
-                dotnet_framework_version = "v5.0"
+                dotnet_framework_version = "v6.0"
                 scm_type                 = "someValue"
                 }
               }