diff --git a/patches/pyink.patch b/patches/pyink.patch index 7bfcd6442f5..1cab23bc882 100644 --- a/patches/pyink.patch +++ b/patches/pyink.patch @@ -52,7 +52,7 @@ from pyink.nodes import STARS, is_number_token, is_simple_decorator_expression, syms from pyink.output import color_diff, diff, dump_to_file, err, ipynb_diff, out from pyink.parsing import ( # noqa F401 -@@ -90,9 +91,8 @@ from pyink.ranges import ( +@@ -84,9 +85,8 @@ from pyink.ranges import ( parse_line_ranges, sanitized_lines, ) @@ -63,7 +63,7 @@ COMPILED = Path(__file__).suffix in (".pyd", ".so") -@@ -273,25 +273,26 @@ def validate_regex( +@@ -264,25 +264,26 @@ def validate_regex( multiple=True, help=( "Python versions that should be supported by Black's output. You should" @@ -97,7 +97,7 @@ ), ) @click.option( -@@ -326,17 +327,17 @@ def validate_regex( +@@ -317,17 +318,17 @@ def validate_regex( "--preview", is_flag=True, help=( @@ -120,7 +120,7 @@ ), ) @click.option( -@@ -351,20 +352,56 @@ def validate_regex( +@@ -342,20 +343,56 @@ def validate_regex( ), ) @click.option( @@ -182,7 +182,7 @@ ), ) @click.option( -@@ -377,11 +404,11 @@ def validate_regex( +@@ -368,11 +405,11 @@ def validate_regex( multiple=True, metavar="START-END", help=( @@ -199,7 +199,7 @@ ), default=(), ) -@@ -389,9 +416,9 @@ def validate_regex( +@@ -380,9 +417,9 @@ def validate_regex( "--fast/--safe", is_flag=True, help=( @@ -212,7 +212,7 @@ ), ) @click.option( -@@ -401,8 +428,8 @@ def validate_regex( +@@ -392,8 +429,8 @@ def validate_regex( "Require a specific version of Black to be running. This is useful for" " ensuring that all contributors to your project are using the same" " version, because different versions of Black may format code a little" @@ -223,7 +223,7 @@ ), ) @click.option( -@@ -410,11 +437,12 @@ def validate_regex( +@@ -401,11 +438,12 @@ def validate_regex( type=str, callback=validate_regex, help=( @@ -241,7 +241,7 @@ ), show_default=False, ) -@@ -423,8 +451,8 @@ def validate_regex( +@@ -414,8 +452,8 @@ def validate_regex( type=str, callback=validate_regex, help=( @@ -252,7 +252,7 @@ ), ) @click.option( -@@ -432,10 +460,10 @@ def validate_regex( +@@ -423,10 +461,10 @@ def validate_regex( type=str, callback=validate_regex, help=( @@ -267,7 +267,7 @@ ), ) @click.option( -@@ -443,9 +471,9 @@ def validate_regex( +@@ -434,9 +472,9 @@ def validate_regex( type=str, is_eager=True, help=( @@ -280,7 +280,7 @@ ), ) @click.option( -@@ -455,10 +483,10 @@ def validate_regex( +@@ -446,10 +484,10 @@ def validate_regex( callback=validate_regex, help=( "A regular expression that matches files and directories that should be" @@ -295,7 +295,7 @@ ), show_default=True, ) -@@ -468,10 +496,10 @@ def validate_regex( +@@ -459,10 +497,10 @@ def validate_regex( type=click.IntRange(min=1), default=None, help=( @@ -310,7 +310,7 @@ ), ) @click.option( -@@ -479,8 +507,8 @@ def validate_regex( +@@ -470,8 +508,8 @@ def validate_regex( "--quiet", is_flag=True, help=( @@ -321,7 +321,7 @@ ), ) @click.option( -@@ -496,15 +524,20 @@ def validate_regex( +@@ -487,15 +525,20 @@ def validate_regex( @click.version_option( version=__version__, message=( @@ -345,7 +345,7 @@ ), is_eager=True, metavar="SRC ...", -@@ -543,6 +576,10 @@ def main( # noqa: C901 +@@ -534,6 +577,10 @@ def main( # noqa: C901 preview: bool, unstable: bool, enable_unstable_feature: List[Preview], @@ -356,7 +356,7 @@ quiet: bool, verbose: bool, required_version: Optional[str], -@@ -640,7 +677,12 @@ def main( # noqa: C901 +@@ -631,7 +678,12 @@ def main( # noqa: C901 preview=preview, unstable=unstable, python_cell_magics=set(python_cell_magics), @@ -370,7 +370,7 @@ ) lines: List[Tuple[int, int]] = [] -@@ -1153,9 +677,10 @@ +@@ -1098,9 +1150,10 @@ def validate_cell(src: str, mode: Mode) """ if any(transformed_magic in src for transformed_magic in TRANSFORMED_MAGICS): raise NothingChanged @@ -384,7 +384,7 @@ ): raise NothingChanged -@@ -1175,7 +1219,6 @@ +@@ -1164,7 +1217,6 @@ def format_ipynb_string(src_contents: st raise NothingChanged trailing_newline = src_contents[-1] == "\n" @@ -392,7 +392,7 @@ nb = json.loads(src_contents) validate_metadata(nb) for cell in nb["cells"]: -@@ -1184,14 +1230,15 @@ +@@ -1176,14 +1228,15 @@ def format_ipynb_string(src_contents: st pass else: cell["source"] = dst.splitlines(keepends=True) @@ -416,7 +416,7 @@ def format_str( -@@ -1253,6 +1294,8 @@ def _format_str_once( +@@ -1244,6 +1297,8 @@ def _format_str_once( future_imports = get_future_imports(src_node) versions = detect_target_versions(src_node, future_imports=future_imports) @@ -442,9 +442,20 @@ (917760, 917999, 0), -] +) +--- a/files.py ++++ b/files.py +@@ -231,7 +231,7 @@ def strip_specifier_set(specifier_set: S + def find_user_pyproject_toml() -> Path: + r"""Return the path to the top-level user configuration for pyink. + +- This looks for ~\.black on Windows and ~/.config/black on Linux and other ++ This looks for ~\.pyink on Windows and ~/.config/pyink on Linux and other + Unix systems. + + May raise: --- a/handle_ipynb_magics.py +++ b/handle_ipynb_magics.py -@@ -263,6 +263,8 @@ +@@ -273,6 +273,8 @@ def unmask_cell(src: str, replacements: """ for replacement in replacements: src = src.replace(replacement.mask, replacement.src) @@ -475,7 +486,7 @@ Line, RHSResult, append_leaves, -@@ -88,6 +94,15 @@ LeafID = int +@@ -87,6 +93,15 @@ LeafID = int LN = Union[Leaf, Node] @@ -491,7 +502,7 @@ class CannotSplit(CannotTransform): """A readable split that fits the allotted line length is impossible.""" -@@ -107,7 +122,9 @@ class LineGenerator(Visitor[Line]): +@@ -106,7 +121,9 @@ class LineGenerator(Visitor[Line]): self.current_line: Line self.__post_init__() @@ -502,7 +513,7 @@ """Generate a line. If the line is empty, only emit if it makes sense. -@@ -116,7 +133,10 @@ class LineGenerator(Visitor[Line]): +@@ -115,7 +132,10 @@ class LineGenerator(Visitor[Line]): If any lines were generated, set up a new current_line. """ if not self.current_line: @@ -514,7 +525,7 @@ return # Line is empty, don't emit. Creating a new one unnecessary. if len(self.current_line.leaves) == 1 and is_async_stmt_or_funcdef( -@@ -129,7 +149,13 @@ class LineGenerator(Visitor[Line]): +@@ -128,7 +148,13 @@ class LineGenerator(Visitor[Line]): return complete_line = self.current_line @@ -529,7 +540,7 @@ yield complete_line def visit_default(self, node: LN) -> Iterator[Line]: -@@ -166,26 +194,27 @@ class LineGenerator(Visitor[Line]): +@@ -160,26 +186,27 @@ class LineGenerator(Visitor[Line]): def visit_test(self, node: Node) -> Iterator[Line]: """Visit an `x if y else z` test""" @@ -570,7 +581,7 @@ yield from self.visit_default(node) def visit_DEDENT(self, node: Leaf) -> Iterator[Line]: -@@ -200,7 +229,7 @@ class LineGenerator(Visitor[Line]): +@@ -194,7 +221,7 @@ class LineGenerator(Visitor[Line]): yield from self.visit_default(node) # Finally, emit the dedent. @@ -579,7 +590,7 @@ def visit_stmt( self, node: Node, keywords: Set[str], parens: Set[str] -@@ -293,7 +322,9 @@ class LineGenerator(Visitor[Line]): +@@ -287,7 +314,9 @@ class LineGenerator(Visitor[Line]): def visit_suite(self, node: Node) -> Iterator[Line]: """Visit a suite.""" @@ -590,7 +601,7 @@ yield from self.visit(node.children[2]) else: yield from self.visit_default(node) -@@ -307,15 +338,23 @@ class LineGenerator(Visitor[Line]): +@@ -301,15 +330,23 @@ class LineGenerator(Visitor[Line]): prev_type = child.type if node.parent and node.parent.type in STATEMENT: @@ -618,7 +629,7 @@ node.prefix = "" yield from self.visit_default(node) return -@@ -414,7 +453,10 @@ class LineGenerator(Visitor[Line]): +@@ -411,7 +448,10 @@ class LineGenerator(Visitor[Line]): yield from self.visit_default(node) def visit_STRING(self, leaf: Leaf) -> Iterator[Line]: @@ -630,7 +641,7 @@ normalize_unicode_escape_sequences(leaf) if is_docstring(leaf, self.mode) and not re.search(r"\\\s*\n", leaf.value): -@@ -428,7 +470,9 @@ class LineGenerator(Visitor[Line]): +@@ -424,7 +464,9 @@ class LineGenerator(Visitor[Line]): # see padding logic below), there's a possibility for unstable # formatting. To avoid a situation where this function formats a # docstring differently on the second pass, normalize it early. @@ -641,7 +652,7 @@ else: docstring = leaf.value prefix = get_string_prefix(docstring) -@@ -442,7 +486,7 @@ class LineGenerator(Visitor[Line]): +@@ -438,7 +480,7 @@ class LineGenerator(Visitor[Line]): quote_len = 1 if docstring[1] != quote_char else 3 docstring = docstring[quote_len:-quote_len] docstring_started_empty = not docstring @@ -650,7 +661,7 @@ if is_multiline_string(leaf): docstring = fix_docstring(docstring, indent) -@@ -484,7 +528,13 @@ class LineGenerator(Visitor[Line]): +@@ -473,7 +515,13 @@ class LineGenerator(Visitor[Line]): # If docstring is one line, we don't put the closing quotes on a # separate line because it looks ugly (#3320). lines = docstring.splitlines() @@ -665,17 +676,7 @@ # If adding closing quotes would cause the last line to exceed # the maximum line length, and the closing quote is not -@@ -531,7 +581,8 @@ 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"}) -+ if not self.mode.is_pyink: -+ 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 -@@ -499,7 +556,9 @@ def visit_STRING( +@@ -499,7 +547,9 @@ class LineGenerator(Visitor[Line]): if self.mode.string_normalization and leaf.type == token.STRING: leaf.value = normalize_string_prefix(leaf.value) @@ -686,7 +687,17 @@ yield from self.visit_default(leaf) def visit_NUMBER(self, leaf: Leaf) -> Iterator[Line]: -@@ -577,10 +628,19 @@ def transform_line( +@@ -575,7 +625,8 @@ 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"}) ++ if not self.mode.is_pyink: ++ 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 +@@ -621,10 +672,19 @@ def transform_line( ll = mode.line_length sn = mode.string_normalization @@ -710,7 +721,7 @@ transformers: List[Transformer] if ( -@@ -787,7 +847,6 @@ def _first_right_hand_split( +@@ -831,7 +891,6 @@ def _first_right_hand_split( omit: Collection[LeafID] = (), ) -> RHSResult: """Split the line into head, body, tail starting with the last bracket pair. @@ -718,7 +729,7 @@ Note: this function should not have side effects. It's relied upon by _maybe_split_omitting_optional_parens to get an opinion whether to prefer splitting on the right side of an assignment statement. -@@ -1054,7 +1113,7 @@ def bracket_split_build_line( +@@ -1098,7 +1157,7 @@ def bracket_split_build_line( result = Line(mode=original.mode, depth=original.depth) if component is _BracketSplitComponent.body: result.inside_brackets = True @@ -727,7 +738,7 @@ if leaves: no_commas = ( # Ensure a trailing comma for imports and standalone function arguments -@@ -1637,7 +1696,7 @@ def generate_trailers_to_omit(line: Line +@@ -1691,7 +1750,7 @@ def generate_trailers_to_omit(line: Line if not line.magic_trailing_comma: yield omit @@ -786,7 +797,7 @@ def append( self, leaf: Leaf, preformatted: bool = False, track_bracket: bool = False ) -> None: -@@ -103,7 +123,7 @@ class Line: +@@ -108,7 +128,7 @@ class Line: or when a standalone comment is not the first leaf on the line. """ if ( @@ -795,7 +806,7 @@ or self.bracket_tracker.any_open_for_or_lambda() ): if self.is_comment: -@@ -337,6 +357,29 @@ class Line: +@@ -342,6 +362,29 @@ class Line: return False @@ -825,7 +836,7 @@ def contains_multiline_strings(self) -> bool: return any(is_multiline_string(leaf) for leaf in self.leaves) -@@ -487,7 +530,7 @@ class Line: +@@ -492,7 +535,7 @@ class Line: if not self: return "\n" @@ -834,7 +845,7 @@ leaves = iter(self.leaves) first = next(leaves) res = f"{first.prefix}{indent}{first.value}" -@@ -559,7 +602,7 @@ class EmptyLineTracker: +@@ -564,7 +607,7 @@ class EmptyLineTracker: lines (two on module-level). """ form_feed = ( @@ -843,7 +854,7 @@ and bool(current_line.leaves) and "\f\n" in current_line.leaves[0].prefix ) -@@ -604,7 +647,7 @@ class EmptyLineTracker: +@@ -609,7 +652,7 @@ class EmptyLineTracker: def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]: # noqa: C901 max_allowed = 1 @@ -852,7 +863,7 @@ max_allowed = 1 if self.mode.is_pyi else 2 if current_line.leaves: -@@ -621,7 +664,7 @@ class EmptyLineTracker: +@@ -626,7 +669,7 @@ class EmptyLineTracker: # Mutate self.previous_defs, remainder of this function should be pure previous_def = None @@ -861,7 +872,7 @@ previous_def = self.previous_defs.pop() if current_line.is_def or current_line.is_class: self.previous_defs.append(current_line) -@@ -677,10 +720,25 @@ class EmptyLineTracker: +@@ -682,10 +725,25 @@ class EmptyLineTracker: ) if ( @@ -889,7 +900,7 @@ ): return (before or 1), 0 -@@ -697,8 +755,9 @@ class EmptyLineTracker: +@@ -702,8 +760,9 @@ class EmptyLineTracker: return 0, 1 return 0, 0 @@ -901,7 +912,7 @@ ): if self.mode.is_pyi: return 0, 0 -@@ -707,7 +766,7 @@ class EmptyLineTracker: +@@ -712,7 +771,7 @@ class EmptyLineTracker: comment_to_add_newlines: Optional[LinesBlock] = None if ( self.previous_line.is_comment @@ -910,7 +921,7 @@ and before == 0 ): slc = self.semantic_leading_comment -@@ -724,9 +783,9 @@ class EmptyLineTracker: +@@ -729,9 +788,9 @@ class EmptyLineTracker: if self.mode.is_pyi: if current_line.is_class or self.previous_line.is_class: @@ -922,7 +933,7 @@ newlines = 1 elif current_line.is_stub_class and self.previous_line.is_stub_class: # No blank line between classes with an empty body -@@ -755,7 +814,11 @@ class EmptyLineTracker: +@@ -760,7 +819,11 @@ class EmptyLineTracker: newlines = 1 if current_line.depth else 2 # If a user has left no space after a dummy implementation, don't insert # new lines. This is useful for instance for @overload or Protocols. @@ -935,7 +946,7 @@ newlines = 0 if comment_to_add_newlines is not None: previous_block = comment_to_add_newlines.previous_block -@@ -810,9 +873,14 @@ def is_line_short_enough( # noqa: C901 +@@ -815,9 +878,14 @@ def is_line_short_enough( # noqa: C901 if not line_str: line_str = line_to_string(line) @@ -951,7 +962,7 @@ and "\n" not in line_str # multiline strings and not line.contains_standalone_comments() ) -@@ -821,7 +889,7 @@ def is_line_short_enough( # noqa: C901 +@@ -826,7 +894,7 @@ def is_line_short_enough( # noqa: C901 return False if "\n" not in line_str: # No multiline strings (MLS) present @@ -960,7 +971,7 @@ first, *_, last = line_str.split("\n") if str_width(first) > mode.line_length or str_width(last) > mode.line_length: -@@ -1024,7 +1092,7 @@ def can_omit_invisible_parens( +@@ -1031,7 +1099,7 @@ def can_omit_invisible_parens( def _can_omit_opening_paren(line: Line, *, first: Leaf, line_length: int) -> bool: """See `can_omit_invisible_parens`.""" remainder = False @@ -969,7 +980,7 @@ _index = -1 for _index, leaf, leaf_length in line.enumerate_with_length(): if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first: -@@ -1048,7 +1116,7 @@ def _can_omit_opening_paren(line: Line, +@@ -1055,7 +1123,7 @@ def _can_omit_opening_paren(line: Line, def _can_omit_closing_paren(line: Line, *, last: Leaf, line_length: int) -> bool: """See `can_omit_invisible_parens`.""" @@ -989,7 +1000,7 @@ from pyink.const import DEFAULT_LINE_LENGTH -@@ -198,6 +198,24 @@ class Deprecated(UserWarning): +@@ -224,6 +224,24 @@ class Deprecated(UserWarning): """Visible deprecation warning.""" @@ -1014,7 +1025,7 @@ _MAX_CACHE_KEY_PART_LENGTH: Final = 32 -@@ -206,12 +224,19 @@ class Mode: +@@ -232,12 +250,19 @@ class Mode: target_versions: Set[TargetVersion] = field(default_factory=set) line_length: int = DEFAULT_LINE_LENGTH string_normalization: bool = True @@ -1034,7 +1045,7 @@ unstable: bool = False enabled_features: Set[Preview] = field(default_factory=set) -@@ -223,6 +247,9 @@ class Mode: +@@ -249,6 +274,9 @@ class Mode: except those in UNSTABLE_FEATURES are enabled. Any features in `self.enabled_features` are also enabled. """ @@ -1044,7 +1055,7 @@ if self.unstable: return True if feature in self.enabled_features: -@@ -254,11 +281,25 @@ class Mode: +@@ -280,11 +308,25 @@ class Mode: version_str, str(self.line_length), str(int(self.string_normalization)), @@ -1072,7 +1083,7 @@ + return Quote.DOUBLE --- a/nodes.py +++ b/nodes.py -@@ -763,9 +765,13 @@ def is_function_or_class(node: Node) -> +@@ -798,9 +798,13 @@ def is_function_or_class(node: Node) -> return node.type in {syms.funcdef, syms.classdef, syms.async_funcdef} @@ -1152,7 +1163,7 @@ classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Console", -@@ -70,53 +42,38 @@ dependencies = [ +@@ -71,53 +42,38 @@ dependencies = [ "platformdirs>=2", "tomli>=1.1.0; python_version < '3.11'", "typing_extensions>=4.0.1; python_version < '3.11'", @@ -1177,7 +1188,7 @@ -black = "black:patched_main" -blackd = "blackd:patched_main [d]" +pyink = "pyink:patched_main" - + [project.entry-points."validate_pyproject.tool_schema"] -black = "black.schema:get_schema" +pyink = "pyink.schema:get_schema" @@ -1214,7 +1225,7 @@ [tool.hatch.build.targets.wheel] only-include = ["src"] sources = ["src"] -@@ -125,7 +80,6 @@ macos-max-compat = true +@@ -128,7 +84,6 @@ macos-max-compat = true # Option below requires `tests/optional.py` addopts = "--strict-config --strict-markers" optional-tests = [ @@ -1222,7 +1233,7 @@ "no_jupyter: run when `jupyter` extra NOT installed", ] markers = [ -@@ -149,36 +103,3 @@ filterwarnings = [ +@@ -152,36 +107,3 @@ filterwarnings = [ # https://github.com/aio-libs/aiohttp/pull/7302 "ignore:datetime.*utcfromtimestamp\\(\\) is deprecated and scheduled for removal:DeprecationWarning", ] @@ -1314,6 +1325,16 @@ return f"{prefix}{new_quote}{new_body}{new_quote}" +--- a/tests/conftest.py ++++ b/tests/conftest.py +@@ -1,6 +1,6 @@ + import pytest + +-pytest_plugins = ["tests.optional"] ++pytest_plugins = ["pyink.tests.optional"] + + PRINT_FULL_TREE: bool = False + PRINT_TREE_DIFF: bool = True --- a/tests/empty.toml +++ b/tests/empty.toml @@ -1 +1,5 @@ @@ -1324,7 +1345,7 @@ +pyink = false --- a/tests/test_black.py +++ b/tests/test_black.py -@@ -2772,6 +2772,82 @@ class TestFileCollection: +@@ -2809,6 +2809,82 @@ class TestFileCollection: stdin_filename=stdin_filename, ) @@ -1409,7 +1430,7 @@ ) -> None: --- a/tests/test_ipynb.py +++ b/tests/test_ipynb.py -@@ -12,6 +12,7 @@ +@@ -12,6 +12,7 @@ from click.testing import CliRunner from pyink import ( Mode, NothingChanged, @@ -1417,7 +1438,7 @@ format_cell, format_file_contents, format_file_in_place, -@@ -26,8 +26,10 @@ +@@ -27,8 +28,10 @@ pytest.importorskip("IPython", reason="I pytest.importorskip("tokenize_rt", reason="tokenize-rt is an optional dependency") JUPYTER_MODE = Mode(is_ipynb=True) @@ -1428,7 +1449,7 @@ runner = CliRunner() -@@ -209,6 +209,29 @@ +@@ -208,6 +211,29 @@ def test_cell_magic_with_custom_python_m assert result == expected_output @@ -1458,7 +1479,7 @@ def test_cell_magic_nested() -> None: src = "%%time\n%%time\n2+2" result = format_cell(src, fast=True, mode=JUPYTER_MODE) -@@ -385,6 +385,45 @@ +@@ -381,6 +407,45 @@ def test_entire_notebook_no_trailing_new assert result == expected @@ -1504,7 +1525,7 @@ def test_entire_notebook_without_changes() -> None: content = read_jupyter_notebook("jupyter", "notebook_without_changes") with pytest.raises(NothingChanged): -@@ -472,6 +472,30 @@ +@@ -432,6 +497,30 @@ def test_ipynb_diff_with_no_change() -> assert expected in result.output @@ -1537,7 +1558,7 @@ ) -> None: --- a/tests/util.py +++ b/tests/util.py -@@ -271,6 +271,11 @@ def get_flags_parser() -> argparse.Argum +@@ -264,6 +264,11 @@ def get_flags_parser() -> argparse.Argum ), ) parser.add_argument("--line-ranges", action="append") @@ -1549,7 +1570,7 @@ parser.add_argument( "--no-preview-line-length-1", default=False, -@@ -294,6 +296,9 @@ def parse_mode(flags_line: str) -> TestC +@@ -287,6 +292,9 @@ def parse_mode(flags_line: str) -> TestC is_ipynb=args.ipynb, magic_trailing_comma=not args.skip_magic_trailing_comma, preview=args.preview, @@ -1559,7 +1580,7 @@ unstable=args.unstable, ) if args.line_ranges: -@@ -355,7 +355,8 @@ +@@ -340,7 +348,8 @@ def read_jupyter_notebook(subdir_name: s def read_jupyter_notebook_from_file(file_name: Path) -> str: with open(file_name, mode="rb") as fd: content_bytes = fd.read()