Structural Pattern Matching#
PyBryt supports structural pattern matching in order to allow you to create annotations that check
the structure of objects instead of using an == check. Structural patterns can be created by
accessing attributes of the singleton
pybryt.structural and calling them
with attribute-value pairs as arguments. For example, if you’re matching an instance of
mypackage.Foo with attribute bar set to 2; a structural pattern for this could be
created with
pybryt.structural.mypackage.Foo(bar=2)
If there are attributes you want to look for without a specific name, you can pass these as positional arguments:
pybryt.structural.mypackage.Foo(3, bar=2)
To determine whether an object matches the structural pattern, PyBryt imports the package and retrieves the specified class. In the examples above, this would look like
getattr(importlib.import_module("mypackage"), "Foo")
If the provided object is an instance of this class and has the specified attributes, the object
matches. You can determine if an object matches a structural pattern using an == comparison.
If no package is specified for the class, the pattern just checks that the name of the class matches the name of the class in the structural pattern, without importing any modules. For example:
df_pattern = pybryt.structural.DataFrame()
df_pattern == pd.DataFrame() # returns True
class DataFrame:
pass
df_pattern == DataFrame() # returns True
Attribute values are matched using the same algorithm as
Value annotations. If you would like to make use of
the options available to Value annotations, you can
also pass an annotation as an attribute value:
pybryt.structural.mypackage.Foo(pi=pybryt.Value(np.pi, atol=1e-5))
For checking whether an object contains specific members (determined via the use of Python’s
in operator), use the contains_ method:
pybryt.structural.mypackage.MyList().contains_(1, 2, 3)
To use structural patterns, pass them as values to Value
annotations. When a value annotation is checking for a structural pattern, it uses the pattern’s
== check to determine whether any object in the memory footprint matches.
pybryt.Value(pybryt.structural.mypackage.MyList())