"""Tools for extracting emoticon data."""

from __future__ import division
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import re


EMOTICON_REGEX = re.compile(
    r'\((\w{1,15})\)',
    re.UNICODE | re.IGNORECASE | re.MULTILINE,
)

MAX_EMOTICON_LENGTH = 15


def emoticons_regex(text):
    """Generate an iterable of (emoticons) from a given text body.

    This implementation uses regular expressions to select emoticon text from
    the source. If valid emoticons cannot contain parenthesis characters then
    this implementation cannot be used as the recursive (emoti(con)) would have
    the (con) portion returned as an emoticon.

    Args:
        text (str): The body text of a chat message.

    Returns:
        iter of str: An iterable of strings that represent the emoticons used
            within the body text.
    """
    for match in EMOTICON_REGEX.findall(text):

        yield match


def emoticons(text, max_length=MAX_EMOTICON_LENGTH):
    """Generate an iterable of emoticons from a given text body.

    This implementation bypasses the use of regex in order to filter out
    invalid emoticons containing nested parenthesis characters. This method
    will read a top level emoticon (emoti(con)) until the final enclosing
    parenthesis is read. If the resulting capture contains any nested
    parenthesis characters the result is discarded.

    Args:
        text (str): The body text of a chat message.
        max_length (int): The maximum string length of a valid emoticon.

    Returns:
        iter of str: An iterable of strings that represent the emoticons used
            within the body text.
    """
    emoticon = []
    level = 0
    for letter in text:

        if letter == '(':

            level += 1

        if letter == ')':

            level -= 1

        if level > 0:

            emoticon.append(letter)

        if level < 1 and emoticon:

            result = ''.join(emoticon)[1:]
            emoticon = []
            if '(' in result or ')' in result:

                continue

            if not result or len(result) > max_length:

                continue

            yield result

@@ -198,16 +198,41 @@
 rt re%0A%0A%0A
+MAX_EMOTICON_LENGTH = 15%0A
 EMOTICON
@@ -268,17 +268,48 @@
 (%5Cw%7B
+%7B
 1,
-15
+%7B0%7D%7D
 %7D)%5C)'
+.format(MAX_EMOTICON_LENGTH)
 ,%0A  
@@ -357,37 +357,11 @@
 NE,%0A
+
 )%0A%0A
-MAX_EMOTICON_LENGTH = 15%0A%0A
 %0Adef

Add configurable max length to emoticon regex