Merge pull request #719 from pre-commit/all-repos_autofix_drop-py36

drop python3.6 support
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d5d4778..4b49600 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -25,12 +25,12 @@
     rev: v2.6.0
     hooks:
     -   id: reorder-python-imports
-        args: [--py3-plus]
+        args: [--py37-plus, --add-import, 'from __future__ import annotations']
 -   repo: https://github.com/asottile/pyupgrade
     rev: v2.31.0
     hooks:
     -   id: pyupgrade
-        args: [--py36-plus]
+        args: [--py37-plus]
 -   repo: https://github.com/asottile/add-trailing-comma
     rev: v2.2.1
     hooks:
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 58dc61d..d54596e 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -10,7 +10,7 @@
       type: github
       endpoint: github
       name: asottile/azure-pipeline-templates
-      ref: refs/tags/v2.1.0
+      ref: refs/tags/v2.4.0
 
 jobs:
 - template: job--python-tox.yml@asottile
@@ -19,5 +19,5 @@
     os: windows
 - template: job--python-tox.yml@asottile
   parameters:
-    toxenvs: [pypy3, py36, py37, py38]
+    toxenvs: [py37, py38, py39, py310]
     os: linux
diff --git a/pre_commit_hooks/check_added_large_files.py b/pre_commit_hooks/check_added_large_files.py
index e1beb4e..79c8d4e 100644
--- a/pre_commit_hooks/check_added_large_files.py
+++ b/pre_commit_hooks/check_added_large_files.py
@@ -1,16 +1,16 @@
+from __future__ import annotations
+
 import argparse
 import math
 import os
 import subprocess
-from typing import Optional
 from typing import Sequence
-from typing import Set
 
 from pre_commit_hooks.util import added_files
 from pre_commit_hooks.util import zsplit
 
 
-def filter_lfs_files(filenames: Set[str]) -> None:  # pragma: no cover (lfs)
+def filter_lfs_files(filenames: set[str]) -> None:  # pragma: no cover (lfs)
     """Remove files tracked by git-lfs from the set."""
     if not filenames:
         return
@@ -54,7 +54,7 @@
     return retv
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         'filenames', nargs='*',
diff --git a/pre_commit_hooks/check_ast.py b/pre_commit_hooks/check_ast.py
index ab5661d..fdac361 100644
--- a/pre_commit_hooks/check_ast.py
+++ b/pre_commit_hooks/check_ast.py
@@ -1,13 +1,14 @@
+from __future__ import annotations
+
 import argparse
 import ast
 import platform
 import sys
 import traceback
-from typing import Optional
 from typing import Sequence
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_builtin_literals.py b/pre_commit_hooks/check_builtin_literals.py
index 3fbae3e..d3054aa 100644
--- a/pre_commit_hooks/check_builtin_literals.py
+++ b/pre_commit_hooks/check_builtin_literals.py
@@ -1,10 +1,9 @@
+from __future__ import annotations
+
 import argparse
 import ast
-from typing import List
 from typing import NamedTuple
-from typing import Optional
 from typing import Sequence
-from typing import Set
 
 
 BUILTIN_TYPES = {
@@ -27,10 +26,10 @@
 class Visitor(ast.NodeVisitor):
     def __init__(
             self,
-            ignore: Optional[Sequence[str]] = None,
+            ignore: Sequence[str] | None = None,
             allow_dict_kwargs: bool = True,
     ) -> None:
-        self.builtin_type_calls: List[Call] = []
+        self.builtin_type_calls: list[Call] = []
         self.ignore = set(ignore) if ignore else set()
         self.allow_dict_kwargs = allow_dict_kwargs
 
@@ -56,9 +55,9 @@
 
 def check_file(
         filename: str,
-        ignore: Optional[Sequence[str]] = None,
+        ignore: Sequence[str] | None = None,
         allow_dict_kwargs: bool = True,
-) -> List[Call]:
+) -> list[Call]:
     with open(filename, 'rb') as f:
         tree = ast.parse(f.read(), filename=filename)
     visitor = Visitor(ignore=ignore, allow_dict_kwargs=allow_dict_kwargs)
@@ -66,11 +65,11 @@
     return visitor.builtin_type_calls
 
 
-def parse_ignore(value: str) -> Set[str]:
+def parse_ignore(value: str) -> set[str]:
     return set(value.split(','))
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*')
     parser.add_argument('--ignore', type=parse_ignore, default=set())
diff --git a/pre_commit_hooks/check_byte_order_marker.py b/pre_commit_hooks/check_byte_order_marker.py
index fda05e8..59cc561 100644
--- a/pre_commit_hooks/check_byte_order_marker.py
+++ b/pre_commit_hooks/check_byte_order_marker.py
@@ -1,9 +1,10 @@
+from __future__ import annotations
+
 import argparse
-from typing import Optional
 from typing import Sequence
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to check')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_case_conflict.py b/pre_commit_hooks/check_case_conflict.py
index c3f39db..33a13f1 100644
--- a/pre_commit_hooks/check_case_conflict.py
+++ b/pre_commit_hooks/check_case_conflict.py
@@ -1,15 +1,15 @@
+from __future__ import annotations
+
 import argparse
 from typing import Iterable
 from typing import Iterator
-from typing import Optional
 from typing import Sequence
-from typing import Set
 
 from pre_commit_hooks.util import added_files
 from pre_commit_hooks.util import cmd_output
 
 
-def lower_set(iterable: Iterable[str]) -> Set[str]:
+def lower_set(iterable: Iterable[str]) -> set[str]:
     return {x.lower() for x in iterable}
 
 
@@ -21,7 +21,7 @@
         path_parts.pop()
 
 
-def directories_for(files: Set[str]) -> Set[str]:
+def directories_for(files: set[str]) -> set[str]:
     return {parent for file in files for parent in parents(file)}
 
 
@@ -56,7 +56,7 @@
     return retv
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         'filenames', nargs='*',
diff --git a/pre_commit_hooks/check_docstring_first.py b/pre_commit_hooks/check_docstring_first.py
index 875c0fb..1744919 100644
--- a/pre_commit_hooks/check_docstring_first.py
+++ b/pre_commit_hooks/check_docstring_first.py
@@ -1,8 +1,9 @@
+from __future__ import annotations
+
 import argparse
 import io
 import tokenize
 from tokenize import tokenize as tokenize_tokenize
-from typing import Optional
 from typing import Sequence
 
 NON_CODE_TOKENS = frozenset((
@@ -45,7 +46,7 @@
     return 0
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_executables_have_shebangs.py b/pre_commit_hooks/check_executables_have_shebangs.py
index 34af5ca..6b5402a 100644
--- a/pre_commit_hooks/check_executables_have_shebangs.py
+++ b/pre_commit_hooks/check_executables_have_shebangs.py
@@ -1,13 +1,12 @@
 """Check that executable text files have a shebang."""
+from __future__ import annotations
+
 import argparse
 import shlex
 import sys
 from typing import Generator
-from typing import List
 from typing import NamedTuple
-from typing import Optional
 from typing import Sequence
-from typing import Set
 
 from pre_commit_hooks.util import cmd_output
 from pre_commit_hooks.util import zsplit
@@ -15,7 +14,7 @@
 EXECUTABLE_VALUES = frozenset(('1', '3', '5', '7'))
 
 
-def check_executables(paths: List[str]) -> int:
+def check_executables(paths: list[str]) -> int:
     if sys.platform == 'win32':  # pragma: win32 cover
         return _check_git_filemode(paths)
     else:  # pragma: win32 no cover
@@ -42,7 +41,7 @@
 
 
 def _check_git_filemode(paths: Sequence[str]) -> int:
-    seen: Set[str] = set()
+    seen: set[str] = set()
     for ls_file in git_ls_files(paths):
         is_executable = any(b in EXECUTABLE_VALUES for b in ls_file.mode[-3:])
         if is_executable and not has_shebang(ls_file.filename):
@@ -71,7 +70,7 @@
     )
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument('filenames', nargs='*')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_json.py b/pre_commit_hooks/check_json.py
index 96ba024..6a679fe 100644
--- a/pre_commit_hooks/check_json.py
+++ b/pre_commit_hooks/check_json.py
@@ -1,16 +1,14 @@
+from __future__ import annotations
+
 import argparse
 import json
 from typing import Any
-from typing import Dict
-from typing import List
-from typing import Optional
 from typing import Sequence
-from typing import Tuple
 
 
 def raise_duplicate_keys(
-        ordered_pairs: List[Tuple[str, Any]],
-) -> Dict[str, Any]:
+        ordered_pairs: list[tuple[str, Any]],
+) -> dict[str, Any]:
     d = {}
     for key, val in ordered_pairs:
         if key in d:
@@ -20,7 +18,7 @@
     return d
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to check.')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_merge_conflict.py b/pre_commit_hooks/check_merge_conflict.py
index aed1e9c..22031a2 100644
--- a/pre_commit_hooks/check_merge_conflict.py
+++ b/pre_commit_hooks/check_merge_conflict.py
@@ -1,6 +1,7 @@
+from __future__ import annotations
+
 import argparse
 import os.path
-from typing import Optional
 from typing import Sequence
 
 from pre_commit_hooks.util import cmd_output
@@ -26,7 +27,7 @@
     )
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*')
     parser.add_argument('--assume-in-merge', action='store_true')
diff --git a/pre_commit_hooks/check_shebang_scripts_are_executable.py b/pre_commit_hooks/check_shebang_scripts_are_executable.py
index 50bc9c0..0f35650 100644
--- a/pre_commit_hooks/check_shebang_scripts_are_executable.py
+++ b/pre_commit_hooks/check_shebang_scripts_are_executable.py
@@ -1,18 +1,17 @@
 """Check that text files with a shebang are executable."""
+from __future__ import annotations
+
 import argparse
 import shlex
 import sys
-from typing import List
-from typing import Optional
 from typing import Sequence
-from typing import Set
 
 from pre_commit_hooks.check_executables_have_shebangs import EXECUTABLE_VALUES
 from pre_commit_hooks.check_executables_have_shebangs import git_ls_files
 from pre_commit_hooks.check_executables_have_shebangs import has_shebang
 
 
-def check_shebangs(paths: List[str]) -> int:
+def check_shebangs(paths: list[str]) -> int:
     # Cannot optimize on non-executability here if we intend this check to
     # work on win32 -- and that's where problems caused by non-executability
     # (elsewhere) are most likely to arise from.
@@ -20,7 +19,7 @@
 
 
 def _check_git_filemode(paths: Sequence[str]) -> int:
-    seen: Set[str] = set()
+    seen: set[str] = set()
     for ls_file in git_ls_files(paths):
         is_executable = any(b in EXECUTABLE_VALUES for b in ls_file.mode[-3:])
         if not is_executable and has_shebang(ls_file.filename):
@@ -41,7 +40,7 @@
     )
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument('filenames', nargs='*')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_symlinks.py b/pre_commit_hooks/check_symlinks.py
index db3b4fe..a85c82a 100644
--- a/pre_commit_hooks/check_symlinks.py
+++ b/pre_commit_hooks/check_symlinks.py
@@ -1,10 +1,11 @@
+from __future__ import annotations
+
 import argparse
 import os.path
-from typing import Optional
 from typing import Sequence
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser(description='Checks for broken symlinks.')
     parser.add_argument('filenames', nargs='*', help='Filenames to check')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_toml.py b/pre_commit_hooks/check_toml.py
index f623e68..88f7086 100644
--- a/pre_commit_hooks/check_toml.py
+++ b/pre_commit_hooks/check_toml.py
@@ -1,11 +1,12 @@
+from __future__ import annotations
+
 import argparse
-from typing import Optional
 from typing import Sequence
 
 import toml
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to check.')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_vcs_permalinks.py b/pre_commit_hooks/check_vcs_permalinks.py
index 1c77b9a..68639bd 100644
--- a/pre_commit_hooks/check_vcs_permalinks.py
+++ b/pre_commit_hooks/check_vcs_permalinks.py
@@ -1,8 +1,8 @@
+from __future__ import annotations
+
 import argparse
 import re
 import sys
-from typing import List
-from typing import Optional
 from typing import Pattern
 from typing import Sequence
 
@@ -15,7 +15,7 @@
     return re.compile(regex.encode())
 
 
-def _check_filename(filename: str, patterns: List[Pattern[bytes]]) -> int:
+def _check_filename(filename: str, patterns: list[Pattern[bytes]]) -> int:
     retv = 0
     with open(filename, 'rb') as f:
         for i, line in enumerate(f, 1):
@@ -28,7 +28,7 @@
     return retv
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*')
     parser.add_argument(
diff --git a/pre_commit_hooks/check_xml.py b/pre_commit_hooks/check_xml.py
index 0fa6bb2..c256af9 100644
--- a/pre_commit_hooks/check_xml.py
+++ b/pre_commit_hooks/check_xml.py
@@ -1,10 +1,11 @@
+from __future__ import annotations
+
 import argparse
 import xml.sax.handler
-from typing import Optional
 from typing import Sequence
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='XML filenames to check.')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/check_yaml.py b/pre_commit_hooks/check_yaml.py
index 5e86b73..250794e 100644
--- a/pre_commit_hooks/check_yaml.py
+++ b/pre_commit_hooks/check_yaml.py
@@ -1,8 +1,9 @@
+from __future__ import annotations
+
 import argparse
 from typing import Any
 from typing import Generator
 from typing import NamedTuple
-from typing import Optional
 from typing import Sequence
 
 import ruamel.yaml
@@ -36,7 +37,7 @@
 }
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         '-m', '--multi', '--allow-multiple-documents', action='store_true',
diff --git a/pre_commit_hooks/debug_statement_hook.py b/pre_commit_hooks/debug_statement_hook.py
index f78d6d6..00b6798 100644
--- a/pre_commit_hooks/debug_statement_hook.py
+++ b/pre_commit_hooks/debug_statement_hook.py
@@ -1,9 +1,9 @@
+from __future__ import annotations
+
 import argparse
 import ast
 import traceback
-from typing import List
 from typing import NamedTuple
-from typing import Optional
 from typing import Sequence
 
 
@@ -29,7 +29,7 @@
 
 class DebugStatementParser(ast.NodeVisitor):
     def __init__(self) -> None:
-        self.breakpoints: List[Debug] = []
+        self.breakpoints: list[Debug] = []
 
     def visit_Import(self, node: ast.Import) -> None:
         for name in node.names:
@@ -70,7 +70,7 @@
     return int(bool(visitor.breakpoints))
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to run')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/destroyed_symlinks.py b/pre_commit_hooks/destroyed_symlinks.py
index a3f122f..88253c0 100644
--- a/pre_commit_hooks/destroyed_symlinks.py
+++ b/pre_commit_hooks/destroyed_symlinks.py
@@ -1,8 +1,8 @@
+from __future__ import annotations
+
 import argparse
 import shlex
 import subprocess
-from typing import List
-from typing import Optional
 from typing import Sequence
 
 from pre_commit_hooks.util import cmd_output
@@ -13,8 +13,8 @@
 PERMS_NONEXIST = '000000'
 
 
-def find_destroyed_symlinks(files: Sequence[str]) -> List[str]:
-    destroyed_links: List[str] = []
+def find_destroyed_symlinks(files: Sequence[str]) -> list[str]:
+    destroyed_links: list[str] = []
     if not files:
         return destroyed_links
     for line in zsplit(
@@ -66,7 +66,7 @@
     return destroyed_links
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to check.')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/detect_aws_credentials.py b/pre_commit_hooks/detect_aws_credentials.py
index ba1d789..4f59d9c 100644
--- a/pre_commit_hooks/detect_aws_credentials.py
+++ b/pre_commit_hooks/detect_aws_credentials.py
@@ -1,11 +1,10 @@
+from __future__ import annotations
+
 import argparse
 import configparser
 import os
-from typing import List
 from typing import NamedTuple
-from typing import Optional
 from typing import Sequence
-from typing import Set
 
 
 class BadFile(NamedTuple):
@@ -13,7 +12,7 @@
     key: str
 
 
-def get_aws_cred_files_from_env() -> Set[str]:
+def get_aws_cred_files_from_env() -> set[str]:
     """Extract credential file paths from environment variables."""
     return {
         os.environ[env_var]
@@ -25,7 +24,7 @@
     }
 
 
-def get_aws_secrets_from_env() -> Set[str]:
+def get_aws_secrets_from_env() -> set[str]:
     """Extract AWS secrets from environment variables."""
     keys = set()
     for env_var in (
@@ -36,7 +35,7 @@
     return keys
 
 
-def get_aws_secrets_from_file(credentials_file: str) -> Set[str]:
+def get_aws_secrets_from_file(credentials_file: str) -> set[str]:
     """Extract AWS secrets from configuration files.
 
     Read an ini-style configuration file and return a set with all found AWS
@@ -69,8 +68,8 @@
 
 def check_file_for_aws_keys(
         filenames: Sequence[str],
-        keys: Set[bytes],
-) -> List[BadFile]:
+        keys: set[bytes],
+) -> list[BadFile]:
     """Check if files contain AWS secrets.
 
     Return a list of all files containing AWS secrets and keys found, with all
@@ -90,7 +89,7 @@
     return bad_files
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='+', help='Filenames to run')
     parser.add_argument(
@@ -119,7 +118,7 @@
     # of files to to gather AWS secrets from.
     credential_files |= get_aws_cred_files_from_env()
 
-    keys: Set[str] = set()
+    keys: set[str] = set()
     for credential_file in credential_files:
         keys |= get_aws_secrets_from_file(credential_file)
 
diff --git a/pre_commit_hooks/detect_private_key.py b/pre_commit_hooks/detect_private_key.py
index 18f9539..cd51f90 100644
--- a/pre_commit_hooks/detect_private_key.py
+++ b/pre_commit_hooks/detect_private_key.py
@@ -1,5 +1,6 @@
+from __future__ import annotations
+
 import argparse
-from typing import Optional
 from typing import Sequence
 
 BLACKLIST = [
@@ -16,7 +17,7 @@
 ]
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to check')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/end_of_file_fixer.py b/pre_commit_hooks/end_of_file_fixer.py
index 40e8821..a30dce9 100644
--- a/pre_commit_hooks/end_of_file_fixer.py
+++ b/pre_commit_hooks/end_of_file_fixer.py
@@ -1,7 +1,8 @@
+from __future__ import annotations
+
 import argparse
 import os
 from typing import IO
-from typing import Optional
 from typing import Sequence
 
 
@@ -48,7 +49,7 @@
     return 0
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to fix')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/file_contents_sorter.py b/pre_commit_hooks/file_contents_sorter.py
index 392e226..c5691f0 100644
--- a/pre_commit_hooks/file_contents_sorter.py
+++ b/pre_commit_hooks/file_contents_sorter.py
@@ -9,12 +9,13 @@
 this hook on that file should reduce the instances of git merge
 conflicts and keep the file nicely ordered.
 """
+from __future__ import annotations
+
 import argparse
 from typing import Any
 from typing import Callable
 from typing import IO
 from typing import Iterable
-from typing import Optional
 from typing import Sequence
 
 PASS = 0
@@ -23,7 +24,7 @@
 
 def sort_file_contents(
     f: IO[bytes],
-    key: Optional[Callable[[bytes], Any]],
+    key: Callable[[bytes], Any] | None,
     *,
     unique: bool = False,
 ) -> int:
@@ -47,7 +48,7 @@
         return FAIL
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='+', help='Files to sort')
     parser.add_argument(
diff --git a/pre_commit_hooks/fix_byte_order_marker.py b/pre_commit_hooks/fix_byte_order_marker.py
index 51b94e1..22a4990 100644
--- a/pre_commit_hooks/fix_byte_order_marker.py
+++ b/pre_commit_hooks/fix_byte_order_marker.py
@@ -1,9 +1,10 @@
+from __future__ import annotations
+
 import argparse
-from typing import Optional
 from typing import Sequence
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to check')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/fix_encoding_pragma.py b/pre_commit_hooks/fix_encoding_pragma.py
index c704774..60c71ee 100644
--- a/pre_commit_hooks/fix_encoding_pragma.py
+++ b/pre_commit_hooks/fix_encoding_pragma.py
@@ -1,7 +1,8 @@
+from __future__ import annotations
+
 import argparse
 from typing import IO
 from typing import NamedTuple
-from typing import Optional
 from typing import Sequence
 
 DEFAULT_PRAGMA = b'# -*- coding: utf-8 -*-'
@@ -26,7 +27,7 @@
     # True: has exactly the coding pragma expected
     # False: missing coding pragma entirely
     # None: has a coding pragma, but it does not match
-    pragma_status: Optional[bool]
+    pragma_status: bool | None
     ending: bytes
 
     @property
@@ -55,7 +56,7 @@
         rest = second_line + rest
 
     if potential_coding.rstrip(b'\r\n') == expected_pragma:
-        pragma_status: Optional[bool] = True
+        pragma_status: bool | None = True
     elif has_coding(potential_coding):
         pragma_status = None
     else:
@@ -105,7 +106,7 @@
     return pragma.encode().rstrip()
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser(
         'Fixes the encoding pragma of python files',
     )
diff --git a/pre_commit_hooks/forbid_new_submodules.py b/pre_commit_hooks/forbid_new_submodules.py
index 0275808..b806cad 100644
--- a/pre_commit_hooks/forbid_new_submodules.py
+++ b/pre_commit_hooks/forbid_new_submodules.py
@@ -1,12 +1,13 @@
+from __future__ import annotations
+
 import argparse
 import os
-from typing import Optional
 from typing import Sequence
 
 from pre_commit_hooks.util import cmd_output
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/mixed_line_ending.py b/pre_commit_hooks/mixed_line_ending.py
index 4e07ed9..0328e86 100644
--- a/pre_commit_hooks/mixed_line_ending.py
+++ b/pre_commit_hooks/mixed_line_ending.py
@@ -1,7 +1,7 @@
+from __future__ import annotations
+
 import argparse
 import collections
-from typing import Dict
-from typing import Optional
 from typing import Sequence
 
 
@@ -25,7 +25,7 @@
     with open(filename, 'rb') as f:
         contents = f.read()
 
-    counts: Dict[bytes, int] = collections.defaultdict(int)
+    counts: dict[bytes, int] = collections.defaultdict(int)
 
     for line in contents.splitlines(True):
         for ending in ALL_ENDINGS:
@@ -62,7 +62,7 @@
         return other_endings
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         '-f', '--fix',
diff --git a/pre_commit_hooks/no_commit_to_branch.py b/pre_commit_hooks/no_commit_to_branch.py
index db84850..741f726 100644
--- a/pre_commit_hooks/no_commit_to_branch.py
+++ b/pre_commit_hooks/no_commit_to_branch.py
@@ -1,7 +1,8 @@
+from __future__ import annotations
+
 import argparse
 import re
 from typing import AbstractSet
-from typing import Optional
 from typing import Sequence
 
 from pre_commit_hooks.util import CalledProcessError
@@ -23,7 +24,7 @@
     )
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         '-b', '--branch', action='append',
diff --git a/pre_commit_hooks/pretty_format_json.py b/pre_commit_hooks/pretty_format_json.py
index 33ad5a1..627a11c 100644
--- a/pre_commit_hooks/pretty_format_json.py
+++ b/pre_commit_hooks/pretty_format_json.py
@@ -1,13 +1,11 @@
+from __future__ import annotations
+
 import argparse
 import json
 import sys
 from difflib import unified_diff
-from typing import List
 from typing import Mapping
-from typing import Optional
 from typing import Sequence
-from typing import Tuple
-from typing import Union
 
 
 def _get_pretty_format(
@@ -17,7 +15,7 @@
         sort_keys: bool = True,
         top_keys: Sequence[str] = (),
 ) -> str:
-    def pairs_first(pairs: Sequence[Tuple[str, str]]) -> Mapping[str, str]:
+    def pairs_first(pairs: Sequence[tuple[str, str]]) -> Mapping[str, str]:
         before = [pair for pair in pairs if pair[0] in top_keys]
         before = sorted(before, key=lambda x: top_keys.index(x[0]))
         after = [pair for pair in pairs if pair[0] not in top_keys]
@@ -38,7 +36,7 @@
         f.write(new_contents)
 
 
-def parse_num_to_int(s: str) -> Union[int, str]:
+def parse_num_to_int(s: str) -> int | str:
     """Convert string numbers to int, leaving strings as is."""
     try:
         return int(s)
@@ -46,7 +44,7 @@
         return s
 
 
-def parse_topkeys(s: str) -> List[str]:
+def parse_topkeys(s: str) -> list[str]:
     return s.split(',')
 
 
@@ -57,7 +55,7 @@
     return ''.join(diff)
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         '--autofix',
diff --git a/pre_commit_hooks/removed.py b/pre_commit_hooks/removed.py
index 236cbf8..6f6c7b7 100644
--- a/pre_commit_hooks/removed.py
+++ b/pre_commit_hooks/removed.py
@@ -1,9 +1,10 @@
+from __future__ import annotations
+
 import sys
-from typing import Optional
 from typing import Sequence
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     argv = argv if argv is not None else sys.argv[1:]
     hookid, new_hookid, url = argv[:3]
     raise SystemExit(
diff --git a/pre_commit_hooks/requirements_txt_fixer.py b/pre_commit_hooks/requirements_txt_fixer.py
index 63f891f..5884394 100644
--- a/pre_commit_hooks/requirements_txt_fixer.py
+++ b/pre_commit_hooks/requirements_txt_fixer.py
@@ -1,8 +1,8 @@
+from __future__ import annotations
+
 import argparse
 import re
 from typing import IO
-from typing import List
-from typing import Optional
 from typing import Sequence
 
 
@@ -15,8 +15,8 @@
     UNTIL_SEP = re.compile(rb'[^;\s]+')
 
     def __init__(self) -> None:
-        self.value: Optional[bytes] = None
-        self.comments: List[bytes] = []
+        self.value: bytes | None = None
+        self.comments: list[bytes] = []
 
     @property
     def name(self) -> bytes:
@@ -36,7 +36,7 @@
 
         return name[:m.start()]
 
-    def __lt__(self, requirement: 'Requirement') -> bool:
+    def __lt__(self, requirement: Requirement) -> bool:
         # \n means top of file comment, so always return True,
         # otherwise just do a string comparison with value.
         assert self.value is not None, self.value
@@ -61,9 +61,9 @@
 
 
 def fix_requirements(f: IO[bytes]) -> int:
-    requirements: List[Requirement] = []
+    requirements: list[Requirement] = []
     before = list(f)
-    after: List[bytes] = []
+    after: list[bytes] = []
 
     before_string = b''.join(before)
 
@@ -130,7 +130,7 @@
         return FAIL
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to fix')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/sort_simple_yaml.py b/pre_commit_hooks/sort_simple_yaml.py
index 39f683e..116b5c1 100644
--- a/pre_commit_hooks/sort_simple_yaml.py
+++ b/pre_commit_hooks/sort_simple_yaml.py
@@ -17,16 +17,16 @@
 In other words, we don't sort deeper than the top layer, and might corrupt
 complicated YAML files.
 """
+from __future__ import annotations
+
 import argparse
-from typing import List
-from typing import Optional
 from typing import Sequence
 
 
 QUOTES = ["'", '"']
 
 
-def sort(lines: List[str]) -> List[str]:
+def sort(lines: list[str]) -> list[str]:
     """Sort a YAML file in alphabetical order, keeping blocks together.
 
     :param lines: array of strings (without newlines)
@@ -44,7 +44,7 @@
     return new_lines
 
 
-def parse_block(lines: List[str], header: bool = False) -> List[str]:
+def parse_block(lines: list[str], header: bool = False) -> list[str]:
     """Parse and return a single block, popping off the start of `lines`.
 
     If parsing a header block, we stop after we reach a line that is not a
@@ -60,7 +60,7 @@
     return block_lines
 
 
-def parse_blocks(lines: List[str]) -> List[List[str]]:
+def parse_blocks(lines: list[str]) -> list[list[str]]:
     """Parse and return all possible blocks, popping off the start of `lines`.
 
     :param lines: list of lines
@@ -77,7 +77,7 @@
     return blocks
 
 
-def first_key(lines: List[str]) -> str:
+def first_key(lines: list[str]) -> str:
     """Returns a string representing the sort key of a block.
 
     The sort key is the first YAML key we encounter, ignoring comments, and
@@ -99,7 +99,7 @@
         return ''  # not actually reached in reality
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to fix')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/string_fixer.py b/pre_commit_hooks/string_fixer.py
index a08a5f7..0ef9bc7 100644
--- a/pre_commit_hooks/string_fixer.py
+++ b/pre_commit_hooks/string_fixer.py
@@ -1,9 +1,9 @@
+from __future__ import annotations
+
 import argparse
 import io
 import re
 import tokenize
-from typing import List
-from typing import Optional
 from typing import Sequence
 
 START_QUOTE_RE = re.compile('^[a-zA-Z]*"')
@@ -24,7 +24,7 @@
         return token_text
 
 
-def get_line_offsets_by_line_no(src: str) -> List[int]:
+def get_line_offsets_by_line_no(src: str) -> list[int]:
     # Padded so we can index with line number
     offsets = [-1, 0]
     for line in src.splitlines(True):
@@ -60,7 +60,7 @@
         return 0
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*', help='Filenames to fix')
     args = parser.parse_args(argv)
diff --git a/pre_commit_hooks/tests_should_end_in_test.py b/pre_commit_hooks/tests_should_end_in_test.py
index bffb0c4..e1ffe36 100644
--- a/pre_commit_hooks/tests_should_end_in_test.py
+++ b/pre_commit_hooks/tests_should_end_in_test.py
@@ -1,11 +1,12 @@
+from __future__ import annotations
+
 import argparse
 import os.path
 import re
-from typing import Optional
 from typing import Sequence
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument('filenames', nargs='*')
     parser.add_argument(
diff --git a/pre_commit_hooks/trailing_whitespace_fixer.py b/pre_commit_hooks/trailing_whitespace_fixer.py
index 82faa2d..84f5067 100644
--- a/pre_commit_hooks/trailing_whitespace_fixer.py
+++ b/pre_commit_hooks/trailing_whitespace_fixer.py
@@ -1,13 +1,14 @@
+from __future__ import annotations
+
 import argparse
 import os
-from typing import Optional
 from typing import Sequence
 
 
 def _fix_file(
         filename: str,
         is_markdown: bool,
-        chars: Optional[bytes],
+        chars: bytes | None,
 ) -> bool:
     with open(filename, mode='rb') as file_processed:
         lines = file_processed.readlines()
@@ -24,7 +25,7 @@
 def _process_line(
         line: bytes,
         is_markdown: bool,
-        chars: Optional[bytes],
+        chars: bytes | None,
 ) -> bytes:
     if line[-2:] == b'\r\n':
         eol = b'\r\n'
@@ -40,7 +41,7 @@
     return line.rstrip(chars) + eol
 
 
-def main(argv: Optional[Sequence[str]] = None) -> int:
+def main(argv: Sequence[str] | None = None) -> int:
     parser = argparse.ArgumentParser()
     parser.add_argument(
         '--no-markdown-linebreak-ext',
diff --git a/pre_commit_hooks/util.py b/pre_commit_hooks/util.py
index 402e33e..d6c90ae 100644
--- a/pre_commit_hooks/util.py
+++ b/pre_commit_hooks/util.py
@@ -1,20 +1,19 @@
+from __future__ import annotations
+
 import subprocess
 from typing import Any
-from typing import List
-from typing import Optional
-from typing import Set
 
 
 class CalledProcessError(RuntimeError):
     pass
 
 
-def added_files() -> Set[str]:
+def added_files() -> set[str]:
     cmd = ('git', 'diff', '--staged', '--name-only', '--diff-filter=A')
     return set(cmd_output(*cmd).splitlines())
 
 
-def cmd_output(*cmd: str, retcode: Optional[int] = 0, **kwargs: Any) -> str:
+def cmd_output(*cmd: str, retcode: int | None = 0, **kwargs: Any) -> str:
     kwargs.setdefault('stdout', subprocess.PIPE)
     kwargs.setdefault('stderr', subprocess.PIPE)
     proc = subprocess.Popen(cmd, **kwargs)
@@ -25,7 +24,7 @@
     return stdout
 
 
-def zsplit(s: str) -> List[str]:
+def zsplit(s: str) -> list[str]:
     s = s.strip('\0')
     if s:
         return s.split('\0')
diff --git a/setup.cfg b/setup.cfg
index 45498eb..5b0f7ca 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -13,7 +13,6 @@
     License :: OSI Approved :: MIT License
     Programming Language :: Python :: 3
     Programming Language :: Python :: 3 :: Only
-    Programming Language :: Python :: 3.6
     Programming Language :: Python :: 3.7
     Programming Language :: Python :: 3.8
     Programming Language :: Python :: 3.9
@@ -26,7 +25,7 @@
 install_requires =
     ruamel.yaml>=0.15
     toml
-python_requires = >=3.6.1
+python_requires = >=3.7
 
 [options.packages.find]
 exclude =
diff --git a/setup.py b/setup.py
index 8bf1ba9..3d93aef 100644
--- a/setup.py
+++ b/setup.py
@@ -1,2 +1,4 @@
+from __future__ import annotations
+
 from setuptools import setup
 setup()
diff --git a/testing/util.py b/testing/util.py
index 5043754..2bbbe64 100644
--- a/testing/util.py
+++ b/testing/util.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os.path
 import subprocess
 
diff --git a/tests/check_added_large_files_test.py b/tests/check_added_large_files_test.py
index c16bf5a..54c4e68 100644
--- a/tests/check_added_large_files_test.py
+++ b/tests/check_added_large_files_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import shutil
 
 import pytest
diff --git a/tests/check_ast_test.py b/tests/check_ast_test.py
index 686fd11..6243966 100644
--- a/tests/check_ast_test.py
+++ b/tests/check_ast_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from pre_commit_hooks.check_ast import main
 from testing.util import get_resource_path
 
diff --git a/tests/check_builtin_literals_test.py b/tests/check_builtin_literals_test.py
index e936798..1b18257 100644
--- a/tests/check_builtin_literals_test.py
+++ b/tests/check_builtin_literals_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import ast
 
 import pytest
diff --git a/tests/check_byte_order_marker_test.py b/tests/check_byte_order_marker_test.py
index 4c40247..909a39b 100644
--- a/tests/check_byte_order_marker_test.py
+++ b/tests/check_byte_order_marker_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from pre_commit_hooks import check_byte_order_marker
 
 
diff --git a/tests/check_case_conflict_test.py b/tests/check_case_conflict_test.py
index d9211b5..a914f45 100644
--- a/tests/check_case_conflict_test.py
+++ b/tests/check_case_conflict_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import sys
 
 import pytest
diff --git a/tests/check_docstring_first_test.py b/tests/check_docstring_first_test.py
index ed5c08e..079896f 100644
--- a/tests/check_docstring_first_test.py
+++ b/tests/check_docstring_first_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.check_docstring_first import check_docstring_first
diff --git a/tests/check_executables_have_shebangs_test.py b/tests/check_executables_have_shebangs_test.py
index 5703ede..82d03e3 100644
--- a/tests/check_executables_have_shebangs_test.py
+++ b/tests/check_executables_have_shebangs_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 import sys
 
diff --git a/tests/check_json_test.py b/tests/check_json_test.py
index 3ec67f1..53e1f52 100644
--- a/tests/check_json_test.py
+++ b/tests/check_json_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.check_json import main
diff --git a/tests/check_merge_conflict_test.py b/tests/check_merge_conflict_test.py
index 79c1b11..d3322db 100644
--- a/tests/check_merge_conflict_test.py
+++ b/tests/check_merge_conflict_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 import shutil
 
diff --git a/tests/check_shebang_scripts_are_executable_test.py b/tests/check_shebang_scripts_are_executable_test.py
index 9e78b06..e4bd07c 100644
--- a/tests/check_shebang_scripts_are_executable_test.py
+++ b/tests/check_shebang_scripts_are_executable_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 
 import pytest
diff --git a/tests/check_symlinks_test.py b/tests/check_symlinks_test.py
index 07c1168..e2c2c78 100644
--- a/tests/check_symlinks_test.py
+++ b/tests/check_symlinks_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 
 import pytest
diff --git a/tests/check_toml_test.py b/tests/check_toml_test.py
index c7251eb..d594f81 100644
--- a/tests/check_toml_test.py
+++ b/tests/check_toml_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from pre_commit_hooks.check_toml import main
 
 
diff --git a/tests/check_vcs_permalinks_test.py b/tests/check_vcs_permalinks_test.py
index ad59151..01ce94d 100644
--- a/tests/check_vcs_permalinks_test.py
+++ b/tests/check_vcs_permalinks_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from pre_commit_hooks.check_vcs_permalinks import main
 
 
diff --git a/tests/check_xml_test.py b/tests/check_xml_test.py
index 357bad6..767619f 100644
--- a/tests/check_xml_test.py
+++ b/tests/check_xml_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.check_xml import main
diff --git a/tests/check_yaml_test.py b/tests/check_yaml_test.py
index 1a017a1..54eb16e 100644
--- a/tests/check_yaml_test.py
+++ b/tests/check_yaml_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.check_yaml import main
diff --git a/tests/conftest.py b/tests/conftest.py
index f92cfc1..807f15b 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.util import cmd_output
diff --git a/tests/debug_statement_hook_test.py b/tests/debug_statement_hook_test.py
index 428421a..349fe89 100644
--- a/tests/debug_statement_hook_test.py
+++ b/tests/debug_statement_hook_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import ast
 
 from pre_commit_hooks.debug_statement_hook import Debug
diff --git a/tests/destroyed_symlinks_test.py b/tests/destroyed_symlinks_test.py
index cde06cf..39c474a 100644
--- a/tests/destroyed_symlinks_test.py
+++ b/tests/destroyed_symlinks_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 import subprocess
 
diff --git a/tests/detect_aws_credentials_test.py b/tests/detect_aws_credentials_test.py
index 7212509..afda47a 100644
--- a/tests/detect_aws_credentials_test.py
+++ b/tests/detect_aws_credentials_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from unittest.mock import patch
 
 import pytest
diff --git a/tests/detect_private_key_test.py b/tests/detect_private_key_test.py
index d2c724f..41f8bae 100644
--- a/tests/detect_private_key_test.py
+++ b/tests/detect_private_key_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.detect_private_key import main
diff --git a/tests/end_of_file_fixer_test.py b/tests/end_of_file_fixer_test.py
index 60b9e82..8a5d889 100644
--- a/tests/end_of_file_fixer_test.py
+++ b/tests/end_of_file_fixer_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import io
 
 import pytest
diff --git a/tests/file_contents_sorter_test.py b/tests/file_contents_sorter_test.py
index 15f1134..5e79e40 100644
--- a/tests/file_contents_sorter_test.py
+++ b/tests/file_contents_sorter_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.file_contents_sorter import FAIL
diff --git a/tests/fix_byte_order_marker_test.py b/tests/fix_byte_order_marker_test.py
index da150e3..d7a6599 100644
--- a/tests/fix_byte_order_marker_test.py
+++ b/tests/fix_byte_order_marker_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from pre_commit_hooks import fix_byte_order_marker
 
 
diff --git a/tests/fix_encoding_pragma_test.py b/tests/fix_encoding_pragma_test.py
index f3afa09..98557e9 100644
--- a/tests/fix_encoding_pragma_test.py
+++ b/tests/fix_encoding_pragma_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import io
 
 import pytest
diff --git a/tests/forbid_new_submodules_test.py b/tests/forbid_new_submodules_test.py
index 0326d94..058a329 100644
--- a/tests/forbid_new_submodules_test.py
+++ b/tests/forbid_new_submodules_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 import subprocess
 from unittest import mock
diff --git a/tests/mixed_line_ending_test.py b/tests/mixed_line_ending_test.py
index f1c2641..a7e7971 100644
--- a/tests/mixed_line_ending_test.py
+++ b/tests/mixed_line_ending_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.mixed_line_ending import main
diff --git a/tests/no_commit_to_branch_test.py b/tests/no_commit_to_branch_test.py
index 9fcb580..eaae5e6 100644
--- a/tests/no_commit_to_branch_test.py
+++ b/tests/no_commit_to_branch_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.no_commit_to_branch import is_on_branch
diff --git a/tests/pretty_format_json_test.py b/tests/pretty_format_json_test.py
index 7fda23b..5ded724 100644
--- a/tests/pretty_format_json_test.py
+++ b/tests/pretty_format_json_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 import shutil
 
diff --git a/tests/readme_test.py b/tests/readme_test.py
index 7df7fcf..038868d 100644
--- a/tests/readme_test.py
+++ b/tests/readme_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from pre_commit_hooks.check_yaml import yaml
 
 
diff --git a/tests/removed_test.py b/tests/removed_test.py
index d635eb1..cd66957 100644
--- a/tests/removed_test.py
+++ b/tests/removed_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.removed import main
diff --git a/tests/requirements_txt_fixer_test.py b/tests/requirements_txt_fixer_test.py
index e3c6ed5..b725afa 100644
--- a/tests/requirements_txt_fixer_test.py
+++ b/tests/requirements_txt_fixer_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.requirements_txt_fixer import FAIL
diff --git a/tests/sort_simple_yaml_test.py b/tests/sort_simple_yaml_test.py
index a682c15..6cbda85 100644
--- a/tests/sort_simple_yaml_test.py
+++ b/tests/sort_simple_yaml_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 
 import pytest
diff --git a/tests/string_fixer_test.py b/tests/string_fixer_test.py
index 6ddb0ac..9dd7315 100644
--- a/tests/string_fixer_test.py
+++ b/tests/string_fixer_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import textwrap
 
 import pytest
diff --git a/tests/tests_should_end_in_test_test.py b/tests/tests_should_end_in_test_test.py
index 4df2963..dc3744b 100644
--- a/tests/tests_should_end_in_test_test.py
+++ b/tests/tests_should_end_in_test_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from pre_commit_hooks.tests_should_end_in_test import main
 
 
diff --git a/tests/trailing_whitespace_fixer_test.py b/tests/trailing_whitespace_fixer_test.py
index bb3b62d..c07497a 100644
--- a/tests/trailing_whitespace_fixer_test.py
+++ b/tests/trailing_whitespace_fixer_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.trailing_whitespace_fixer import main
diff --git a/tests/util_test.py b/tests/util_test.py
index 7f48816..92473e5 100644
--- a/tests/util_test.py
+++ b/tests/util_test.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import pytest
 
 from pre_commit_hooks.util import CalledProcessError
diff --git a/tox.ini b/tox.ini
index 790ce7f..cb2b92a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py36,py37,py38,pypy3,pre-commit
+envlist = py37,py38,pypy3,pre-commit
 
 [testenv]
 deps = -rrequirements-dev.txt