Skip to content

feat(cli): add server workers option#1851

Open
adityasingh2400 wants to merge 8 commits into
NVIDIA-NeMo:developfrom
adityasingh2400:feat/server-workers-option
Open

feat(cli): add server workers option#1851
adityasingh2400 wants to merge 8 commits into
NVIDIA-NeMo:developfrom
adityasingh2400:feat/server-workers-option

Conversation

@adityasingh2400
Copy link
Copy Markdown

@adityasingh2400 adityasingh2400 commented May 6, 2026

Summary

  • Add a --workers option to nemoguardrails server.
  • Pass the configured worker count through to uvicorn.run.
  • Document the new CLI option in the server command reference.

Fixes #1746

Verification

  • python3 -m compileall nemoguardrails/cli/__init__.py

PR overlap check

  • Searched open PRs for 1746; no existing open PR covers this issue.

Summary by CodeRabbit

  • New Features
    • Added --workers CLI option to the server command for specifying the number of Uvicorn worker processes to run (default: 1, minimum: 1), enabling multi-process serving configurations.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Documentation preview

https://nvidia-nemo.github.io/Guardrails/review/pr-1851

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR adds a --workers N option to nemoguardrails server that passes the worker count to uvicorn, solving the long-standing limitation of single-process serving. To make config options visible to worker sub-processes, the CLI now propagates settings through environment variables (NEMO_GUARDRAILS_CONFIG_PATH, NEMO_GUARDRAILS_AUTO_RELOAD, etc.) before spawning workers, and api.py reads those env vars at module-import time.

  • workers > 1 uses \"nemoguardrails.server.api:create_app\" with factory=True (correct uvicorn multi-worker API) and guards against incompatible --prefix and --auto-reload options with clear error messages.
  • A create_app() factory function returning the module-level app singleton is added to api.py; env-var reads at module level ensure each spawned worker inherits the full CLI configuration.
  • Four new tests cover the factory-dispatch path, the two rejection cases, and the verbose env-var propagation — all with proper @patch.dict/os.getcwd/os.path.exists isolation.

Confidence Score: 4/5

The multi-worker plumbing is functionally correct; two pre-existing tests remain broken because they lack the os.getcwd/os.path.exists mocks needed by the new os.fspath code path introduced in this PR.

The env-var propagation strategy and factory pattern are sound, and the four new tests are properly isolated. However, test_server_with_disable_chat_ui and test_server_with_auto_reload will raise TypeError (via os.fspath on a MagicMock) whenever there is no config/ directory in the working directory, causing those test assertions to fail in CI.

tests/cli/test_cli_main.py — the two pre-existing server tests still lack the os.getcwd/os.path.exists mocks needed by the new os.fspath call; nemoguardrails/cli/init.py — guard ordering could be moved earlier for cleanliness.

Important Files Changed

Filename Overview
nemoguardrails/cli/init.py Adds --workers option; propagates config via env vars before worker spawn; guards against incompatible --prefix/--auto-reload combinations, but those guards come after env/app state has already been mutated.
nemoguardrails/server/api.py Adds module-level env-var reads for NEMO_GUARDRAILS_CONFIG_PATH, AUTO_RELOAD, DEFAULT_CONFIG_ID, and VERBOSE so worker processes pick up config at import time; adds create_app factory returning the module-level singleton.
tests/cli/test_cli_main.py New tests for workers factory path, reject cases, and verbose env var — all correctly isolated with @patch.dict/getcwd/exists mocks; the two pre-existing tests (test_server_with_disable_chat_ui, test_server_with_auto_reload) remain unpatched and will fail when no config/ dir exists in cwd, as flagged in the previous review.
docs/reference/cli/index.md Documents the new --workers option with default value; entry is accurate and placed in correct table position.

Sequence Diagram

sequenceDiagram
    participant CLI as nemoguardrails server CLI
    participant Env as os.environ
    participant Uvicorn as uvicorn.run
    participant Worker as Worker Process
    participant ApiPy as nemoguardrails.server.api

    CLI->>Env: Set NEMO_GUARDRAILS_CONFIG_PATH
    CLI->>Env: Set NEMO_GUARDRAILS_VERBOSE (if --verbose)
    CLI->>Env: Set NEMO_GUARDRAILS_DISABLE_CHAT_UI (if --disable-chat-ui)
    CLI->>Env: Set NEMO_GUARDRAILS_AUTO_RELOAD (if --auto-reload)
    CLI->>Env: Set NEMO_GUARDRAILS_DEFAULT_CONFIG_ID (if --default-config-id)

    alt "workers == 1"
        CLI->>Uvicorn: run(server_app, port, ...)
        Uvicorn->>ApiPy: already imported in parent process
    else "workers > 1"
        CLI->>CLI: Guard: reject --prefix or --auto-reload
        CLI->>Uvicorn: "run(api:create_app, factory=True, workers=N)"
        loop Each worker process
            Uvicorn->>Worker: spawn/fork
            Worker->>ApiPy: import reads env vars at module level
            ApiPy-->>Worker: app with rails_config_path auto_reload etc
            Worker->>ApiPy: create_app returns module-level app singleton
        end
    end
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
nemoguardrails/cli/__init__.py:213-235
**Incompatibility guards fire after state has already been mutated**

The checks for `--prefix` and `--auto-reload` against `workers > 1` are evaluated only after env vars (`NEMO_GUARDRAILS_CONFIG_PATH`, `NEMO_GUARDRAILS_DEFAULT_CONFIG_ID`, etc.) have been written, `FastAPI().mount()` has been called, and `set_default_config_id` has executed. When the command exits with code 1, this state is already in place. Moving the guards to just before the prefix-mount block would keep the failure path clean and prevent any unnecessary side effects from running before the error is reported.

Reviews (8): Last reviewed commit: "test(server): isolate verbose worker env..." | Re-trigger Greptile

Comment thread nemoguardrails/cli/__init__.py Outdated
api.set_default_config_id(default_config_id) # Call function

uvicorn.run(server_app, port=port, log_level="info", host="0.0.0.0")
uvicorn.run(server_app, port=port, log_level="info", host="0.0.0.0", workers=workers)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 workers > 1 silently exits when app is passed as an instance

Uvicorn requires an import string (e.g. "nemoguardrails.server.api:app") — not an application object — when workers is set to anything greater than 1. Passing the live server_app object with workers=2 causes uvicorn to print "You must pass the application as an import string to enable 'reload' or 'workers'" and then exit with SystemError 1. This means every invocation of --workers N where N > 1 is silently broken.

The fix requires either (a) passing the app as an import string when workers > 1 (which complicates the current per-process attribute-patching approach used for rails_config_path, disable_chat_ui, etc.), or (b) raising an explicit error when workers > 1 with a clear message about this constraint until a proper solution is implemented.

Prompt To Fix With AI
This is a comment left during a code review.
Path: nemoguardrails/cli/__init__.py
Line: 204

Comment:
**`workers > 1` silently exits when app is passed as an instance**

Uvicorn requires an import string (e.g. `"nemoguardrails.server.api:app"`) — not an application object — when `workers` is set to anything greater than 1. Passing the live `server_app` object with `workers=2` causes uvicorn to print `"You must pass the application as an import string to enable 'reload' or 'workers'"` and then exit with `SystemError 1`. This means every invocation of `--workers N` where N > 1 is silently broken.

The fix requires either (a) passing the app as an import string when `workers > 1` (which complicates the current per-process attribute-patching approach used for `rails_config_path`, `disable_chat_ui`, etc.), or (b) raising an explicit error when `workers > 1` with a clear message about this constraint until a proper solution is implemented.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in eb00418. --workers > 1 no longer passes a live app instance to uvicorn.

The server now calls uvicorn.run("nemoguardrails.server.api:create_app", factory=True, workers=workers). create_app is a new factory in api.py that reads the same env vars the parent process sets (NEMO_GUARDRAILS_CONFIG_PATH, NEMO_GUARDRAILS_DISABLE_CHAT_UI, NEMO_GUARDRAILS_DEFAULT_CONFIG_ID, the auto-reload flag) and rebuilds the app from scratch in each worker, so the previously-relied-on parent-process attribute patches (api.app.rails_config_path = ... etc.) are no longer needed in worker mode.

The single-worker path is unchanged and still uses the live server_app so --prefix (which mounts the app at a sub-path) keeps working as before. workers > 1 rejects --prefix explicitly with a clear error (commit 1a85158).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

A --workers CLI flag is added to the NeMo Guardrails server command, allowing users to specify the number of Uvicorn worker processes. The parameter defaults to 1 for backward compatibility and is passed directly to uvicorn.run(). Documentation is updated accordingly.

Changes

Multi-Worker Server Support

Layer / File(s) Summary
Parameter Definition
nemoguardrails/cli/__init__.py
New workers parameter added to the server() command with typer.Option(default=1, min=1) to accept worker count from CLI.
Uvicorn Integration
nemoguardrails/cli/__init__.py
The workers argument is passed to uvicorn.run() to enable multi-worker serving.
Documentation
docs/reference/cli/index.md
Server options table updated to document the new --workers flag and its behavior (default: 1).

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Test Results For Major Changes ⚠️ Warning Major new feature (--workers CLI option) added without test results or testing information. Only syntax verification mentioned, no functional tests. Add test results or test cases verifying --workers works correctly, especially for multi-worker scenarios. Include functional testing in PR description or add tests.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a server workers option to the CLI. It is specific and clearly indicates the primary modification.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from issue #1746: adds a workers parameter with default value of 1, passes it to uvicorn.run, and documents the option.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the --workers flag feature. Documentation and CLI code modifications are both in scope for the linked issue.
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 unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@nemoguardrails/cli/__init__.py`:
- Line 204: The current call uvicorn.run(server_app, ...) passes a live app
instance so --workers>1 fails and the per-process mutations (rails_config_path,
disable_chat_ui, auto_reload, default_config_id set between lines 173-202) don’t
propagate to workers; change to run Uvicorn with an import string or factory so
workers spawn correctly and receive configuration: expose a factory like
create_app(...) or export the ASGI app as a module-level name (e.g.,
"nemoguardrails.cli.__init__:server_app" or better
"nemoguardrails.cli.__init__:create_app") and call uvicorn.run with that import
string when workers>1, and move the mutating logic (rails_config_path,
disable_chat_ui, auto_reload, default_config_id) into the app factory or into
startup hooks/environment variables so each worker initializes with the intended
config.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f065d2bf-33da-4e7d-9f2d-b9bcf077d8cf

📥 Commits

Reviewing files that changed from the base of the PR and between 6a8fdf3 and 52e617a.

📒 Files selected for processing (2)
  • docs/reference/cli/index.md
  • nemoguardrails/cli/__init__.py

Comment thread nemoguardrails/cli/__init__.py Outdated
Comment on lines +210 to +216
if workers > 1:
if prefix:
typer.secho(
"The --prefix option is not supported with --workers > 1.",
fg=typer.colors.RED,
)
raise typer.Exit(1)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 When --auto-reload and --workers > 1 are combined, each uvicorn worker process inherits NEMO_GUARDRAILS_AUTO_RELOAD=true and independently enters the lifespan's start_auto_reload_monitoring branch, spawning N concurrent file watchers on the same directory. This causes redundant reload signals and potential race conditions. The PR already guards --prefix against workers > 1; the same guard is needed for --auto-reload.

Suggested change
if workers > 1:
if prefix:
typer.secho(
"The --prefix option is not supported with --workers > 1.",
fg=typer.colors.RED,
)
raise typer.Exit(1)
if workers > 1:
if prefix:
typer.secho(
"The --prefix option is not supported with --workers > 1.",
fg=typer.colors.RED,
)
raise typer.Exit(1)
if auto_reload:
typer.secho(
"The --auto-reload option is not supported with --workers > 1.",
fg=typer.colors.RED,
)
raise typer.Exit(1)
Prompt To Fix With AI
This is a comment left during a code review.
Path: nemoguardrails/cli/__init__.py
Line: 210-216

Comment:
When `--auto-reload` and `--workers > 1` are combined, each uvicorn worker process inherits `NEMO_GUARDRAILS_AUTO_RELOAD=true` and independently enters the lifespan's `start_auto_reload_monitoring` branch, spawning N concurrent file watchers on the same directory. This causes redundant reload signals and potential race conditions. The PR already guards `--prefix` against `workers > 1`; the same guard is needed for `--auto-reload`.

```suggestion
    if workers > 1:
        if prefix:
            typer.secho(
                "The --prefix option is not supported with --workers > 1.",
                fg=typer.colors.RED,
            )
            raise typer.Exit(1)
        if auto_reload:
            typer.secho(
                "The --auto-reload option is not supported with --workers > 1.",
                fg=typer.colors.RED,
            )
            raise typer.Exit(1)
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 0932b17.

Added the same explicit guard pattern that already existed for --prefix. --auto-reload combined with --workers > 1 now exits 1 with "The --auto-reload option is not supported with --workers > 1." before uvicorn is invoked, so the N-concurrent-file-watchers race never happens. The guard is paired with a unit test in tests/cli/test_cli_main.py that asserts the reject path and confirms uvicorn.run is not called.

Comment on lines +257 to +273
@patch("uvicorn.run")
@patch("nemoguardrails.server.api.app")
def test_server_rejects_prefix_with_workers(self, mock_app, mock_uvicorn):
result = runner.invoke(app, ["server", "--workers=2", "--prefix=/api/v1"])

assert result.exit_code == 1
assert "The --prefix option is not supported with --workers > 1." in result.output
mock_uvicorn.assert_not_called()

@patch("uvicorn.run")
@patch("nemoguardrails.server.api.app")
def test_server_rejects_auto_reload_with_workers(self, mock_app, mock_uvicorn):
result = runner.invoke(app, ["server", "--workers=2", "--auto-reload"])

assert result.exit_code == 1
assert "The --auto-reload option is not supported with --workers > 1." in result.output
mock_uvicorn.assert_not_called()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 The two reject tests don't mock os.getcwd() / os.path.exists() and don't guard the environment with @patch.dict. When there is no config/ directory in the working directory, rails_config_path falls back to api.app.rails_config_path (a MagicMock), which means os.fspath returns "" and NEMO_GUARDRAILS_CONFIG_PATH is set to an empty string in the real os.environ. That leaked value persists into subsequent tests in the same process and could silently affect any test that reads NEMO_GUARDRAILS_CONFIG_PATH without clearing it first. Adding the same isolation decoration used by the other workers test fixes both problems.

Suggested change
@patch("uvicorn.run")
@patch("nemoguardrails.server.api.app")
def test_server_rejects_prefix_with_workers(self, mock_app, mock_uvicorn):
result = runner.invoke(app, ["server", "--workers=2", "--prefix=/api/v1"])
assert result.exit_code == 1
assert "The --prefix option is not supported with --workers > 1." in result.output
mock_uvicorn.assert_not_called()
@patch("uvicorn.run")
@patch("nemoguardrails.server.api.app")
def test_server_rejects_auto_reload_with_workers(self, mock_app, mock_uvicorn):
result = runner.invoke(app, ["server", "--workers=2", "--auto-reload"])
assert result.exit_code == 1
assert "The --auto-reload option is not supported with --workers > 1." in result.output
mock_uvicorn.assert_not_called()
@patch.dict(os.environ, {}, clear=True)
@patch("uvicorn.run")
@patch("nemoguardrails.server.api.app")
@patch("os.path.exists")
@patch("os.getcwd")
def test_server_rejects_prefix_with_workers(
self, mock_getcwd, mock_exists, mock_app, mock_uvicorn
):
mock_getcwd.return_value = "/current/dir"
mock_exists.return_value = True
result = runner.invoke(app, ["server", "--workers=2", "--prefix=/api/v1"])
assert result.exit_code == 1
assert "The --prefix option is not supported with --workers > 1." in result.output
mock_uvicorn.assert_not_called()
@patch.dict(os.environ, {}, clear=True)
@patch("uvicorn.run")
@patch("nemoguardrails.server.api.app")
@patch("os.path.exists")
@patch("os.getcwd")
def test_server_rejects_auto_reload_with_workers(
self, mock_getcwd, mock_exists, mock_app, mock_uvicorn
):
mock_getcwd.return_value = "/current/dir"
mock_exists.return_value = True
result = runner.invoke(app, ["server", "--workers=2", "--auto-reload"])
assert result.exit_code == 1
assert "The --auto-reload option is not supported with --workers > 1." in result.output
mock_uvicorn.assert_not_called()
Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/cli/test_cli_main.py
Line: 257-273

Comment:
The two reject tests don't mock `os.getcwd()` / `os.path.exists()` and don't guard the environment with `@patch.dict`. When there is no `config/` directory in the working directory, `rails_config_path` falls back to `api.app.rails_config_path` (a `MagicMock`), which means `os.fspath` returns `""` and `NEMO_GUARDRAILS_CONFIG_PATH` is set to an empty string in the real `os.environ`. That leaked value persists into subsequent tests in the same process and could silently affect any test that reads `NEMO_GUARDRAILS_CONFIG_PATH` without clearing it first. Adding the same isolation decoration used by the other workers test fixes both problems.

```suggestion
    @patch.dict(os.environ, {}, clear=True)
    @patch("uvicorn.run")
    @patch("nemoguardrails.server.api.app")
    @patch("os.path.exists")
    @patch("os.getcwd")
    def test_server_rejects_prefix_with_workers(
        self, mock_getcwd, mock_exists, mock_app, mock_uvicorn
    ):
        mock_getcwd.return_value = "/current/dir"
        mock_exists.return_value = True
        result = runner.invoke(app, ["server", "--workers=2", "--prefix=/api/v1"])

        assert result.exit_code == 1
        assert "The --prefix option is not supported with --workers > 1." in result.output
        mock_uvicorn.assert_not_called()

    @patch.dict(os.environ, {}, clear=True)
    @patch("uvicorn.run")
    @patch("nemoguardrails.server.api.app")
    @patch("os.path.exists")
    @patch("os.getcwd")
    def test_server_rejects_auto_reload_with_workers(
        self, mock_getcwd, mock_exists, mock_app, mock_uvicorn
    ):
        mock_getcwd.return_value = "/current/dir"
        mock_exists.return_value = True
        result = runner.invoke(app, ["server", "--workers=2", "--auto-reload"])

        assert result.exit_code == 1
        assert "The --auto-reload option is not supported with --workers > 1." in result.output
        mock_uvicorn.assert_not_called()
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in b7520be.

Both test_server_rejects_prefix_with_workers and test_server_rejects_auto_reload_with_workers now use the same @patch.dict(os.environ, {}, clear=True) plus @patch("os.getcwd") / @patch("os.path.exists") decoration suggested above. mock_getcwd.return_value = "/current/dir" and mock_exists.return_value = True so the CLI takes the local_configs_path branch deterministically and never falls through to the MagicMock-leakage path. The env var leak into subsequent tests is gone.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 88.88889% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
nemoguardrails/server/api.py 62.50% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

Comment on lines +209 to +215
@patch.dict(os.environ, {}, clear=True)
@patch("uvicorn.run")
@patch("nemoguardrails.server.api.app")
def test_server_with_verbose_sets_worker_env(self, mock_app, mock_uvicorn):
result = runner.invoke(app, ["server", "--verbose"])
assert result.exit_code == 0
assert os.environ["NEMO_GUARDRAILS_VERBOSE"] == "true"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Missing os.getcwd / os.path.exists mocks — test fails in CI

When neither --config is passed nor a config/ directory exists in the cwd, the CLI falls back to rails_config_path = api.app.rails_config_path (the patched MagicMock). The subsequent os.fspath(mock_app.rails_config_path) call requires __fspath__() to return a str or bytes; a MagicMock auto-attribute satisfies neither, so os.fspath raises TypeError. The repo root has no config/ directory, so os.path.exists returns False and the error path is always hit. result.exit_code will be 1 and the assert result.exit_code == 0 will fail. The three newly-added worker/reject tests correctly use @patch("os.getcwd") + @patch("os.path.exists") for exactly this reason — the same fix is needed here.

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/cli/test_cli_main.py
Line: 209-215

Comment:
**Missing `os.getcwd` / `os.path.exists` mocks — test fails in CI**

When neither `--config` is passed nor a `config/` directory exists in the cwd, the CLI falls back to `rails_config_path = api.app.rails_config_path` (the patched MagicMock). The subsequent `os.fspath(mock_app.rails_config_path)` call requires `__fspath__()` to return a `str` or `bytes`; a MagicMock auto-attribute satisfies neither, so `os.fspath` raises `TypeError`. The repo root has no `config/` directory, so `os.path.exists` returns `False` and the error path is always hit. `result.exit_code` will be `1` and the `assert result.exit_code == 0` will fail. The three newly-added worker/reject tests correctly use `@patch("os.getcwd")` + `@patch("os.path.exists")` for exactly this reason — the same fix is needed here.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 8f05fd2.

test_server_with_verbose_sets_env_var (and the related verbose tests) now mock os.getcwd and os.path.exists exactly like the new worker-guard tests do, plus @patch.dict(os.environ, {}, clear=True) to keep NEMO_GUARDRAILS_CONFIG_PATH from leaking into the next test in the process. The TypeError from os.fspath(MagicMock()) is gone because the CLI now takes the local_configs_path branch where mock_exists.return_value = True.

@Pouyanpi Pouyanpi force-pushed the develop branch 4 times, most recently from a6be550 to c69efe5 Compare May 6, 2026 16:01
@adityasingh2400
Copy link
Copy Markdown
Author

Addressed greptile review comment on the missing os.getcwd / os.path.exists mocks in test_server_with_verbose_sets_worker_env (commit 2492720). The test now follows the same isolation pattern as the other worker-related tests, so it no longer depends on MagicMock.__fspath__ behavior or the absence of a config/ directory in the working tree.

Add os.getcwd / os.path.exists mocks to test_server_with_verbose_sets_worker_env so
it does not rely on MagicMock's __fspath__ fallback or the absence of a config/
directory in the working tree, matching the isolation pattern used by the other
worker-related tests.

Signed-off-by: Aditya Singh <adisin650@gmail.com>
@adityasingh2400 adityasingh2400 force-pushed the feat/server-workers-option branch from 2492720 to 8f05fd2 Compare May 19, 2026 23:17
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.

feature: Add --workers flag to nemoguardrails server for multi-worker uvicorn support

1 participant