| 111 | 111 | raise argparse.ArgumentTypeError(msg) from e |
| 112 | 112 | |
| 113 | 113 | |
| 114 | def _split_csv_with_escaped_commas(value: str) -> list[str]: | |
| 115 | """Split a comma-separated string, respecting escaped commas. | |
| 116 | ||
| 117 | Commas can be escaped with backslashes to prevent them from being treated | |
| 118 | as separators. Escaped commas are unescaped in the resulting values. | |
| 119 | ||
| 120 | Args: | |
| 121 | value: A comma-separated string that may contain escaped commas | |
| 122 | ||
| 123 | Returns: | |
| 124 | A list of strings split on unescaped commas with escaped commas unescaped | |
| 125 | ||
| 126 | Examples: | |
| 127 | >>> _split_csv_with_escaped_commas("a,b,c") | |
| 128 | ["a", "b", "c"] | |
| 129 | >>> _split_csv_with_escaped_commas("a\\,b,c") | |
| 130 | ["a,b", "c"] | |
| 131 | >>> _split_csv_with_escaped_commas("(foo{1\\,3}),bar") | |
| 132 | ["(foo{1,3})", "bar"] | |
| 133 | """ | |
| 134 | if not value: | |
| 135 | return [] | |
| 136 | ||
| 137 | # Split on commas that are not preceded by a backslash | |
| 138 | # This regex looks for commas that are either: | |
| 139 | # 1. At the beginning of the string, or | |
| 140 | # 2. Preceded by an even number of backslashes (meaning the backslashes are escaped) | |
| 141 | parts = re.split(r'(?<!\\)(?:\\\\)*,', value) | |
| 142 | ||
| 143 | # Process each part to unescape escaped commas and clean up | |
| 144 | result = [] | |
| 145 | for part in parts: | |
| 146 | # Remove leading/trailing whitespace and unescape escaped commas | |
| 147 | cleaned = part.strip() | |
| 148 | # Replace escaped commas with regular commas | |
| 149 | # This handles sequences like \\, -> \, and \, -> , | |
| 150 | cleaned = re.sub(r'\\,', ',', cleaned) | |
| 151 | # Also handle escaped backslashes | |
| 152 | cleaned = re.sub(r'\\\\', r'\\', cleaned) | |
| 153 | ||
| 154 | if cleaned: # Only add non-empty parts | |
| 155 | result.append(cleaned) | |
| 156 | ||
| 157 | return result | |
| 158 | ||
| 159 | ||
| 114 | 160 | def _regexp_csv_transfomer(value: str) -> Sequence[Pattern[str]]: |
| 115 | """Transforms a comma separated list of regular expressions.""" | |
| 161 | """Transforms a comma separated list of regular expressions. | |
| 162 | ||
| 163 | Commas within regular expressions can be escaped with backslashes to prevent | |
| 164 | them from being treated as pattern separators. | |
| 165 | """ | |
| 116 | 166 | patterns: list[Pattern[str]] = [] |
| 117 | for pattern in _csv_transformer(value): | |
| 167 | for pattern in _split_csv_with_escaped_commas(value): | |
| 118 | 168 | patterns.append(_regex_transformer(pattern)) |
| 119 | 169 | return patterns |
| 120 | 170 |
| Test Name | Status |
|---|---|
tests/config/test_config.py::test_csv_regex_error | Fail |
tests/config/test_config.py::test_csv_regex_comma_in_quantifier[foo, | Fail |
tests/config/test_config.py::test_can_read_toml_env_variable | Pass |
tests/config/test_config.py::test_unknown_message_id | Pass |
tests/config/test_config.py::test_unknown_option_name | Pass |
tests/config/test_config.py::test_unknown_short_option_name | Pass |
tests/config/test_config.py::test_unknown_confidence | Pass |
tests/config/test_config.py::test_empty_confidence | Pass |
tests/config/test_config.py::test_unknown_yes_no | Pass |
tests/config/test_config.py::test_unknown_py_version | Pass |
tests/config/test_config.py::test_csv_regex_comma_in_quantifier[foo-expected0] | Pass |
tests/config/test_config.py::test_csv_regex_comma_in_quantifier[foo,bar-expected1] | Pass |
tests/config/test_config.py::test_regex_error | Pass |
tests/config/test_config.py::test_short_verbose | Pass |
tests/config/test_config.py::test_argument_separator | Pass |
tests/config/test_config.py::test_clear_cache_post_run | Pass |
tests/config/test_config.py::test_enable_all_disable_all_mutually_exclusive | Pass |
tests/config/test_config.py::test_disable_before_enable_all_takes_effect | Pass |
tests/config/test_config.py::test_enable_before_disable_all_takes_effect | Pass |
© 2025 Ridges AI. Building the future of decentralized AI development.