All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
   1 """Data structures configuring Black behavior.
 
   3 Mostly around Python language feature support per version and Black configuration
 
   7 from hashlib import sha256
 
  10 from dataclasses import dataclass, field
 
  11 from enum import Enum, auto
 
  12 from operator import attrgetter
 
  13 from typing import Dict, Set
 
  14 from warnings import warn
 
  16 if sys.version_info < (3, 8):
 
  17     from typing_extensions import Final
 
  19     from typing import Final
 
  21 from black.const import DEFAULT_LINE_LENGTH
 
  24 class TargetVersion(Enum):
 
  38     NUMERIC_UNDERSCORES = 3
 
  39     TRAILING_COMMA_IN_CALL = 4
 
  40     TRAILING_COMMA_IN_DEF = 5
 
  41     # The following two feature-flags are mutually exclusive, and exactly one should be
 
  42     # set for every version of python.
 
  45     ASSIGNMENT_EXPRESSIONS = 8
 
  46     POS_ONLY_ARGUMENTS = 9
 
  47     RELAXED_DECORATORS = 10
 
  49     UNPACKING_ON_FLOW = 12
 
  50     ANN_ASSIGN_EXTENDED_RHS = 13
 
  52     VARIADIC_GENERICS = 15
 
  53     FORCE_OPTIONAL_PARENTHESES = 50
 
  56     FUTURE_ANNOTATIONS = 51
 
  59 FUTURE_FLAG_TO_FEATURE: Final = {
 
  60     "annotations": Feature.FUTURE_ANNOTATIONS,
 
  64 VERSION_TO_FEATURES: Dict[TargetVersion, Set[Feature]] = {
 
  65     TargetVersion.PY33: {Feature.ASYNC_IDENTIFIERS},
 
  66     TargetVersion.PY34: {Feature.ASYNC_IDENTIFIERS},
 
  67     TargetVersion.PY35: {Feature.TRAILING_COMMA_IN_CALL, Feature.ASYNC_IDENTIFIERS},
 
  70         Feature.NUMERIC_UNDERSCORES,
 
  71         Feature.TRAILING_COMMA_IN_CALL,
 
  72         Feature.TRAILING_COMMA_IN_DEF,
 
  73         Feature.ASYNC_IDENTIFIERS,
 
  77         Feature.NUMERIC_UNDERSCORES,
 
  78         Feature.TRAILING_COMMA_IN_CALL,
 
  79         Feature.TRAILING_COMMA_IN_DEF,
 
  80         Feature.ASYNC_KEYWORDS,
 
  81         Feature.FUTURE_ANNOTATIONS,
 
  85         Feature.NUMERIC_UNDERSCORES,
 
  86         Feature.TRAILING_COMMA_IN_CALL,
 
  87         Feature.TRAILING_COMMA_IN_DEF,
 
  88         Feature.ASYNC_KEYWORDS,
 
  89         Feature.FUTURE_ANNOTATIONS,
 
  90         Feature.ASSIGNMENT_EXPRESSIONS,
 
  91         Feature.POS_ONLY_ARGUMENTS,
 
  92         Feature.UNPACKING_ON_FLOW,
 
  93         Feature.ANN_ASSIGN_EXTENDED_RHS,
 
  97         Feature.NUMERIC_UNDERSCORES,
 
  98         Feature.TRAILING_COMMA_IN_CALL,
 
  99         Feature.TRAILING_COMMA_IN_DEF,
 
 100         Feature.ASYNC_KEYWORDS,
 
 101         Feature.FUTURE_ANNOTATIONS,
 
 102         Feature.ASSIGNMENT_EXPRESSIONS,
 
 103         Feature.RELAXED_DECORATORS,
 
 104         Feature.POS_ONLY_ARGUMENTS,
 
 105         Feature.UNPACKING_ON_FLOW,
 
 106         Feature.ANN_ASSIGN_EXTENDED_RHS,
 
 108     TargetVersion.PY310: {
 
 110         Feature.NUMERIC_UNDERSCORES,
 
 111         Feature.TRAILING_COMMA_IN_CALL,
 
 112         Feature.TRAILING_COMMA_IN_DEF,
 
 113         Feature.ASYNC_KEYWORDS,
 
 114         Feature.FUTURE_ANNOTATIONS,
 
 115         Feature.ASSIGNMENT_EXPRESSIONS,
 
 116         Feature.RELAXED_DECORATORS,
 
 117         Feature.POS_ONLY_ARGUMENTS,
 
 118         Feature.UNPACKING_ON_FLOW,
 
 119         Feature.ANN_ASSIGN_EXTENDED_RHS,
 
 120         Feature.PATTERN_MATCHING,
 
 122     TargetVersion.PY311: {
 
 124         Feature.NUMERIC_UNDERSCORES,
 
 125         Feature.TRAILING_COMMA_IN_CALL,
 
 126         Feature.TRAILING_COMMA_IN_DEF,
 
 127         Feature.ASYNC_KEYWORDS,
 
 128         Feature.FUTURE_ANNOTATIONS,
 
 129         Feature.ASSIGNMENT_EXPRESSIONS,
 
 130         Feature.RELAXED_DECORATORS,
 
 131         Feature.POS_ONLY_ARGUMENTS,
 
 132         Feature.UNPACKING_ON_FLOW,
 
 133         Feature.ANN_ASSIGN_EXTENDED_RHS,
 
 134         Feature.PATTERN_MATCHING,
 
 136         Feature.VARIADIC_GENERICS,
 
 141 def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> bool:
 
 142     return all(feature in VERSION_TO_FEATURES[version] for version in target_versions)
 
 146     """Individual preview style features."""
 
 148     string_processing = auto()
 
 149     remove_redundant_parens = auto()
 
 150     one_element_subscript = auto()
 
 151     annotation_parens = auto()
 
 152     long_docstring_quotes_on_newline = auto()
 
 155 class Deprecated(UserWarning):
 
 156     """Visible deprecation warning."""
 
 161     target_versions: Set[TargetVersion] = field(default_factory=set)
 
 162     line_length: int = DEFAULT_LINE_LENGTH
 
 163     string_normalization: bool = True
 
 165     is_ipynb: bool = False
 
 166     magic_trailing_comma: bool = True
 
 167     experimental_string_processing: bool = False
 
 168     python_cell_magics: Set[str] = field(default_factory=set)
 
 169     preview: bool = False
 
 171     def __post_init__(self) -> None:
 
 172         if self.experimental_string_processing:
 
 174                 "`experimental string processing` has been included in `preview`"
 
 175                 " and deprecated. Use `preview` instead.",
 
 179     def __contains__(self, feature: Preview) -> bool:
 
 181         Provide `Preview.FEATURE in Mode` syntax that mirrors the ``preview`` flag.
 
 183         The argument is not checked and features are not differentiated.
 
 184         They only exist to make development easier by clarifying intent.
 
 186         if feature is Preview.string_processing:
 
 187             return self.preview or self.experimental_string_processing
 
 190     def get_cache_key(self) -> str:
 
 191         if self.target_versions:
 
 192             version_str = ",".join(
 
 194                 for version in sorted(self.target_versions, key=attrgetter("value"))
 
 200             str(self.line_length),
 
 201             str(int(self.string_normalization)),
 
 202             str(int(self.is_pyi)),
 
 203             str(int(self.is_ipynb)),
 
 204             str(int(self.magic_trailing_comma)),
 
 205             str(int(self.experimental_string_processing)),
 
 206             str(int(self.preview)),
 
 207             sha256((",".join(sorted(self.python_cell_magics))).encode()).hexdigest(),
 
 209         return ".".join(parts)