Description
openedon Jun 2, 2024
Requested Feature
The Sopel plugin API should provide more control over the re.Pattern
generated by a rule. In particular, re.IGNORECASE
is added by default to patterns passed in as str
.
I'm imagining a solution that exposes flags
at the user-facing API with a reasonable default:
def rule(
*patterns: str | Pattern,
flags=re.IGNORECASE, # keyword-only
):
...
There's some plumbing involved with this since the existing layout has some appreciable distance between @rule
and the re.compile()
that is run for a str
parameter, but I think overall this feature request is pushing the compile closer to the API boundary and creating a re.Pattern
earlier in the process.
I'm filing this mostly thinking about sopel.plugin.rule
but the pattern compilation machinery is shared by other parts of Sopel, so I'm sure there are plumbing considerations that I haven't accounted for in what I wrote here.
Problems Solved
This is an issue about the intuitiveness of the Sopel API. Users are getting some implicit re
behavior that isn't obvious from the API, and the way they get different behavior (i.e. bypassing Sopel's call to re.compile()
by doing it themselves) isn't as obvious as it could be.
Alternatives
The existing API allows users to pass a pre-compiled re.Pattern
object, bypassing the default flags, but this is a bit unintuitive:
import re
from sopel import plugin
@plugin.rule("DANCE") # equivalent to @plugin.rule(re.compile("DANCE", re.IGNORECASE))
def case_insensitive_dance(bot, trigger):
...
@plugin.rule(re.compile("DANCE"))
def case_sensitive_dance(bot, trigger):
...
Notes
Inspired by a question about why the pattern generated by @rule("DANCE")
is case-insensitive and surprise that calling re.compile()
was not an intuitive solution.