rewrapped package

Submodules

rewrapped.patterns module

class rewrapped.patterns.ReWrap(string, mObj)[source]

The base class from which to inherit your own pattern definition.

Every such class must have a matchOn field (usually a string or pattern object) defining what instances of the class are to match.

In order to be useful, the class also has to contain match fields to refer to match contents.

classmethod findall(string, *args, **kwargs)[source]

A wrapper for re.regex.findall; just wraps a list around this class’s finditer

Parameters:string – the string in which to search
Returns:a list of all match instances on the argument string
See:https://docs.python.org/3.6/library/re.html#re.regex.findall
classmethod finditer(string, *args, **kwargs)[source]

A wrapper for re.regex.finditer: Returns an iterator over non-overlapping matches in the argument string. Takes optional parameters like re.regex.finditer.

Parameters:string – the string in which to search
Returns:an iterator, possibly empty, over instances of this class
See:https://docs.python.org/3.6/library/re.html#re.regex.finditer
classmethod fullmatch(string, *args, **kwargs)[source]

A wrapper for re.regex.fullmatch: Tries to match the argument string completely. Takes optional parameters like re.regex.fullmatch.

Parameters:string – the string which to match
Returns:an instance of this class, if the string is a match; None otherwise
See:https://docs.python.org/3.6/library/re.html#re.regex.fullmatch
classmethod match(string, *args, **kwargs)[source]

A wrapper for re.regex.match: Tries to match the argument string from the beginning. Takes optional parameters like re.regex.match.

Parameters:string – the string which to match from the beginning
Returns:an instance of this class, if a match was found; None otherwise
See:https://docs.python.org/3.6/library/re.html#re.regex.match
matchOn = None

The pattern on which this class should match. Every ReWrap subclass has to define this field. It can be anything that can passed to re.compile, e.g.:

>>> from rewrapped import ReWrap
>>> class Word(ReWrap):
...     matchOn = "\w+"
...
>>>

If the argument is a string, is is compiled to a pattern object at class compile time, so any error is detected at that point:

>>> from rewrapped import ReWrap
>>> class Word(ReWrap):
...     matchOn = "(\w+]"
...
Traceback (most recent call last):
 ...
sre_constants.error: missing ), unterminated subpattern at position 0

The string can optionally be followed by match flags in the manner one would pass them to re.compile:

>>> from re import IGNORECASE, MULTILINE
>>> from rewrapped import ReWrap,matched
>>> class Word(ReWrap):
...     matchOn = "^abc", IGNORECASE | MULTILINE
...     abc = matched.g0
...
>>> m = Word.search("123\nABC")
>>> m.abc
'ABC'
classmethod search(string, *args, **kwargs)[source]

A wrapper for re.regex.search: Searches for a match in the argument string. Takes optional parameters like re.regex.search. :param string: the string in which to search :return: an instance of this class, if a match was found; None otherwise

See:https://docs.python.org/3.6/library/re.html#re.regex.search
wrapNone = False

A boolean flag indicating whether to wrap a None no-match result in an instance of the respective ReWrap subclass. All groups of that instance will evaluate to None, and before and after match fields will both yield the complete searched (and unmatched) string. The start and end fields return -1.

>>> from rewrapped import ReWrap,matched
>>> class Word(ReWrap):
...     matchOn = "abc"
...     wrapNone = True
...     abc = matched.g0
...     before = matched.before
...     after = matched.after
...
>>> m = Word.search("nothing here")
>>> type(m)
<class 'Word'>
>>> m.abc is None
True
>>> m.before
'nothing here'
>>> m.after
'nothing here'

Only affects methods which can return None results (e.g., search()); does not affect methods which return collections or iterators (e.g., findall()).

Defaults to False: Return None when no match has been found.

You can set this on the ReWrap baseclass directly if you want it to apply to all your subclasses.

class rewrapped.patterns.MatchField[source]

The marker class for which fields in ReWrap classes are initialized. Only defines the required behaviour: being able to check and fill a field.

See matched for predefined fields.

rewrapped.matched module

Provides predefined match fields for use with ReWrap classes. The module modders provides chainable modifiers to do more with these fields.

rewrapped.matched.group(*indices)[source]

One or more match groups with the argument index or indices. Mirrors Python’s match group method

Note that, in difference to the Python group method, this does not support named groups (yet).

Parameters:indices – the non-negative indices of the desired match groups; optional - if none are given, the whole match, as if called with zero
Returns:a matcher for the group or groups of the argument index or indices

Example:

>>> from rewrapped import ReWrap, matched
>>> class FullName(ReWrap):
...     matchOn = "(\w+)\s+(\w+)"
...     first = matched.group(1)
...     last = matched.group(2)
...
>>> m = FullName.search("Isaac Newton, physicist")
>>> m.first, m.last
('Isaac', 'Newton')
rewrapped.matched.g(idx: int)[source]

The basic single match group as a field on a ReWrap class. In match instances of that class, the field is the content of the respective single capturing match group content. For multiple groups, use gTuple() or group().

For the whole match, you can use the abbreviation g0. Likewise, the first nine groups have the abbrevations g1 to g9.

Parameters:idx – the non-negative index of the desired match group, where zero is the whole match
Returns:a match field for the group of the argument index
See:https://docs.python.org/3/library/re.html#re.match.group

Example:

>>> from rewrapped import ReWrap, matched
>>> class TwoWords(ReWrap):
...     matchOn = "(\w+)\s+(\w+)"
...     firstWord = matched.g(1)
...     secondWord = matched.g(2)
...     allOfIt = matched.g(0)
...
>>> w = TwoWords.search("hello world")
>>> w.firstWord
'hello'
>>> w.secondWord
'world'
>>> w.allOfIt
'hello world'
rewrapped.matched.gOr(idx: int, defaultValue)[source]

A single match group like g(), but with a default value in case the group is not matched. Only makes sense for optional matches.

Parameters:
  • idx – the non-negative index of the desired match group
  • defaultValue – the value to return in case the group is not matched
Returns:

a matcher for the group of the argument index

Example:

>>> from rewrapped import ReWrap, matched
>>> class OptionalYear(ReWrap):
...     matchOn = "([0-9]{2})\.([0-9]{2})\.([0-9]{4})?"
...     day = matched.g1.asInt
...     month = matched.g2.asInt
...     year = matched.gOr(3, 2018).asInt
...
>>> m = OptionalYear.search("02.03.")
>>> m.day, m.month, m.year
(2, 3, 2018)
>>> m = OptionalYear.search("02.03.1999")
>>> m.day, m.month, m.year
(2, 3, 1999)

Note that the default only applies to unmatched groups (i.e., which have a value of None), not to zero-length groups, which are matched to the empty string. In the following example, the default value will apply on a missing numbers group:

>>> from rewrapped import ReWrap, matched
>>> class OptNumbers(ReWrap):
...     matchOn = "([0-9])? ([a-z]+)"
...     numbers = matched.gOr(1, -1)
...     letters = matched.g2
...
>>> m = OptNumbers.search(" abc")
>>> m.numbers, m.letters
(-1, 'abc')

But if the number group can have a zero length, Python matches it as such, and consequently you get the empty string, not the default value:

>>> from rewrapped import ReWrap, matched
>>> class SomeNumbers(ReWrap):
...     matchOn = "([0-9]*) ([a-z]+)"
...     numbers = matched.gOr(1, -1)
...     letters = matched.g2
...
>>> m = SomeNumbers.search(" xyz")
>>> m.numbers, m.letters
('', 'xyz')
rewrapped.matched.gTuple(*indices)[source]

Multiple match groups with the argument indices.

Parameters:indices – the non-negative indices of the desired match groups; optional - if none are given, all groups of the match.
Returns:a matcher for the groups of the argument indices

Example:

>>> from rewrapped import ReWrap, matched
>>> class FullName(ReWrap):
...     matchOn = "(\w+)\s+(\w+)"
...     lastFirst = matched.gTuple(2, 1)
...
>>> m = FullName.search("Isaac Newton, physicist")
>>> m.lastFirst
('Newton', 'Isaac')

Note the difference to group() when called without arguments: gTuple() returns all groups in this case, whereas group() does the same as Python’s match group method and returns the match (i.e., as if called as group(0)):

>>> from rewrapped import ReWrap, matched
>>> class Address(ReWrap):
...     matchOn = "([0-9]+)\s+(\w+)\s*(\w*)"
...     street = matched.gTuple()
...     line = matched.group()
...
>>> m = Address.search("123 newton avenue")
>>> m.street
('123', 'newton', 'avenue')
>>> m.line
'123 newton avenue'
>>> m = Address.search("123 pappelallee")
>>> m.street
('123', 'pappelallee', '')
>>> m.line
'123 pappelallee'
rewrapped.matched.after = <rewrapped.modders.SingleValueField object>

The part of a searched string behind the match.

Example:

>>> from rewrapped import ReWrap, matched
>>> class Word(ReWrap):
...     matchOn = "(\w)+"
...     rest = matched.after
...
>>> m = Word.search("... coconuts! and more!")
>>> m.rest
'! and more!'
rewrapped.matched.before = <rewrapped.modders.SingleValueField object>

The part of a searched string in front of the match.

Example:

>>> from rewrapped import ReWrap, matched
>>> class Word(ReWrap):
...     matchOn = "(\w)+"
...     inFront = matched.before
...
>>> m = Word.search(" ... coconut! and more!")
>>> m.inFront
' ... '
rewrapped.matched.start = <rewrapped.modders.SingleValueField object>

The start of the match.

Example:

>>> from rewrapped import ReWrap, matched
>>> class Word(ReWrap):
...     matchOn = "([a-z]+)"
...     start = matched.start
...
>>> m = Word.search("123 Xabc")
>>> m.start
5
rewrapped.matched.end = <rewrapped.modders.SingleValueField object>

The end of the match.

Example:

>>> from rewrapped import ReWrap, matched
>>> class Word(ReWrap):
...     matchOn = "([a-z]+)"
...     end = matched.end
...
>>> m = Word.search("123 Xabc")
>>> m.end
8
rewrapped.matched.g0 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(0) - the whole match, like matchobject.group() or matchobject.group(0):

>>> from rewrapped import ReWrap, matched
>>> class Word(ReWrap):
...     matchOn = "(\w)+"
...     txt = matched.g0
...
>>> m = Word.search("... coconut! ")
>>> m.txt
'coconut'
rewrapped.matched.g1 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(1) - the content of the first capturing group, like matchobject.group(1)

rewrapped.matched.g2 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(2) - the content of the second capturing group, like matchobject.group(2)

rewrapped.matched.g3 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(3) - the content of the third capturing group, like matchobject.group(3)

rewrapped.matched.g4 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(4) - the content of the fourth capturing group, like matchobject.group(4)

rewrapped.matched.g5 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(5) - the content of the fifth capturing group, like matchobject.group(5)

rewrapped.matched.g6 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(6) - the content of the sixth capturing group, like matchobject.group(6)

rewrapped.matched.g7 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(7) - the content of the seventh capturing group, like matchobject.group(7)

rewrapped.matched.g8 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(8) - the content of the eigth capturing group, like matchobject.group(8)

rewrapped.matched.g9 = <rewrapped.modders.SingleValueField object>

An abbreviation for g(9) - the content of the ninth capturing group, like matchobject.group(9)

rewrapped.modders module

Provides modifiers for match fields such as type conversions and function applications.

class rewrapped.modders.SingleValueField(originField, modders=None)[source]

Bases: rewrapped.modders._ModdableField

apply(valFunc)[source]

Apply the argument function on the field value.

>>> from rewrapped import ReWrap, matched
>>> class Code(ReWrap):
...     matchOn = "letters: ([a-z ]+)"
...     letters = matched.g1.apply(set).apply(sorted)
...
>>> c = Code.search("letters: a b a za b")
>>> c.letters
[' ', 'a', 'b', 'z']
asFloat

Return the field value as a float:

>>> from rewrapped import ReWrap, matched
>>> class Direction(ReWrap):
...     matchOn = "([0-9]+\.[0-9]+)"
...     distance = matched.g1.asFloat
...
>>> d = Direction.search("left 3.12 km")
>>> d.distance
3.12
>>> type(d.distance)
<class 'float'>
asInt

Return the field value as an integer:

>>> from rewrapped import ReWrap, matched
>>> class Inventory(ReWrap):
...     matchOn = "([0-9]+)"
...     count = matched.g1.asInt
...
>>> i = Inventory.search("there are 45 oranges left")
>>> i.count
45
>>> type(i.count)
<class 'int'>
breakOn(breakVal=None)[source]

Do not evaluate following field modifiers if the field value is the argument value; return that value instead:

>>> from rewrapped import ReWrap, matched
>>> class Quantity(ReWrap):
...     matchOn = "(NA|[0-9]+)"
...     amount = matched.g0.breakOn("NA").asInt
...
>>> qs = Quantity.findall("measured NA 123")
>>> tuple((q.amount, type(q.amount)) for q in qs)
(('NA', <class 'str'>), (123, <class 'int'>))
breakOnNone

Do not evaluate following field modifiers if the field value is None; return None as the value instead:

>>> from rewrapped import ReWrap, matched
>>> class Counted(ReWrap):
...     matchOn = "the ([0-9]+)?\s*parrots"
...     number = matched.g1.breakOnNone.asInt
...
>>> c = Counted.search("the 24 parrots")
>>> c.number
24
>>> c = Counted.search("the parrots")
>>> c.number is None
True

Short for breakOn(None)

strip

Strip whitespace from the field value:

>>> from rewrapped import ReWrap, matched
>>> class FirstWord(ReWrap):
...     matchOn = "\s*\S+"
...     word = matched.g0.strip
...
>>> f = FirstWord.search("  Make sweet some vial")
>>> f.word
'Make'
class rewrapped.modders.TupleValueField(originField, modders=None)[source]

Bases: rewrapped.modders._ModdableField

apply(valsFunc)[source]

Apply the argument function on the field values. The function will be passed as many value arguments as the field has groups, in the field’s order:

>>> import datetime
>>> from rewrapped import ReWrap, matched
>>> class StartedDate(ReWrap):
...     matchOn = "started ([0-9]{4})-([0-9]{2})-([0-9]{2})"
...     when = matched.gTuple().asInts.apply(datetime.datetime)
...
>>> s = StartedDate.search("started 1969-10-05")
>>> s.when
datetime.datetime(1969, 10, 5, 0, 0)
asFloats

Return the field values as floats:

>>> from rewrapped import ReWrap, matched
>>> class ErrorMargin(ReWrap):
...     matchOn = "between ([0-9]+\.[0-9]+) and ([0-9]+\.[0-9]+)"
...     interval = matched.gTuple(1,2).asFloats
...
>>> e = ErrorMargin.search("between 4.5 and 6.7 units")
>>> e.interval
(4.5, 6.7)
asInts

Return the field values as integers:

>>> from rewrapped import ReWrap, matched
>>> class Inventory(ReWrap):
...     matchOn = "between ([0-9]+) and ([0-9]+)"
...     estimate = matched.gTuple(1,2).asInts
...
>>> i = Inventory.search("there are between 45 and 67 oranges left")
>>> i.estimate
(45, 67)

Module contents

class rewrapped.ReWrap(string, mObj)[source]

Bases: object

The base class from which to inherit your own pattern definition.

Every such class must have a matchOn field (usually a string or pattern object) defining what instances of the class are to match.

In order to be useful, the class also has to contain match fields to refer to match contents.

classmethod findall(string, *args, **kwargs)[source]

A wrapper for re.regex.findall; just wraps a list around this class’s finditer

Parameters:string – the string in which to search
Returns:a list of all match instances on the argument string
See:https://docs.python.org/3.6/library/re.html#re.regex.findall
classmethod finditer(string, *args, **kwargs)[source]

A wrapper for re.regex.finditer: Returns an iterator over non-overlapping matches in the argument string. Takes optional parameters like re.regex.finditer.

Parameters:string – the string in which to search
Returns:an iterator, possibly empty, over instances of this class
See:https://docs.python.org/3.6/library/re.html#re.regex.finditer
classmethod fullmatch(string, *args, **kwargs)[source]

A wrapper for re.regex.fullmatch: Tries to match the argument string completely. Takes optional parameters like re.regex.fullmatch.

Parameters:string – the string which to match
Returns:an instance of this class, if the string is a match; None otherwise
See:https://docs.python.org/3.6/library/re.html#re.regex.fullmatch
classmethod match(string, *args, **kwargs)[source]

A wrapper for re.regex.match: Tries to match the argument string from the beginning. Takes optional parameters like re.regex.match.

Parameters:string – the string which to match from the beginning
Returns:an instance of this class, if a match was found; None otherwise
See:https://docs.python.org/3.6/library/re.html#re.regex.match
matchOn = None

The pattern on which this class should match. Every ReWrap subclass has to define this field. It can be anything that can passed to re.compile, e.g.:

>>> from rewrapped import ReWrap
>>> class Word(ReWrap):
...     matchOn = "\w+"
...
>>>

If the argument is a string, is is compiled to a pattern object at class compile time, so any error is detected at that point:

>>> from rewrapped import ReWrap
>>> class Word(ReWrap):
...     matchOn = "(\w+]"
...
Traceback (most recent call last):
 ...
sre_constants.error: missing ), unterminated subpattern at position 0

The string can optionally be followed by match flags in the manner one would pass them to re.compile:

>>> from re import IGNORECASE, MULTILINE
>>> from rewrapped import ReWrap,matched
>>> class Word(ReWrap):
...     matchOn = "^abc", IGNORECASE | MULTILINE
...     abc = matched.g0
...
>>> m = Word.search("123\nABC")
>>> m.abc
'ABC'
classmethod search(string, *args, **kwargs)[source]

A wrapper for re.regex.search: Searches for a match in the argument string. Takes optional parameters like re.regex.search. :param string: the string in which to search :return: an instance of this class, if a match was found; None otherwise

See:https://docs.python.org/3.6/library/re.html#re.regex.search
wrapNone = False

A boolean flag indicating whether to wrap a None no-match result in an instance of the respective ReWrap subclass. All groups of that instance will evaluate to None, and before and after match fields will both yield the complete searched (and unmatched) string. The start and end fields return -1.

>>> from rewrapped import ReWrap,matched
>>> class Word(ReWrap):
...     matchOn = "abc"
...     wrapNone = True
...     abc = matched.g0
...     before = matched.before
...     after = matched.after
...
>>> m = Word.search("nothing here")
>>> type(m)
<class 'Word'>
>>> m.abc is None
True
>>> m.before
'nothing here'
>>> m.after
'nothing here'

Only affects methods which can return None results (e.g., search()); does not affect methods which return collections or iterators (e.g., findall()).

Defaults to False: Return None when no match has been found.

You can set this on the ReWrap baseclass directly if you want it to apply to all your subclasses.