# Path: ronin/utils/unicode.py

# 
# Path: ronin/contexts.py
# def current_context(immutable=True):
#     """
#     Returns the current context if there is one, otherwise raises :class:`NoContextException`.
#     
#     By default, the context will be treated as immutable.
#     
#     :param immutable: set to False in order to allow changes to the context
#     :type immutable: bool
#     :returns: current context
#     :rtype: :class:`Context`
#     """
# 
#     ctx = Context._peek_thread_local()
#     if ctx is None:
#         raise NoContextException()
#     return Context(ctx, True) if immutable else ctx


from .unicode import to_str
from ..contexts import current_context
import re

UNESCAPED_STRING_RE = re.compile(r'(?<!\\) ')


def stringify(value):
    """
    Casts the value to a Unicode string. If the value is a function, calls it using
    :func:`ronin.contexts.current_context` as its only argument, and recurses until a
    non-FunctionType value is returned.
    
    None values are preserved, whether None is directly sent to this function or is the return
    value of function argument.
    
    This function is the heart of Rōnin's deferred value capability, as it allows lambdas to be
    passed around instead of strings.
    
    :param value: value or None
    :type value: str|FunctionType
    :returns: stringified value or None
    :rtype: str
    """
    
    if value is None:
        return None
    elif hasattr(value, '__call__'):
        with current_context() as ctx:
            value = value(ctx)
        return stringify(value)
    else:
        try:

# Path: ronin/utils/unicode.py

# 
# Path: ronin/contexts.py
# def current_context(immutable=True):
#     """
#     Returns the current context if there is one, otherwise raises :class:`NoContextException`.
#     
#     By default, the context will be treated as immutable.
#     
#     :param immutable: set to False in order to allow changes to the context
#     :type immutable: bool
#     :returns: current context
#     :rtype: :class:`Context`
#     """
# 
#     ctx = Context._peek_thread_local()
#     if ctx is None:
#         raise NoContextException()
#     return Context(ctx, True) if immutable else ctx


# Path: ronin/utils/strings.py
from .unicode import to_str
from ..contexts import current_context
import re


UNESCAPED_STRING_RE = re.compile(r'(?<!\\) ')


def stringify(value):
    """
    Casts the value to a Unicode string. If the value is a function, calls it using
    :func:`ronin.contexts.current_context` as its only argument, and recurses until a
    non-FunctionType value is returned.
    
    None values are preserved, whether None is directly sent to this function or is the return
    value of function argument.
    
    This function is the heart of Rōnin's deferred value capability, as it allows lambdas to be
    passed around instead of strings.
    
    :param value: value or None
    :type value: str|FunctionType
    :returns: stringified value or None
    :rtype: str
    """
    
    if value is None:
        return None
    elif hasattr(value, '__call__'):
        with current_context() as ctx:
            value = value(ctx)
        return stringify(value)
    else:
        try:

            return to_str(value)