diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 244446a..8008011 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,10 +13,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python 3.10 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.10" cache: pip @@ -34,7 +34,7 @@ jobs: if: github.event_name == 'release' && needs.tests.result == 'success' steps: - name: Check out repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build and upload dist run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f59f1e..1e133d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,14 +7,14 @@ exclude: tests/fixtures/raw_nb.py repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.5 + rev: v0.3.0 hooks: - id: ruff args: [--fix] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.0 + rev: v1.8.0 hooks: - id: mypy diff --git a/format_ipy_cells/helpers.py b/format_ipy_cells/helpers.py index 4735677..f28c64c 100644 --- a/format_ipy_cells/helpers.py +++ b/format_ipy_cells/helpers.py @@ -96,3 +96,24 @@ def delete_last_cell_if_empty(text: str) -> str: """ # \Z matches only at end of string return re.sub(r"(?m)\s+^# %%\s*\Z", r"\n", text) + + +def single_blank_line_after_doc_string(text: str) -> str: + """Ensure single blank line between cell delimiter and preceding module doc string. + + Added to avoid clash with ruff format. Started enforcing single blank line in 0.3.0. + + --- before --- + '''module doc string.''' + + + # %% + some_code = 'here' + + --- after --- + '''module doc string.''' + + # %% + some_code = 'here' + """ + return re.sub(r'(?m)(["\']{3})\n+(# %%)', r"\1\n\n\2", text) diff --git a/format_ipy_cells/main.py b/format_ipy_cells/main.py index f1385be..2212ac1 100644 --- a/format_ipy_cells/main.py +++ b/format_ipy_cells/main.py @@ -9,6 +9,7 @@ format_comments_after_cell_delimiters, remove_empty_cells, remove_empty_lines_starting_cell, + single_blank_line_after_doc_string, ) @@ -39,6 +40,8 @@ def fix_file(filename: str) -> int: text = delete_last_cell_if_empty(text) + text = single_blank_line_after_doc_string(text) + if orig_text != text: print(f"Rewriting {filename}") diff --git a/pyproject.toml b/pyproject.toml index 9472756..9c0d219 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ no_implicit_optional = false target-version = "py310" select = ["ALL"] ignore = [ + "COM812", # trailing comma missing "D100", # Missing docstring in public module "D104", # Missing docstring in public package "D205", # 1 blank line required between summary line and description diff --git a/tests/fixtures/clean_nb.py b/tests/fixtures/clean_nb.py index ea45f89..72e6cc6 100644 --- a/tests/fixtures/clean_nb.py +++ b/tests/fixtures/clean_nb.py @@ -1,3 +1,5 @@ +"""module doc string.""" + # %% foo = "hello" @@ -9,6 +11,7 @@ # %% a comment following a cell delimiter with too much space baz = 42 +"""longer comment""" # %% empty cell with comment (should not be removed despite empty) diff --git a/tests/fixtures/raw_nb.py b/tests/fixtures/raw_nb.py index 3d618f1..23ec433 100644 --- a/tests/fixtures/raw_nb.py +++ b/tests/fixtures/raw_nb.py @@ -1,3 +1,6 @@ +"""module doc string.""" + + # %% foo = "hello" # %%a comment following a cell delimiter without space @@ -5,7 +8,10 @@ # %% a comment following a cell delimiter with too much space baz = 42 +"""longer comment""" + + # %% empty cell with comment (should not be removed despite empty) diff --git a/tests/test_main.py b/tests/test_main.py index 1e27a73..37e40ad 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,3 +1,4 @@ +import difflib import filecmp import shutil from importlib.metadata import version @@ -15,10 +16,18 @@ def test_main_format_cells(tmp_path: Path, capsys: pytest.CaptureFixture[str]) - shutil.copy2(clean_nb, clean_tmp := str(tmp_path / "clean_nb.py")) ret = main((raw_tmp, clean_tmp)) - assert ret == 1 - assert filecmp.cmp(raw_tmp, clean_nb), "Formatted file has unexpected content" - assert filecmp.cmp(clean_tmp, clean_nb), "clean file should not have changed" + + with open(clean_nb) as file, open(clean_tmp) as tmp_file: + clean_lines, tmp_lines = file.readlines(), tmp_file.readlines() + file_diff = "\n".join(difflib.unified_diff(clean_lines, tmp_lines)) + + assert filecmp.cmp( + raw_tmp, clean_nb, shallow=False + ), f"Formatted file has unexpected content:\n{file_diff}" + assert filecmp.cmp( + clean_tmp, clean_nb, shallow=False + ), "clean file should not have changed" out, err = capsys.readouterr() assert out == f"Rewriting {raw_tmp}\n"