re.sub always parses the replacement as a template, so a backslash in the replacement (e.g. C:\1) raised PatternError even in literal mode. Also drop an unused import and align js import paths with the documented two-level extension path. Bump to 2.0.13.
672 lines
24 KiB
Python
672 lines
24 KiB
Python
import unittest
|
|
from string_strip_node import StringStripNode
|
|
from string_multi_replace_node import StringMultiReplaceNode
|
|
from string_conditional_append_node import StringConditionalAppendNode
|
|
from string_contains_any_node import StringContainsAnyNode
|
|
|
|
class TestStringNodes(unittest.TestCase):
|
|
def setUp(self):
|
|
self.strip_node = StringStripNode()
|
|
self.replace_node = StringMultiReplaceNode()
|
|
self.append_node = StringConditionalAppendNode()
|
|
self.contains_any_node = StringContainsAnyNode()
|
|
|
|
def test_strip_basic_functionality(self):
|
|
input_string = "This is a test string with test word"
|
|
strings_to_remove = "test"
|
|
result = self.strip_node.string_strip(
|
|
input_string=input_string,
|
|
strings_to_remove=strings_to_remove,
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "This is a string with word")
|
|
|
|
def test_strip_multiple_strings(self):
|
|
input_string = "This is a test string with another test and More Text"
|
|
strings_to_remove = """test
|
|
More Text"""
|
|
result = self.strip_node.string_strip(
|
|
input_string=input_string,
|
|
strings_to_remove=strings_to_remove,
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "This is a string with another and")
|
|
|
|
def test_strip_case_sensitivity(self):
|
|
input_string = "Test TEST test"
|
|
strings_to_remove = "test"
|
|
|
|
# Case-insensitive
|
|
result1 = self.strip_node.string_strip(
|
|
input_string=input_string,
|
|
strings_to_remove=strings_to_remove,
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result1, "")
|
|
|
|
# Case-sensitive
|
|
result2 = self.strip_node.string_strip(
|
|
input_string=input_string,
|
|
strings_to_remove=strings_to_remove,
|
|
match_case=True,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result2, "Test TEST")
|
|
|
|
def test_strip_punctuation_preserved(self):
|
|
# Test Issue #6 fix: punctuation should be preserved
|
|
input_string = "Let's meet, Grandma!"
|
|
strings_to_remove = "meet"
|
|
result = self.strip_node.string_strip(
|
|
input_string=input_string,
|
|
strings_to_remove=strings_to_remove,
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "Let's, Grandma!")
|
|
|
|
def test_strip_punctuation_removed(self):
|
|
# Test legacy behavior: punctuation removed
|
|
input_string = "test, test: test. test; test"
|
|
strings_to_remove = "test"
|
|
result = self.strip_node.string_strip(
|
|
input_string=input_string,
|
|
strings_to_remove=strings_to_remove,
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=False,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "")
|
|
|
|
def test_replace_basic_functionality(self):
|
|
input_string = "Hello world"
|
|
replacement_pairs = "world::everyone"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "Hello everyone")
|
|
|
|
def test_replace_literal_backslash_replacement(self):
|
|
# With use_regex disabled, replacement text is literal: backslash
|
|
# sequences must not be treated as re.sub group references.
|
|
result = self.replace_node.string_replace(
|
|
input_string="path is X",
|
|
replacement_pairs=r"X::C:\1",
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=False
|
|
)[0]
|
|
self.assertEqual(result, r"path is C:\1")
|
|
|
|
def test_replace_multiple_pairs(self):
|
|
input_string = "The quick brown fox jumps over the lazy dog"
|
|
replacement_pairs = """quick::slow
|
|
brown::black
|
|
fox::cat"""
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "The slow black cat jumps over the lazy dog")
|
|
|
|
def test_replace_case_sensitivity(self):
|
|
input_string = "Hello HELLO hello"
|
|
replacement_pairs = "hello::hi"
|
|
|
|
# Case-insensitive
|
|
result1 = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result1, "hi hi hi")
|
|
|
|
# Case-sensitive
|
|
result2 = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=True,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result2, "Hello HELLO hi")
|
|
|
|
def test_replace_custom_delimiter(self):
|
|
input_string = "Hello world"
|
|
replacement_pairs = "world->everyone"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="->",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "Hello everyone")
|
|
|
|
def test_replace_punctuation_preserved(self):
|
|
# Test Issue #6 fix: punctuation preserved in replace
|
|
input_string = "Let's meet, Grandma!"
|
|
replacement_pairs = "meet::eat"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "Let's eat, Grandma!")
|
|
|
|
def test_replace_prompt_syntax_preserved(self):
|
|
# Test Issue #6: Prompt control syntax like [A1111:Forge:.5]
|
|
input_string = "A prompt with [word1:word2:.5] syntax"
|
|
replacement_pairs = "prompt::modified"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result, "A modified with [word1:word2:.5] syntax")
|
|
|
|
def test_extra_spaces_handling(self):
|
|
# Test for StringStripNode
|
|
input_string = "This is a test string"
|
|
strings_to_remove = "test"
|
|
result1 = self.strip_node.string_strip(
|
|
input_string=input_string,
|
|
strings_to_remove=strings_to_remove,
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result1, "This is a string")
|
|
|
|
# Test for StringMultiReplaceNode
|
|
replacement_pairs = "is::was"
|
|
result2 = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True
|
|
)[0]
|
|
self.assertEqual(result2, "This was a test string")
|
|
|
|
# Tests for StringConditionalAppendNode (Issue #5)
|
|
def test_append_string_not_found(self):
|
|
# String not found, should append
|
|
input_string = "Hello world"
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check="goodbye",
|
|
position="end",
|
|
match_case=False,
|
|
separator=", "
|
|
)
|
|
self.assertEqual(result, "Hello world, goodbye")
|
|
self.assertTrue(was_appended)
|
|
|
|
def test_append_string_found(self):
|
|
# String found, should not append
|
|
input_string = "Hello world"
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check="world",
|
|
position="end",
|
|
match_case=False,
|
|
separator=", "
|
|
)
|
|
self.assertEqual(result, "Hello world")
|
|
self.assertFalse(was_appended)
|
|
|
|
def test_append_beginning(self):
|
|
# Append at beginning
|
|
input_string = "world"
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check="Hello",
|
|
position="beginning",
|
|
match_case=False,
|
|
separator=", "
|
|
)
|
|
self.assertEqual(result, "Hello, world")
|
|
self.assertTrue(was_appended)
|
|
|
|
def test_append_case_insensitive(self):
|
|
# Case insensitive search
|
|
input_string = "Hello WORLD"
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check="world",
|
|
position="end",
|
|
match_case=False,
|
|
separator=", "
|
|
)
|
|
self.assertEqual(result, "Hello WORLD")
|
|
self.assertFalse(was_appended)
|
|
|
|
def test_append_case_sensitive(self):
|
|
# Case sensitive search
|
|
input_string = "Hello WORLD"
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check="world",
|
|
position="end",
|
|
match_case=True,
|
|
separator=", "
|
|
)
|
|
self.assertEqual(result, "Hello WORLD, world")
|
|
self.assertTrue(was_appended)
|
|
|
|
def test_append_custom_separator(self):
|
|
# Custom separator
|
|
input_string = "Hello"
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check="world",
|
|
position="end",
|
|
match_case=False,
|
|
separator=" | "
|
|
)
|
|
self.assertEqual(result, "Hello | world")
|
|
self.assertTrue(was_appended)
|
|
|
|
def test_append_no_separator(self):
|
|
# No separator (empty string)
|
|
input_string = "Hello"
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check="world",
|
|
position="end",
|
|
match_case=False,
|
|
separator=""
|
|
)
|
|
self.assertEqual(result, "Helloworld")
|
|
self.assertTrue(was_appended)
|
|
|
|
def test_append_multiple_strings(self):
|
|
# Multiple strings to check, some found, some not
|
|
input_string = "Hello world"
|
|
strings_to_check = """world
|
|
goodbye
|
|
thanks"""
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check=strings_to_check,
|
|
position="end",
|
|
match_case=False,
|
|
separator=", "
|
|
)
|
|
# "world" is found, "goodbye" and "thanks" should be appended
|
|
self.assertEqual(result, "Hello world, goodbye, thanks")
|
|
self.assertTrue(was_appended)
|
|
|
|
def test_append_multiple_all_found(self):
|
|
# All strings found, nothing appended
|
|
input_string = "Hello world goodbye"
|
|
strings_to_check = """Hello
|
|
world
|
|
goodbye"""
|
|
result, was_appended = self.append_node.conditional_append(
|
|
input_string=input_string,
|
|
strings_to_check=strings_to_check,
|
|
position="end",
|
|
match_case=False,
|
|
separator=", "
|
|
)
|
|
self.assertEqual(result, "Hello world goodbye")
|
|
self.assertFalse(was_appended)
|
|
|
|
def test_replace_with_space(self):
|
|
# Test Issue #8: Replace with space (trailing space should be preserved)
|
|
input_string = "hello_world_test"
|
|
replacement_pairs = "_:: "
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=False
|
|
)[0]
|
|
self.assertEqual(result, "hello world test")
|
|
|
|
def test_replace_with_leading_space(self):
|
|
# Test Issue #8: Replace with leading space
|
|
input_string = "value1,value2,value3"
|
|
replacement_pairs = ",::, "
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=False
|
|
)[0]
|
|
self.assertEqual(result, "value1, value2, value3")
|
|
|
|
def test_replace_with_whitespace_only(self):
|
|
# Test Issue #8: Replace with only whitespace
|
|
input_string = "word1___word2"
|
|
replacement_pairs = "___:: "
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=False
|
|
)[0]
|
|
self.assertEqual(result, "word1 word2")
|
|
|
|
def test_replace_with_tab(self):
|
|
# Test Issue #8: Replace with tab character
|
|
input_string = "column1|column2|column3"
|
|
replacement_pairs = "|::\t"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=False
|
|
)[0]
|
|
self.assertEqual(result, "column1\tcolumn2\tcolumn3")
|
|
|
|
# Tests for StringContainsAnyNode (Issue #9)
|
|
def test_contains_any_found(self):
|
|
# Substring present, returns True
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful anime portrait",
|
|
substrings="anime",
|
|
match_case=False
|
|
)
|
|
self.assertTrue(result)
|
|
self.assertEqual(matched, "anime")
|
|
|
|
def test_contains_any_not_found(self):
|
|
# No match, returns False
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful landscape",
|
|
substrings="anime",
|
|
match_case=False
|
|
)
|
|
self.assertFalse(result)
|
|
self.assertEqual(matched, "")
|
|
|
|
def test_contains_any_multiple_first_match(self):
|
|
# Returns first matched substring
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful anime manga portrait",
|
|
substrings="""cel-shaded
|
|
anime
|
|
manga""",
|
|
match_case=False
|
|
)
|
|
self.assertTrue(result)
|
|
self.assertEqual(matched, "anime")
|
|
|
|
def test_contains_any_case_insensitive(self):
|
|
# Default case-insensitive behavior
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful ANIME portrait",
|
|
substrings="anime",
|
|
match_case=False
|
|
)
|
|
self.assertTrue(result)
|
|
self.assertEqual(matched, "anime")
|
|
|
|
def test_contains_any_case_sensitive(self):
|
|
# Case-sensitive matching
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful ANIME portrait",
|
|
substrings="anime",
|
|
match_case=True
|
|
)
|
|
self.assertFalse(result)
|
|
self.assertEqual(matched, "")
|
|
|
|
def test_contains_any_case_sensitive_found(self):
|
|
# Case-sensitive matching with exact case
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful ANIME portrait",
|
|
substrings="ANIME",
|
|
match_case=True
|
|
)
|
|
self.assertTrue(result)
|
|
self.assertEqual(matched, "ANIME")
|
|
|
|
def test_contains_any_empty_input(self):
|
|
# Empty input string
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="",
|
|
substrings="anime",
|
|
match_case=False
|
|
)
|
|
self.assertFalse(result)
|
|
self.assertEqual(matched, "")
|
|
|
|
def test_contains_any_empty_substrings(self):
|
|
# Empty substrings
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful anime portrait",
|
|
substrings="",
|
|
match_case=False
|
|
)
|
|
self.assertFalse(result)
|
|
self.assertEqual(matched, "")
|
|
|
|
def test_contains_any_whitespace_substrings(self):
|
|
# Substrings with only whitespace lines (should be ignored)
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful anime portrait",
|
|
substrings="""
|
|
anime
|
|
""",
|
|
match_case=False
|
|
)
|
|
self.assertTrue(result)
|
|
self.assertEqual(matched, "anime")
|
|
|
|
def test_contains_any_partial_match(self):
|
|
# Partial substring match (anime matches animation)
|
|
result, matched = self.contains_any_node.contains_any(
|
|
input_string="A beautiful animation",
|
|
substrings="anim",
|
|
match_case=False
|
|
)
|
|
self.assertTrue(result)
|
|
self.assertEqual(matched, "anim")
|
|
|
|
|
|
# Tests for sort_by_length parameter (Issue #11)
|
|
def test_replace_sort_by_length_default(self):
|
|
# Default behavior: longest match first prevents substring clobbering
|
|
input_string = "this is a test"
|
|
replacement_pairs = """is::WAS
|
|
this::THAT"""
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True,
|
|
sort_by_length=True
|
|
)[0]
|
|
# "this" (4 chars) replaced before "is" (2 chars), so "this" is not mangled
|
|
self.assertEqual(result, "THAT WAS a test")
|
|
|
|
def test_replace_sort_by_length_disabled(self):
|
|
# Input-order replacement: pairs processed in the order given
|
|
input_string = "cat is here"
|
|
replacement_pairs = """cat::dog
|
|
dog::fish"""
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True,
|
|
sort_by_length=False
|
|
)[0]
|
|
# "cat" -> "dog" first, then "dog" -> "fish" (chained replacement)
|
|
self.assertEqual(result, "fish is here")
|
|
|
|
def test_replace_sort_by_length_enabled_no_chaining(self):
|
|
# With sort enabled, equal-length pairs are sorted reverse-alphabetically,
|
|
# so "dog::fish" runs before "cat::dog". Since "dog" isn't in the original
|
|
# string, only "cat::dog" produces a match. No chaining occurs.
|
|
input_string = "cat is here"
|
|
replacement_pairs = """cat::dog
|
|
dog::fish"""
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=True,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True,
|
|
sort_by_length=True
|
|
)[0]
|
|
self.assertEqual(result, "dog is here")
|
|
|
|
# Tests for use_regex parameter (Issue #11)
|
|
def test_replace_use_regex_basic(self):
|
|
# Regex pattern matching
|
|
input_string = "hello123world456"
|
|
replacement_pairs = r"\d+:: "
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=False,
|
|
use_regex=True
|
|
)[0]
|
|
self.assertEqual(result, "hello world ")
|
|
|
|
def test_replace_use_regex_disabled(self):
|
|
# Without regex, special chars are treated literally
|
|
input_string = r"hello\d+world"
|
|
replacement_pairs = r"\d+::REPLACED"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True,
|
|
use_regex=False
|
|
)[0]
|
|
self.assertEqual(result, "helloREPLACEDworld")
|
|
|
|
def test_replace_use_regex_with_groups(self):
|
|
# Regex with capture groups in replacement
|
|
input_string = "2024-01-15"
|
|
replacement_pairs = r"(\d{4})-(\d{2})-(\d{2})::\3/\2/\1"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True,
|
|
use_regex=True
|
|
)[0]
|
|
self.assertEqual(result, "15/01/2024")
|
|
|
|
def test_replace_use_regex_character_class(self):
|
|
# Regex with character class
|
|
input_string = "Hello, World! How are you?"
|
|
replacement_pairs = "[!?,]::;"
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True,
|
|
use_regex=True
|
|
)[0]
|
|
self.assertEqual(result, "Hello; World; How are you;")
|
|
|
|
def test_replace_regex_with_input_order(self):
|
|
# Combine regex + input-order for chained regex replacements
|
|
input_string = "foo123bar456baz"
|
|
replacement_pairs = r"""\d+::_
|
|
foo_bar::REPLACED"""
|
|
result = self.replace_node.string_replace(
|
|
input_string=input_string,
|
|
replacement_pairs=replacement_pairs,
|
|
replacement_delimiter="::",
|
|
match_case=False,
|
|
match_whole_string=False,
|
|
preserve_punctuation=True,
|
|
remove_extra_spaces=True,
|
|
sort_by_length=False,
|
|
use_regex=True
|
|
)[0]
|
|
# First: \d+ -> _ gives "foo_bar_baz"
|
|
# Then: foo_bar -> REPLACED gives "REPLACED_baz"
|
|
self.assertEqual(result, "REPLACED_baz")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main() |