Skip to main content

Data-structure pattern matching and unpacking for Python

Project description

Usage

Call the patternmatching.match() function with two arguments:

  • Argument 1: the pattern to match against

  • Argument 2: the data structure to match

  • Optional argument flatten: True to have the matched values flattened, i.e. returned as a flat tuple regardless of their position in the structure of the matched data.

Return value:

if flatten is true:
    match_ok, [matched_value, matched_value, matched_value, ...]
if flatten is not true:
    match_ok, matched_data_structure

Caveat: if all matched values in the pattern are ignored, match() does not return a tuple but a boolean.

YES:

match_ok = match(PATTERN, DATA)

NO:

match_ok, = match(PATTERN, DATA)

Built-in match objects

  • ANY

  • IS_INSTANCE

Any match object can be wrapped with IGNORE() to ignore the value matched by the match object in the returned values.

IGNORE itself can be used as a shortcut for IGNORE(ANY).

assert True == match(IGNORE, 123)

Usage in (unit) tests (but also anywhere else)

Comparing the return values of functions is tedious if you can’t simply use the == operator. For example when a function returns a tuple and you only care about some parts of the tuple and not the entire tuple:

retval = some_function_under_test()
assert retval and isinstance(retval, tuple) \
    and len(retval) == 3 and retval[0] == 'foo' \
    and isinstance(retval[1], tuple) and len(retval[1]) == 2 \
    and isinstance(retval[1][1], SomeException)

With pattern matching:

retval = some_function_under_test()
assert retval == ('foo', (ANY, IS_INSTANCE(SomeException)), ANY)

Examples

MATCH OK

match_ok, value = match(ANY, 'foobar')
assert match_ok and value == 'foobar'

match_ok = match(IGNORE(ANY), 'foobar')
assert match_ok

match_ok, value1, value2 match((ANY, ANY), ('foo', 'bar'))
assert match_ok and value1 == 'foo' and value2 == 'bar'

match_ok, (value1, value2) = match((ANY, ANY), ('foo', 'bar'), flatten=False)
assert match_ok and value1 == 'foo' and value2 == 'bar'

match_ok, (value1, ) = match((ANY, IGNORE(ANY)), ('foo', 'whatev'))
assert match_ok and value1 == 'foo'

match_ok, value1, value2 = match(('foo', ANY, ANY), ('foo', 1, 2))
assert match_ok and value1 == 1 and value2 == 2

match_ok, value1, value2, value3 = match(('foo', ANY, (ANY, ANY)), ('foo', 1, (2, 3)))
assert match_ok and value1 == 1 and value2 == 2 and value3 = 3

match_ok, (value1, (value2, value3)) = match(('foo', ANY, (ANY, ANY)), ('foo', 1, (2, 3)), flatten=False)
assert match_ok and value1 == 1 and value2 == 2 and value3 = 3

NO MATCH

match_ok = match(3, 4)
assert not match_ok

# notice how you can still successfully do unpacking of return values and just ignore `value` if the match failed
match_ok, value = match(IS_INSTANCE(unicode), '123132')
assert not match_ok

# notice how you can still successfully do unpacking of return values and just ignore `value` if the match failed
match_ok, (value1, (value2, value3)) = match(('foo', (ANY, (ANY, ANY))), ('not-foo', (1, (2, 3))))
assert not match_ok

# ...even when the structure of the data completely mismatches
match_ok, (value1, (value2, value3)) = match(('foo', (ANY, (ANY, ANY))), ('foo', 'blabla'))
assert not match_ok

# ...don't rely on `value1`, `value2` and `value3` being `None` though--the matcher can still return whatever it wants there; you have to check `match_ok` yourself.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py-pattern-matching-0.1.1.tar.gz (3.9 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page