API reference#

Pattern#

class remagic.Pattern(node=Seq(parts=()))[source]#

An immutable piece of regular expression.

Strings combined with a pattern are matched literally. Combining patterns adds (?:…) only where precedence requires it.

>>> (Pattern.literal("a") | "b").times(2).source
'(?:a|b){2}'
property source#

The regex source as built, before any optimisation.

property precedence#

How tightly this pattern binds when combined.

property needs_regex#

Whether only the regex module can compile this pattern.

classmethod literal(text)[source]#

Match text exactly, escaping every special character.

Return type:

Pattern

classmethod coerce(value)[source]#

Return value as a pattern; strings become literals.

Return type:

Pattern

__add__(other)[source]#

Concatenate: a + b matches a then b.

Return type:

Pattern

__or__(other)[source]#

Alternate: a | b matches a or b.

Return type:

Pattern

__mul__(count)[source]#

a * 3 is a.times(3).

Return type:

Pattern

times(count, *, lazy=False, possessive=False)[source]#

Repeat exactly count times.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").times(3))
'a{3}'
between(low, high, *, lazy=False, possessive=False)[source]#

Repeat from low to high times, inclusive.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").between(2, 4))
'a{2,4}'
at_least(low, *, lazy=False, possessive=False)[source]#

Repeat low or more times.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").at_least(2))
'a{2,}'
optional(*, lazy=False, possessive=False)[source]#

Match zero or one time.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").optional(lazy=True))
'a??'
zero_or_more(*, lazy=False, possessive=False)[source]#

Match zero or more times.

Return type:

Pattern

Example

>>> str(Pattern.literal("ab").zero_or_more())
'(?:ab)*'
one_or_more(*, lazy=False, possessive=False)[source]#

Match one or more times.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").one_or_more(possessive=True))
'a++'
group(name=None)[source]#

Capture as a numbered group, or as a named group if name is given.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").group("first"))
'(?P<first>a)'
non_capturing()[source]#

Group without capturing.

Return type:

Pattern

Example

>>> str(Pattern.literal("ab").non_capturing())
'(?:ab)'
atomic()[source]#

Match without backtracking into the group.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").atomic())
'(?>a)'
scoped(on='', off='')[source]#

Apply inline flags to this pattern only.

on and off are flag letters as in (?i-s:…).

Return type:

Pattern

ignore_case()[source]#

Match case-insensitively.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").ignore_case())
'(?i:a)'
multiline()[source]#

Make ^ and $ match at line boundaries.

Return type:

Pattern

dotall()[source]#

Make . match newlines.

Return type:

Pattern

lookahead()[source]#

Assert that this pattern follows, without consuming it.

Return type:

Pattern

negative_lookahead()[source]#

Assert that this pattern does not follow.

Return type:

Pattern

lookbehind()[source]#

Assert that this pattern precedes.

Return type:

Pattern

negative_lookbehind()[source]#

Assert that this pattern does not precede.

Return type:

Pattern

followed_by(other)[source]#

Match this pattern only when other follows.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").followed_by("b"))
'a(?=b)'
not_followed_by(other)[source]#

Match this pattern only when other does not follow.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").not_followed_by("b"))
'a(?!b)'
preceded_by(other)[source]#

Match this pattern only when other precedes.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").preceded_by("b"))
'(?<=b)a'
not_preceded_by(other)[source]#

Match this pattern only when other does not precede.

Return type:

Pattern

Example

>>> str(Pattern.literal("a").not_preceded_by("b"))
'(?<!b)a'
optimized(level='safe', flags=0)[source]#

Return the cheaper equivalent pattern that compile would use.

safe keeps match spans and groups identical. aggressive also factors and reorders alternatives, which can change which match is found, so use it with fullmatch or yes/no checks only.

Return type:

Pattern

Example

>>> import remagic as rm
>>> str(rm.any_of("abc").one_or_more().one_or_more().optimized())
'[abc]++'
compile(flags=0, *, engine='auto', optimize=True)[source]#

Compile with re, or with regex when the pattern needs it.

optimize rewrites the pattern to a cheaper one with the same matches (True or “safe”), also factors alternatives for fullmatch use (“aggressive”), or compiles the pattern as built (False).

Raises:

RemagicException – if the chosen engine cannot compile the pattern.

Return type:

Pattern[str]

Functions#

Free-function builders; each mirrors a Pattern method.

remagic.interface.create(value)[source]#

Return value as a pattern; strings are matched literally.

Return type:

Pattern

remagic.interface.exactly(text)[source]#

Match text literally.

Return type:

Pattern

remagic.interface.optional(value, *, lazy=False, possessive=False)[source]#

Zero or one of value.

Return type:

Pattern

remagic.interface.zero_or_more(value, *, lazy=False, possessive=False)[source]#

Zero or more of value.

Return type:

Pattern

remagic.interface.one_or_more(value, *, lazy=False, possessive=False)[source]#

One or more of value.

Return type:

Pattern

remagic.interface.times(value, count, *, lazy=False, possessive=False)[source]#

Exactly count of value.

Return type:

Pattern

remagic.interface.between(value, low, high, *, lazy=False, possessive=False)[source]#

low to high of value.

Return type:

Pattern

remagic.interface.at_least(value, low, *, lazy=False, possessive=False)[source]#

low or more of value.

Return type:

Pattern

remagic.interface.group(value, name=None)[source]#

Capture value, optionally under name.

Return type:

Pattern

remagic.interface.non_capturing(value)[source]#

Group value without capturing.

Return type:

Pattern

remagic.interface.atomic(value)[source]#

Group value so it is never backtracked into.

Return type:

Pattern

remagic.interface.scoped(value, on='', off='')[source]#

Apply inline flags to value only.

Return type:

Pattern

remagic.interface.any_of(values)[source]#

Match any one of values, trying them in order.

Return type:

Pattern

>>> str(any_of(["a.b", "c"]))
'a\\.b|c'
remagic.interface.char_in(chars, *, ranges=())[source]#

Match one character from chars or from the inclusive ranges.

Return type:

Pattern

remagic.interface.char_not_in(chars, *, ranges=())[source]#

Match one character that is not in chars or ranges.

Return type:

Pattern

remagic.interface.char_range(low, high)[source]#

Match one character from low to high, inclusive.

Return type:

Pattern

remagic.interface.unicode_property(name, *, negate=False)[source]#

Match a Unicode property such as L or Greek; needs regex.

Return type:

Pattern

remagic.interface.before(value)[source]#

Assert that value follows the current position.

Return type:

Pattern

remagic.interface.not_before(value)[source]#

Assert that value does not follow the current position.

Return type:

Pattern

remagic.interface.after(value)[source]#

Assert that value precedes the current position.

Return type:

Pattern

remagic.interface.not_after(value)[source]#

Assert that value does not precede the current position.

Return type:

Pattern

remagic.interface.ref(reference)[source]#

Match the text captured by a numbered or named group.

Return type:

Pattern

Constants#

Ready-made patterns for common character classes and anchors.

remagic.constants.CHAR = Pattern('.')#

Any character except a newline.

remagic.constants.WHITESPACE = Pattern('\\s')#

One whitespace character; also available as WS.

remagic.constants.WS = Pattern('\\s')#

One whitespace character; also available as WS.

remagic.constants.NOT_WHITESPACE = Pattern('\\S')#

One non-whitespace character; also available as NOT_WS.

remagic.constants.NOT_WS = Pattern('\\S')#

One non-whitespace character; also available as NOT_WS.

remagic.constants.WORD = Pattern('\\w')#

One word character (letter, digit or underscore).

remagic.constants.NOT_WORD = Pattern('\\W')#

One non-word character.

remagic.constants.DIGIT = Pattern('\\d')#

One decimal digit.

remagic.constants.NOT_DIGIT = Pattern('\\D')#

One character that is not a digit.

remagic.constants.LETTER = Pattern('[A-Za-z]')#

One ASCII letter.

remagic.constants.NOT_LETTER = Pattern('[^A-Za-z]')#

One character that is not an ASCII letter.

remagic.constants.TAB = Pattern('\\t')#

A tab.

remagic.constants.NEWLINE = Pattern('\\n')#

A newline; also available as N.

remagic.constants.N = Pattern('\\n')#

A newline; also available as N.

remagic.constants.NOT_NEWLINE = Pattern('[^\\n]')#

Any character except a newline; also available as NOT_N.

remagic.constants.NOT_N = Pattern('[^\\n]')#

Any character except a newline; also available as NOT_N.

remagic.constants.CARRIAGE_RETURN = Pattern('\\r')#

A carriage return; also available as R.

remagic.constants.R = Pattern('\\r')#

A carriage return; also available as R.

remagic.constants.START = Pattern('^')#

The start of the string, or of a line when multiline.

remagic.constants.END = Pattern('$')#

The end of the string, or of a line when multiline.

remagic.constants.START_OF_STRING = Pattern('\\A')#

The very start of the string.

remagic.constants.END_OF_STRING = Pattern('\\Z')#

The very end of the string.

remagic.constants.WORD_BOUNDARY = Pattern('\\b')#

The boundary between a word and a non-word character.

remagic.constants.NOT_WORD_BOUNDARY = Pattern('\\B')#

Any position that is not a word boundary.

Exceptions#

exception remagic.RemagicException[source]#

Raised when a pattern cannot be built or compiled.

Escape hatch#

Escape hatch for regex source that remagic cannot build.

Patterns made here are opaque: remagic cannot check or optimize them, and mistakes surface only when the engine compiles the result. Prefer the builders in remagic and reach for this module only when nothing there fits.

remagic.unsafe.raw(source, *, needs_regex=False)[source]#

Wrap existing regex source, treated as lowest precedence.

Return type:

Pattern

Example

>>> from remagic import unsafe
>>> str(unsafe.raw("a|b") + "c")
'(?:a|b)c'