My first custom Django template filter   :)

This is getting fun.

from  django import template
from  django.conf import settings

register = template.Library()

@register.filter(is_safe=True)
def multival_to_str(value, arg):
    """
        Given multiple values in "find-what" and "replace-with" lists,
        returns a replacement string from the "replace-with" list that
        has the same index as its corresponding "find-what" element.

        RETURNS
            multival_to_str_base(value, arg)
    """
    #test_multival_to_str_base()
    return  multival_to_str_base(value, arg)

def _get_value_or_crash_for_error(value, bad_args):
    if(settings.DEBUG):
        raise  ValueError("Attempting multival_to_str_base: value=\"" + str(value) + "\", args=\"" + str(bad_args) + "\"")
    else:
        return  value

def multival_to_str_base(value, arg, item_sep=',', list_sep="->", do_ignore_case=False):
    """
        Given multiple values in "find-what" and "replace-with" lists,
        returns a replacement string from the "replace-with" list that
        has the same index as its corresponding "find-what" element.

        arg
            Contains both lists, which must separated by `list_sep` and
            elements within each list must be separated by `item_sep`.
            Each element *should* be unique and at least one character
            in length.

            The replace-with list must either be exactly the same length
            or exactly one greater than the find-what list. If equal in
            length and the `value` is *not in the find-what list*, the
            value itself is returned. However, when the replace-with
            list is one greater, then the final item is returned as the
            "default value".

            It is expected but not verified, that each replace-with
            element contains only HTML-safe content.

            If arg is improperly formatted and DEBUG in settings.py is

                - `True`: This raises a ValueError
                - `False`: `value` is returned.

        item_sep
            The separator required between each element in each list.
            *should* be exactly one character in length.
        list_sep
            The separator that required between the what and with lists.
            *should* not contain item_sep, or be less than one character
            in length.
        do_ignore_case
            If `True`, then case is ignored. If `False`, case is
            required.

        EXAMPLE USAGE
            `<P><IMG SRC="/static/images/{{ album.officiality|multival_to_str:"J,I,U->major,minor,unofficial,broken_image"}}.jpg" height="20"/></P>`

        RETURNS
            Example with default params                       RETURNS
            ------------------------------------------------------------
            B|multival_to_str:A,B,C->one,two,three            two
            D|multival_to_str:A,B,C->one,two,three            D
            D|multival_to_str:A,B,C->one,two,three,four       four

    """
    if(arg is None):
        return  _get_value_or_crash_for_error(value, arg)
    bits = arg.split(list_sep)
    if(len(bits) != 2):
        return  _get_value_or_crash_for_error(value, arg)

    find_whats = bits[0].split(item_sep)
    rplc_withs = bits[1].split(item_sep)

    what_len = len(find_whats)
    with_len = len(rplc_withs)               #max eclusive
    if(what_len not in range((with_len - 1), (with_len + 1))):
        return  _get_value_or_crash_for_error(value, arg)

    if(value not in find_whats):
        if(with_len == what_len):
            return  _get_value_or_crash_for_error(value, arg)

        #what_len is one greater than with_len
        return  rplc_withs[-1]

    #value is in find_whats
    return  rplc_withs[find_whats.index(value)]


def test_multival_to_str_base():
    crash_if_test_fails("two", multival_to_str_base("B", "A,B,C->one,two,three"))
    crash_if_test_fails("D", multival_to_str_base("D", "A,B,C->one,two,three"))
    crash_if_test_fails("four", multival_to_str_base("D", "A,B,C->one,two,three,four"))

def crash_if_test_fails(expected, actual):
    if(expected != actual):
        print("FAILURE: expected=" + str(expected) + ", actual=" + str(actual))
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s