asottile /
add-trailing-comma
A tool (and pre-commit hook) to automatically add trailing commas to calls and literals.
83/100 healthLoading repository data…
asottile / repository
A tool (and pre-commit hook) to automatically upgrade syntax for newer versions of the language.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
A tool (and pre-commit hook) to automatically upgrade syntax for newer versions of the language.
pip install pyupgrade
See pre-commit for instructions
Sample .pre-commit-config.yaml:
- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:
- id: pyupgrade
-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}
-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}
collections.defaultdict calls-defaultdict(lambda: [])
+defaultdict(list)
-defaultdict(lambda: list())
+defaultdict(list)
-defaultdict(lambda: {})
+defaultdict(dict)
-defaultdict(lambda: dict())
+defaultdict(dict)
-defaultdict(lambda: ())
+defaultdict(tuple)
-defaultdict(lambda: tuple())
+defaultdict(tuple)
-defaultdict(lambda: set())
+defaultdict(set)
-defaultdict(lambda: 0)
+defaultdict(int)
-defaultdict(lambda: 0.0)
+defaultdict(float)
-defaultdict(lambda: 0j)
+defaultdict(complex)
-defaultdict(lambda: '')
+defaultdict(str)
-'{0} {1}'.format(1, 2)
+'{} {}'.format(1, 2)
-'{0}' '{1}'.format(1, 2)
+'{}' '{}'.format(1, 2)
Availability:
--keep-percent-format is passed.-'%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)
-u'foo'
+'foo'
-u"foo"
+'foo'
-u'''foo'''
+'''foo'''
# 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'
is / is not comparison to constant literalsIn python3.8+, comparison to literals becomes a SyntaxWarning as the success
of those comparisons is implementation specific (due to common object caching).
-x is 5
+x == 5
-x is not 5
+x != 5
-x is 'foo'
+x == 'foo'
.encode() to bytes literals-'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'
print(...)A fix for python-modernize/python-modernize#178
# 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")
isinstance / issubclass / except-isinstance(x, (int, int))
+isinstance(x, int)
-issubclass(y, (str, str))
+issubclass(y, str)
try:
raises()
-except (Error1, Error1, Error2):
+except (Error1, Error2):
pass
Rewrites deprecated unittest method aliases to their non-deprecated forms.
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 class C(Base):
def f(self):
- super(C, self).f()
+ super().f()
-class C(object): pass
+class C: pass
-class C(B, object): pass
+class C(B): pass
__metaclass__ = type declaration class C:
- __metaclass__ = type
str("native") literals-str()
+''
-str("foo")
+"foo"
.encode("utf-8")-"foo".encode("utf-8")
+"foo".encode()
# coding: ... commentas of PEP 3120, the default encoding for python source is UTF-8
-# coding: utf-8
x = 1
__future__ import removalAvailability:
nested_scopes, generators, with_statement,
absolute_import, division, print_function, unicode_literals--py37-plus will also remove generator_stop-from __future__ import with_statement
-from io import open
-from six.moves import map
-from builtins import object # python-future
Availability:
--py36-plus (and others) will replace importssee also reorder-python-imports
some examples:
-from collections import deque, Mapping
+from collections import deque
+from collections.abc import Mapping
-from typing import Sequence
+from collections.abc import Sequence
-from typing_extensions import Concatenate
+from typing import Concatenate
mock importsAvailability:
-from mock import patch
+from unittest.mock import patch
yield => yield from def f():
- for x in y:
- yield x
+ yield from y
- for a, b in c:
- yield (a, b)
+ yield from c
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 # 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.
six compatibility code-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-with io.open('f.txt') as f:
+with open('f.txt') as f:
...
open modes-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 # 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()
TimeoutError aliasesAvailability:
--py310-plus for socket.timeout--py311-plus for asyncio.TimeoutError
def throw(a):
if a:
- raise asyncio.TimeoutError('boom')
+ raise TimeoutError('boom')
else:
- raise socket.timeout('boom')
+ raise TimeoutError('boom')
def catch(a):
try:
throw(a)
- except (asyncio.TimeoutError, socket.timeout):
+ except TimeoutError:
handle_error()
typing.Text str alias-def f(x: Text) -> None:
+def f(x: str) -> None:
...
-foo, bar, baz = [fn(x) for x in items]
+foo, bar, baz = (fn(x) for x in items)
xml.etree.cElementTree to xml.etree.ElementTree-import xml.etree.cElementTree as ET
+import xml.etree.ElementTree as ET
-from xml.etree.cElementTree import XML
+from xml.etree.ElementTree import XML
type of primitive-type('')
+str
-type(b'')
+bytes
-type(0)
+int
-type(0.)
+float
typing.NamedTuple / typing.TypedDict py36+ syntaxAvailability:
--py36-plus is passed on the commandline.-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
Availability:
--py36-plus is passed on the commandline.-'{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
Selected from shared topics, language and repository description—not editorial ratings.
asottile /
A tool (and pre-commit hook) to automatically add trailing commas to calls and literals.
83/100 healtha5chin /
A production-ready Python development environment template using modern tools: uv for blazing-fast package management, Ruff for lightning-fast linting and formatting, ty for fast and reliable type checking, and VSCode Dev Containers for reproducible development environments.
88/100 healthgauraang01 /
This project proposes a cost-effective solution for testing AWS CloudFormation templates in through open-source tools. By integrating cfn-lint, cfn-nag, cfn-guard, cloud-radar, and localstack into a CI/CD pipeline through pre-commit and utilizing github actions .
fchastanet /
AI Linter is a validation tool for AI skills and agent configurations. It enforces structure, frontmatter, content length, token limits, and file reference checks for SKILL.md and AGENTS.md files. Includes YAML config, pre-commit, and VS Code integration for robust, automated linting in AI projects
44/100 healthofficial-mary /
Production-ready Ansible dev workstation setup — isolated Python env, VS Code tooling, SSH config, Git hooks and pre-commit linting.
42/100 healthlukepoo101 /
Template Repository for a UV based python application with pre commit tools and ruff for linting.
37/100 health