Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pyupgrade for
openSUSE:Factory checked in at 2023-06-03 00:07:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyupgrade (Old)
and /work/SRC/openSUSE:Factory/.python-pyupgrade.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pyupgrade"
Sat Jun 3 00:07:25 2023 rev:30 rq:1090388 version:3.4.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyupgrade/python-pyupgrade.changes
2022-12-03 12:48:35.698140645 +0100
+++
/work/SRC/openSUSE:Factory/.python-pyupgrade.new.15902/python-pyupgrade.changes
2023-06-03 00:07:33.478107359 +0200
@@ -1,0 +2,7 @@
+Thu Jun 1 20:18:41 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to 3.4.0:
+ * drop python37 support
+ * remove use of deprecated ast
+
+-------------------------------------------------------------------
Old:
----
python-pyupgrade-3.2.2.tar.gz
New:
----
python-pyupgrade-3.4.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pyupgrade.spec ++++++
--- /var/tmp/diff_new_pack.JqJBRh/_old 2023-06-03 00:07:34.114111115 +0200
+++ /var/tmp/diff_new_pack.JqJBRh/_new 2023-06-03 00:07:34.122111162 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-pyupgrade
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -16,10 +16,9 @@
#
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
-%define skip_python2 1
+%{?sle15_python_module_pythons}
Name: python-pyupgrade
-Version: 3.2.2
+Version: 3.4.0
Release: 0
Summary: A tool to automatically upgrade syntax for newer versions
License: MIT
++++++ python-pyupgrade-3.2.2.tar.gz -> python-pyupgrade-3.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/.github/workflows/main.yml
new/pyupgrade-3.4.0/.github/workflows/main.yml
--- old/pyupgrade-3.2.2/.github/workflows/main.yml 1970-01-01
01:00:00.000000000 +0100
+++ new/pyupgrade-3.4.0/.github/workflows/main.yml 2023-05-06
23:09:25.000000000 +0200
@@ -0,0 +1,19 @@
+name: main
+
+on:
+ push:
+ branches: [main, test-me-*]
+ tags:
+ pull_request:
+
+jobs:
+ main-windows:
+ uses: asottile/workflows/.github/workflows/[email protected]
+ with:
+ env: '["py38"]'
+ os: windows-latest
+ main-linux:
+ uses: asottile/workflows/.github/workflows/[email protected]
+ with:
+ env: '["py38", "py39", "py310"]'
+ os: ubuntu-latest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/.pre-commit-config.yaml
new/pyupgrade-3.4.0/.pre-commit-config.yaml
--- old/pyupgrade-3.2.2/.pre-commit-config.yaml 2022-11-10 16:38:09.000000000
+0100
+++ new/pyupgrade-3.4.0/.pre-commit-config.yaml 2023-05-06 23:09:25.000000000
+0200
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.3.0
+ rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@@ -17,26 +17,26 @@
rev: v3.9.0
hooks:
- id: reorder-python-imports
- args: [--py37-plus, --add-import, 'from __future__ import annotations']
+ args: [--py38-plus, --add-import, 'from __future__ import annotations']
- repo: https://github.com/asottile/add-trailing-comma
- rev: v2.3.0
+ rev: v2.4.0
hooks:
- id: add-trailing-comma
args: [--py36-plus]
- repo: https://github.com/asottile/pyupgrade
- rev: v3.2.2
+ rev: v3.4.0
hooks:
- id: pyupgrade
- args: [--py37-plus]
+ args: [--py38-plus]
- repo: https://github.com/pre-commit/mirrors-autopep8
- rev: v2.0.0
+ rev: v2.0.2
hooks:
- id: autopep8
- repo: https://github.com/PyCQA/flake8
- rev: 5.0.4
+ rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v0.982
+ rev: v1.2.0
hooks:
- id: mypy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/README.md
new/pyupgrade-3.4.0/README.md
--- old/pyupgrade-3.2.2/README.md 2022-11-10 16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/README.md 2023-05-06 23:09:25.000000000 +0200
@@ -1,5 +1,4 @@
-[](https://dev.azure.com/asottile/asottile/_build/latest?definitionId=2&branchName=main)
-[](https://dev.azure.com/asottile/asottile/_build/latest?definitionId=2&branchName=main)
+[](https://github.com/asottile/pyupgrade/actions/workflows/main.yml)
[](https://results.pre-commit.ci/latest/github/asottile/pyupgrade/main)
pyupgrade
@@ -22,7 +21,7 @@
```yaml
- repo: https://github.com/asottile/pyupgrade
- rev: v3.2.2
+ rev: v3.4.0
hooks:
- id: pyupgrade
```
@@ -694,3 +693,16 @@
-def f(x: 'queue.Queue[int]') -> C:
+def f(x: queue.Queue[int]) -> C:
```
+
+
+### use `datetime.UTC` alias
+
+Availability:
+- `--py311-plus` is passed on the commandline.
+
+```diff
+ import datetime
+
+-datetime.timezone.utc
++datetime.UTC
+```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/azure-pipelines.yml
new/pyupgrade-3.4.0/azure-pipelines.yml
--- old/pyupgrade-3.2.2/azure-pipelines.yml 2022-11-10 16:38:09.000000000
+0100
+++ new/pyupgrade-3.4.0/azure-pipelines.yml 1970-01-01 01:00:00.000000000
+0100
@@ -1,23 +0,0 @@
-trigger:
- branches:
- include: [main, test-me-*]
- tags:
- include: ['*']
-
-resources:
- repositories:
- - repository: asottile
- type: github
- endpoint: github
- name: asottile/azure-pipeline-templates
- ref: refs/tags/v2.4.1
-
-jobs:
-- template: job--python-tox.yml@asottile
- parameters:
- toxenvs: [py37]
- os: windows
-- template: job--python-tox.yml@asottile
- parameters:
- toxenvs: [py37, py38, py39]
- os: linux
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/pyupgrade/_plugins/datetime_utc_alias.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/datetime_utc_alias.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/datetime_utc_alias.py
1970-01-01 01:00:00.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/datetime_utc_alias.py
2023-05-06 23:09:25.000000000 +0200
@@ -0,0 +1,35 @@
+from __future__ import annotations
+
+import ast
+import functools
+from typing import Iterable
+
+from tokenize_rt import Offset
+
+from pyupgrade._ast_helpers import ast_to_offset
+from pyupgrade._data import register
+from pyupgrade._data import State
+from pyupgrade._data import TokenFunc
+from pyupgrade._token_helpers import replace_name
+
+
+@register(ast.Attribute)
+def visit_Attribute(
+ state: State,
+ node: ast.Attribute,
+ parent: ast.AST,
+) -> Iterable[tuple[Offset, TokenFunc]]:
+ if (
+ state.settings.min_version >= (3, 11) and
+ node.attr == 'utc' and
+ isinstance(node.value, ast.Attribute) and
+ node.value.attr == 'timezone' and
+ isinstance(node.value.value, ast.Name) and
+ node.value.value.id == 'datetime'
+ ):
+ func = functools.partial(
+ replace_name,
+ name='utc',
+ new='datetime.UTC',
+ )
+ yield ast_to_offset(node), func
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/pyupgrade/_plugins/default_encoding.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/default_encoding.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/default_encoding.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/default_encoding.py 2023-05-06
23:09:25.000000000 +0200
@@ -29,12 +29,18 @@
parent: ast.AST,
) -> Iterable[tuple[Offset, TokenFunc]]:
if (
- isinstance(node.func, ast.Attribute) and
- isinstance(node.func.value, (ast.Str, ast.JoinedStr)) and
+ isinstance(node.func, ast.Attribute) and (
+ (
+ isinstance(node.func.value, ast.Constant) and
+ isinstance(node.func.value.value, str)
+ ) or
+ isinstance(node.func.value, ast.JoinedStr)
+ ) and
node.func.attr == 'encode' and
not has_starargs(node) and
len(node.args) == 1 and
- isinstance(node.args[0], ast.Str) and
- is_codec(node.args[0].s, 'utf-8')
+ isinstance(node.args[0], ast.Constant) and
+ isinstance(node.args[0].value, str) and
+ is_codec(node.args[0].value, 'utf-8')
):
yield ast_to_offset(node), _fix_default_encoding
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/format_locals.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/format_locals.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/format_locals.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/format_locals.py 2023-05-06
23:09:25.000000000 +0200
@@ -35,7 +35,8 @@
if (
state.settings.min_version >= (3, 6) and
isinstance(node.func, ast.Attribute) and
- isinstance(node.func.value, ast.Str) and
+ isinstance(node.func.value, ast.Constant) and
+ isinstance(node.func.value.value, str) and
node.func.attr == 'format' and
len(node.args) == 0 and
len(node.keywords) == 1 and
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/fstrings.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/fstrings.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/fstrings.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/fstrings.py 2023-05-06
23:09:25.000000000 +0200
@@ -4,6 +4,7 @@
from typing import Iterable
from tokenize_rt import Offset
+from tokenize_rt import parse_string_literal
from tokenize_rt import Token
from tokenize_rt import tokens_to_src
@@ -43,7 +44,12 @@
parts = []
i = 0
- for s, name, spec, conv in parse_format('f' + src):
+
+ # need to remove `u` prefix so it isn't invalid syntax
+ prefix, rest = parse_string_literal(src)
+ new_src = 'f' + prefix.translate({ord('u'): None, ord('U'): None}) + rest
+
+ for s, name, spec, conv in parse_format(new_src):
if name is not None:
k, dot, rest = name.partition('.')
name = ''.join((params[k or str(i)], dot, rest))
@@ -93,12 +99,13 @@
if (
isinstance(node.func, ast.Attribute) and
- isinstance(node.func.value, ast.Str) and
+ isinstance(node.func.value, ast.Constant) and
+ isinstance(node.func.value.value, str) and
node.func.attr == 'format' and
not has_starargs(node)
):
try:
- parsed = parse_format(node.func.value.s)
+ parsed = parse_format(node.func.value.value)
except ValueError:
return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/pyupgrade/_plugins/identity_equality.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/identity_equality.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/identity_equality.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/identity_equality.py 2023-05-06
23:09:25.000000000 +0200
@@ -12,8 +12,6 @@
from pyupgrade._data import State
from pyupgrade._data import TokenFunc
-LITERAL_TYPES = (ast.Str, ast.Num, ast.Bytes)
-
def _fix_is_literal(
i: int,
@@ -35,6 +33,14 @@
tokens[i] = Token('EMPTY', '')
+def _is_literal(n: ast.AST) -> bool:
+ return (
+ isinstance(n, ast.Constant) and
+ n.value not in {True, False} and
+ isinstance(n.value, (str, bytes, int, float))
+ )
+
+
@register(ast.Compare)
def visit_Compare(
state: State,
@@ -45,10 +51,7 @@
for op, right in zip(node.ops, node.comparators):
if (
isinstance(op, (ast.Is, ast.IsNot)) and
- (
- isinstance(left, LITERAL_TYPES) or
- isinstance(right, LITERAL_TYPES)
- )
+ (_is_literal(left) or _is_literal(right))
):
func = functools.partial(_fix_is_literal, op=op)
yield ast_to_offset(right), func
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/imports.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/imports.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/imports.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/imports.py 2023-05-06
23:09:25.000000000 +0200
@@ -281,6 +281,7 @@
mod_start: int
mod_end: int
names: tuple[int, ...]
+ ends: tuple[int, ...]
end: int
@classmethod
@@ -310,11 +311,14 @@
for j in range(import_token + 1, end)
if tokens[j].name == 'NAME'
]
+ ends_by_offset = {}
for i in reversed(range(len(names))):
if tokens[names[i]].src == 'as':
+ ends_by_offset[names[i - 1]] = names[i + 1]
del names[i:i + 2]
+ ends = tuple(ends_by_offset.get(pos, pos) for pos in names)
- return cls(start, mod_start, mod_end + 1, tuple(names), end)
+ return cls(start, mod_start, mod_end + 1, tuple(names), ends, end)
def remove_self(self, tokens: list[Token]) -> None:
del tokens[self.start:self.end]
@@ -327,10 +331,10 @@
if idx == 0: # look forward until next name and del
del tokens[self.names[idx]:self.names[idx + 1]]
else: # look backward for comma and del
- j = end = self.names[idx]
+ j = self.names[idx]
while tokens[j].src != ',':
j -= 1
- del tokens[j:end + 1]
+ del tokens[j:self.ends[idx] + 1]
def _alias_to_s(alias: ast.alias) -> str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/lru_cache.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/lru_cache.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/lru_cache.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/lru_cache.py 2023-05-06
23:09:25.000000000 +0200
@@ -28,7 +28,7 @@
) -> bool:
return (
keyword.arg == name and
- isinstance(keyword.value, ast.NameConstant) and
+ isinstance(keyword.value, ast.Constant) and
keyword.value.value is value
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/pyupgrade/_plugins/native_literals.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/native_literals.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/native_literals.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/native_literals.py 2023-05-06
23:09:25.000000000 +0200
@@ -44,7 +44,11 @@
not has_starargs(node) and
(
len(node.args) == 0 or
- (len(node.args) == 1 and isinstance(node.args[0], ast.Str))
+ (
+ len(node.args) == 1 and
+ isinstance(node.args[0], ast.Constant) and
+ isinstance(node.args[0].value, str)
+ )
)
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/open_mode.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/open_mode.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/open_mode.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/open_mode.py 2023-05-06
23:09:25.000000000 +0200
@@ -81,10 +81,14 @@
) and
not has_starargs(node)
):
- if len(node.args) >= 2 and isinstance(node.args[1], ast.Str):
+ if (
+ len(node.args) >= 2 and
+ isinstance(node.args[1], ast.Constant) and
+ isinstance(node.args[1].value, str)
+ ):
if (
- node.args[1].s in MODE_REPLACE or
- (len(node.args) == 2 and node.args[1].s in MODE_REMOVE)
+ node.args[1].value in MODE_REPLACE or
+ (len(node.args) == 2 and node.args[1].value in MODE_REMOVE)
):
func = functools.partial(_fix_open_mode, arg_idx=1)
yield ast_to_offset(node), func
@@ -99,10 +103,11 @@
)
if (
mode is not None and
- isinstance(mode.value, ast.Str) and
+ isinstance(mode.value, ast.Constant) and
+ isinstance(mode.value.value, str) and
(
- mode.value.s in MODE_REMOVE or
- mode.value.s in MODE_REPLACE
+ mode.value.value in MODE_REMOVE or
+ mode.value.value in MODE_REPLACE
)
):
func = functools.partial(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/percent_format.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/percent_format.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/percent_format.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/percent_format.py 2023-05-06
23:09:25.000000000 +0200
@@ -184,18 +184,18 @@
for k in node_right.keys:
# not a string key
- if not isinstance(k, ast.Str):
+ if not isinstance(k, ast.Constant) or not isinstance(k.value, str):
return
# duplicate key
- elif k.s in seen_keys:
+ elif k.value in seen_keys:
return
# not an identifier
- elif not k.s.isidentifier():
+ elif not k.value.isidentifier():
return
# a keyword
- elif k.s in KEYWORDS:
+ elif k.value in KEYWORDS:
return
- seen_keys.add(k.s)
+ seen_keys.add(k.value)
keys[ast_to_offset(k)] = k
# TODO: this is overly timid
@@ -212,13 +212,13 @@
if key is None:
continue
# we found the key, but the string didn't match (implicit join?)
- elif ast.literal_eval(token.src) != key.s:
+ elif ast.literal_eval(token.src) != key.value:
return
# the map uses some strange syntax that's not `'key': value`
elif tokens[j + 1].src != ':' or tokens[j + 2].src != ' ':
return
else:
- key_indices.append((j, key.s))
+ key_indices.append((j, key.value))
assert not keys, keys
tokens[brace_end] = tokens[brace_end]._replace(src=')')
@@ -238,10 +238,11 @@
if (
not state.settings.keep_percent_format and
isinstance(node.op, ast.Mod) and
- isinstance(node.left, ast.Str)
+ isinstance(node.left, ast.Constant) and
+ isinstance(node.left.value, str)
):
try:
- parsed = _parse_percent_format(node.left.s)
+ parsed = _parse_percent_format(node.left.value)
except ValueError:
pass
else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/six_calls.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/six_calls.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/six_calls.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/six_calls.py 2023-05-06
23:09:25.000000000 +0200
@@ -2,7 +2,6 @@
import ast
import functools
-import sys
from typing import Iterable
from tokenize_rt import Offset
@@ -21,10 +20,8 @@
_EXPR_NEEDS_PARENS: tuple[type[ast.expr], ...] = (
ast.Await, ast.BinOp, ast.BoolOp, ast.Compare, ast.GeneratorExp, ast.IfExp,
- ast.Lambda, ast.UnaryOp,
+ ast.Lambda, ast.UnaryOp, ast.NamedExpr,
)
-if sys.version_info >= (3, 8): # pragma: >=3.8 cover
- _EXPR_NEEDS_PARENS += (ast.NamedExpr,)
SIX_CALLS = {
'u': '{args[0]}',
@@ -143,7 +140,8 @@
not node.keywords and
not has_starargs(node) and
len(node.args) == 1 and
- isinstance(node.args[0], ast.Str)
+ isinstance(node.args[0], ast.Constant) and
+ isinstance(node.args[0].value, str)
):
yield ast_to_offset(node), _fix_six_b
elif (
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/pyupgrade/_plugins/type_of_primitive.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/type_of_primitive.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/type_of_primitive.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/type_of_primitive.py 2023-05-06
23:09:25.000000000 +0200
@@ -14,7 +14,10 @@
from pyupgrade._token_helpers import find_closing_bracket
from pyupgrade._token_helpers import find_open_paren
-NUM_TYPES = {
+_TYPES = {
+ bool: 'bool',
+ bytes: 'bytes',
+ str: 'str',
int: 'int',
float: 'float',
complex: 'complex',
@@ -42,23 +45,12 @@
if (
isinstance(node.func, ast.Name) and
node.func.id == 'type' and
- len(node.args) == 1
+ len(node.args) == 1 and
+ isinstance(node.args[0], ast.Constant) and
+ node.args[0].value not in {Ellipsis, None}
):
- if isinstance(node.args[0], ast.Str):
- func = functools.partial(
- _rewrite_type_of_primitive,
- src='str',
- )
- yield ast_to_offset(node), func
- elif isinstance(node.args[0], ast.Bytes):
- func = functools.partial(
- _rewrite_type_of_primitive,
- src='bytes',
- )
- yield ast_to_offset(node), func
- elif isinstance(node.args[0], ast.Num):
- func = functools.partial(
- _rewrite_type_of_primitive,
- src=NUM_TYPES[type(node.args[0].n)],
- )
- yield ast_to_offset(node), func
+ func = functools.partial(
+ _rewrite_type_of_primitive,
+ src=_TYPES[type(node.args[0].value)],
+ )
+ yield ast_to_offset(node), func
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/typing_classes.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/typing_classes.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/typing_classes.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/typing_classes.py 2023-05-06
23:09:25.000000000 +0200
@@ -38,14 +38,19 @@
else:
slice_s = _unparse(node_slice)
return f'{_unparse(node.value)}[{slice_s}]'
- elif isinstance(node, (ast.Str, ast.Bytes)):
- return repr(node.s)
- elif isinstance(node, ast.Ellipsis):
+ elif (
+ isinstance(node, ast.Constant) and
+ isinstance(node.value, (str, bytes))
+ ):
+ return repr(node.value)
+ elif isinstance(node, ast.Constant) and node.value is Ellipsis:
return '...'
elif isinstance(node, ast.List):
return '[{}]'.format(', '.join(_unparse(elt) for elt in node.elts))
- elif isinstance(node, ast.NameConstant):
+ elif isinstance(node, ast.Constant) and node.value in {True, False, None}:
return repr(node.value)
+ elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr):
+ return f'{_unparse(node.left)} | {_unparse(node.right)}'
else:
raise NotImplementedError(ast.dump(node))
@@ -95,7 +100,7 @@
def _fix_named_tuple(i: int, tokens: list[Token], *, call: ast.Call) -> None:
types = {
- tup.elts[0].s: tup.elts[1]
+ tup.elts[0].value: tup.elts[1]
for tup in call.args[1].elts # type: ignore # (checked below)
}
end, attrs = _typed_class_replacement(tokens, i, call, types)
@@ -121,7 +126,7 @@
call: ast.Call,
) -> None:
types = {
- k.s: v
+ k.value: v
for k, v in zip(
call.args[1].keys, # type: ignore # (checked below)
call.args[1].values, # type: ignore # (checked below)
@@ -158,8 +163,9 @@
isinstance(node.targets[0], ast.Name) and
isinstance(node.value, ast.Call) and
len(node.value.args) >= 1 and
- isinstance(node.value.args[0], ast.Str) and
- node.targets[0].id == node.value.args[0].s and
+ isinstance(node.value.args[0], ast.Constant) and
+ isinstance(node.value.args[0].value, str) and
+ node.targets[0].id == node.value.args[0].value and
not has_starargs(node.value)
):
if (
@@ -176,9 +182,10 @@
all(
isinstance(tup, ast.Tuple) and
len(tup.elts) == 2 and
- isinstance(tup.elts[0], ast.Str) and
- tup.elts[0].s.isidentifier() and
- tup.elts[0].s not in KEYWORDS
+ isinstance(tup.elts[0], ast.Constant) and
+ isinstance(tup.elts[0].value, str) and
+ tup.elts[0].value.isidentifier() and
+ tup.elts[0].value not in KEYWORDS
for tup in node.value.args[1].elts
)
):
@@ -222,9 +229,10 @@
isinstance(node.value.args[1], ast.Dict) and
node.value.args[1].keys and
all(
- isinstance(k, ast.Str) and
- k.s.isidentifier() and
- k.s not in KEYWORDS
+ isinstance(k, ast.Constant) and
+ isinstance(k.value, str) and
+ k.value.isidentifier() and
+ k.value not in KEYWORDS
for k in node.value.args[1].keys
)
):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/typing_pep563.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/typing_pep563.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/typing_pep563.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/typing_pep563.py 2023-05-06
23:09:25.000000000 +0200
@@ -113,8 +113,8 @@
nodes.extend(_process_call(node))
elif isinstance(node, ast.Subscript):
nodes.extend(_process_subscript(node))
- elif isinstance(node, ast.Str):
- func = functools.partial(_dequote, new=node.s)
+ elif isinstance(node, ast.Constant) and isinstance(node.value, str):
+ func = functools.partial(_dequote, new=node.value)
yield ast_to_offset(node), func
else:
for name in node._fields:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_plugins/typing_pep604.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/typing_pep604.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/typing_pep604.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/typing_pep604.py 2023-05-06
23:09:25.000000000 +0200
@@ -128,9 +128,16 @@
def _any_arg_is_str(node_slice: ast.expr) -> bool:
return (
- isinstance(node_slice, ast.Str) or (
+ (
+ isinstance(node_slice, ast.Constant) and
+ isinstance(node_slice.value, str)
+ ) or (
isinstance(node_slice, ast.Tuple) and
- any(isinstance(elt, ast.Str) for elt in node_slice.elts)
+ any(
+ isinstance(elt, ast.Constant) and
+ isinstance(elt.value, str)
+ for elt in node_slice.elts
+ )
)
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/pyupgrade/_plugins/unpack_list_comprehension.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/unpack_list_comprehension.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/unpack_list_comprehension.py
2022-11-10 16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/unpack_list_comprehension.py
2023-05-06 23:09:25.000000000 +0200
@@ -12,11 +12,10 @@
from pyupgrade._data import State
from pyupgrade._data import TokenFunc
from pyupgrade._token_helpers import find_closing_bracket
-from pyupgrade._token_helpers import find_comprehension_opening_bracket
def _replace_list_comprehension(i: int, tokens: list[Token]) -> None:
- start = find_comprehension_opening_bracket(i, tokens)
+ start = i
end = find_closing_bracket(tokens, start)
tokens[start] = tokens[start]._replace(src='(')
tokens[end] = tokens[end]._replace(src=')')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/pyupgrade/_plugins/versioned_branches.py
new/pyupgrade-3.4.0/pyupgrade/_plugins/versioned_branches.py
--- old/pyupgrade-3.2.2/pyupgrade/_plugins/versioned_branches.py
2022-11-10 16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_plugins/versioned_branches.py
2023-05-06 23:09:25.000000000 +0200
@@ -3,7 +3,6 @@
import ast
from typing import cast
from typing import Iterable
-from typing import List
from tokenize_rt import Offset
from tokenize_rt import Token
@@ -69,8 +68,8 @@
def _eq(test: ast.Compare, n: int) -> bool:
return (
isinstance(test.ops[0], ast.Eq) and
- isinstance(test.comparators[0], ast.Num) and
- test.comparators[0].n == n
+ isinstance(test.comparators[0], ast.Constant) and
+ test.comparators[0].value == n
)
@@ -83,14 +82,17 @@
isinstance(test.ops[0], op) and
isinstance(test.comparators[0], ast.Tuple) and
len(test.comparators[0].elts) >= 1 and
- all(isinstance(n, ast.Num) for n in test.comparators[0].elts)
+ all(
+ isinstance(n, ast.Constant) and isinstance(n.value, int)
+ for n in test.comparators[0].elts
+ )
):
return False
# checked above but mypy needs help
- ast_elts = cast('List[ast.Num]', test.comparators[0].elts)
+ ast_elts = cast('list[ast.Constant]', test.comparators[0].elts)
# padding a 0 for compatibility with (3,) used as a spec
- elts = tuple(e.n for e in ast_elts) + (0,)
+ elts = tuple(e.value for e in ast_elts) + (0,)
return elts[:2] == (3, minor) and all(n == 0 for n in elts[2:])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/pyupgrade/_token_helpers.py
new/pyupgrade-3.4.0/pyupgrade/_token_helpers.py
--- old/pyupgrade-3.2.2/pyupgrade/_token_helpers.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/pyupgrade/_token_helpers.py 2023-05-06
23:09:25.000000000 +0200
@@ -2,7 +2,6 @@
import ast
import keyword
-import sys
from typing import NamedTuple
from typing import Sequence
@@ -64,28 +63,11 @@
return i
-if sys.version_info >= (3, 8): # pragma: >=3.8 cover
- # python 3.8 fixed the offsets of generators / tuples
- def _arg_token_index(tokens: list[Token], i: int, arg: ast.expr) -> int:
- idx = _search_until(tokens, i, arg) + 1
- while idx < len(tokens) and tokens[idx].name in NON_CODING_TOKENS:
- idx += 1
- return idx
-else: # pragma: <3.8 cover
- def _arg_token_index(tokens: list[Token], i: int, arg: ast.expr) -> int:
- # lists containing non-tuples report the first element correctly
- if isinstance(arg, ast.List):
- # If the first element is a tuple, the ast lies to us about its col
- # offset. We must find the first `(` token after the start of the
- # list element.
- if isinstance(arg.elts[0], ast.Tuple):
- i = _search_until(tokens, i, arg)
- return find_open_paren(tokens, i)
- else:
- return _search_until(tokens, i, arg.elts[0])
- # others' start position points at their first child node already
- else:
- return _search_until(tokens, i, arg)
+def _arg_token_index(tokens: list[Token], i: int, arg: ast.expr) -> int:
+ idx = _search_until(tokens, i, arg) + 1
+ while idx < len(tokens) and tokens[idx].name in NON_CODING_TOKENS:
+ idx += 1
+ return idx
def victims(
@@ -499,17 +481,6 @@
tokens[start_idx:end_idx] = [Token('SRC', new)]
-def find_comprehension_opening_bracket(i: int, tokens: list[Token]) -> int:
- """Find opening bracket of comprehension given first argument."""
- if sys.version_info < (3, 8): # pragma: <3.8 cover
- i -= 1
- while not (tokens[i].name == 'OP' and tokens[i].src == '[') and i:
- i -= 1
- return i
- else: # pragma: >=3.8 cover
- return i
-
-
def has_space_before(i: int, tokens: list[Token]) -> bool:
return i >= 1 and tokens[i - 1].name in {UNIMPORTANT_WS, 'INDENT'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/setup.cfg
new/pyupgrade-3.4.0/setup.cfg
--- old/pyupgrade-3.2.2/setup.cfg 2022-11-10 16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/setup.cfg 2023-05-06 23:09:25.000000000 +0200
@@ -1,6 +1,6 @@
[metadata]
name = pyupgrade
-version = 3.2.2
+version = 3.4.0
description = A tool to automatically upgrade syntax for newer versions.
long_description = file: README.md
long_description_content_type = text/markdown
@@ -20,7 +20,7 @@
packages = find:
install_requires =
tokenize-rt>=3.2.0
-python_requires = >=3.7
+python_requires = >=3.8
[options.packages.find]
exclude =
@@ -42,7 +42,6 @@
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
-no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/tests/features/datetime_utc_alias_test.py
new/pyupgrade-3.4.0/tests/features/datetime_utc_alias_test.py
--- old/pyupgrade-3.2.2/tests/features/datetime_utc_alias_test.py
1970-01-01 01:00:00.000000000 +0100
+++ new/pyupgrade-3.4.0/tests/features/datetime_utc_alias_test.py
2023-05-06 23:09:25.000000000 +0200
@@ -0,0 +1,41 @@
+from __future__ import annotations
+
+import pytest
+
+from pyupgrade._data import Settings
+from pyupgrade._main import _fix_plugins
+
+
[email protected](
+ ('s',),
+ (
+ pytest.param(
+ 'import datetime\n'
+ 'print(datetime.timezone(-1))',
+
+ id='not rewriting timezone object to alias',
+ ),
+ ),
+)
+def test_fix_datetime_utc_alias_noop(s):
+ assert _fix_plugins(s, settings=Settings(min_version=(3,))) == s
+ assert _fix_plugins(s, settings=Settings(min_version=(3, 11))) == s
+
+
[email protected](
+ ('s', 'expected'),
+ (
+ pytest.param(
+ 'import datetime\n'
+ 'print(datetime.timezone.utc)',
+
+ 'import datetime\n'
+ 'print(datetime.UTC)',
+
+ id='rewriting to alias',
+ ),
+ ),
+)
+def test_fix_datetime_utc_alias(s, expected):
+ assert _fix_plugins(s, settings=Settings(min_version=(3,))) == s
+ assert _fix_plugins(s, settings=Settings(min_version=(3, 11))) == expected
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/tests/features/fstrings_test.py
new/pyupgrade-3.4.0/tests/features/fstrings_test.py
--- old/pyupgrade-3.2.2/tests/features/fstrings_test.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/tests/features/fstrings_test.py 2023-05-06
23:09:25.000000000 +0200
@@ -64,6 +64,11 @@
r'f"\N{snowman} {a}"',
id='named escape sequences',
),
+ pytest.param(
+ 'u"foo{}".format(1)',
+ 'f"foo{1}"',
+ id='u-prefixed format',
+ ),
),
)
def test_fix_fstrings(s, expected):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/tests/features/import_replaces_test.py
new/pyupgrade-3.4.0/tests/features/import_replaces_test.py
--- old/pyupgrade-3.2.2/tests/features/import_replaces_test.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/tests/features/import_replaces_test.py 2023-05-06
23:09:25.000000000 +0200
@@ -305,6 +305,13 @@
'from collections.abc import Callable\n',
id='typing.Callable is rewritable in 3.10+ only',
),
+ pytest.param(
+ 'from typing import Optional, Sequence as S\n',
+ (3, 10),
+ 'from typing import Optional\n'
+ 'from collections.abc import Sequence as S\n',
+ id='aliasing in multi from import',
+ ),
),
)
def test_import_replaces(s, min_version, expected):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/tests/features/six_test.py
new/pyupgrade-3.4.0/tests/features/six_test.py
--- old/pyupgrade-3.2.2/tests/features/six_test.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/tests/features/six_test.py 2023-05-06
23:09:25.000000000 +0200
@@ -1,7 +1,5 @@
from __future__ import annotations
-import sys
-
import pytest
from pyupgrade._data import Settings
@@ -387,17 +385,6 @@
'x = map(str, ints)\n',
id='six.moves builtin attrs',
),
- ),
-)
-def test_fix_six(s, expected):
- ret = _fix_plugins(s, settings=Settings())
- assert ret == expected
-
-
[email protected](sys.version_info < (3, 8), reason='walrus')
[email protected](
- ('s', 'expected'),
- (
pytest.param(
'for _ in six.itervalues(x := y): pass',
'for _ in (x := y).values(): pass',
@@ -405,7 +392,7 @@
),
),
)
-def test_fix_six_py38_plus(s, expected):
+def test_fix_six(s, expected):
ret = _fix_plugins(s, settings=Settings())
assert ret == expected
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/tests/features/type_of_primitive_test.py
new/pyupgrade-3.4.0/tests/features/type_of_primitive_test.py
--- old/pyupgrade-3.2.2/tests/features/type_of_primitive_test.py
2022-11-10 16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/tests/features/type_of_primitive_test.py
2023-05-06 23:09:25.000000000 +0200
@@ -14,6 +14,10 @@
id='NoneType',
),
pytest.param(
+ 'type(...)\n',
+ id='ellipsis',
+ ),
+ pytest.param(
'foo = "foo"\n'
'type(foo)\n',
id='String assigned to variable',
@@ -62,6 +66,13 @@
id='Empty bytes string -> bytes',
),
+ pytest.param(
+ 'type(True)\n',
+
+ 'bool\n',
+
+ id='bool',
+ ),
),
)
def test_fix_type_of_primitive(s, expected):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pyupgrade-3.2.2/tests/features/typing_classes_test.py
new/pyupgrade-3.4.0/tests/features/typing_classes_test.py
--- old/pyupgrade-3.2.2/tests/features/typing_classes_test.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/tests/features/typing_classes_test.py 2023-05-06
23:09:25.000000000 +0200
@@ -210,6 +210,16 @@
id='preserves comments without alignment',
),
+ pytest.param(
+ 'from typing import NamedTuple\n'
+ 'Foo = NamedTuple("Foo", [("union", str | None)])',
+
+ 'from typing import NamedTuple\n'
+ 'class Foo(NamedTuple):\n'
+ ' union: str | None',
+
+ id='BitOr unparse error',
+ ),
),
)
def test_fix_typing_named_tuple(s, expected):
@@ -393,6 +403,16 @@
id='right after a dedent',
),
+ pytest.param(
+ 'from typing import TypedDict\n'
+ 'Foo = TypedDict("Foo", {"union": str | int | None})',
+
+ 'from typing import TypedDict\n'
+ 'class Foo(TypedDict):\n'
+ ' union: str | int | None',
+
+ id='BitOr unparse error',
+ ),
),
)
def test_typing_typed_dict(s, expected):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/tests/features/typing_pep563_test.py
new/pyupgrade-3.4.0/tests/features/typing_pep563_test.py
--- old/pyupgrade-3.2.2/tests/features/typing_pep563_test.py 2022-11-10
16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/tests/features/typing_pep563_test.py 2023-05-06
23:09:25.000000000 +0200
@@ -1,7 +1,5 @@
from __future__ import annotations
-import sys
-
import pytest
from pyupgrade._data import Settings
@@ -338,27 +336,19 @@
id='NamedTuple with no args (invalid syntax)',
),
+ pytest.param(
+ 'from __future__ import annotations\n'
+ 'def foo(var0, /, var1: "MyClass") -> "MyClass":\n'
+ ' x: "MyClass"\n',
+
+ 'from __future__ import annotations\n'
+ 'def foo(var0, /, var1: MyClass) -> MyClass:\n'
+ ' x: MyClass\n',
+
+ id='posonly args',
+ ),
),
)
def test_fix_typing_pep563(s, expected):
ret = _fix_plugins(s, settings=Settings(min_version=(3, 7)))
assert ret == expected
-
-
[email protected](
- sys.version_info < (3, 8),
- reason='posonly args not available in Python3.7',
-)
-def test_fix_typing_pep563_posonlyargs():
- s = (
- 'from __future__ import annotations\n'
- 'def foo(var0, /, var1: "MyClass") -> "MyClass":\n'
- ' x: "MyClass"\n'
- )
- expected = (
- 'from __future__ import annotations\n'
- 'def foo(var0, /, var1: MyClass) -> MyClass:\n'
- ' x: MyClass\n'
- )
- ret = _fix_plugins(s, settings=Settings(min_version=(3, 8)))
- assert ret == expected
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyupgrade-3.2.2/tox.ini new/pyupgrade-3.4.0/tox.ini
--- old/pyupgrade-3.2.2/tox.ini 2022-11-10 16:38:09.000000000 +0100
+++ new/pyupgrade-3.4.0/tox.ini 2023-05-06 23:09:25.000000000 +0200
@@ -1,5 +1,5 @@
[tox]
-envlist = py37,py38,py39,pypy3,pre-commit
+envlist = py,pypy3,pre-commit
[testenv]
deps = -rrequirements-dev.txt