Skip to content

Conversation

@ulgens
Copy link
Owner

@ulgens ulgens commented Jan 3, 2026

No description provided.

@codecov
Copy link

codecov bot commented Jan 3, 2026

❌ 2 Tests Failed:

Tests completed Failed Passed Skipped
76 2 74 0
View the top 2 failed test(s) by shortest run time
tests/test_ruffen_docs.py::test_integration_modifies
Stack Traces | 0.004s run time
tmp_path = PosixPath('.../pytest-of-runner/pytest-0/test_integration_modifies0')
capsys = <_pytest.capture.CaptureFixture object at 0x7f5fc2eeab60>

    def test_integration_modifies(tmp_path, capsys):
        f = tmp_path / "f.md"
        f.write_text(
            "```python\nf(1,2,3)\n```\n",
        )
    
        result = run_black((str(f),))
    
        assert result == 1
        out, _ = capsys.readouterr()
>       assert out == f"{f}: Rewriting...\n"
E       AssertionError: assert '/tmp/pytest-...ewriting...\n' == '/tmp/pytest-...ewriting...\n'
E         
E         Skipping 52 identical leading characters in diff, use -v to show
E         - fies0/f.md: Rewriting...
E         + fies0/f.md
E         + .../pytest-of-runner/pytest-0/test_integration_modifies0/f.md: Rewriting...

tests/test_ruffen_docs.py:904: AssertionError
tests/test_ruffen_docs.py::test_integration_syntax_error
Stack Traces | 0.005s run time
tmp_path = PosixPath('.../pytest-of-runner/pytest-0/test_integration_syntax_error0')
capsys = <_pytest.capture.CaptureFixture object at 0x7f5fc3181690>

    def test_integration_syntax_error(tmp_path, capsys):
        f = tmp_path / "f.md"
        f.write_text(
            "```python\nf(\n```\n",
        )
    
        result = run_black((str(f),))
    
        assert result == 2
        out, _ = capsys.readouterr()
>       assert out.startswith(f"{f}:1: code block parse error")
E       AssertionError: assert False
E        +  where False = <built-in method startswith of str object at 0x7f5fc3062ef0>('.../pytest-of-runner/pytest-0/test_integration_syntax_error0/f.md:1: code block parse error')
E        +    where <built-in method startswith of str object at 0x7f5fc3062ef0> = '.../pytest-of-runner/pytest-0/test_integration_syntax_error0/f.md\n.../pytest-of-runner/pytest-0/test_integration_syntax_error0/f.md:1: code block parse error Cannot parse: 1:2: Unexpected EOF in multi-line statement\n'.startswith

tests/test_ruffen_docs.py:1106: AssertionError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Ruff support to ruffen-docs by introducing two new processor classes (RuffChecker and RuffFormatter) alongside the existing BlackFormatter. The module is renamed from formatters to processors to better reflect its expanded purpose.

Key Changes:

  • Added RuffChecker and RuffFormatter processor classes that use subprocess to call ruff commands
  • Renamed module from formatters to processors and updated imports
  • Added two new pre-commit hooks: ruffen-docs-check and ruffen-docs-format

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/ruffen_docs/processors.py Added subprocess import, ruff.main import, and two new processor classes (RuffChecker and RuffFormatter)
src/ruffen_docs/__init__.py Updated import to use processors module instead of formatters
tests/test_ruffen_docs.py Updated import to use processors module instead of formatters
.pre-commit-config.yaml Added two new pre-commit hooks for ruffen-docs-check and ruffen-docs-format with ruff 0.14.10 dependency
Comments suppressed due to low confidence (6)

src/ruffen_docs/processors.py:364

  • The commented out check=True parameter should either be removed or uncommented with proper error handling. If check=True is uncommented, subprocess.run will raise CalledProcessError automatically on non-zero exit, making the subsequent check_returncode() call redundant. Currently, using check_returncode() separately is correct, but the commented code creates ambiguity about the intended approach.
    src/ruffen_docs/processors.py:337
  • The init methods in both RuffChecker and RuffFormatter are redundant as they only call super().init() without adding any initialization logic. These methods can be removed to simplify the code.
    src/ruffen_docs/processors.py:355
  • The init methods in both RuffChecker and RuffFormatter are redundant as they only call super().init() without adding any initialization logic. These methods can be removed to simplify the code.
    src/ruffen_docs/processors.py:350
  • The RuffChecker.process_code_block method returns result.stdout, but ruff check does not output the formatted code to stdout - it outputs diagnostic messages. The process_code_block method should return the original code_block unchanged since ruff check is meant to validate, not transform the code. This is a fundamental difference from ruff format which actually outputs the formatted code.
    src/ruffen_docs/processors.py:368
  • The newly added RuffChecker and RuffFormatter classes lack test coverage. Since the existing BlackFormatter has comprehensive test coverage (as seen in tests/test_ruffen_docs.py with numerous test functions), these new processor classes should also have corresponding tests to verify their behavior with various code block formats (markdown, RST, pycon, etc.).
    src/ruffen_docs/processors.py:346
  • The commented out check=True parameter should either be removed or uncommented with proper error handling. If check=True is uncommented, subprocess.run will raise CalledProcessError automatically on non-zero exit, making the subsequent check_returncode() call redundant. Currently, using check_returncode() separately is correct, but the commented code creates ambiguity about the intended approach.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ulgens added 3 commits January 3, 2026 03:52
"formatter" is not the best term to cover ruff's "check" and "format" behaviour together
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (6)

src/ruffen_docs/processors.py:368

  • The new RuffChecker and RuffFormatter classes lack test coverage. Similar tests should be added for these new processors, following the same pattern as the existing BlackFormatter tests in this file.
    src/ruffen_docs/processors.py:348
  • The subprocess call does not specify a timeout parameter, which could cause the process to hang indefinitely if ruff encounters an issue. Consider adding a timeout to prevent the process from blocking forever.
    src/ruffen_docs/processors.py:349
  • Calling check_returncode() will raise a CalledProcessError when ruff check finds linting violations (non-zero exit code), which will be caught by the _collect_error context manager and treated as a processing error. For a checker, this is incorrect behavior - finding linting violations should not be treated as a processing error. The method should handle the return code appropriately and return the original code_block unchanged.
    src/ruffen_docs/processors.py:350
  • The RuffChecker.process_code_block method returns result.stdout, but ruff check typically outputs diagnostics to stderr and returns an empty stdout for valid code. This will likely return an empty string even when the check passes, which may not be the intended behavior. Consider returning the original code_block when the check passes, or handle the output differently.
    src/ruffen_docs/processors.py:366
  • The subprocess call does not specify a timeout parameter, which could cause the process to hang indefinitely if ruff encounters an issue. Consider adding a timeout to prevent the process from blocking forever.
    src/ruffen_docs/processors.py:364
  • These commented-out lines should either be removed if they're not needed, or uncommented and implemented if they are. Leaving commented code in the codebase reduces clarity about what the intended behavior should be.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


retv = 0
for filename in args.filenames:
print(filename)
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This debug print statement should be removed. It appears to have been added during development and will output filenames to stdout during normal operation, which could interfere with the tool's output and usage in automated environments.

Suggested change
print(filename)

Copilot uses AI. Check for mistakes.
Comment on lines +130 to +134
filenames = []

retv = 0

for filename in filenames:
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filenames list is initialized as empty but is never populated with args.filenames. This means the loop will never execute, and no files will be processed. You should use args.filenames directly in the loop, similar to how run_check and run_black are implemented.

Suggested change
filenames = []
retv = 0
for filename in filenames:
retv = 0
for filename in args.filenames:

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +97
parser = argparse.ArgumentParser()
parser.add_argument(
"-l",
"--line-length",
type=int,
default=DEFAULT_LINE_LENGTH,
)
parser.add_argument(
"-S",
"--skip-string-normalization",
action="store_true",
)
parser.add_argument("-E", "--skip-errors", action="store_true")
parser.add_argument("filenames", nargs="*")
args = parser.parse_args(argv)
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The run_check and run_format functions accept line-length and skip-string-normalization arguments that are parsed but never used. These parameters should either be passed to the RuffChecker and RuffFormatter constructors (if they support configuration), or the argument parsing should be removed to avoid misleading users.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +128
parser = argparse.ArgumentParser()
parser.add_argument(
"-l",
"--line-length",
type=int,
default=DEFAULT_LINE_LENGTH,
)
parser.add_argument(
"-S",
"--skip-string-normalization",
action="store_true",
)
parser.add_argument("-E", "--skip-errors", action="store_true")
parser.add_argument("filenames", nargs="*")
args = parser.parse_args(argv)

retv = 0

for filename in args.filenames:
formatter = RuffChecker()
retv |= formatter.format_file(
filename,
skip_errors=args.skip_errors,
# rst_literal_blocks=args.rst_literal_blocks,
# check_only=args.check,
)

return retv


def run_format(argv: Sequence[str] | None = None) -> int:
...
return 1
parser = argparse.ArgumentParser()
parser.add_argument(
"-l",
"--line-length",
type=int,
default=DEFAULT_LINE_LENGTH,
)
parser.add_argument(
"-S",
"--skip-string-normalization",
action="store_true",
)
parser.add_argument("-E", "--skip-errors", action="store_true")
parser.add_argument("filenames", nargs="*")
args = parser.parse_args(argv)
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The argument parsing code in run_check and run_format is largely duplicated from run_black. Consider extracting this into a shared helper function to reduce code duplication and improve maintainability.

Copilot uses AI. Check for mistakes.
Comment on lines +106 to +108
# rst_literal_blocks=args.rst_literal_blocks,
# check_only=args.check,
)
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These commented-out lines should either be removed if they're not needed, or uncommented and implemented if they are. Leaving commented code in the codebase reduces clarity about what the intended behavior should be.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +103
formatter = RuffChecker()
retv |= formatter.format_file(
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name 'formatter' is misleading when the instance is actually a RuffChecker, not a formatter. Consider renaming to 'checker' for clarity and consistency with the class name.

Suggested change
formatter = RuffChecker()
retv |= formatter.format_file(
checker = RuffChecker()
retv |= checker.format_file(

Copilot uses AI. Check for mistakes.
Comment on lines +139 to +141
# rst_literal_blocks=args.rst_literal_blocks,
# check_only=args.check,
)
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These commented-out lines should either be removed if they're not needed, or uncommented and implemented if they are. Leaving commented code in the codebase reduces clarity about what the intended behavior should be.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants