Support PEP 696 (#4327)

This commit is contained in:
Jelle Zijlstra 2024-04-23 22:08:37 -07:00 committed by GitHub
parent 2f88085da5
commit 3f0f8f1956
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 137 additions and 7 deletions

View File

@ -30,6 +30,9 @@
<!-- Changes to the parser or to version autodetection -->
- Add support for type parameter defaults, a new syntactic feature added to Python 3.13
by PEP 696 (#4327)
### Performance
<!-- Changes that improve Black's performance. -->

View File

@ -1436,6 +1436,12 @@ def get_features_used( # noqa: C901
elif n.type in (syms.type_stmt, syms.typeparams):
features.add(Feature.TYPE_PARAMS)
elif (
n.type in (syms.typevartuple, syms.paramspec, syms.typevar)
and n.children[-2].type == token.EQUAL
):
features.add(Feature.TYPE_PARAM_DEFAULTS)
return features

View File

@ -24,6 +24,7 @@ class TargetVersion(Enum):
PY310 = 10
PY311 = 11
PY312 = 12
PY313 = 13
class Feature(Enum):
@ -47,6 +48,7 @@ class Feature(Enum):
PARENTHESIZED_CONTEXT_MANAGERS = 17
TYPE_PARAMS = 18
FSTRING_PARSING = 19
TYPE_PARAM_DEFAULTS = 20
FORCE_OPTIONAL_PARENTHESES = 50
# __future__ flags
@ -159,6 +161,27 @@ class Feature(Enum):
Feature.TYPE_PARAMS,
Feature.FSTRING_PARSING,
},
TargetVersion.PY313: {
Feature.F_STRINGS,
Feature.DEBUG_F_STRINGS,
Feature.NUMERIC_UNDERSCORES,
Feature.TRAILING_COMMA_IN_CALL,
Feature.TRAILING_COMMA_IN_DEF,
Feature.ASYNC_KEYWORDS,
Feature.FUTURE_ANNOTATIONS,
Feature.ASSIGNMENT_EXPRESSIONS,
Feature.RELAXED_DECORATORS,
Feature.POS_ONLY_ARGUMENTS,
Feature.UNPACKING_ON_FLOW,
Feature.ANN_ASSIGN_EXTENDED_RHS,
Feature.PARENTHESIZED_CONTEXT_MANAGERS,
Feature.PATTERN_MATCHING,
Feature.EXCEPT_STAR,
Feature.VARIADIC_GENERICS,
Feature.TYPE_PARAMS,
Feature.FSTRING_PARSING,
Feature.TYPE_PARAM_DEFAULTS,
},
}

View File

@ -27,7 +27,8 @@
"py39",
"py310",
"py311",
"py312"
"py312",
"py313"
]
},
"description": "Python versions that should be supported by Black's output. You should include all versions that your code supports. By default, Black will infer target versions from the project metadata in pyproject.toml. If this does not yield conclusive results, Black will use per-file auto-detection."

View File

@ -12,9 +12,9 @@ file_input: (NEWLINE | stmt)* ENDMARKER
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
eval_input: testlist NEWLINE* ENDMARKER
typevar: NAME [':' expr]
paramspec: '**' NAME
typevartuple: '*' NAME
typevar: NAME [':' expr] ['=' expr]
paramspec: '**' NAME ['=' expr]
typevartuple: '*' NAME ['=' (expr|star_expr)]
typeparam: typevar | paramspec | typevartuple
typeparams: '[' typeparam (',' typeparam)* [','] ']'

View File

@ -0,0 +1,61 @@
# flags: --minimum-version=3.13
type A[T=int] = float
type B[*P=int] = float
type C[*Ts=int] = float
type D[*Ts=*int] = float
type D[something_that_is_very_very_very_long=something_that_is_very_very_very_long] = float
type D[*something_that_is_very_very_very_long=*something_that_is_very_very_very_long] = float
type something_that_is_long[something_that_is_long=something_that_is_long] = something_that_is_long
def simple[T=something_that_is_long](short1: int, short2: str, short3: bytes) -> float:
pass
def longer[something_that_is_long=something_that_is_long](something_that_is_long: something_that_is_long) -> something_that_is_long:
pass
def trailing_comma1[T=int,](a: str):
pass
def trailing_comma2[T=int](a: str,):
pass
# output
type A[T = int] = float
type B[*P = int] = float
type C[*Ts = int] = float
type D[*Ts = *int] = float
type D[
something_that_is_very_very_very_long = something_that_is_very_very_very_long
] = float
type D[
*something_that_is_very_very_very_long = *something_that_is_very_very_very_long
] = float
type something_that_is_long[
something_that_is_long = something_that_is_long
] = something_that_is_long
def simple[
T = something_that_is_long
](short1: int, short2: str, short3: bytes) -> float:
pass
def longer[
something_that_is_long = something_that_is_long
](something_that_is_long: something_that_is_long) -> something_that_is_long:
pass
def trailing_comma1[
T = int,
](a: str):
pass
def trailing_comma2[
T = int
](a: str,):
pass

View File

@ -263,6 +263,21 @@ def test_pep_695_version_detection(self) -> None:
versions = black.detect_target_versions(root)
self.assertIn(black.TargetVersion.PY312, versions)
def test_pep_696_version_detection(self) -> None:
source, _ = read_data("cases", "type_param_defaults")
samples = [
source,
"type X[T=int] = float",
"type X[T:int=int]=int",
"type X[*Ts=int]=int",
"type X[*Ts=*int]=int",
"type X[**P=int]=int",
]
for sample in samples:
root = black.lib2to3_parse(sample)
features = black.get_features_used(root)
self.assertIn(black.Feature.TYPE_PARAM_DEFAULTS, features)
def test_expression_ff(self) -> None:
source, expected = read_data("cases", "expression.py")
tmp_file = Path(black.dump_to_file(source))
@ -1531,16 +1546,34 @@ def test_infer_target_version(self) -> None:
for version, expected in [
("3.6", [TargetVersion.PY36]),
("3.11.0rc1", [TargetVersion.PY311]),
(">=3.10", [TargetVersion.PY310, TargetVersion.PY311, TargetVersion.PY312]),
(
">=3.10",
[
TargetVersion.PY310,
TargetVersion.PY311,
TargetVersion.PY312,
TargetVersion.PY313,
],
),
(
">=3.10.6",
[TargetVersion.PY310, TargetVersion.PY311, TargetVersion.PY312],
[
TargetVersion.PY310,
TargetVersion.PY311,
TargetVersion.PY312,
TargetVersion.PY313,
],
),
("<3.6", [TargetVersion.PY33, TargetVersion.PY34, TargetVersion.PY35]),
(">3.7,<3.10", [TargetVersion.PY38, TargetVersion.PY39]),
(
">3.7,!=3.8,!=3.9",
[TargetVersion.PY310, TargetVersion.PY311, TargetVersion.PY312],
[
TargetVersion.PY310,
TargetVersion.PY311,
TargetVersion.PY312,
TargetVersion.PY313,
],
),
(
"> 3.9.4, != 3.10.3",
@ -1549,6 +1582,7 @@ def test_infer_target_version(self) -> None:
TargetVersion.PY310,
TargetVersion.PY311,
TargetVersion.PY312,
TargetVersion.PY313,
],
),
(
@ -1562,6 +1596,7 @@ def test_infer_target_version(self) -> None:
TargetVersion.PY310,
TargetVersion.PY311,
TargetVersion.PY312,
TargetVersion.PY313,
],
),
(
@ -1577,6 +1612,7 @@ def test_infer_target_version(self) -> None:
TargetVersion.PY310,
TargetVersion.PY311,
TargetVersion.PY312,
TargetVersion.PY313,
],
),
("==3.8.*", [TargetVersion.PY38]),