aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornatsuoto <[email protected]>2026-07-01 17:42:49 +0530
committernatsuoto <[email protected]>2026-07-01 17:42:49 +0530
commitf8cfe6cd98f751591ff2fd2cd5bed8cb59ddeb17 (patch)
tree4a1ccf3a5dec32d8227aec701fc88db4f3a676d0
parent060b4089f93ea7add1ca70a2b63e6411967f9a97 (diff)
downloadedify-f8cfe6cd98f751591ff2fd2cd5bed8cb59ddeb17.tar.xz
edify-f8cfe6cd98f751591ff2fd2cd5bed8cb59ddeb17.zip
feat: terminal flag kwargs on .to_regex(ignore_case=..., multiline=..., dotall=...)
-rw-r--r--edify/builder/mixins/terminals.py27
-rw-r--r--tests/builder/flags.test.py64
2 files changed, 89 insertions, 2 deletions
diff --git a/edify/builder/mixins/terminals.py b/edify/builder/mixins/terminals.py
index 9b7e62a..0887afa 100644
--- a/edify/builder/mixins/terminals.py
+++ b/edify/builder/mixins/terminals.py
@@ -43,15 +43,38 @@ class TerminalsMixin(BuilderProtocol):
return _EMPTY_NON_CAPTURING_GROUP
return unescaped_pattern
- def to_regex(self) -> Regex:
+ def to_regex(
+ self,
+ *,
+ ascii_only: bool = False,
+ debug: bool = False,
+ ignore_case: bool = False,
+ multiline: bool = False,
+ dotall: bool = False,
+ verbose: bool = False,
+ ) -> Regex:
"""Return the pattern + flags compiled and wrapped in :class:`edify.result.Regex`.
The wrapper exposes the pattern string as ``.source`` and the underlying
:class:`re.Pattern` as ``.compiled``, plus the eight :mod:`re` query
methods as direct delegates.
+
+ Keyword arguments are OR-merged into the flag snapshot the builder
+ already carries — passing ``ignore_case=True`` here is equivalent to
+ having called ``.ignore_case()`` in the chain. Flags never turn off,
+ only on.
"""
pattern_string = self.to_regex_string()
- flag_bitmask = _build_flag_bitmask(self._state.flags)
+ kwarg_flags = Flags(
+ ascii_only=ascii_only,
+ debug=debug,
+ ignore_case=ignore_case,
+ multiline=multiline,
+ dotall=dotall,
+ verbose=verbose,
+ )
+ effective_flags = self._state.flags.with_merged(kwarg_flags)
+ flag_bitmask = _build_flag_bitmask(effective_flags)
try:
compiled_pattern = re.compile(pattern_string, flags=flag_bitmask)
except re.error as compile_error:
diff --git a/tests/builder/flags.test.py b/tests/builder/flags.test.py
new file mode 100644
index 0000000..ad177c0
--- /dev/null
+++ b/tests/builder/flags.test.py
@@ -0,0 +1,64 @@
+"""Tests for the flag keyword arguments on :meth:`TerminalsMixin.to_regex`."""
+
+import re
+
+from edify import Pattern, RegexBuilder
+
+
+def test_no_kwargs_uses_only_the_chain_flag_snapshot():
+ compiled = RegexBuilder().string("hi").to_regex()
+ assert compiled.compiled.flags & re.I == 0
+
+
+def test_ignore_case_kwarg_enables_the_ignore_case_flag():
+ compiled = RegexBuilder().string("hi").to_regex(ignore_case=True)
+ assert compiled.compiled.flags & re.I == re.I
+
+
+def test_multiline_kwarg_enables_the_multiline_flag():
+ compiled = RegexBuilder().string("hi").to_regex(multiline=True)
+ assert compiled.compiled.flags & re.M == re.M
+
+
+def test_dotall_kwarg_enables_the_dotall_flag():
+ compiled = RegexBuilder().string("hi").to_regex(dotall=True)
+ assert compiled.compiled.flags & re.S == re.S
+
+
+def test_ascii_only_kwarg_enables_the_ascii_flag():
+ compiled = RegexBuilder().string("hi").to_regex(ascii_only=True)
+ assert compiled.compiled.flags & re.A == re.A
+
+
+def test_verbose_kwarg_enables_the_verbose_flag():
+ compiled = RegexBuilder().string("hi").to_regex(verbose=True)
+ assert compiled.compiled.flags & re.X == re.X
+
+
+def test_debug_kwarg_enables_the_debug_flag(capsys):
+ RegexBuilder().string("hi").to_regex(debug=True)
+ captured = capsys.readouterr()
+ assert captured.out != ""
+
+
+def test_kwargs_or_merge_with_chain_flags():
+ compiled = RegexBuilder().ignore_case().string("hi").to_regex(multiline=True)
+ assert compiled.compiled.flags & re.I == re.I
+ assert compiled.compiled.flags & re.M == re.M
+
+
+def test_kwargs_never_turn_off_a_chain_flag():
+ compiled = RegexBuilder().ignore_case().string("hi").to_regex(ignore_case=False)
+ assert compiled.compiled.flags & re.I == re.I
+
+
+def test_kwargs_work_on_pattern_too():
+ compiled = Pattern().string("hi").to_regex(ignore_case=True)
+ assert compiled.compiled.flags & re.I == re.I
+
+
+def test_multiple_kwargs_combine():
+ compiled = RegexBuilder().string("hi").to_regex(ignore_case=True, multiline=True, dotall=True)
+ assert compiled.compiled.flags & re.I == re.I
+ assert compiled.compiled.flags & re.M == re.M
+ assert compiled.compiled.flags & re.S == re.S