Skip to content

fix(langchain): coerce None in format_store_content - #2561

Closed
Bartok9 wants to merge 2 commits into
Canner:mainfrom
Bartok9:fix/langchain-store-content-none-20260722
Closed

fix(langchain): coerce None in format_store_content#2561
Bartok9 wants to merge 2 commits into
Canner:mainfrom
Bartok9:fix/langchain-store-content-none-20260722

Conversation

@Bartok9

@Bartok9 Bartok9 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Coerce None nl/sql in format_store_content so store envelopes do not AttributeError on .strip().

Motivation

Tool callers can emit store confirmations before fields are fully populated.

Real behavior proof

$ python3 -m pytest sdk/wren-langchain/tests/unit/test_format_store_content_none.py -v
3 passed

License

Touches sdk/wren-langchain/** (Apache-2.0).

Summary by CodeRabbit

  • Bug Fixes

    • Improved stored-content formatting to gracefully handle cases where SQL and/or natural-language descriptions are missing.
    • Prevented formatting failures when optional fields aren’t provided.
    • Kept existing SQL preview behavior, truncation, and tag-count display consistent.
  • Tests

    • Added unit tests covering missing SQL, missing natural-language descriptions, and long SQL truncation with tag-count verification.

Memory/tool callers may pass None nl/sql before validation.
Bare sql.strip() AttributeError aborted the store envelope.
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e55fa153-c79c-438c-858a-98415e4da6e2

📥 Commits

Reviewing files that changed from the base of the PR and between 02c17b6 and 0797ff3.

📒 Files selected for processing (1)
  • sdk/wren-langchain/tests/unit/test_format_store_content_none.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • sdk/wren-langchain/tests/unit/test_format_store_content_none.py

Walkthrough

format_store_content now accepts None SQL and natural-language inputs while preserving SQL preview truncation and tag-count behavior. New tests cover missing inputs and existing formatting behavior.

Changes

Stored content formatting

Layer / File(s) Summary
None-safe formatting and validation
sdk/wren-langchain/src/wren_langchain/_format.py, sdk/wren-langchain/tests/unit/test_format_store_content_none.py
format_store_content normalizes missing inputs before constructing the stored-content envelope. Tests verify None handling, SQL output, preview truncation, and tag counts.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • Canner/WrenAI#2524: Updates the same formatter with related None handling and preview behavior.

Poem

A bunny found blank SQL in the hay,
And safely tucked the nulls away.
“Stored!” it cheered, with tags in a row,
While trimmed previews neatly flow.
Hop, hop—tests now guard the show!

🚥 Pre-merge checks | ✅ 5
✅ 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 clearly matches the main change: handling None values in format_store_content.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3

🤖 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 `@sdk/wren-langchain/src/wren_langchain/_format.py`:
- Around line 120-125: Update the format_store_content signature so nl and sql
are annotated as str | None, matching the existing None-handling behavior in
nl_text and sql_text; leave tags and the function implementation unchanged.

In `@sdk/wren-langchain/tests/unit/test_format_store_content_none.py`:
- Around line 5-19: Update the _PATH resolution block in
test_format_store_content_none.py so the primary path is assigned once and the
fallback remains conditional on !_PATH.exists(). Remove the duplicate
unconditional _PATH assignment and retain a single working resolution flow for
both layouts.
- Around line 25-33: Strengthen test_none_sql and test_none_nl_and_tags to
assert the complete normalized string returned by format_store_content,
verifying that None inputs are rendered as empty strings rather than the literal
"None". Preserve the existing input combinations and use the exact expected
output for each case.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 624db374-ba08-43da-96a5-1503f807c04b

📥 Commits

Reviewing files that changed from the base of the PR and between f4b45ed and 02c17b6.

📒 Files selected for processing (2)
  • sdk/wren-langchain/src/wren_langchain/_format.py
  • sdk/wren-langchain/tests/unit/test_format_store_content_none.py

Comment on lines 120 to +125
def format_store_content(nl: str, sql: str, tags: list[str] | None) -> str:
"""One-liner ``Stored: "<nl>" → <sql preview> (N tags)``."""
sql_preview = sql.strip().split("\n")[0]
# Memory/tool callers may pass None for sql/nl before validation; bare
# ``sql.strip()`` raised AttributeError and aborted the store envelope.
nl_text = "" if nl is None else str(nl)
sql_text = "" if sql is None else str(sql)

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Align the type annotations with the new None behavior.

nl and sql now intentionally accept None, but their annotations still declare str. Update the signature so type checkers and callers see the supported contract.

Proposed fix
-def format_store_content(nl: str, sql: str, tags: list[str] | None) -> str:
+def format_store_content(
+    nl: str | None, sql: str | None, tags: list[str] | None
+) -> str:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def format_store_content(nl: str, sql: str, tags: list[str] | None) -> str:
"""One-liner ``Stored: "<nl>" → <sql preview> (N tags)``."""
sql_preview = sql.strip().split("\n")[0]
# Memory/tool callers may pass None for sql/nl before validation; bare
# ``sql.strip()`` raised AttributeError and aborted the store envelope.
nl_text = "" if nl is None else str(nl)
sql_text = "" if sql is None else str(sql)
def format_store_content(
nl: str | None, sql: str | None, tags: list[str] | None
) -> str:
"""One-liner ``Stored: "<nl>" → <sql preview> (N tags)``."""
# Memory/tool callers may pass None for sql/nl before validation; bare
# ``sql.strip()`` raised AttributeError and aborted the store envelope.
nl_text = "" if nl is None else str(nl)
sql_text = "" if sql is None else str(sql)
🤖 Prompt for 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.

In `@sdk/wren-langchain/src/wren_langchain/_format.py` around lines 120 - 125,
Update the format_store_content signature so nl and sql are annotated as str |
None, matching the existing None-handling behavior in nl_text and sql_text;
leave tags and the function implementation unchanged.

Comment thread sdk/wren-langchain/tests/unit/test_format_store_content_none.py Outdated
Comment on lines +25 to +33
def test_none_sql():
out = _mod.format_store_content("q", None, None)
assert "Stored:" in out
assert "q" in out


def test_none_nl_and_tags():
out = _mod.format_store_content(None, "SELECT 1", None)
assert "SELECT 1" in out

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the normalized output, not only that formatting succeeds.

These tests would still pass if None were rendered as the literal string "None". Assert the complete output to lock in the intended empty-string behavior.

Proposed test assertions
 def test_none_sql():
     out = _mod.format_store_content("q", None, None)
-    assert "Stored:" in out
-    assert "q" in out
+    assert out == 'Stored: "q" →  (0 tags)'

 def test_none_nl_and_tags():
     out = _mod.format_store_content(None, "SELECT 1", None)
-    assert "SELECT 1" in out
+    assert out == 'Stored: "" → SELECT 1 (0 tags)'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_none_sql():
out = _mod.format_store_content("q", None, None)
assert "Stored:" in out
assert "q" in out
def test_none_nl_and_tags():
out = _mod.format_store_content(None, "SELECT 1", None)
assert "SELECT 1" in out
def test_none_sql():
out = _mod.format_store_content("q", None, None)
assert out == 'Stored: "q" → (0 tags)'
def test_none_nl_and_tags():
out = _mod.format_store_content(None, "SELECT 1", None)
assert out == 'Stored: "" → SELECT 1 (0 tags)'
🤖 Prompt for 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.

In `@sdk/wren-langchain/tests/unit/test_format_store_content_none.py` around lines
25 - 33, Strengthen test_none_sql and test_none_nl_and_tags to assert the
complete normalized string returned by format_store_content, verifying that None
inputs are rendered as empty strings rather than the literal "None". Preserve
the existing input combinations and use the exact expected output for each case.

CI lint fails on ruff format --check for the new unit test.
@Bartok9

Bartok9 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Closing as superseded — None coercion in format_store_content already merged via #2524. Duplicate of landed work; closing to tidy the queue.

@Bartok9 Bartok9 closed this Jul 24, 2026
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.

1 participant