@@ -512,5 +512,147 @@ def test_contains_any_partial_match(self):
512512 self .assertEqual (matched , "anim" )
513513
514514
515+ # Tests for sort_by_length parameter (Issue #11)
516+ def test_replace_sort_by_length_default (self ):
517+ # Default behavior: longest match first prevents substring clobbering
518+ input_string = "this is a test"
519+ replacement_pairs = """is::WAS
520+ this::THAT"""
521+ result = self .replace_node .string_replace (
522+ input_string = input_string ,
523+ replacement_pairs = replacement_pairs ,
524+ replacement_delimiter = "::" ,
525+ match_case = False ,
526+ match_whole_string = True ,
527+ preserve_punctuation = True ,
528+ remove_extra_spaces = True ,
529+ sort_by_length = True
530+ )[0 ]
531+ # "this" (4 chars) replaced before "is" (2 chars), so "this" is not mangled
532+ self .assertEqual (result , "THAT WAS a test" )
533+
534+ def test_replace_sort_by_length_disabled (self ):
535+ # Input-order replacement: pairs processed in the order given
536+ input_string = "cat is here"
537+ replacement_pairs = """cat::dog
538+ dog::fish"""
539+ result = self .replace_node .string_replace (
540+ input_string = input_string ,
541+ replacement_pairs = replacement_pairs ,
542+ replacement_delimiter = "::" ,
543+ match_case = False ,
544+ match_whole_string = True ,
545+ preserve_punctuation = True ,
546+ remove_extra_spaces = True ,
547+ sort_by_length = False
548+ )[0 ]
549+ # "cat" -> "dog" first, then "dog" -> "fish" (chained replacement)
550+ self .assertEqual (result , "fish is here" )
551+
552+ def test_replace_sort_by_length_enabled_no_chaining (self ):
553+ # With sort enabled, equal-length pairs are sorted reverse-alphabetically,
554+ # so "dog::fish" runs before "cat::dog". Since "dog" isn't in the original
555+ # string, only "cat::dog" produces a match. No chaining occurs.
556+ input_string = "cat is here"
557+ replacement_pairs = """cat::dog
558+ dog::fish"""
559+ result = self .replace_node .string_replace (
560+ input_string = input_string ,
561+ replacement_pairs = replacement_pairs ,
562+ replacement_delimiter = "::" ,
563+ match_case = False ,
564+ match_whole_string = True ,
565+ preserve_punctuation = True ,
566+ remove_extra_spaces = True ,
567+ sort_by_length = True
568+ )[0 ]
569+ self .assertEqual (result , "dog is here" )
570+
571+ # Tests for use_regex parameter (Issue #11)
572+ def test_replace_use_regex_basic (self ):
573+ # Regex pattern matching
574+ input_string = "hello123world456"
575+ replacement_pairs = r"\d+:: "
576+ result = self .replace_node .string_replace (
577+ input_string = input_string ,
578+ replacement_pairs = replacement_pairs ,
579+ replacement_delimiter = "::" ,
580+ match_case = False ,
581+ match_whole_string = False ,
582+ preserve_punctuation = True ,
583+ remove_extra_spaces = False ,
584+ use_regex = True
585+ )[0 ]
586+ self .assertEqual (result , "hello world " )
587+
588+ def test_replace_use_regex_disabled (self ):
589+ # Without regex, special chars are treated literally
590+ input_string = r"hello\d+world"
591+ replacement_pairs = r"\d+::REPLACED"
592+ result = self .replace_node .string_replace (
593+ input_string = input_string ,
594+ replacement_pairs = replacement_pairs ,
595+ replacement_delimiter = "::" ,
596+ match_case = False ,
597+ match_whole_string = False ,
598+ preserve_punctuation = True ,
599+ remove_extra_spaces = True ,
600+ use_regex = False
601+ )[0 ]
602+ self .assertEqual (result , "helloREPLACEDworld" )
603+
604+ def test_replace_use_regex_with_groups (self ):
605+ # Regex with capture groups in replacement
606+ input_string = "2024-01-15"
607+ replacement_pairs = r"(\d{4})-(\d{2})-(\d{2})::\3/\2/\1"
608+ result = self .replace_node .string_replace (
609+ input_string = input_string ,
610+ replacement_pairs = replacement_pairs ,
611+ replacement_delimiter = "::" ,
612+ match_case = False ,
613+ match_whole_string = False ,
614+ preserve_punctuation = True ,
615+ remove_extra_spaces = True ,
616+ use_regex = True
617+ )[0 ]
618+ self .assertEqual (result , "15/01/2024" )
619+
620+ def test_replace_use_regex_character_class (self ):
621+ # Regex with character class
622+ input_string = "Hello, World! How are you?"
623+ replacement_pairs = "[!?,]::;"
624+ result = self .replace_node .string_replace (
625+ input_string = input_string ,
626+ replacement_pairs = replacement_pairs ,
627+ replacement_delimiter = "::" ,
628+ match_case = False ,
629+ match_whole_string = False ,
630+ preserve_punctuation = True ,
631+ remove_extra_spaces = True ,
632+ use_regex = True
633+ )[0 ]
634+ self .assertEqual (result , "Hello; World; How are you;" )
635+
636+ def test_replace_regex_with_input_order (self ):
637+ # Combine regex + input-order for chained regex replacements
638+ input_string = "foo123bar456baz"
639+ replacement_pairs = r"""\d+::_
640+ foo_bar::REPLACED"""
641+ result = self .replace_node .string_replace (
642+ input_string = input_string ,
643+ replacement_pairs = replacement_pairs ,
644+ replacement_delimiter = "::" ,
645+ match_case = False ,
646+ match_whole_string = False ,
647+ preserve_punctuation = True ,
648+ remove_extra_spaces = True ,
649+ sort_by_length = False ,
650+ use_regex = True
651+ )[0 ]
652+ # First: \d+ -> _ gives "foo_bar_baz"
653+ # Then: foo_bar -> REPLACED gives "REPLACED_baz"
654+ self .assertEqual (result , "REPLACED_baz" )
655+
656+
515657if __name__ == '__main__' :
516658 unittest .main ()
0 commit comments