def sets(verb, typ, ctx):
    """
    A rule to represent sets. Will only use specialized Dynamo sets, to abide by principle
    of least astonishment.

    Valid python types include Set[Decimal], Set[str], Set[bytes], or FrozenSet for any of
    these. Also, any number that converts from Decimal and converts to a decimal if str is
    called should work.
    """
    if not has_origin(typ, (set, frozenset), num_args=1):
        return
    (inner,) = typ.__args__
    con = get_origin(typ)
    if inner == bytes:
        if verb == DDB2PY:
            return partial(decode_binary_set, con=con)
        elif verb == PY2DDB:
            return encode_binary_set

    if inner != bool and issub_safe(inner, (Decimal, Real)):
        if verb == DDB2PY:
            return partial(decode_number_set, elem=inner, con=con)
        elif verb == PY2DDB:
            return encode_number_set

    if inner == str:
        if verb == DDB2PY:
            return partial(decode_string_set, con=con)
        elif verb == PY2DDB:
            return encode_string_set
def dicts(verb, typ, ctx):
    """
    A rule to represent lists as Dynamo list values.
    """
    if verb not in _STRING_ACTIONS or not has_origin(typ, dict, num_args=2):
        return
    (key_typ, val_typ) = typ.__args__
    inner_key = ctx.lookup(verb=_STRING_ACTIONS[verb], typ=key_typ)
    inner_val = ctx.lookup(verb=verb, typ=val_typ)
    if verb == DDB2PY:
        return partial(
            decode_dict, inner_key=inner_key, inner_val=inner_val, con=get_origin(typ)
        )
    elif verb == PY2DDB:
        return partial(encode_dict, inner_key=inner_key, inner_val=inner_val)
def lists(verb, typ, ctx):
    """
    A rule to represent lists as Dynamo list values.
    """
    if has_origin(typ, list, num_args=1):
        (inner,) = typ.__args__
    elif has_origin(typ, tuple, num_args=2):
        (inner, ell) = typ.__args__
        if ell is not Ellipsis:
            return
    else:
        return
    inner = ctx.lookup(verb=verb, typ=inner)
    if verb == DDB2PY:
        return partial(decode_list, inner=inner, typ=get_origin(typ))
    elif verb == PY2DDB:
        return partial(encode_list, inner=inner)