X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/250ba7f04b300df284ba80cd4bb4122b45b41efb..129ebd53a66b4a8069321742aeecfafb44c76fd9:/black.py diff --git a/black.py b/black.py index 34bd59e..24ff781 100644 --- a/black.py +++ b/black.py @@ -113,20 +113,19 @@ class Changed(Enum): class TargetVersion(Enum): - PYPY35 = 1 - CPY27 = 2 - CPY33 = 3 - CPY34 = 4 - CPY35 = 5 - CPY36 = 6 - CPY37 = 7 - CPY38 = 8 + PY27 = 2 + PY33 = 3 + PY34 = 4 + PY35 = 5 + PY36 = 6 + PY37 = 7 + PY38 = 8 def is_python2(self) -> bool: - return self is TargetVersion.CPY27 + return self is TargetVersion.PY27 -PY36_VERSIONS = {TargetVersion.CPY36, TargetVersion.CPY37, TargetVersion.CPY38} +PY36_VERSIONS = {TargetVersion.PY36, TargetVersion.PY37, TargetVersion.PY38} class Feature(Enum): @@ -138,24 +137,23 @@ class Feature(Enum): VERSION_TO_FEATURES: Dict[TargetVersion, Set[Feature]] = { - TargetVersion.CPY27: set(), - TargetVersion.PYPY35: {Feature.UNICODE_LITERALS, Feature.F_STRINGS}, - TargetVersion.CPY33: {Feature.UNICODE_LITERALS}, - TargetVersion.CPY34: {Feature.UNICODE_LITERALS}, - TargetVersion.CPY35: {Feature.UNICODE_LITERALS, Feature.TRAILING_COMMA}, - TargetVersion.CPY36: { + TargetVersion.PY27: set(), + TargetVersion.PY33: {Feature.UNICODE_LITERALS}, + TargetVersion.PY34: {Feature.UNICODE_LITERALS}, + TargetVersion.PY35: {Feature.UNICODE_LITERALS, Feature.TRAILING_COMMA}, + TargetVersion.PY36: { Feature.UNICODE_LITERALS, Feature.F_STRINGS, Feature.NUMERIC_UNDERSCORES, Feature.TRAILING_COMMA, }, - TargetVersion.CPY37: { + TargetVersion.PY37: { Feature.UNICODE_LITERALS, Feature.F_STRINGS, Feature.NUMERIC_UNDERSCORES, Feature.TRAILING_COMMA, }, - TargetVersion.CPY38: { + TargetVersion.PY38: { Feature.UNICODE_LITERALS, Feature.F_STRINGS, Feature.NUMERIC_UNDERSCORES, @@ -254,7 +252,8 @@ def read_pyproject_toml( help=( "Allow using Python 3.6-only syntax on all input files. This will put " "trailing commas in function signatures and calls also after *args and " - "**kwargs. [default: per-file auto-detection]" + "**kwargs. Deprecated; use --target-version instead. " + "[default: per-file auto-detection]" ), ) @click.option( @@ -378,6 +377,10 @@ def main( else: versions = set(target_version) elif py36: + err( + "--py36 is deprecated and will be removed in a future version. " + "Use --target-version py36 instead." + ) versions = PY36_VERSIONS else: # We'll autodetect later. @@ -1079,9 +1082,7 @@ class Line: depth: int = 0 leaves: List[Leaf] = Factory(list) - # The LeafID keys of comments must remain ordered by the corresponding leaf's index - # in leaves - comments: Dict[LeafID, List[Leaf]] = Factory(dict) + comments: Dict[LeafID, List[Leaf]] = Factory(dict) # keys ordered like `leaves` bracket_tracker: BracketTracker = Factory(BracketTracker) inside_brackets: bool = False should_explode: bool = False @@ -1212,6 +1213,29 @@ class Line: if leaf.type == STANDALONE_COMMENT: if leaf.bracket_depth <= depth_limit: return True + return False + + def contains_inner_type_comments(self) -> bool: + ignored_ids = set() + try: + last_leaf = self.leaves[-1] + ignored_ids.add(id(last_leaf)) + if last_leaf.type == token.COMMA: + # When trailing commas are inserted by Black for consistency, comments + # after the previous last element are not moved (they don't have to, + # rendering will still be correct). So we ignore trailing commas. + last_leaf = self.leaves[-2] + ignored_ids.add(id(last_leaf)) + except IndexError: + return False + + for leaf_id, comments in self.comments.items(): + if leaf_id in ignored_ids: + continue + + for comment in comments: + if is_type_comment(comment): + return True return False @@ -1293,13 +1317,8 @@ class Line: comment.prefix = "" return False - else: - leaf_id = id(self.leaves[-1]) - if leaf_id not in self.comments: - self.comments[leaf_id] = [comment] - else: - self.comments[leaf_id].append(comment) - return True + self.comments.setdefault(id(self.leaves[-1]), []).append(comment) + return True def comments_after(self, leaf: Leaf) -> List[Leaf]: """Generate comments that should appear directly after `leaf`.""" @@ -1307,17 +1326,11 @@ class Line: def remove_trailing_comma(self) -> None: """Remove the trailing comma and moves the comments attached to it.""" - # Remember, the LeafID keys of self.comments are ordered by the - # corresponding leaf's index in self.leaves - # If id(self.leaves[-2]) is in self.comments, the order doesn't change. - # Otherwise, we insert it into self.comments, and it becomes the last entry. - # However, since we delete id(self.leaves[-1]) from self.comments, the invariant - # is maintained - self.comments.setdefault(id(self.leaves[-2]), []).extend( - self.comments.get(id(self.leaves[-1]), []) + trailing_comma = self.leaves.pop() + trailing_comma_comments = self.comments.pop(id(trailing_comma), []) + self.comments.setdefault(id(self.leaves[-1]), []).extend( + trailing_comma_comments ) - self.comments.pop(id(self.leaves[-1]), None) - self.leaves.pop() def is_complex_subscript(self, leaf: Leaf) -> bool: """Return True iff `leaf` is part of a slice with non-trivial exprs.""" @@ -1646,6 +1659,7 @@ class LineGenerator(Visitor[Line]): self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS) self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"}) self.visit_import_from = partial(v, keywords=Ø, parens={"import"}) + self.visit_del_stmt = partial(v, keywords=Ø, parens={"del"}) self.visit_async_funcdef = self.visit_async_stmt self.visit_decorated = self.visit_decorators @@ -2165,16 +2179,8 @@ def split_line( line_str = str(line).strip("\n") - # we don't want to split special comments like type annotations - # https://github.com/python/typing/issues/186 - has_special_comment = False - for leaf in line.leaves: - for comment in line.comments_after(leaf): - if leaf.type == token.COMMA and is_special_comment(comment): - has_special_comment = True - if ( - not has_special_comment + not line.contains_inner_type_comments() and not line.should_explode and is_line_short_enough(line, line_length=line_length, line_str=line_str) ): @@ -2445,8 +2451,8 @@ def delimiter_split( ) -> Iterator[Line]: """Split according to delimiters of the highest priority. - If `py36` is True, the split will add trailing commas also in function - signatures that contain `*` and `**`. + If `supports_trailing_commas` is True, the split will add trailing commas + also in function signatures that contain `*` and `**`. """ try: last_leaf = line.leaves[-1] @@ -2550,14 +2556,12 @@ def is_import(leaf: Leaf) -> bool: ) -def is_special_comment(leaf: Leaf) -> bool: +def is_type_comment(leaf: Leaf) -> bool: """Return True if the given leaf is a special comment. Only returns true for type comments for now.""" t = leaf.type v = leaf.value - return bool( - (t == token.COMMENT or t == STANDALONE_COMMENT) and (v.startswith("# type:")) - ) + return t in {token.COMMENT, t == STANDALONE_COMMENT} and v.startswith("# type:") def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None: @@ -3350,7 +3354,16 @@ def assert_equivalent(src: str, dst: str) -> None: if isinstance(value, list): for item in value: - if isinstance(item, ast.AST): + # Ignore nested tuples within del statements, because we may insert + # parentheses and they change the AST. + if ( + field == "targets" + and isinstance(node, ast.Delete) + and isinstance(item, ast.Tuple) + ): + for item in item.elts: + yield from _v(item, depth + 2) + elif isinstance(item, ast.AST): yield from _v(item, depth + 2) elif isinstance(value, ast.AST): @@ -3444,8 +3457,12 @@ def cancel(tasks: Iterable[asyncio.Task]) -> None: def shutdown(loop: BaseEventLoop) -> None: """Cancel all pending tasks on `loop`, wait for them, and close the loop.""" try: + if sys.version_info[:2] >= (3, 7): + all_tasks = asyncio.all_tasks + else: + all_tasks = asyncio.Task.all_tasks # This part is borrowed from asyncio/runners.py in Python 3.7b2. - to_cancel = [task for task in asyncio.Task.all_tasks(loop) if not task.done()] + to_cancel = [task for task in all_tasks(loop) if not task.done()] if not to_cancel: return