don't require typed-ast
diff --git a/CHANGES.md b/CHANGES.md
index 7da7be7b842..97a3be33c93 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -40,6 +40,11 @@
 
 - Lines ending with `fmt: skip` will now be not formatted (#1800)
 
+- PR #2053: Black no longer relies on typed-ast for Python 3.8 and higher
+
+- PR #2053: Python 2 support is now optional, install with
+  `python3 -m pip install black[python2]` to maintain support.
+
 #### _Packaging_
 
 - Self-contained native _Black_ binaries are now provided for releases via GitHub
diff --git a/README.md b/README.md
index 411a8c8609d..0be356e3b84 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,8 @@ _Contents:_ **[Installation and usage](#installation-and-usage)** |
 ### Installation
 
 _Black_ can be installed by running `pip install black`. It requires Python 3.6.2+ to
-run but you can reformat Python 2 code with it, too.
+run. If you want to format Python 2 code as well, install with
+`pip install black[python2]`.
 
 #### Install from GitHub
 
diff --git a/setup.py b/setup.py
index efdf6933025..856c7fadb0c 100644
--- a/setup.py
+++ b/setup.py
@@ -71,7 +71,7 @@ def get_long_description() -> str:
         "click>=7.1.2",
         "appdirs",
         "toml>=0.10.1",
-        "typed-ast>=1.4.2",
+        "typed-ast>=1.4.2; python_version < '3.8'",
         "regex>=2020.1.8",
         "pathspec>=0.6, <1",
         "dataclasses>=0.6; python_version < '3.7'",
@@ -81,6 +81,7 @@ def get_long_description() -> str:
     extras_require={
         "d": ["aiohttp>=3.3.2", "aiohttp-cors"],
         "colorama": ["colorama>=0.4.3"],
+        "python2": ["typed-ast>=1.4.2"],
     },
     test_suite="tests.test_black",
     classifiers=[
diff --git a/src/black/__init__.py b/src/black/__init__.py
index a8f4f89a6bb..52a57695aef 100644
--- a/src/black/__init__.py
+++ b/src/black/__init__.py
@@ -48,7 +48,20 @@
 from dataclasses import dataclass, field, replace
 import click
 import toml
-from typed_ast import ast3, ast27
+
+try:
+    from typed_ast import ast3, ast27
+except ImportError:
+    if sys.version_info < (3, 8):
+        print(
+            "The typed_ast package is not installed.\n"
+            "You can install it with `python3 -m pip install typed-ast`.",
+            file=sys.stderr,
+        )
+        sys.exit(1)
+    else:
+        ast3 = ast27 = ast
+
 from pathspec import PathSpec
 
 # lib2to3 fork
@@ -6336,7 +6349,12 @@ def parse_ast(src: str) -> Union[ast.AST, ast3.AST, ast27.AST]:
                 return ast3.parse(src, filename, feature_version=feature_version)
             except SyntaxError:
                 continue
-
+    if ast27.__name__ == "ast":
+        raise SyntaxError(
+            "The requested source code has invalid Python 3 syntax.\n"
+            "If you are trying to format Python 2 files please reinstall Black"
+            " with the 'python2' extra: `python3 -m pip install black[python2]`."
+        )
     return ast27.parse(src)
 
 
diff --git a/tox.ini b/tox.ini
index 500a2cad579..9bb809abe41 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,7 +7,7 @@ skip_install = True
 deps =
     -r{toxinidir}/test_requirements.txt
 commands =
-    pip install -e .[d]
+    pip install -e .[d,python2]
     coverage erase
     coverage run -m pytest tests
     coverage report

#2044 