Skip to content

Handle mermaid CLI timeouts and environment errors#22

Merged
leynos merged 5 commits intomainfrom
codex/fix-timeout-exception-handling-in-asyncio
Aug 15, 2025
Merged

Handle mermaid CLI timeouts and environment errors#22
leynos merged 5 commits intomainfrom
codex/fix-timeout-exception-handling-in-asyncio

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Aug 13, 2025

Summary

  • Catch asyncio.TimeoutError in wait_for_proc and reuse _run_mermaid_cli from _render_diagram
  • Surface a clear message when no Node.js or Bun runtime is available
  • Ensure temporary Puppeteer config files are cleaned up and add timeout test

Testing

  • make fmt
  • make check-fmt
  • make lint
  • make typecheck
  • make test

https://chatgpt.com/codex/tasks/task_e_689d160d9b3883229ef0b3ce662304f0

Summary by Sourcery

Improve CLI error handling and resource cleanup for Mermaid rendering, and strengthen test coverage.

New Features:

  • Surface a clear error when no Node.js or Bun runtime is available for Mermaid CLI

Enhancements:

  • Catch asyncio.TimeoutError in wait_for_proc and centralize Mermaid CLI subprocess handling
  • Ensure temporary Puppeteer config files are removed after use

Tests:

  • Add test_wait_for_proc to verify timeout behavior
  • Update Puppeteer config test to confirm file cleanup

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 13, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Summary by CodeRabbit

  • Bug Fixes
    • More robust timeout handling during diagram rendering; processes are terminated cleanly and failures reported consistently.
    • Clearer user guidance when the required CLI or Node environment is unavailable.
  • Refactor
    • Centralised CLI execution and validation to ensure consistent behaviour and error reporting.
  • Tests
    • Added asynchronous tests covering timeout scenarios.
    • Enhanced tests to verify temporary configuration files are cleaned up after use.

Walkthrough

Centralise mermaid CLI invocation into _run_mermaid_cli, strengthen wait_for_proc to catch asyncio.TimeoutError and return (False, b""), update _render_diagram to delegate to the runner and raise RuntimeError on CLI failure, add NoNodeEnvironmentAvailableError handling in render_block, and add/adjust unit tests for timeout and temp-file cleanup.

Changes

Cohort / File(s) Summary
CLI execution and error handling
nixie/cli.py
Extract subprocess invocation into _run_mermaid_cli; move executable validation into that runner (raises UnexpectedExecutableError when invalid); update _render_diagram to call the runner and raise RuntimeError with parsed stderr on failure; handle NoNodeEnvironmentAvailableError in render_block; update wait_for_proc to catch asyncio.TimeoutError, kill and await the process, print a timeout message, and return (False, b"").
Unit test: Puppeteer config cleanup
nixie/unittests/test_puppeteer_config.py
Import Path under TYPE_CHECKING; capture the config path from create_puppeteer_config() into a `Path
New async timeout tests
nixie/unittests/test_wait_for_proc.py
Add asynchronous tests exercising wait_for_proc timeout behaviour: assert asyncio.wait_for(..., 0.01) raises asyncio.TimeoutError and wait_for_proc(...) returns (False, b"") for a short timeout with piped subprocess IO.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as render_block / _render_diagram
  participant Runner as _run_mermaid_cli
  participant Proc as mermaid-cli (subprocess)
  participant Waiter as wait_for_proc

  Caller->>Runner: provide cmd, semaphore, path, idx, timeout
  Runner->>Proc: spawn subprocess (stdout/stderr piped)
  Runner->>Waiter: wait_for_proc(proc, path, idx, timeout)
  alt completes in time
    Waiter-->>Runner: (True, stderr)
    Runner-->>Caller: (success, stderr)
  else timeout
    Waiter->>Proc: kill and wait
    Waiter-->>Runner: (False, b"")
    Runner-->>Caller: (failure, b"")
    Caller->>Caller: raise RuntimeError with parsed stderr
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Possibly related PRs

Poem

A runner shepherds mermaid’s call,
Timeouts trimmed before they stall.
Empty stderr, processes cease,
Tests keep watch and grant release.
Semaphore hums — diagrams flow on. 🧜‍♀️✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a943c7d and 0737f94.

📒 Files selected for processing (1)
  • nixie/cli.py (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit Configuration File

**/*.py: - Keep cyclomatic complexity ≤ 12

  • Follow single responsibility and CQRS (command/query segregation)
  • Docstrings must follow the numpy style guide. Use a single-line summary for private functions and methods, and full structured docs for all public interfaces.
  • Move conditionals with >2 branches to predicate/helper functions
  • Avoid eval, exec, pickle, monkey-patching, ctypes, unsafe shell
  • Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate.
  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
  • Lint suppressions:
    • Blanket # noqa, file-level skips, and categories are forbidden
    • Only narrow in-line disables (# noqa: XYZ) are permitted, and must be accompanied by FIXME: or a ticket link, and used only as a last resort.
  • Use pytest fixtures for shared setup (conftest.py or fixtures/)
  • Replace duplicate tests with @pytest.mark.parametrize
  • Prefer pytest-mock or unittest.mock for stubs/mocks
  • Use assert …, "message" over bare asserts
  • Reflect all API/behaviour changes in docs/ and update roadmap on completion
  • Files must not exceed 400 logical lines:
    • Decompose large modules into subpackages
    • Split large match/case or dispatch tables by domain and collocate with targets if appropriate
    • Move bulky data (fixtures, templates) to external files for parsing at runtime
  • Mutable defaults and shadowed built-ins are forbidden
  • All code must have clear type hints using modern style (A | B, list[str], class Foo[A]:, type Bar = int, etc.), with ABC imports drawn from the correct stdlib module.

Files:

  • nixie/cli.py
🔇 Additional comments (4)
nixie/cli.py (4)

149-154: Catch asyncio.TimeoutError correctly and clean up the process

Catching the correct exception, killing the process, and awaiting termination avoids zombies and matches the intended semantics. Tests added in this PR cover this path.


175-176: Return wait_for_proc result within the semaphore scope (LGTM)

Keep the semaphore held for the full lifetime of the subprocess to accurately cap concurrent executions.


220-229: Delegate CLI invocation to _run_mermaid_cli (LGTM)

Centralise subprocess execution and error plumbing. Raising RuntimeError with a parsed CLI error yields clearer diagnostics to callers.


291-296: Log missing Node environment without traceback (LGTM)

Log at error level with exc_info=False and an annotated noqa, aligning with lint policy and treating this as an expected operational error.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/fix-timeout-exception-handling-in-asyncio

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Aug 13, 2025

Reviewer's Guide

This PR refines Mermaid CLI execution by catching CLI timeouts in a dedicated helper, centralizes process invocation, surfaces clear errors for missing Node.js/Bun environments, ensures temporary Puppeteer configs are cleaned up, and adds tests for timeout behavior and config cleanup.

Sequence diagram for error handling when Node.js/Bun is missing

sequenceDiagram
    participant CLIHandler
    participant Logger
    participant User
    CLIHandler->>CLIHandler: _render_diagram()
    CLIHandler->>CLIHandler: get_mmdc_cmd()
    alt No Node.js/Bun environment
        CLIHandler->>Logger: LOGGER.exception("No supported node environment found...")
        Logger->>User: Display error message
    end
Loading

Class diagram for updated Mermaid CLI process handling

classDiagram
    class CLIHandler {
        +wait_for_proc(proc, path, idx, timeout)
        +_run_mermaid_cli(cmd, semaphore, path, idx, timeout)
        +_render_diagram(block, path, idx, timeout)
    }
    class NoNodeEnvironmentAvailableError
    class UnexpectedExecutableError
    CLIHandler --> NoNodeEnvironmentAvailableError
    CLIHandler --> UnexpectedExecutableError
    CLIHandler : uses wait_for_proc
    CLIHandler : uses _run_mermaid_cli
    CLIHandler : uses _render_diagram
    NoNodeEnvironmentAvailableError <|-- Exception
    UnexpectedExecutableError <|-- Exception
Loading

File-Level Changes

Change Details Files
Catch and handle Mermaid CLI timeouts in wait_for_proc
  • Changed except to catch asyncio.TimeoutError
  • Added proc.kill() and await proc.wait() on timeout
  • Printed timeout message to stderr
nixie/cli.py
Refactor subprocess invocation into _run_mermaid_cli and use it in rendering
  • Removed manual subprocess creation in _render_diagram
  • Delegated process launch and waiting to _run_mermaid_cli
  • Dropped redundant executable checks in render path
nixie/cli.py
Surface clear message when no Node.js or Bun runtime is available
  • Added except NoNodeEnvironmentAvailableError block in render_block
  • Logged instructions to install Node.js, Bun, or Mermaid CLI
nixie/cli.py
Ensure temporary Puppeteer config files are cleaned up
  • Captured config file path in tests
  • Asserted config file no longer exists after exiting context
nixie/unittests/test_puppeteer_config.py
Add timeout test for wait_for_proc
  • Created test_wait_for_proc.py
  • Asserted wait_for_proc returns False and empty stderr on timeout
nixie/unittests/test_wait_for_proc.py

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, no comments

Edit Code Review Bot Settings | Greptile

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Add a test to demonstrate the bug fix for catching asyncio.TimeoutError instead of TimeoutError. (link)
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `nixie/cli.py:149` </location>
<code_context>
     try:
         _, stderr = await asyncio.wait_for(proc.communicate(), timeout)
-    except TimeoutError:
+    except asyncio.TimeoutError:  # noqa: UP041
         proc.kill()
         await proc.wait()
</code_context>

<issue_to_address>
Add a test to demonstrate the bug fix for catching asyncio.TimeoutError instead of TimeoutError.

You changed the exception caught from TimeoutError to asyncio.TimeoutError, which is a bug fix. You must add a test that demonstrates this fix, ensuring that the correct exception is handled and the timeout logic works as intended.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread nixie/cli.py Outdated
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Aug 14, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 14, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (4)
nixie/cli.py (3)

149-154: Drop the noqa, and log the timeout instead of printing to stderr.

Align with project guidelines: avoid blanket/narrow suppressions unless justified with FIXME/ticket, and prefer the module logger over print for consistency and testability.

Apply:

-    except asyncio.TimeoutError:  # noqa: UP041
+    except asyncio.TimeoutError:
         proc.kill()
         await proc.wait()
-        print(f"{path}: diagram {idx} timed out", file=sys.stderr)
+        LOGGER.warning("%s: diagram %s timed out", path, idx)
         return (False, b"")

169-174: Document the Semgrep suppression with a FIXME rationale.

Project guidelines require inline suppressions to include a FIXME or ticket and be a last resort. Add context explaining why this subprocess call is safe (allow-list of executables and controlled args).

-        # nosemgrep: python.lang.security.audit.dangerous-asyncio-create-exec-audit
+        # nosemgrep: python.lang.security.audit.dangerous-asyncio-create-exec-audit
+        # FIXME: Allowed executables are constrained via ALLOWED_EXECUTABLES/get_mmdc_cmd,
+        # and arguments are constructed from validated Paths. Review if inputs change.

299-301: Fix invalid isinstance() usage with a union type at runtime.

isinstance(exc, KeyboardInterrupt | SystemExit) is not valid at runtime. Pass a tuple of types.

-        if isinstance(exc, KeyboardInterrupt | SystemExit):
+        if isinstance(exc, (KeyboardInterrupt, SystemExit)):
             raise
nixie/unittests/test_wait_for_proc.py (1)

18-41: Also assert the timeout message is emitted to stderr.

Capture and assert the warning to guard against regressions in user-visible output.

-@pytest.mark.asyncio
-async def test_wait_for_proc_handles_asyncio_timeout_error(tmp_path: Path) -> None:
+@pytest.mark.asyncio
+async def test_wait_for_proc_handles_asyncio_timeout_error(
+    tmp_path: Path, capfd: pytest.CaptureFixture[str]
+) -> None:
@@
-    success, stderr = await wait_for_proc(proc, tmp_path / "dummy.md", 1, timeout=0.01)
+    success, stderr = await wait_for_proc(proc, tmp_path / "dummy.md", 1, timeout=0.01)
     assert not success
     assert stderr == b""
+    out = capfd.readouterr()
+    assert "dummy.md: diagram 1 timed out" in out.err, "stderr timeout message missing"
♻️ Duplicate comments (1)
nixie/unittests/test_wait_for_proc.py (1)

18-41: Demonstrate the asyncio.TimeoutError fix and assert API behaviour.

The test exercises the timeout path correctly and validates the returned (False, b"") pair, addressing the earlier review request to cover the bug fix.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9a91927 and 18b9cd8.

📒 Files selected for processing (3)
  • nixie/cli.py (4 hunks)
  • nixie/unittests/test_puppeteer_config.py (1 hunks)
  • nixie/unittests/test_wait_for_proc.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit Configuration File

**/*.py: - Keep cyclomatic complexity ≤ 12

  • Follow single responsibility and CQRS (command/query segregation)
  • Docstrings must follow the numpy style guide. Use a single-line summary for private functions and methods, and full structured docs for all public interfaces.
  • Move conditionals with >2 branches to predicate/helper functions
  • Avoid eval, exec, pickle, monkey-patching, ctypes, unsafe shell
  • Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate.
  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
  • Lint suppressions:
    • Blanket # noqa, file-level skips, and categories are forbidden
    • Only narrow in-line disables (# noqa: XYZ) are permitted, and must be accompanied by FIXME: or a ticket link, and used only as a last resort.
  • Use pytest fixtures for shared setup (conftest.py or fixtures/)
  • Replace duplicate tests with @pytest.mark.parametrize
  • Prefer pytest-mock or unittest.mock for stubs/mocks
  • Use assert …, "message" over bare asserts
  • Reflect all API/behaviour changes in docs/ and update roadmap on completion
  • Files must not exceed 400 logical lines:
    • Decompose large modules into subpackages
    • Split large match/case or dispatch tables by domain and collocate with targets if appropriate
    • Move bulky data (fixtures, templates) to external files for parsing at runtime
  • Mutable defaults and shadowed built-ins are forbidden
  • All code must have clear type hints using modern style (A | B, list[str], class Foo[A]:, type Bar = int, etc.), with ABC imports drawn from the correct stdlib module.

Files:

  • nixie/unittests/test_wait_for_proc.py
  • nixie/unittests/test_puppeteer_config.py
  • nixie/cli.py
🧬 Code Graph Analysis (2)
nixie/unittests/test_wait_for_proc.py (1)
nixie/cli.py (2)
  • cli (395-405)
  • wait_for_proc (143-155)
nixie/unittests/test_puppeteer_config.py (1)
nixie/cli.py (1)
  • create_puppeteer_config (84-106)
🔇 Additional comments (4)
nixie/cli.py (2)

175-176: LGTM: Delegate process waiting to the central helper.

Returning the awaitable directly keeps the flow simple and consolidates timeout handling in one place.


220-229: LGTM: Centralise CLI invocation and surface actionable errors.

Using _run_mermaid_cli here reduces duplication, and raising RuntimeError with a parsed message improves UX.

nixie/unittests/test_puppeteer_config.py (2)

11-13: LGTM: Keep typing-only imports lightweight.

Importing Path under TYPE_CHECKING pairs well with from __future__ import annotations and avoids runtime dependencies.


20-27: LGTM: Assert temporary Puppeteer config is cleaned up.

Capturing the path out-of-context and asserting it no longer exists robustly validates cleanup semantics.

Comment thread nixie/cli.py
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Aug 15, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 15, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (3)
nixie/cli.py (3)

158-166: Add a private docstring to _run_mermaid_cli.

Private functions must have a one-line summary docstring per the guidelines.

Apply this diff:

 async def _run_mermaid_cli(
     cmd: list[str],
     sem: asyncio.Semaphore,
     path: Path,
     idx: int,
     timeout: float,
 ) -> tuple[bool, bytes]:
+    """Run mermaid-cli under a semaphore and return (success, stderr)."""

296-305: Fix invalid isinstance usage and unreachable re-raise; restructure except blocks.

isinstance(exc, KeyboardInterrupt | SystemExit) raises at runtime; also, those exceptions are not caught by except Exception, so the check is redundant. Restructure the handlers.

Apply this diff:

-    except RuntimeError:
-        LOGGER.exception("Runtime error while rendering diagram")
-    except Exception as exc:
-        if isinstance(exc, KeyboardInterrupt | SystemExit):
-            raise
-        LOGGER.exception(
-            "%s: unexpected error in diagram %s",
-            path,
-            idx,
-        )
+    except (KeyboardInterrupt, SystemExit):
+        raise
+    except RuntimeError:
+        LOGGER.exception("Runtime error while rendering diagram")
+    except Exception:
+        LOGGER.exception(
+            "%s: unexpected error in diagram %s",
+            path,
+            idx,
+        )

1-410: Split this module; it exceeds the 400-line limit.

Extract the rendering/subprocess helpers (_run_mermaid_cli, wait_for_proc, get_mmdc_cmd, format_cli_error, create_puppeteer_config) into a dedicated module (e.g., nixie/mermaid_cli.py) and keep CLI/glue in cli.py.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 18b9cd8 and a943c7d.

📒 Files selected for processing (1)
  • nixie/cli.py (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

⚙️ CodeRabbit Configuration File

**/*.py: - Keep cyclomatic complexity ≤ 12

  • Follow single responsibility and CQRS (command/query segregation)
  • Docstrings must follow the numpy style guide. Use a single-line summary for private functions and methods, and full structured docs for all public interfaces.
  • Move conditionals with >2 branches to predicate/helper functions
  • Avoid eval, exec, pickle, monkey-patching, ctypes, unsafe shell
  • Every module must begin with a triple-quoted docstring explaining its purpose, utility, and usage, including example calls if appropriate.
  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
  • Lint suppressions:
    • Blanket # noqa, file-level skips, and categories are forbidden
    • Only narrow in-line disables (# noqa: XYZ) are permitted, and must be accompanied by FIXME: or a ticket link, and used only as a last resort.
  • Use pytest fixtures for shared setup (conftest.py or fixtures/)
  • Replace duplicate tests with @pytest.mark.parametrize
  • Prefer pytest-mock or unittest.mock for stubs/mocks
  • Use assert …, "message" over bare asserts
  • Reflect all API/behaviour changes in docs/ and update roadmap on completion
  • Files must not exceed 400 logical lines:
    • Decompose large modules into subpackages
    • Split large match/case or dispatch tables by domain and collocate with targets if appropriate
    • Move bulky data (fixtures, templates) to external files for parsing at runtime
  • Mutable defaults and shadowed built-ins are forbidden
  • All code must have clear type hints using modern style (A | B, list[str], class Foo[A]:, type Bar = int, etc.), with ABC imports drawn from the correct stdlib module.

Files:

  • nixie/cli.py
🔇 Additional comments (4)
nixie/cli.py (4)

147-155: LGTM: Correctly catch asyncio.TimeoutError and clean up the process.

Catching asyncio.TimeoutError is the right exception in this context; killing and awaiting the process and returning a consistent (False, b"") is sound.


175-175: LGTM: Delegate process waiting to wait_for_proc.

Returning the awaited result centralises lifecycle and timeout handling.


222-222: LGTM: Reuse _run_mermaid_cli to centralise subprocess execution.

This removes duplication and keeps error handling consistent.


291-295: LGTM: Log missing Node environment as an operational error, not an exception.

Avoiding a traceback for this expected case is the right UX.

Comment thread nixie/cli.py Outdated
Comment thread nixie/cli.py
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Aug 15, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 15, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos leynos merged commit 8906f21 into main Aug 15, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant