diff options
Diffstat (limited to 'python-pyupgrade.spec')
| -rw-r--r-- | python-pyupgrade.spec | 1696 |
1 files changed, 1696 insertions, 0 deletions
diff --git a/python-pyupgrade.spec b/python-pyupgrade.spec new file mode 100644 index 0000000..390a073 --- /dev/null +++ b/python-pyupgrade.spec @@ -0,0 +1,1696 @@ +%global _empty_manifest_terminate_build 0 +Name: python-pyupgrade +Version: 3.3.1 +Release: 1 +Summary: A tool to automatically upgrade syntax for newer versions. +License: MIT +URL: https://github.com/asottile/pyupgrade +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/b4/e8/4c3f29d281a6dcf7ffe19a19a446fd385b34802b3b33d25ebcc5ec03d285/pyupgrade-3.3.1.tar.gz +BuildArch: noarch + +Requires: python3-tokenize-rt + +%description +A tool (and pre-commit hook) to automatically upgrade syntax for newer +versions of the language. +## Installation +```bash +pip install pyupgrade +``` +## As a pre-commit hook +See [pre-commit](https://github.com/pre-commit/pre-commit) for instructions +Sample `.pre-commit-config.yaml`: +```yaml +- repo: https://github.com/asottile/pyupgrade + rev: v3.3.1 + hooks: + - id: pyupgrade +``` +## Implemented features +### Set literals +```diff +-set(()) ++set() +-set([]) ++set() +-set((1,)) ++{1} +-set((1, 2)) ++{1, 2} +-set([1, 2]) ++{1, 2} +-set(x for x in y) ++{x for x in y} +-set([x for x in y]) ++{x for x in y} +``` +### Dictionary comprehensions +```diff +-dict((a, b) for a, b in y) ++{a: b for a, b in y} +-dict([(a, b) for a, b in y]) ++{a: b for a, b in y} +``` +### Format Specifiers +```diff +-'{0} {1}'.format(1, 2) ++'{} {}'.format(1, 2) +-'{0}' '{1}'.format(1, 2) ++'{}' '{}'.format(1, 2) +``` +### printf-style string formatting +Availability: +- Unless `--keep-percent-format` is passed. +```diff +-'%s %s' % (a, b) ++'{} {}'.format(a, b) +-'%r %2f' % (a, b) ++'{!r} {:2f}'.format(a, b) +-'%(a)s %(b)s' % {'a': 1, 'b': 2} ++'{a} {b}'.format(a=1, b=2) +``` +### Unicode literals +```diff +-u'foo' ++'foo' +-u"foo" ++'foo' +-u'''foo''' ++'''foo''' +``` +### Invalid escape sequences +```diff + # strings with only invalid sequences become raw strings +-'\d' ++r'\d' + # strings with mixed valid / invalid sequences get escaped +-'\n\d' ++'\n\\d' +-u'\d' ++r'\d' + # this fixes a syntax error in python3.3+ +-'\N' ++r'\N' +# note: pyupgrade is timid in one case (that's usually a mistake) +# in python2.x `'\u2603'` is the same as `'\\u2603'` without `unicode_literals` +# but in python3.x, that's our friend ☃ +``` +### `is` / `is not` comparison to constant literals +In python3.8+, comparison to literals becomes a `SyntaxWarning` as the success +of those comparisons is implementation specific (due to common object caching). +```diff +-x is 5 ++x == 5 +-x is not 5 ++x != 5 +-x is 'foo' ++x == 'foo' +``` +### `.encode()` to bytes literals +```diff +-'foo'.encode() ++b'foo' +-'foo'.encode('ascii') ++b'foo' +-'foo'.encode('utf-8') ++b'foo' +-u'foo'.encode() ++b'foo' +-'\xa0'.encode('latin1') ++b'\xa0' +``` +### extraneous parens in `print(...)` +A fix for [python-modernize/python-modernize#178] +```diff + # ok: printing an empty tuple + print(()) + # ok: printing a tuple + print((1,)) + # ok: parenthesized generator argument + sum((i for i in range(3)), []) + # fixed: +-print(("foo")) ++print("foo") +``` +[python-modernize/python-modernize#178]: https://github.com/python-modernize/python-modernize/issues/178 +### unittest deprecated aliases +Rewrites [deprecated unittest method aliases](https://docs.python.org/3/library/unittest.html#deprecated-aliases) to their non-deprecated forms. +```diff + from unittest import TestCase + class MyTests(TestCase): + def test_something(self): +- self.failUnlessEqual(1, 1) ++ self.assertEqual(1, 1) +- self.assertEquals(1, 1) ++ self.assertEqual(1, 1) +``` +### `super()` calls +```diff + class C(Base): + def f(self): +- super(C, self).f() ++ super().f() +``` +### "new style" classes +#### rewrites class declaration +```diff +-class C(object): pass ++class C: pass +-class C(B, object): pass ++class C(B): pass +``` +#### removes `__metaclass__ = type` declaration +```diff + class C: +- __metaclass__ = type +``` +### forced `str("native")` literals +```diff +-str() ++'' +-str("foo") ++"foo" +``` +### `.encode("utf-8")` +```diff +-"foo".encode("utf-8") ++"foo".encode() +``` +### `# coding: ...` comment +as of [PEP 3120], the default encoding for python source is UTF-8 +```diff +-# coding: utf-8 + x = 1 +``` +[PEP 3120]: https://www.python.org/dev/peps/pep-3120/ +### `__future__` import removal +Availability: +- by default removes `nested_scopes`, `generators`, `with_statement`, + `absolute_import`, `division`, `print_function`, `unicode_literals` +- `--py37-plus` will also remove `generator_stop` +```diff +-from __future__ import with_statement +``` +### Remove unnecessary py3-compat imports +```diff +-from io import open +-from six.moves import map +-from builtins import object # python-future +``` +### import replacements +Availability: +- `--py36-plus` (and others) will replace imports +see also [reorder-python-imports](https://github.com/asottile/reorder_python_imports#removing--rewriting-obsolete-six-imports) +some examples: +```diff +-from collections import deque, Mapping ++from collections import deque ++from collections.abc import Mapping +``` +```diff +-from typing import Sequence ++from collections.abc import Sequence +``` +```diff +-from typing_extensions import Concatenate ++from typing import Concatenate +``` +### rewrite `mock` imports +Availability: +- [Unless `--keep-mock` is passed on the commandline](https://github.com/asottile/pyupgrade/issues/314). +```diff +-from mock import patch ++from unittest.mock import patch +``` +### `yield` => `yield from` +```diff + def f(): +- for x in y: +- yield x ++ yield from y +- for a, b in c: +- yield (a, b) ++ yield from c +``` +### Python2 and old Python3.x blocks +```diff + import sys +-if sys.version_info < (3,): # also understands `six.PY2` (and `not`), `six.PY3` (and `not`) +- print('py2') +-else: +- print('py3') ++print('py3') +``` +Availability: +- `--py36-plus` will remove Python <= 3.5 only blocks +- `--py37-plus` will remove Python <= 3.6 only blocks +- so on and so forth +```diff + # using --py36-plus for this example + import sys +-if sys.version_info < (3, 6): +- print('py3.5') +-else: +- print('py3.6+') ++print('py3.6+') +-if sys.version_info <= (3, 5): +- print('py3.5') +-else: +- print('py3.6+') ++print('py3.6+') +-if sys.version_info >= (3, 6): +- print('py3.6+') +-else: +- print('py3.5') ++print('py3.6+') +``` +Note that `if` blocks without an `else` will not be rewritten as it could introduce a syntax error. +### remove `six` compatibility code +```diff +-six.text_type ++str +-six.binary_type ++bytes +-six.class_types ++(type,) +-six.string_types ++(str,) +-six.integer_types ++(int,) +-six.unichr ++chr +-six.iterbytes ++iter +-six.print_(...) ++print(...) +-six.exec_(c, g, l) ++exec(c, g, l) +-six.advance_iterator(it) ++next(it) +-six.next(it) ++next(it) +-six.callable(x) ++callable(x) +-six.moves.range(x) ++range(x) +-six.moves.xrange(x) ++range(x) +-from six import text_type +-text_type ++str +-@six.python_2_unicode_compatible + class C: + def __str__(self): + return u'C()' +-class C(six.Iterator): pass ++class C: pass +-class C(six.with_metaclass(M, B)): pass ++class C(B, metaclass=M): pass +-@six.add_metaclass(M) +-class C(B): pass ++class C(B, metaclass=M): pass +-isinstance(..., six.class_types) ++isinstance(..., type) +-issubclass(..., six.integer_types) ++issubclass(..., int) +-isinstance(..., six.string_types) ++isinstance(..., str) +-six.b('...') ++b'...' +-six.u('...') ++'...' +-six.byte2int(bs) ++bs[0] +-six.indexbytes(bs, i) ++bs[i] +-six.int2byte(i) ++bytes((i,)) +-six.iteritems(dct) ++dct.items() +-six.iterkeys(dct) ++dct.keys() +-six.itervalues(dct) ++dct.values() +-next(six.iteritems(dct)) ++next(iter(dct.items())) +-next(six.iterkeys(dct)) ++next(iter(dct.keys())) +-next(six.itervalues(dct)) ++next(iter(dct.values())) +-six.viewitems(dct) ++dct.items() +-six.viewkeys(dct) ++dct.keys() +-six.viewvalues(dct) ++dct.values() +-six.create_unbound_method(fn, cls) ++fn +-six.get_unbound_function(meth) ++meth +-six.get_method_function(meth) ++meth.__func__ +-six.get_method_self(meth) ++meth.__self__ +-six.get_function_closure(fn) ++fn.__closure__ +-six.get_function_code(fn) ++fn.__code__ +-six.get_function_defaults(fn) ++fn.__defaults__ +-six.get_function_globals(fn) ++fn.__globals__ +-six.raise_from(exc, exc_from) ++raise exc from exc_from +-six.reraise(tp, exc, tb) ++raise exc.with_traceback(tb) +-six.reraise(*sys.exc_info()) ++raise +-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 +-with io.open('f.txt') as f: ++with open('f.txt') as f: +``` +### redundant `open` modes +```diff +-open("foo", "U") ++open("foo") +-open("foo", "Ur") ++open("foo") +-open("foo", "Ub") ++open("foo", "rb") +-open("foo", "rUb") ++open("foo", "rb") +-open("foo", "r") ++open("foo") +-open("foo", "rt") ++open("foo") +-open("f", "r", encoding="UTF-8") ++open("f", encoding="UTF-8") +-open("f", "wt") ++open("f", "w") +``` +### `OSError` aliases +```diff + # also understands: + # - IOError + # - WindowsError + # - mmap.error and uses of `from mmap import error` + # - select.error and uses of `from select import error` + # - socket.error and uses of `from socket import error` + def throw(): +- raise EnvironmentError('boom') ++ raise OSError('boom') + def catch(): + try: + throw() +- except EnvironmentError: ++ except OSError: + handle_error() +``` +### `typing.Text` str alias +```diff +-def f(x: Text) -> None: ++def f(x: str) -> None: +``` +### Unpacking list comprehensions +```diff +-foo, bar, baz = [fn(x) for x in items] ++foo, bar, baz = (fn(x) for x in items) +``` +### Rewrite `xml.etree.cElementTree` to `xml.etree.ElementTree` +```diff +-import xml.etree.cElementTree as ET ++import xml.etree.ElementTree as ET +-from xml.etree.cElementTree import XML ++from xml.etree.ElementTree import XML +``` +### Rewrite `type` of primitive +```diff +-type('') ++str +-type(b'') ++bytes +-type(0) ++int +-type(0.) ++float +``` +### `typing.NamedTuple` / `typing.TypedDict` py36+ syntax +Availability: +- `--py36-plus` is passed on the commandline. +```diff +-NT = typing.NamedTuple('NT', [('a', int), ('b', Tuple[str, ...])]) ++class NT(typing.NamedTuple): ++ a: int ++ b: Tuple[str, ...] +-D1 = typing.TypedDict('D1', a=int, b=str) ++class D1(typing.TypedDict): ++ a: int ++ b: str +-D2 = typing.TypedDict('D2', {'a': int, 'b': str}) ++class D2(typing.TypedDict): ++ a: int ++ b: str +``` +### f-strings +Availability: +- `--py36-plus` is passed on the commandline. +```diff +-'{foo} {bar}'.format(foo=foo, bar=bar) ++f'{foo} {bar}' +-'{} {}'.format(foo, bar) ++f'{foo} {bar}' +-'{} {}'.format(foo.bar, baz.womp) ++f'{foo.bar} {baz.womp}' +-'{} {}'.format(f(), g()) ++f'{f()} {g()}' +-'{x}'.format(**locals()) ++f'{x}' +``` +_note_: `pyupgrade` is intentionally timid and will not create an f-string +if it would make the expression longer or if the substitution parameters are +sufficiently complicated (as this can decrease readability). +### `subprocess.run`: replace `universal_newlines` with `text` +Availability: +- `--py37-plus` is passed on the commandline. +```diff +-output = subprocess.run(['foo'], universal_newlines=True) ++output = subprocess.run(['foo'], text=True) +``` +### `subprocess.run`: replace `stdout=subprocess.PIPE, stderr=subprocess.PIPE` with `capture_output=True` +Availability: +- `--py37-plus` is passed on the commandline. +```diff +-output = subprocess.run(['foo'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++output = subprocess.run(['foo'], capture_output=True) +``` +### remove parentheses from `@functools.lru_cache()` +Availability: +- `--py38-plus` is passed on the commandline. +```diff + import functools +-@functools.lru_cache() ++@functools.lru_cache + def expensive(): +``` +### replace `@functools.lru_cache(maxsize=None)` with shorthand +Availability: +- `--py39-plus` is passed on the commandline. +```diff + import functools +-@functools.lru_cache(maxsize=None) ++@functools.cache + def expensive(): +``` +### pep 585 typing rewrites +Availability: +- File imports `from __future__ import annotations` + - Unless `--keep-runtime-typing` is passed on the commandline. +- `--py39-plus` is passed on the commandline. +```diff +-def f(x: List[str]) -> None: ++def f(x: list[str]) -> None: +``` +### pep 604 typing rewrites +Availability: +- File imports `from __future__ import annotations` + - Unless `--keep-runtime-typing` is passed on the commandline. +- `--py310-plus` is passed on the commandline. +```diff +-def f() -> Optional[str]: ++def f() -> str | None: +``` +```diff +-def f() -> Union[int, str]: ++def f() -> int | str: +``` +### remove quoted annotations +Availability: +- File imports `from __future__ import annotations` +```diff +-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 +``` + +%package -n python3-pyupgrade +Summary: A tool to automatically upgrade syntax for newer versions. +Provides: python-pyupgrade +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-pyupgrade +A tool (and pre-commit hook) to automatically upgrade syntax for newer +versions of the language. +## Installation +```bash +pip install pyupgrade +``` +## As a pre-commit hook +See [pre-commit](https://github.com/pre-commit/pre-commit) for instructions +Sample `.pre-commit-config.yaml`: +```yaml +- repo: https://github.com/asottile/pyupgrade + rev: v3.3.1 + hooks: + - id: pyupgrade +``` +## Implemented features +### Set literals +```diff +-set(()) ++set() +-set([]) ++set() +-set((1,)) ++{1} +-set((1, 2)) ++{1, 2} +-set([1, 2]) ++{1, 2} +-set(x for x in y) ++{x for x in y} +-set([x for x in y]) ++{x for x in y} +``` +### Dictionary comprehensions +```diff +-dict((a, b) for a, b in y) ++{a: b for a, b in y} +-dict([(a, b) for a, b in y]) ++{a: b for a, b in y} +``` +### Format Specifiers +```diff +-'{0} {1}'.format(1, 2) ++'{} {}'.format(1, 2) +-'{0}' '{1}'.format(1, 2) ++'{}' '{}'.format(1, 2) +``` +### printf-style string formatting +Availability: +- Unless `--keep-percent-format` is passed. +```diff +-'%s %s' % (a, b) ++'{} {}'.format(a, b) +-'%r %2f' % (a, b) ++'{!r} {:2f}'.format(a, b) +-'%(a)s %(b)s' % {'a': 1, 'b': 2} ++'{a} {b}'.format(a=1, b=2) +``` +### Unicode literals +```diff +-u'foo' ++'foo' +-u"foo" ++'foo' +-u'''foo''' ++'''foo''' +``` +### Invalid escape sequences +```diff + # strings with only invalid sequences become raw strings +-'\d' ++r'\d' + # strings with mixed valid / invalid sequences get escaped +-'\n\d' ++'\n\\d' +-u'\d' ++r'\d' + # this fixes a syntax error in python3.3+ +-'\N' ++r'\N' +# note: pyupgrade is timid in one case (that's usually a mistake) +# in python2.x `'\u2603'` is the same as `'\\u2603'` without `unicode_literals` +# but in python3.x, that's our friend ☃ +``` +### `is` / `is not` comparison to constant literals +In python3.8+, comparison to literals becomes a `SyntaxWarning` as the success +of those comparisons is implementation specific (due to common object caching). +```diff +-x is 5 ++x == 5 +-x is not 5 ++x != 5 +-x is 'foo' ++x == 'foo' +``` +### `.encode()` to bytes literals +```diff +-'foo'.encode() ++b'foo' +-'foo'.encode('ascii') ++b'foo' +-'foo'.encode('utf-8') ++b'foo' +-u'foo'.encode() ++b'foo' +-'\xa0'.encode('latin1') ++b'\xa0' +``` +### extraneous parens in `print(...)` +A fix for [python-modernize/python-modernize#178] +```diff + # ok: printing an empty tuple + print(()) + # ok: printing a tuple + print((1,)) + # ok: parenthesized generator argument + sum((i for i in range(3)), []) + # fixed: +-print(("foo")) ++print("foo") +``` +[python-modernize/python-modernize#178]: https://github.com/python-modernize/python-modernize/issues/178 +### unittest deprecated aliases +Rewrites [deprecated unittest method aliases](https://docs.python.org/3/library/unittest.html#deprecated-aliases) to their non-deprecated forms. +```diff + from unittest import TestCase + class MyTests(TestCase): + def test_something(self): +- self.failUnlessEqual(1, 1) ++ self.assertEqual(1, 1) +- self.assertEquals(1, 1) ++ self.assertEqual(1, 1) +``` +### `super()` calls +```diff + class C(Base): + def f(self): +- super(C, self).f() ++ super().f() +``` +### "new style" classes +#### rewrites class declaration +```diff +-class C(object): pass ++class C: pass +-class C(B, object): pass ++class C(B): pass +``` +#### removes `__metaclass__ = type` declaration +```diff + class C: +- __metaclass__ = type +``` +### forced `str("native")` literals +```diff +-str() ++'' +-str("foo") ++"foo" +``` +### `.encode("utf-8")` +```diff +-"foo".encode("utf-8") ++"foo".encode() +``` +### `# coding: ...` comment +as of [PEP 3120], the default encoding for python source is UTF-8 +```diff +-# coding: utf-8 + x = 1 +``` +[PEP 3120]: https://www.python.org/dev/peps/pep-3120/ +### `__future__` import removal +Availability: +- by default removes `nested_scopes`, `generators`, `with_statement`, + `absolute_import`, `division`, `print_function`, `unicode_literals` +- `--py37-plus` will also remove `generator_stop` +```diff +-from __future__ import with_statement +``` +### Remove unnecessary py3-compat imports +```diff +-from io import open +-from six.moves import map +-from builtins import object # python-future +``` +### import replacements +Availability: +- `--py36-plus` (and others) will replace imports +see also [reorder-python-imports](https://github.com/asottile/reorder_python_imports#removing--rewriting-obsolete-six-imports) +some examples: +```diff +-from collections import deque, Mapping ++from collections import deque ++from collections.abc import Mapping +``` +```diff +-from typing import Sequence ++from collections.abc import Sequence +``` +```diff +-from typing_extensions import Concatenate ++from typing import Concatenate +``` +### rewrite `mock` imports +Availability: +- [Unless `--keep-mock` is passed on the commandline](https://github.com/asottile/pyupgrade/issues/314). +```diff +-from mock import patch ++from unittest.mock import patch +``` +### `yield` => `yield from` +```diff + def f(): +- for x in y: +- yield x ++ yield from y +- for a, b in c: +- yield (a, b) ++ yield from c +``` +### Python2 and old Python3.x blocks +```diff + import sys +-if sys.version_info < (3,): # also understands `six.PY2` (and `not`), `six.PY3` (and `not`) +- print('py2') +-else: +- print('py3') ++print('py3') +``` +Availability: +- `--py36-plus` will remove Python <= 3.5 only blocks +- `--py37-plus` will remove Python <= 3.6 only blocks +- so on and so forth +```diff + # using --py36-plus for this example + import sys +-if sys.version_info < (3, 6): +- print('py3.5') +-else: +- print('py3.6+') ++print('py3.6+') +-if sys.version_info <= (3, 5): +- print('py3.5') +-else: +- print('py3.6+') ++print('py3.6+') +-if sys.version_info >= (3, 6): +- print('py3.6+') +-else: +- print('py3.5') ++print('py3.6+') +``` +Note that `if` blocks without an `else` will not be rewritten as it could introduce a syntax error. +### remove `six` compatibility code +```diff +-six.text_type ++str +-six.binary_type ++bytes +-six.class_types ++(type,) +-six.string_types ++(str,) +-six.integer_types ++(int,) +-six.unichr ++chr +-six.iterbytes ++iter +-six.print_(...) ++print(...) +-six.exec_(c, g, l) ++exec(c, g, l) +-six.advance_iterator(it) ++next(it) +-six.next(it) ++next(it) +-six.callable(x) ++callable(x) +-six.moves.range(x) ++range(x) +-six.moves.xrange(x) ++range(x) +-from six import text_type +-text_type ++str +-@six.python_2_unicode_compatible + class C: + def __str__(self): + return u'C()' +-class C(six.Iterator): pass ++class C: pass +-class C(six.with_metaclass(M, B)): pass ++class C(B, metaclass=M): pass +-@six.add_metaclass(M) +-class C(B): pass ++class C(B, metaclass=M): pass +-isinstance(..., six.class_types) ++isinstance(..., type) +-issubclass(..., six.integer_types) ++issubclass(..., int) +-isinstance(..., six.string_types) ++isinstance(..., str) +-six.b('...') ++b'...' +-six.u('...') ++'...' +-six.byte2int(bs) ++bs[0] +-six.indexbytes(bs, i) ++bs[i] +-six.int2byte(i) ++bytes((i,)) +-six.iteritems(dct) ++dct.items() +-six.iterkeys(dct) ++dct.keys() +-six.itervalues(dct) ++dct.values() +-next(six.iteritems(dct)) ++next(iter(dct.items())) +-next(six.iterkeys(dct)) ++next(iter(dct.keys())) +-next(six.itervalues(dct)) ++next(iter(dct.values())) +-six.viewitems(dct) ++dct.items() +-six.viewkeys(dct) ++dct.keys() +-six.viewvalues(dct) ++dct.values() +-six.create_unbound_method(fn, cls) ++fn +-six.get_unbound_function(meth) ++meth +-six.get_method_function(meth) ++meth.__func__ +-six.get_method_self(meth) ++meth.__self__ +-six.get_function_closure(fn) ++fn.__closure__ +-six.get_function_code(fn) ++fn.__code__ +-six.get_function_defaults(fn) ++fn.__defaults__ +-six.get_function_globals(fn) ++fn.__globals__ +-six.raise_from(exc, exc_from) ++raise exc from exc_from +-six.reraise(tp, exc, tb) ++raise exc.with_traceback(tb) +-six.reraise(*sys.exc_info()) ++raise +-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 +-with io.open('f.txt') as f: ++with open('f.txt') as f: +``` +### redundant `open` modes +```diff +-open("foo", "U") ++open("foo") +-open("foo", "Ur") ++open("foo") +-open("foo", "Ub") ++open("foo", "rb") +-open("foo", "rUb") ++open("foo", "rb") +-open("foo", "r") ++open("foo") +-open("foo", "rt") ++open("foo") +-open("f", "r", encoding="UTF-8") ++open("f", encoding="UTF-8") +-open("f", "wt") ++open("f", "w") +``` +### `OSError` aliases +```diff + # also understands: + # - IOError + # - WindowsError + # - mmap.error and uses of `from mmap import error` + # - select.error and uses of `from select import error` + # - socket.error and uses of `from socket import error` + def throw(): +- raise EnvironmentError('boom') ++ raise OSError('boom') + def catch(): + try: + throw() +- except EnvironmentError: ++ except OSError: + handle_error() +``` +### `typing.Text` str alias +```diff +-def f(x: Text) -> None: ++def f(x: str) -> None: +``` +### Unpacking list comprehensions +```diff +-foo, bar, baz = [fn(x) for x in items] ++foo, bar, baz = (fn(x) for x in items) +``` +### Rewrite `xml.etree.cElementTree` to `xml.etree.ElementTree` +```diff +-import xml.etree.cElementTree as ET ++import xml.etree.ElementTree as ET +-from xml.etree.cElementTree import XML ++from xml.etree.ElementTree import XML +``` +### Rewrite `type` of primitive +```diff +-type('') ++str +-type(b'') ++bytes +-type(0) ++int +-type(0.) ++float +``` +### `typing.NamedTuple` / `typing.TypedDict` py36+ syntax +Availability: +- `--py36-plus` is passed on the commandline. +```diff +-NT = typing.NamedTuple('NT', [('a', int), ('b', Tuple[str, ...])]) ++class NT(typing.NamedTuple): ++ a: int ++ b: Tuple[str, ...] +-D1 = typing.TypedDict('D1', a=int, b=str) ++class D1(typing.TypedDict): ++ a: int ++ b: str +-D2 = typing.TypedDict('D2', {'a': int, 'b': str}) ++class D2(typing.TypedDict): ++ a: int ++ b: str +``` +### f-strings +Availability: +- `--py36-plus` is passed on the commandline. +```diff +-'{foo} {bar}'.format(foo=foo, bar=bar) ++f'{foo} {bar}' +-'{} {}'.format(foo, bar) ++f'{foo} {bar}' +-'{} {}'.format(foo.bar, baz.womp) ++f'{foo.bar} {baz.womp}' +-'{} {}'.format(f(), g()) ++f'{f()} {g()}' +-'{x}'.format(**locals()) ++f'{x}' +``` +_note_: `pyupgrade` is intentionally timid and will not create an f-string +if it would make the expression longer or if the substitution parameters are +sufficiently complicated (as this can decrease readability). +### `subprocess.run`: replace `universal_newlines` with `text` +Availability: +- `--py37-plus` is passed on the commandline. +```diff +-output = subprocess.run(['foo'], universal_newlines=True) ++output = subprocess.run(['foo'], text=True) +``` +### `subprocess.run`: replace `stdout=subprocess.PIPE, stderr=subprocess.PIPE` with `capture_output=True` +Availability: +- `--py37-plus` is passed on the commandline. +```diff +-output = subprocess.run(['foo'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++output = subprocess.run(['foo'], capture_output=True) +``` +### remove parentheses from `@functools.lru_cache()` +Availability: +- `--py38-plus` is passed on the commandline. +```diff + import functools +-@functools.lru_cache() ++@functools.lru_cache + def expensive(): +``` +### replace `@functools.lru_cache(maxsize=None)` with shorthand +Availability: +- `--py39-plus` is passed on the commandline. +```diff + import functools +-@functools.lru_cache(maxsize=None) ++@functools.cache + def expensive(): +``` +### pep 585 typing rewrites +Availability: +- File imports `from __future__ import annotations` + - Unless `--keep-runtime-typing` is passed on the commandline. +- `--py39-plus` is passed on the commandline. +```diff +-def f(x: List[str]) -> None: ++def f(x: list[str]) -> None: +``` +### pep 604 typing rewrites +Availability: +- File imports `from __future__ import annotations` + - Unless `--keep-runtime-typing` is passed on the commandline. +- `--py310-plus` is passed on the commandline. +```diff +-def f() -> Optional[str]: ++def f() -> str | None: +``` +```diff +-def f() -> Union[int, str]: ++def f() -> int | str: +``` +### remove quoted annotations +Availability: +- File imports `from __future__ import annotations` +```diff +-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 +``` + +%package help +Summary: Development documents and examples for pyupgrade +Provides: python3-pyupgrade-doc +%description help +A tool (and pre-commit hook) to automatically upgrade syntax for newer +versions of the language. +## Installation +```bash +pip install pyupgrade +``` +## As a pre-commit hook +See [pre-commit](https://github.com/pre-commit/pre-commit) for instructions +Sample `.pre-commit-config.yaml`: +```yaml +- repo: https://github.com/asottile/pyupgrade + rev: v3.3.1 + hooks: + - id: pyupgrade +``` +## Implemented features +### Set literals +```diff +-set(()) ++set() +-set([]) ++set() +-set((1,)) ++{1} +-set((1, 2)) ++{1, 2} +-set([1, 2]) ++{1, 2} +-set(x for x in y) ++{x for x in y} +-set([x for x in y]) ++{x for x in y} +``` +### Dictionary comprehensions +```diff +-dict((a, b) for a, b in y) ++{a: b for a, b in y} +-dict([(a, b) for a, b in y]) ++{a: b for a, b in y} +``` +### Format Specifiers +```diff +-'{0} {1}'.format(1, 2) ++'{} {}'.format(1, 2) +-'{0}' '{1}'.format(1, 2) ++'{}' '{}'.format(1, 2) +``` +### printf-style string formatting +Availability: +- Unless `--keep-percent-format` is passed. +```diff +-'%s %s' % (a, b) ++'{} {}'.format(a, b) +-'%r %2f' % (a, b) ++'{!r} {:2f}'.format(a, b) +-'%(a)s %(b)s' % {'a': 1, 'b': 2} ++'{a} {b}'.format(a=1, b=2) +``` +### Unicode literals +```diff +-u'foo' ++'foo' +-u"foo" ++'foo' +-u'''foo''' ++'''foo''' +``` +### Invalid escape sequences +```diff + # strings with only invalid sequences become raw strings +-'\d' ++r'\d' + # strings with mixed valid / invalid sequences get escaped +-'\n\d' ++'\n\\d' +-u'\d' ++r'\d' + # this fixes a syntax error in python3.3+ +-'\N' ++r'\N' +# note: pyupgrade is timid in one case (that's usually a mistake) +# in python2.x `'\u2603'` is the same as `'\\u2603'` without `unicode_literals` +# but in python3.x, that's our friend ☃ +``` +### `is` / `is not` comparison to constant literals +In python3.8+, comparison to literals becomes a `SyntaxWarning` as the success +of those comparisons is implementation specific (due to common object caching). +```diff +-x is 5 ++x == 5 +-x is not 5 ++x != 5 +-x is 'foo' ++x == 'foo' +``` +### `.encode()` to bytes literals +```diff +-'foo'.encode() ++b'foo' +-'foo'.encode('ascii') ++b'foo' +-'foo'.encode('utf-8') ++b'foo' +-u'foo'.encode() ++b'foo' +-'\xa0'.encode('latin1') ++b'\xa0' +``` +### extraneous parens in `print(...)` +A fix for [python-modernize/python-modernize#178] +```diff + # ok: printing an empty tuple + print(()) + # ok: printing a tuple + print((1,)) + # ok: parenthesized generator argument + sum((i for i in range(3)), []) + # fixed: +-print(("foo")) ++print("foo") +``` +[python-modernize/python-modernize#178]: https://github.com/python-modernize/python-modernize/issues/178 +### unittest deprecated aliases +Rewrites [deprecated unittest method aliases](https://docs.python.org/3/library/unittest.html#deprecated-aliases) to their non-deprecated forms. +```diff + from unittest import TestCase + class MyTests(TestCase): + def test_something(self): +- self.failUnlessEqual(1, 1) ++ self.assertEqual(1, 1) +- self.assertEquals(1, 1) ++ self.assertEqual(1, 1) +``` +### `super()` calls +```diff + class C(Base): + def f(self): +- super(C, self).f() ++ super().f() +``` +### "new style" classes +#### rewrites class declaration +```diff +-class C(object): pass ++class C: pass +-class C(B, object): pass ++class C(B): pass +``` +#### removes `__metaclass__ = type` declaration +```diff + class C: +- __metaclass__ = type +``` +### forced `str("native")` literals +```diff +-str() ++'' +-str("foo") ++"foo" +``` +### `.encode("utf-8")` +```diff +-"foo".encode("utf-8") ++"foo".encode() +``` +### `# coding: ...` comment +as of [PEP 3120], the default encoding for python source is UTF-8 +```diff +-# coding: utf-8 + x = 1 +``` +[PEP 3120]: https://www.python.org/dev/peps/pep-3120/ +### `__future__` import removal +Availability: +- by default removes `nested_scopes`, `generators`, `with_statement`, + `absolute_import`, `division`, `print_function`, `unicode_literals` +- `--py37-plus` will also remove `generator_stop` +```diff +-from __future__ import with_statement +``` +### Remove unnecessary py3-compat imports +```diff +-from io import open +-from six.moves import map +-from builtins import object # python-future +``` +### import replacements +Availability: +- `--py36-plus` (and others) will replace imports +see also [reorder-python-imports](https://github.com/asottile/reorder_python_imports#removing--rewriting-obsolete-six-imports) +some examples: +```diff +-from collections import deque, Mapping ++from collections import deque ++from collections.abc import Mapping +``` +```diff +-from typing import Sequence ++from collections.abc import Sequence +``` +```diff +-from typing_extensions import Concatenate ++from typing import Concatenate +``` +### rewrite `mock` imports +Availability: +- [Unless `--keep-mock` is passed on the commandline](https://github.com/asottile/pyupgrade/issues/314). +```diff +-from mock import patch ++from unittest.mock import patch +``` +### `yield` => `yield from` +```diff + def f(): +- for x in y: +- yield x ++ yield from y +- for a, b in c: +- yield (a, b) ++ yield from c +``` +### Python2 and old Python3.x blocks +```diff + import sys +-if sys.version_info < (3,): # also understands `six.PY2` (and `not`), `six.PY3` (and `not`) +- print('py2') +-else: +- print('py3') ++print('py3') +``` +Availability: +- `--py36-plus` will remove Python <= 3.5 only blocks +- `--py37-plus` will remove Python <= 3.6 only blocks +- so on and so forth +```diff + # using --py36-plus for this example + import sys +-if sys.version_info < (3, 6): +- print('py3.5') +-else: +- print('py3.6+') ++print('py3.6+') +-if sys.version_info <= (3, 5): +- print('py3.5') +-else: +- print('py3.6+') ++print('py3.6+') +-if sys.version_info >= (3, 6): +- print('py3.6+') +-else: +- print('py3.5') ++print('py3.6+') +``` +Note that `if` blocks without an `else` will not be rewritten as it could introduce a syntax error. +### remove `six` compatibility code +```diff +-six.text_type ++str +-six.binary_type ++bytes +-six.class_types ++(type,) +-six.string_types ++(str,) +-six.integer_types ++(int,) +-six.unichr ++chr +-six.iterbytes ++iter +-six.print_(...) ++print(...) +-six.exec_(c, g, l) ++exec(c, g, l) +-six.advance_iterator(it) ++next(it) +-six.next(it) ++next(it) +-six.callable(x) ++callable(x) +-six.moves.range(x) ++range(x) +-six.moves.xrange(x) ++range(x) +-from six import text_type +-text_type ++str +-@six.python_2_unicode_compatible + class C: + def __str__(self): + return u'C()' +-class C(six.Iterator): pass ++class C: pass +-class C(six.with_metaclass(M, B)): pass ++class C(B, metaclass=M): pass +-@six.add_metaclass(M) +-class C(B): pass ++class C(B, metaclass=M): pass +-isinstance(..., six.class_types) ++isinstance(..., type) +-issubclass(..., six.integer_types) ++issubclass(..., int) +-isinstance(..., six.string_types) ++isinstance(..., str) +-six.b('...') ++b'...' +-six.u('...') ++'...' +-six.byte2int(bs) ++bs[0] +-six.indexbytes(bs, i) ++bs[i] +-six.int2byte(i) ++bytes((i,)) +-six.iteritems(dct) ++dct.items() +-six.iterkeys(dct) ++dct.keys() +-six.itervalues(dct) ++dct.values() +-next(six.iteritems(dct)) ++next(iter(dct.items())) +-next(six.iterkeys(dct)) ++next(iter(dct.keys())) +-next(six.itervalues(dct)) ++next(iter(dct.values())) +-six.viewitems(dct) ++dct.items() +-six.viewkeys(dct) ++dct.keys() +-six.viewvalues(dct) ++dct.values() +-six.create_unbound_method(fn, cls) ++fn +-six.get_unbound_function(meth) ++meth +-six.get_method_function(meth) ++meth.__func__ +-six.get_method_self(meth) ++meth.__self__ +-six.get_function_closure(fn) ++fn.__closure__ +-six.get_function_code(fn) ++fn.__code__ +-six.get_function_defaults(fn) ++fn.__defaults__ +-six.get_function_globals(fn) ++fn.__globals__ +-six.raise_from(exc, exc_from) ++raise exc from exc_from +-six.reraise(tp, exc, tb) ++raise exc.with_traceback(tb) +-six.reraise(*sys.exc_info()) ++raise +-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 +-with io.open('f.txt') as f: ++with open('f.txt') as f: +``` +### redundant `open` modes +```diff +-open("foo", "U") ++open("foo") +-open("foo", "Ur") ++open("foo") +-open("foo", "Ub") ++open("foo", "rb") +-open("foo", "rUb") ++open("foo", "rb") +-open("foo", "r") ++open("foo") +-open("foo", "rt") ++open("foo") +-open("f", "r", encoding="UTF-8") ++open("f", encoding="UTF-8") +-open("f", "wt") ++open("f", "w") +``` +### `OSError` aliases +```diff + # also understands: + # - IOError + # - WindowsError + # - mmap.error and uses of `from mmap import error` + # - select.error and uses of `from select import error` + # - socket.error and uses of `from socket import error` + def throw(): +- raise EnvironmentError('boom') ++ raise OSError('boom') + def catch(): + try: + throw() +- except EnvironmentError: ++ except OSError: + handle_error() +``` +### `typing.Text` str alias +```diff +-def f(x: Text) -> None: ++def f(x: str) -> None: +``` +### Unpacking list comprehensions +```diff +-foo, bar, baz = [fn(x) for x in items] ++foo, bar, baz = (fn(x) for x in items) +``` +### Rewrite `xml.etree.cElementTree` to `xml.etree.ElementTree` +```diff +-import xml.etree.cElementTree as ET ++import xml.etree.ElementTree as ET +-from xml.etree.cElementTree import XML ++from xml.etree.ElementTree import XML +``` +### Rewrite `type` of primitive +```diff +-type('') ++str +-type(b'') ++bytes +-type(0) ++int +-type(0.) ++float +``` +### `typing.NamedTuple` / `typing.TypedDict` py36+ syntax +Availability: +- `--py36-plus` is passed on the commandline. +```diff +-NT = typing.NamedTuple('NT', [('a', int), ('b', Tuple[str, ...])]) ++class NT(typing.NamedTuple): ++ a: int ++ b: Tuple[str, ...] +-D1 = typing.TypedDict('D1', a=int, b=str) ++class D1(typing.TypedDict): ++ a: int ++ b: str +-D2 = typing.TypedDict('D2', {'a': int, 'b': str}) ++class D2(typing.TypedDict): ++ a: int ++ b: str +``` +### f-strings +Availability: +- `--py36-plus` is passed on the commandline. +```diff +-'{foo} {bar}'.format(foo=foo, bar=bar) ++f'{foo} {bar}' +-'{} {}'.format(foo, bar) ++f'{foo} {bar}' +-'{} {}'.format(foo.bar, baz.womp) ++f'{foo.bar} {baz.womp}' +-'{} {}'.format(f(), g()) ++f'{f()} {g()}' +-'{x}'.format(**locals()) ++f'{x}' +``` +_note_: `pyupgrade` is intentionally timid and will not create an f-string +if it would make the expression longer or if the substitution parameters are +sufficiently complicated (as this can decrease readability). +### `subprocess.run`: replace `universal_newlines` with `text` +Availability: +- `--py37-plus` is passed on the commandline. +```diff +-output = subprocess.run(['foo'], universal_newlines=True) ++output = subprocess.run(['foo'], text=True) +``` +### `subprocess.run`: replace `stdout=subprocess.PIPE, stderr=subprocess.PIPE` with `capture_output=True` +Availability: +- `--py37-plus` is passed on the commandline. +```diff +-output = subprocess.run(['foo'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++output = subprocess.run(['foo'], capture_output=True) +``` +### remove parentheses from `@functools.lru_cache()` +Availability: +- `--py38-plus` is passed on the commandline. +```diff + import functools +-@functools.lru_cache() ++@functools.lru_cache + def expensive(): +``` +### replace `@functools.lru_cache(maxsize=None)` with shorthand +Availability: +- `--py39-plus` is passed on the commandline. +```diff + import functools +-@functools.lru_cache(maxsize=None) ++@functools.cache + def expensive(): +``` +### pep 585 typing rewrites +Availability: +- File imports `from __future__ import annotations` + - Unless `--keep-runtime-typing` is passed on the commandline. +- `--py39-plus` is passed on the commandline. +```diff +-def f(x: List[str]) -> None: ++def f(x: list[str]) -> None: +``` +### pep 604 typing rewrites +Availability: +- File imports `from __future__ import annotations` + - Unless `--keep-runtime-typing` is passed on the commandline. +- `--py310-plus` is passed on the commandline. +```diff +-def f() -> Optional[str]: ++def f() -> str | None: +``` +```diff +-def f() -> Union[int, str]: ++def f() -> int | str: +``` +### remove quoted annotations +Availability: +- File imports `from __future__ import annotations` +```diff +-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 +``` + +%prep +%autosetup -n pyupgrade-3.3.1 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-pyupgrade -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Mon Apr 10 2023 Python_Bot <Python_Bot@openeuler.org> - 3.3.1-1 +- Package Spec generated |
