Source code for structured_data.match

"""Utilities for destructuring values using matchables and match targets.

Given a value to destructure, called ``value``:

- Construct a matchable: ``matchable = Matchable(value)``
- The matchable is initially falsy, but it will become truthy if it is passed a
  **match target** that matches ``value``:
  ``assert matchable(some_pattern_that_matches)`` (Matchable returns itself
  from the call, so you can put the calls in an if-elif block, and only make a
  given call at most once.)
- When the matchable is truthy, it can be indexed to access bindings created by
  the target.
"""

from __future__ import annotations

import typing

from . import _attribute_constructor
from ._class_placeholder import Placeholder
from ._match.descriptor import common
from ._match.descriptor import function as function_
from ._match.descriptor import property_
from ._match.destructure import names
from ._match.match_dict import MatchDict
from ._match.matchable import Matchable
from ._match.patterns.basic_patterns import Pattern
from ._match.patterns.bind import Bind
from ._match.patterns.mapping_match import AttrPattern
from ._match.patterns.mapping_match import DictPattern

# In lower-case for aesthetics.
pat = _attribute_constructor.AttributeConstructor(  # pylint: disable=invalid-name
    Pattern
)


@typing.overload
def function(func: typing.Callable) -> function_.Function:
    """Normal functions and methods go to Functions"""


@typing.overload
def function(func: staticmethod) -> function_.StaticMethod:
    """Static methods go to StaticMethods"""


@typing.overload
def function(func: classmethod) -> function_.ClassMethod:
    """Class methods go to ClassMethods."""


@typing.overload
def function(func: property) -> property_.Property:
    """And properties go to Properties."""


[docs]def function(func: typing.Any) -> common.Descriptor: """Convert a function to dispatch by value. The original function is not called when the dispatch function is invoked. """ if isinstance(func, staticmethod): return function_.StaticMethod(func.__func__) if isinstance(func, classmethod): return function_.ClassMethod(func.__func__) if isinstance(func, property): return property_.Property(func.fget, func.fset, func.fdel, func.__doc__) return function_.Function(func)
Deco = typing.Callable[[typing.Callable], typing.Callable]
[docs]def decorate_in_order(*args: Deco) -> Deco: """Apply decorators in the order they're passed to the function.""" def decorator(func: typing.Callable) -> typing.Callable: for arg in args: func = arg(func) return func return decorator
__all__ = [ "AttrPattern", "Bind", "DictPattern", "MatchDict", "Matchable", "Pattern", "Placeholder", "decorate_in_order", "function", "names", "pat", ]