Skip to main content
Glama
test_file_command.py12 kB
from __future__ import annotations import io from pathlib import Path import pytest from mcp2term_client.file_command import ( FileCommandHelp, FileCommandParseError, ManageFileCommand, parse_manage_file_command, ) @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_inline_content(tmp_path: Path, use_real_dependencies: bool) -> None: command: ManageFileCommand = parse_manage_file_command( [ "create", "notes.txt", "--content", "hello world", "--create-parents", ] ) assert command.operation == "create" assert command.path == "notes.txt" assert command.content == "hello world" assert command.create_parents is True assert command.encoding == "utf-8" assert command.escape_profile == "auto" @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_from_stdin(tmp_path: Path, use_real_dependencies: bool) -> None: stdin_stream = io.StringIO("line-one\nline-two\n") command = parse_manage_file_command( ["write", "story.txt", "--stdin", "--encoding", "utf-8"], stdin=stdin_stream, ) assert command.operation == "write" assert command.content == "line-one\nline-two\n" assert command.encoding == "utf-8" assert command.escape_profile == "auto" assert command.pattern is None assert command.use_regex is False assert command.ignore_case is False assert command.max_replacements is None @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_from_file(tmp_path: Path, use_real_dependencies: bool) -> None: content_file = tmp_path / "payload.txt" content_file.write_text("payload", encoding="utf-8") command = parse_manage_file_command( [ "append", "story.txt", "--content-from-file", str(content_file), "--no-create-if-missing", ] ) assert command.operation == "append" assert command.content == "payload" assert command.create_if_missing is False assert command.escape_profile == "auto" @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_patch_from_file(tmp_path: Path, use_real_dependencies: bool) -> None: diff_file = tmp_path / "delta.diff" diff_file.write_text( """--- a/sample.txt\n+++ b/sample.txt\n@@ -1 +1 @@\n-old\n+new\n""", encoding="utf-8", ) command = parse_manage_file_command( [ "patch", "sample.txt", "--content-from-file", str(diff_file), ] ) assert command.operation == "patch" assert "@@ -1 +1 @@" in (command.content or "") assert command.escape_profile == "auto" @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_patch_requires_content( tmp_path: Path, use_real_dependencies: bool ) -> None: with pytest.raises(FileCommandParseError): parse_manage_file_command([ "patch", "sample.txt", ]) @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_rejects_conflicting_sources( tmp_path: Path, use_real_dependencies: bool ) -> None: with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "write", "story.txt", "--content", "text", "--stdin", ] ) @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_help(tmp_path: Path, use_real_dependencies: bool) -> None: with pytest.raises(FileCommandHelp): parse_manage_file_command(["--help"]) @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_decodes_inline_patch_escape_sequences( tmp_path: Path, use_real_dependencies: bool ) -> None: inline_patch = ( f"--- a/sample.txt\\n" f"+++ b/sample.txt\\n" "@@ -1 +1 @@\\n" "-old\\n" "+new\\n" ) command = parse_manage_file_command( [ "patch", "sample.txt", "--content", inline_patch, ] ) assert command.content is not None assert command.content.splitlines()[0] == f"--- a/sample.txt" assert command.content.splitlines()[-1] == "+new" assert command.escape_profile == "auto" @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_preserves_backslash_leading_lines( tmp_path: Path, use_real_dependencies: bool ) -> None: inline_patch = ( f"--- a/sample.txt\\n" f"+++ b/sample.txt\\n" "@@ -1,2 +1,2 @@\\n" " alpha\\n" "-beta\\n" "\\ No newline at end of file\\n" "+beta-updated\\n" "\\ No newline at end of file\\n" ) command = parse_manage_file_command( [ "patch", "sample.txt", "--content", inline_patch, ] ) assert command.content is not None assert "\\ No newline at end of file" in command.content assert command.escape_profile == "auto" @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_escape_profile_none_disables_decoding( tmp_path: Path, use_real_dependencies: bool ) -> None: inline_patch = "line-one\\nline-two" command = parse_manage_file_command( [ "append", "sample.txt", "--content", inline_patch, "--escape-profile", "none", ] ) assert command.escape_profile == "none" assert command.content == inline_patch assert command.pattern is None @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_rejects_unknown_escape_profile( tmp_path: Path, use_real_dependencies: bool ) -> None: with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "append", "sample.txt", "--content", "text", "--escape-profile", "unknown-profile", ] ) @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_prepend_requires_content( tmp_path: Path, use_real_dependencies: bool ) -> None: with pytest.raises(FileCommandParseError): parse_manage_file_command(["prepend", "story.txt"]) @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_substitute_literal(tmp_path: Path, use_real_dependencies: bool) -> None: command = parse_manage_file_command( [ "substitute", "story.txt", "--pattern", "alpha", "--content", "beta", ] ) assert command.operation == "substitute" assert command.pattern == "alpha" assert command.content == "beta" assert command.use_regex is False assert command.ignore_case is False assert command.max_replacements is None @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_substitute_from_file( tmp_path: Path, use_real_dependencies: bool ) -> None: pattern_path = tmp_path / "pattern.txt" pattern_path.write_text("needle", encoding="utf-8") command = parse_manage_file_command( [ "substitute", "story.txt", "--pattern-from-file", str(pattern_path), "--content", "replacement", "--ignore-case", "--max-replacements", "2", ] ) assert command.pattern == "needle" assert command.ignore_case is True assert command.max_replacements == 2 assert command.use_regex is False @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_substitute_regex(tmp_path: Path, use_real_dependencies: bool) -> None: command = parse_manage_file_command( [ "substitute", "story.txt", "--pattern", "(?P<word>alpha)", "--content", "{word}", "--regex", ] ) assert command.use_regex is True assert command.pattern == "(?P<word>alpha)" assert command.content == "{word}" @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_insert_with_anchor(tmp_path: Path, use_real_dependencies: bool) -> None: command = parse_manage_file_command( [ "insert", "story.txt", "--content", "new-line\n", "--anchor", "beta", "--anchor-after", "--anchor-occurrence", "2", ] ) assert command.operation == "insert" assert command.anchor_text == "beta" assert command.anchor_after is True assert command.anchor_occurrence == 2 assert command.line is None @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_insert_anchor_regex(tmp_path: Path, use_real_dependencies: bool) -> None: command = parse_manage_file_command( [ "insert", "story.txt", "--content", "new-line\n", "--anchor", r"^alpha$", "--anchor-regex", "--anchor-ignore-case", ] ) assert command.anchor_use_regex is True assert command.anchor_ignore_case is True assert command.anchor_occurrence == 1 @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_insert_anchor_validation( tmp_path: Path, use_real_dependencies: bool ) -> None: with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "insert", "story.txt", "--content", "value", "--line", "2", "--anchor", "beta", ] ) with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "insert", "story.txt", "--content", "value", "--anchor-occurrence", "0", ] ) with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "insert", "story.txt", "--content", "value", "--anchor-after", ] ) @pytest.mark.parametrize("use_real_dependencies", [False, True]) def test_parse_manage_file_substitute_rejects_invalid_usage( tmp_path: Path, use_real_dependencies: bool ) -> None: with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "write", "story.txt", "--pattern", "needle", ] ) with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "replace", "story.txt", "--start-line", "1", "--content", "alpha", "--max-replacements", "3", ] ) with pytest.raises(FileCommandParseError): parse_manage_file_command( [ "substitute", "story.txt", "--pattern", "needle", "--content", "replacement", "--max-replacements", "0", ] )

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/FreddyE1982/mcp2term'

If you have feedback or need assistance with the MCP directory API, please join our Discord server