forked from retoor/devplacepy
ticket #84 attempt 1
This commit is contained in:
@@ -5,16 +5,16 @@ import unittest.mock
|
||||
from devplacepy.services.ai_modifier import modify_text
|
||||
|
||||
|
||||
def test_modify_text_prompt_preserves_fenced_code_blocks():
|
||||
def test_modify_text_extracts_and_restores_code_blocks():
|
||||
captured = {}
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
captured["system"] = system
|
||||
captured["text"] = text
|
||||
return ("fake result", {"calls": 1})
|
||||
return ("modification result", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.correction.gateway_complete", fake_gateway
|
||||
"devplacepy.services.ai_modifier.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = modify_text(
|
||||
"test-key",
|
||||
@@ -22,17 +22,95 @@ def test_modify_text_prompt_preserves_fenced_code_blocks():
|
||||
"Some text\n```python\nx = 1\n```\nMore text",
|
||||
)
|
||||
|
||||
assert result == "fake result"
|
||||
system = captured["system"]
|
||||
assert (
|
||||
"Do NOT modify content inside Markdown fenced code blocks" in system
|
||||
), "System prompt must instruct the model to preserve code blocks"
|
||||
assert (
|
||||
"Preserve the code block fences, the language identifier" in system
|
||||
), "System prompt must mention preserving language identifiers"
|
||||
assert (
|
||||
"Only modify prose outside code blocks" in system
|
||||
), "System prompt must limit modifications to non-code text"
|
||||
assert (
|
||||
"triple backticks" in system
|
||||
), "System prompt must mention triple backticks as the delimiter"
|
||||
assert result == "modification result"
|
||||
|
||||
|
||||
def test_modify_text_preserves_fenced_code_blocks_from_ai_corruption():
|
||||
input_text = "Some text\n```python\nx = 1\n```\nMore text"
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
return ("Some text\n{%CODE_BLOCK_0%}\nMore corrected text", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.ai_modifier.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = modify_text(
|
||||
"test-key", "Make it more formal", input_text
|
||||
)
|
||||
|
||||
assert "```python" in result
|
||||
assert "x = 1" in result
|
||||
assert "corrected text" in result
|
||||
|
||||
|
||||
def test_modify_text_preserves_multiple_fenced_code_blocks():
|
||||
input_text = "A\n```python\nx = 1\n```\nB\n```js\ny = 2\n```\nC"
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
return ("A\n{%CODE_BLOCK_0%}\nX\n{%CODE_BLOCK_1%}\nZ", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.ai_modifier.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = modify_text(
|
||||
"test-key", "Make it more formal", input_text
|
||||
)
|
||||
|
||||
assert "```python" in result
|
||||
assert "x = 1" in result
|
||||
assert "```js" in result
|
||||
assert "y = 2" in result
|
||||
|
||||
|
||||
def test_modify_text_preserves_inline_code():
|
||||
input_text = "Use the `os.path.join` function for paths."
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
return ("Use {%CODE_BLOCK_0%} always.", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.ai_modifier.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = modify_text(
|
||||
"test-key", "Make it more formal", input_text
|
||||
)
|
||||
|
||||
assert "`os.path.join`" in result
|
||||
|
||||
|
||||
def test_modify_text_passes_plain_text_untouched():
|
||||
captured = {}
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
captured["text"] = text
|
||||
return ("modified plain text", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.ai_modifier.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = modify_text(
|
||||
"test-key", "Make it more formal", "Just some plain text."
|
||||
)
|
||||
|
||||
assert captured["text"] == "Just some plain text."
|
||||
assert result == "modified plain text"
|
||||
|
||||
|
||||
def test_modify_text_sanitized_text_has_no_code_blocks():
|
||||
captured = {}
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
captured["text"] = text
|
||||
return ("modified", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.ai_modifier.gateway_complete", fake_gateway
|
||||
):
|
||||
modify_text(
|
||||
"test-key",
|
||||
"Make it more formal",
|
||||
"Before\n```python\ncode\n```\nAfter\n`inline`",
|
||||
)
|
||||
|
||||
assert "```" not in captured["text"]
|
||||
assert "`inline`" not in captured["text"]
|
||||
|
||||
@@ -5,13 +5,13 @@ import unittest.mock
|
||||
from devplacepy.services.correction import correct_text
|
||||
|
||||
|
||||
def test_correct_text_prompt_preserves_fenced_code_blocks():
|
||||
def test_correct_text_extracts_and_restores_code_blocks():
|
||||
captured = {}
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
captured["system"] = system
|
||||
captured["text"] = text
|
||||
return ("fake result", {"calls": 1})
|
||||
return ("correction result", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.correction.gateway_complete", fake_gateway
|
||||
@@ -20,17 +20,89 @@ def test_correct_text_prompt_preserves_fenced_code_blocks():
|
||||
"test-key", "Fix spelling", "Some text\n```python\nx = 1\n```\nMore text"
|
||||
)
|
||||
|
||||
assert result == "fake result"
|
||||
system = captured["system"]
|
||||
assert (
|
||||
"Do NOT modify content inside Markdown fenced code blocks" in system
|
||||
), "System prompt must instruct the model to preserve code blocks"
|
||||
assert (
|
||||
"Preserve the code block fences, the language identifier" in system
|
||||
), "System prompt must mention preserving language identifiers"
|
||||
assert (
|
||||
"Only correct prose outside code blocks" in system
|
||||
), "System prompt must limit corrections to non-code text"
|
||||
assert (
|
||||
"triple backticks" in system
|
||||
), "System prompt must mention triple backticks as the delimiter"
|
||||
assert result == "correction result"
|
||||
|
||||
|
||||
def test_correct_text_preserves_fenced_code_blocks_from_ai_corruption():
|
||||
input_text = "Some text\n```python\nx = 1\n```\nMore text"
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
return ("Some text\n{%CODE_BLOCK_0%}\nMore corrected text", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.correction.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = correct_text("test-key", "Fix spelling", input_text)
|
||||
|
||||
assert "```python" in result
|
||||
assert "x = 1" in result
|
||||
assert "corrected text" in result
|
||||
|
||||
|
||||
def test_correct_text_preserves_multiple_fenced_code_blocks():
|
||||
input_text = "A\n```python\nx = 1\n```\nB\n```js\ny = 2\n```\nC"
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
return ("A\n{%CODE_BLOCK_0%}\nX\n{%CODE_BLOCK_1%}\nZ", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.correction.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = correct_text("test-key", "Fix spelling", input_text)
|
||||
|
||||
assert "```python" in result
|
||||
assert "x = 1" in result
|
||||
assert "```js" in result
|
||||
assert "y = 2" in result
|
||||
|
||||
|
||||
def test_correct_text_preserves_inline_code():
|
||||
input_text = "Use the `os.path.join` function for paths."
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
return ("Use {%CODE_BLOCK_0%} always.", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.correction.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = correct_text("test-key", "Fix spelling", input_text)
|
||||
|
||||
assert "`os.path.join`" in result
|
||||
|
||||
|
||||
def test_correct_text_passes_plain_text_untouched():
|
||||
captured = {}
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
captured["text"] = text
|
||||
return ("corrected plain text", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.correction.gateway_complete", fake_gateway
|
||||
):
|
||||
result, _ = correct_text(
|
||||
"test-key", "Fix spelling", "Just some plain text."
|
||||
)
|
||||
|
||||
assert captured["text"] == "Just some plain text."
|
||||
assert result == "corrected plain text"
|
||||
|
||||
|
||||
def test_correct_text_sanitized_text_has_no_code_blocks():
|
||||
captured = {}
|
||||
|
||||
def fake_gateway(api_key, system, text, timeout, max_growth_factor):
|
||||
captured["text"] = text
|
||||
return ("corrected", {"calls": 1})
|
||||
|
||||
with unittest.mock.patch(
|
||||
"devplacepy.services.correction.gateway_complete", fake_gateway
|
||||
):
|
||||
correct_text(
|
||||
"test-key",
|
||||
"Fix spelling",
|
||||
"Before\n```python\ncode\n```\nAfter\n`inline`",
|
||||
)
|
||||
|
||||
assert "```" not in captured["text"]
|
||||
assert "`inline`" not in captured["text"]
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from devplacepy.services.markdown_preserve import MarkdownPreserver
|
||||
|
||||
|
||||
def test_extract_and_restore_round_trip():
|
||||
preserver = MarkdownPreserver()
|
||||
original = "Some text\n```python\nx = 1\n```\nMore text"
|
||||
sanitized = preserver.extract_blocks(original)
|
||||
assert "```" not in sanitized
|
||||
restored = preserver.restore_blocks(sanitized)
|
||||
assert restored == original
|
||||
|
||||
|
||||
def test_extract_empty_text():
|
||||
preserver = MarkdownPreserver()
|
||||
assert preserver.extract_blocks("") == ""
|
||||
assert preserver.extract_blocks(None) == ""
|
||||
|
||||
|
||||
def test_extract_no_code_blocks():
|
||||
preserver = MarkdownPreserver()
|
||||
text = "Just some plain text with no code."
|
||||
sanitized = preserver.extract_blocks(text)
|
||||
assert sanitized == text
|
||||
assert preserver.restore_blocks(sanitized) == text
|
||||
|
||||
|
||||
def test_extract_fenced_with_language():
|
||||
preserver = MarkdownPreserver()
|
||||
original = "Before\n```python\ndef foo():\n pass\n```\nAfter"
|
||||
sanitized = preserver.extract_blocks(original)
|
||||
assert "```" not in sanitized
|
||||
assert preserver.restore_blocks(sanitized) == original
|
||||
|
||||
|
||||
def test_extract_fenced_without_language():
|
||||
preserver = MarkdownPreserver()
|
||||
original = "Before\n```\ncode block\n```\nAfter"
|
||||
sanitized = preserver.extract_blocks(original)
|
||||
assert "```" not in sanitized
|
||||
assert preserver.restore_blocks(sanitized) == original
|
||||
|
||||
|
||||
def test_extract_multiple_fenced_blocks():
|
||||
preserver = MarkdownPreserver()
|
||||
original = "A\n```python\nx = 1\n```\nB\n```js\ny = 2\n```\nC"
|
||||
sanitized = preserver.extract_blocks(original)
|
||||
assert "```" not in sanitized
|
||||
assert preserver.restore_blocks(sanitized) == original
|
||||
|
||||
|
||||
def test_extract_inline_code():
|
||||
preserver = MarkdownPreserver()
|
||||
original = "Use the `os.path.join` function."
|
||||
sanitized = preserver.extract_blocks(original)
|
||||
assert "`" not in sanitized
|
||||
assert preserver.restore_blocks(sanitized) == original
|
||||
|
||||
|
||||
def test_extract_fenced_and_inline():
|
||||
preserver = MarkdownPreserver()
|
||||
original = "Text with `inline` and\n```python\ncode\n```\nmore `code` here."
|
||||
sanitized = preserver.extract_blocks(original)
|
||||
assert "`" not in sanitized
|
||||
assert "```" not in sanitized
|
||||
assert preserver.restore_blocks(sanitized) == original
|
||||
|
||||
|
||||
def test_restore_text_without_placeholders():
|
||||
preserver = MarkdownPreserver()
|
||||
preserver.extract_blocks("```python\nx\n```")
|
||||
result = preserver.restore_blocks("plain text with no tokens")
|
||||
assert result == "plain text with no tokens"
|
||||
|
||||
|
||||
def test_placeholder_uniqueness():
|
||||
preserver = MarkdownPreserver()
|
||||
original = "A\n```a\n1\n```\nB\n```b\n2\n```\nC\n```c\n3\n```"
|
||||
sanitized = preserver.extract_blocks(original)
|
||||
assert len(set(sanitized.split())) == len(sanitized.split())
|
||||
assert preserver.restore_blocks(sanitized) == original
|
||||
|
||||
|
||||
def test_empty_restore():
|
||||
preserver = MarkdownPreserver()
|
||||
assert preserver.restore_blocks("") == ""
|
||||
Reference in New Issue
Block a user