Skip to content

Conversation

@tboy1337
Copy link

@tboy1337 tboy1337 commented Aug 30, 2025

  • Introduced _get_base_command method to dynamically set the base command for PostgreSQL based on the operating system.
  • Added _windows_terminate_process method to handle process termination on Windows, ensuring graceful shutdown before force-killing.
  • Updated stop method to utilize the new Windows-specific termination logic.

Summary by CodeRabbit

  • Bug Fixes
    • Improved cross-platform PostgreSQL process management: startup command is now built dynamically and Windows shutdown prefers graceful termination with a force‑kill fallback when needed.
  • Tests
    • Added comprehensive Windows compatibility tests to validate command formatting, startup/shutdown behaviour and fallback termination scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@tboy1337 tboy1337 mentioned this pull request Aug 30, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 21, 2026

Walkthrough

Replaces a static start command with a dynamic _get_base_command() and adds a Windows-specific _windows_terminate_process(); refactors stop() to run pg_ctl as a list, branch by OS, and fall back to Windows termination when os.killpg is unavailable; adds Windows-focused tests.

Changes

Cohort / File(s) Change Summary
Core executor
pytest_postgresql/executor.py
Removed static BASE_PROC_START_COMMAND; added def _get_base_command(self) -> str; added def _windows_terminate_process(self, sig: Optional[int]=None) -> None; refactored __init__ and stop() to use dynamic command assembly, run pg_ctl as a list (no shell), branch Windows vs non‑Windows, and handle AttributeError fallback; added imports: os, shutil, subprocess, tempfile, time.
Windows compatibility tests
tests/test_windows_compatibility.py
New test suite TestWindowsCompatibility validating _get_base_command formatting, Windows pg_ctl command assembly, _windows_terminate_process() behaviours (graceful, timeout, force kill), stop() branching and fallback paths using mocks/patches.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Executor as PostgreSQLExecutor
    participant OS as OperatingSystem
    participant Process as PostgreSQLProcess

    Client->>Executor: call stop()
    Executor->>Executor: build stop command via _get_base_command()
    alt Windows
        Executor->>Executor: issue pg_ctl stop (list form)
        Executor->>Executor: call _windows_terminate_process()
        Executor->>Process: send graceful terminate, wait
        alt not terminated (timeout)
            Executor->>Process: force kill
            Process-->>Executor: killed
        else terminated
            Process-->>Executor: terminated
        end
    else Non‑Windows
        Executor->>OS: delegate to super().stop() / os.killpg
        OS->>Process: send SIGTERM
        Process-->>OS: terminated
        alt AttributeError (os.killpg unavailable)
            Executor->>Executor: fallback to _windows_terminate_process()
        end
    end
    Executor-->>Client: return
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I hop and craft the command anew,
I nudge the process, patient as dew,
On Windows I coax, then tug if stalled,
A tidy end so nothing's called,
Hooray — a cross‑platform little whoo!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the pull request: refactoring PostgreSQLExecutor to support Windows compatibility for process management.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
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

🤖 Fix all issues with AI agents
In `@pytest_postgresql/executor.py`:
- Around line 263-283: In stop(self, sig: Optional[int] = None, exp_sig:
Optional[int] = None) replace the subprocess.check_output call that builds a
shell string with a list-style invocation (e.g., [self.executable, "stop", "-D",
self.datadir, "-m", "f"]) and remove shell=True so subprocess runs the
executable directly; this avoids breaking paths with spaces and removes the
shell injection risk while keeping the same arguments and behavior before the
platform-specific termination logic (_windows_terminate_process / super().stop).
- Around line 53-66: The _get_base_command constructs the -o string with
unix_socket_directories unquoted which breaks for paths with spaces; update
_get_base_command to detect whitespace in the unixsocketdir variable and wrap
that value in double quotes (or escape quotes) when building the -o option so
the produced fragment becomes -c unix_socket_directories="/path/with space"
(referencing the unix_socket_directories token and BASE_PROC_START_COMMAND
assignment), and add a unit test that passes a datadir/unixsocketdir containing
a space to ensure the command line includes the quoted socket directory (or
alternatively, add explicit validation/documentation and raise a clear error
when whitespace is present).
🧹 Nitpick comments (1)
pytest_postgresql/executor.py (1)

231-262: Tidy up the termination helper API surface.

sig is unused in _windows_terminate_process, and _unix_terminate_process is currently unused. Either wire _unix_terminate_process into stop() for symmetry and use sig, or drop/rename the parameter to avoid dead code and lint noise.

@tboy1337 tboy1337 force-pushed the edit branch 2 times, most recently from 5d4fb91 to efa4633 Compare January 21, 2026 07:59
Copy link
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

🤖 Fix all issues with AI agents
In `@tests/test_windows_compatibility.py`:
- Around line 35-39: The test assertions in tests/test_windows_compatibility.py
don't match the actual string produced by _get_base_command(): update the
assertions to expect the escaped-quote form for unix_socket_directories (i.e.,
include the backslash-escaped double quotes around {unixsocketdir}) and assert
that the non-quoted form is not present; specifically change the positive
assertion referencing unix_socket_directories to look for
unix_socket_directories=\"{unixsocketdir}\" and keep the negative assertion for
unix_socket_directories='{unixsocketdir}' to ensure consistency with
_get_base_command().
- Around line 189-204: The test's expected_parts entry for
unix_socket_directories doesn't match the actual command string (which includes
escaped quotes), so update the expectation in the test to match the
implementation: replace the "-c unix_socket_directories=C:/temp/socket" entry
with the escaped-quote form that appears in executor.command (e.g., -c
unix_socket_directories=\"C:/temp/socket\"), keeping the rest of the
expected_parts and the loop over executor.command unchanged; reference the test
variable executor.command and the expected_parts list when making the change.
🧹 Nitpick comments (2)
pytest_postgresql/executor.py (2)

25-25: Unused import signal.

The signal module is imported but not used anywhere in the file. This appears to be a leftover from development.

🧹 Suggested fix
-import signal

250-269: Good refactor to list-based subprocess call.

The change from shell string to list format ([self.executable, "stop", "-D", self.datadir, "-m", "f"]) properly addresses the previous security concern and handles paths with spaces correctly.

One minor observation: the AttributeError fallback (lines 263-268) uses string matching "killpg" in str(e) which is somewhat fragile. Consider whether this fallback is still needed given the explicit platform.system() check now handles Windows upfront.

"-c unix_socket_directories='{unixsocketdir}' {postgres_options}\" "
'-l "{logfile}" {startparams}'
)
def _get_base_command(self) -> str:
Copy link
Member

Choose a reason for hiding this comment

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

We do not do anything inside with the command template itself, no additional format, no string concatenation. I don't think there's a need to convert it to a method. Please convert that back to the class attribute, but keep your docstring and comment as a old parameter's name docstring/comment.

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