from __future__ import with_statement

import logging
import sys

from django.conf import settings
from django.template import Context
from django.template.loader import get_template
from django.utils.html import conditional_escape
from django.utils.functional import memoize
from django.utils.encoding import force_text

from .base import KeepContext
from .compatibility import text_type, PY2

# Global field template, default template used for rendering a field.

TEMPLATE_PACK = getattr(settings, 'CRISPY_TEMPLATE_PACK', 'bootstrap')
FAIL_SILENTLY = getattr(settings, 'CRISPY_FAIL_SILENTLY', True)


class UnresolvedError(Exception):
    pass


# By memoizeing we avoid loading the template every time render_field
# is called without a template
def default_field_template(template_pack=TEMPLATE_PACK):
    return get_template("%s/field.html" % template_pack)
default_field_template = memoize(default_field_template, {}, 1)


def flatten_list(tuples):
    return list(t for f in tuples for t in (f if isinstance(f, (list, tuple)) else (f,)))


def resolve_value(context, lookup, silent=True):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError

        obj = context
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'

            if callable(obj):
                obj = obj()

            if obj is None:
                raise UnresolvedError

            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                obj = obj[name]

            except (TypeError, KeyError, IndexError):
                try:
                    obj = getattr(obj, name)
                except AttributeError:
                    raise UnresolvedError

        def _resolve_value(value):
            if isinstance(value, dict):
                return dict((rk, rv) for rk, rv in ((k, _resolve_value(v)) for k, v in value.items() if k[0] != '_') if rv)

            if isinstance(value, (tuple, list)):
                return [rv for rv in (_resolve_value(v) for v in value) if rv]

            return value

        return _resolve_value(obj)

    except UnresolvedError:
        if not silent:
            if not FAIL_SILENTLY:
                raise Exception("Could not resolve value for '%s'." % lookup)
            else:
                logging.warning("Could not resolve value for '%s'." % lookup, exc_info=sys.exc_info())


def get_bound_field(context, obj, lookup):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError

        bound_field = None
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'

            if callable(obj):
                obj = obj()

            if obj is None:
                raise UnresolvedError

            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                bound_field = obj[name]
                if hasattr(bound_field.field, 'form'):
                    obj = bound_field.field.widget

            except (TypeError, KeyError, IndexError):
                if i != 0:
                    raise UnresolvedError
                # Fallback to find main object in the context:
                if context is None:
                    raise Exception("context should be given for fields with absolute names")
                obj = context[name]

        if bound_field is None:
            raise UnresolvedError

        return bound_field

    except UnresolvedError:
        if not FAIL_SILENTLY:
            raise Exception("Could not resolve form field '%s'." % lookup)
        else:
            logging.warning("Could not resolve form field '%s'." % lookup, exc_info=sys.exc_info())


def render_field(field, form, form_style, context, template=None, labelclass=None, show_labels=None, layout_object=None, attrs=None, template_pack=TEMPLATE_PACK):
    """
    Renders a django-crispy-forms field

    :param field: Can be a string or a Layout object like `Row`. If it's a layout
        object, we call its render method, otherwise we instantiate a BoundField
        and render it using default template 'CRISPY_TEMPLATE_PACK/field.html'
        The field is added to a list that the form holds called `rendered_fields`
        to avoid double rendering fields.

    :param form: The form/formset to which that field belongs to.

    :param form_style: A way to pass style name to the CSS framework used.

    :template: Template used for rendering the field.

    :layout_object: If passed, it points to the Layout object that is being rendered.
        We use it to store its bound fields in a list called `layout_object.bound_fields`

    :attrs: Attributes for the field's widget
    """
    if field is None:
        return ''
    with KeepContext(context):
        if hasattr(field, 'render'):
            return force_text(field.render(form, form_style, context, template_pack=template_pack))
        else:
            # In Python 2 form field names cannot contain unicode characters without ASCII mapping
            if PY2:
                # This allows fields to be unicode strings, always they don't use non ASCII
                try:
                    if isinstance(field, text_type):
                        field = field.encode('ascii').decode()
                    # If `field` is not unicode then we turn it into a unicode string, otherwise doing
                    # str(field) would give no error and the field would not be resolved, causing confusion
                    else:
                        field = text_type(field)

                except (UnicodeEncodeError, UnicodeDecodeError):
                    raise Exception("Field '%s' is using forbidden unicode characters" % field)

        # Injecting HTML attributes into field's widget, Django handles rendering these
        bound_field = get_bound_field(context, form, field)
        if not bound_field:
            return ''
        field_instance = bound_field.field
        if attrs is not None:
            widgets = getattr(field_instance.widget, 'widgets', [field_instance.widget])

            # We use attrs as a dictionary later, so here we make a copy
            list_attrs = attrs
            if isinstance(attrs, dict):
                list_attrs = [attrs] * len(widgets)

            for index, (widget, attr) in enumerate(zip(widgets, list_attrs)):
                if hasattr(field_instance.widget, 'widgets'):
                    if 'type' in attr and attr['type'] == "hidden":
                        field_instance.widget.widgets[index].is_hidden = True
                        field_instance.widget.widgets[index] = field_instance.hidden_widget()

                    field_instance.widget.widgets[index].attrs.update(attr)
                else:
                    if 'type' in attr and attr['type'] == "hidden":
                        field_instance.widget.is_hidden = True
                        field_instance.widget = field_instance.hidden_widget()

                    field_instance.widget.attrs.update(attr)

        if hasattr(form, 'rendered_fields'):
            if field not in form.rendered_fields:
                form.rendered_fields.add(field)
            else:
                if not FAIL_SILENTLY:
                    raise Exception("A field should only be rendered once: %s" % field)
                else:
                    logging.warning("A field should only be rendered once: %s" % field, exc_info=sys.exc_info())

        if field_instance is None:
            html = ''
        else:
            if template is None:
                if form.crispy_field_template is None:
                    template = default_field_template(template_pack)
                else:   # FormHelper.field_template set
                    template = get_template(form.crispy_field_template)
            else:
                template = get_template(template)

            # We save the Layout object's bound fields in the layout object's `bound_fields` list
            if layout_object is not None:
                if hasattr(layout_object, 'bound_fields') and isinstance(layout_object.bound_fields, list):
                    layout_object.bound_fields.append(bound_field)
                else:
                    layout_object.bound_fields = [bound_field]

            context.update({
                'field': bound_field,
                'labelclass': labelclass,
                'flat_attrs': flatatt(attrs if isinstance(attrs, dict) else {}),
            })
            if show_labels is not None:
                context['form_show_labels'] = show_labels
            html = template.render(context)

        return force_text(html)


def flatatt(attrs):
    """
    Taken from django.core.utils
    Convert a dictionary of attributes to a single string.
    The returned string will contain a leading space followed by key="value",
    XML-style pairs.  It is assumed that the keys do not need to be XML-escaped.
    If the passed dictionary is empty, then return an empty string.
    """
    return u''.join([u' %s="%s"' % (k.replace('_', '-'), conditional_escape(v)) for k, v in attrs.items()])


def render_crispy_form(form, helper=None, context=None):
    """
    Renders a form and returns its HTML output.

    This function wraps the template logic in a function easy to use in a Django view.
    """
    from crispy_forms.templatetags.crispy_forms_tags import CrispyFormNode

    if helper is not None:
        node = CrispyFormNode('form', 'helper')
    else:
        node = CrispyFormNode('form', None)

    node_context = Context(context)
    node_context.update({
        'form': form,
        'helper': helper
    })

    return node.render(node_context)

dd7296abda7e78133015f1d4aa1ce55f8118b29b
<mask token>


class UnresolvedError(Exception):
    pass


def default_field_template(template_pack=TEMPLATE_PACK):
    return get_template('%s/field.html' % template_pack)


<mask token>


def flatten_list(tuples):
    return list(t for f in tuples for t in (f if isinstance(f, (list, tuple
        )) else (f,)))


def resolve_value(context, lookup, silent=True):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        obj = context
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                obj = obj[name]
            except (TypeError, KeyError, IndexError):
                try:
                    obj = getattr(obj, name)
                except AttributeError:
                    raise UnresolvedError

        def _resolve_value(value):
            if isinstance(value, dict):
                return dict((rk, rv) for rk, rv in ((k, _resolve_value(v)) for
                    k, v in value.items() if k[0] != '_') if rv)
            if isinstance(value, (tuple, list)):
                return [rv for rv in (_resolve_value(v) for v in value) if rv]
            return value
        return _resolve_value(obj)
    except UnresolvedError:
        if not silent:
            if not FAIL_SILENTLY:
                raise Exception("Could not resolve value for '%s'." % lookup)
            else:
                logging.warning("Could not resolve value for '%s'." %
                    lookup, exc_info=sys.exc_info())


def get_bound_field(context, obj, lookup):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        bound_field = None
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                bound_field = obj[name]
                if hasattr(bound_field.field, 'form'):
                    obj = bound_field.field.widget
            except (TypeError, KeyError, IndexError):
                if i != 0:
                    raise UnresolvedError
                if context is None:
                    raise Exception(
                        'context should be given for fields with absolute names'
                        )
                obj = context[name]
        if bound_field is None:
            raise UnresolvedError
        return bound_field
    except UnresolvedError:
        if not FAIL_SILENTLY:
            raise Exception("Could not resolve form field '%s'." % lookup)
        else:
            logging.warning("Could not resolve form field '%s'." % lookup,
                exc_info=sys.exc_info())


<mask token>


def flatatt(attrs):
    """
    Taken from django.core.utils
    Convert a dictionary of attributes to a single string.
    The returned string will contain a leading space followed by key="value",
    XML-style pairs.  It is assumed that the keys do not need to be XML-escaped.
    If the passed dictionary is empty, then return an empty string.
    """
    return u''.join([(u' %s="%s"' % (k.replace('_', '-'),
        conditional_escape(v))) for k, v in attrs.items()])


def render_crispy_form(form, helper=None, context=None):
    """
    Renders a form and returns its HTML output.

    This function wraps the template logic in a function easy to use in a Django view.
    """
    from crispy_forms.templatetags.crispy_forms_tags import CrispyFormNode
    if helper is not None:
        node = CrispyFormNode('form', 'helper')
    else:
        node = CrispyFormNode('form', None)
    node_context = Context(context)
    node_context.update({'form': form, 'helper': helper})
    return node.render(node_context)

<mask token>


class UnresolvedError(Exception):
    pass


def default_field_template(template_pack=TEMPLATE_PACK):
    return get_template('%s/field.html' % template_pack)


<mask token>


def flatten_list(tuples):
    return list(t for f in tuples for t in (f if isinstance(f, (list, tuple
        )) else (f,)))


def resolve_value(context, lookup, silent=True):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        obj = context
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                obj = obj[name]
            except (TypeError, KeyError, IndexError):
                try:
                    obj = getattr(obj, name)
                except AttributeError:
                    raise UnresolvedError

        def _resolve_value(value):
            if isinstance(value, dict):
                return dict((rk, rv) for rk, rv in ((k, _resolve_value(v)) for
                    k, v in value.items() if k[0] != '_') if rv)
            if isinstance(value, (tuple, list)):
                return [rv for rv in (_resolve_value(v) for v in value) if rv]
            return value
        return _resolve_value(obj)
    except UnresolvedError:
        if not silent:
            if not FAIL_SILENTLY:
                raise Exception("Could not resolve value for '%s'." % lookup)
            else:
                logging.warning("Could not resolve value for '%s'." %
                    lookup, exc_info=sys.exc_info())


def get_bound_field(context, obj, lookup):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        bound_field = None
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                bound_field = obj[name]
                if hasattr(bound_field.field, 'form'):
                    obj = bound_field.field.widget
            except (TypeError, KeyError, IndexError):
                if i != 0:
                    raise UnresolvedError
                if context is None:
                    raise Exception(
                        'context should be given for fields with absolute names'
                        )
                obj = context[name]
        if bound_field is None:
            raise UnresolvedError
        return bound_field
    except UnresolvedError:
        if not FAIL_SILENTLY:
            raise Exception("Could not resolve form field '%s'." % lookup)
        else:
            logging.warning("Could not resolve form field '%s'." % lookup,
                exc_info=sys.exc_info())


def render_field(field, form, form_style, context, template=None,
    labelclass=None, show_labels=None, layout_object=None, attrs=None,
    template_pack=TEMPLATE_PACK):
    """
    Renders a django-crispy-forms field

    :param field: Can be a string or a Layout object like `Row`. If it's a layout
        object, we call its render method, otherwise we instantiate a BoundField
        and render it using default template 'CRISPY_TEMPLATE_PACK/field.html'
        The field is added to a list that the form holds called `rendered_fields`
        to avoid double rendering fields.

    :param form: The form/formset to which that field belongs to.

    :param form_style: A way to pass style name to the CSS framework used.

    :template: Template used for rendering the field.

    :layout_object: If passed, it points to the Layout object that is being rendered.
        We use it to store its bound fields in a list called `layout_object.bound_fields`

    :attrs: Attributes for the field's widget
    """
    if field is None:
        return ''
    with KeepContext(context):
        if hasattr(field, 'render'):
            return force_text(field.render(form, form_style, context,
                template_pack=template_pack))
        elif PY2:
            try:
                if isinstance(field, text_type):
                    field = field.encode('ascii').decode()
                else:
                    field = text_type(field)
            except (UnicodeEncodeError, UnicodeDecodeError):
                raise Exception(
                    "Field '%s' is using forbidden unicode characters" % field)
        bound_field = get_bound_field(context, form, field)
        if not bound_field:
            return ''
        field_instance = bound_field.field
        if attrs is not None:
            widgets = getattr(field_instance.widget, 'widgets', [
                field_instance.widget])
            list_attrs = attrs
            if isinstance(attrs, dict):
                list_attrs = [attrs] * len(widgets)
            for index, (widget, attr) in enumerate(zip(widgets, list_attrs)):
                if hasattr(field_instance.widget, 'widgets'):
                    if 'type' in attr and attr['type'] == 'hidden':
                        field_instance.widget.widgets[index].is_hidden = True
                        field_instance.widget.widgets[index
                            ] = field_instance.hidden_widget()
                    field_instance.widget.widgets[index].attrs.update(attr)
                else:
                    if 'type' in attr and attr['type'] == 'hidden':
                        field_instance.widget.is_hidden = True
                        field_instance.widget = field_instance.hidden_widget()
                    field_instance.widget.attrs.update(attr)
        if hasattr(form, 'rendered_fields'):
            if field not in form.rendered_fields:
                form.rendered_fields.add(field)
            elif not FAIL_SILENTLY:
                raise Exception('A field should only be rendered once: %s' %
                    field)
            else:
                logging.warning('A field should only be rendered once: %s' %
                    field, exc_info=sys.exc_info())
        if field_instance is None:
            html = ''
        else:
            if template is None:
                if form.crispy_field_template is None:
                    template = default_field_template(template_pack)
                else:
                    template = get_template(form.crispy_field_template)
            else:
                template = get_template(template)
            if layout_object is not None:
                if hasattr(layout_object, 'bound_fields') and isinstance(
                    layout_object.bound_fields, list):
                    layout_object.bound_fields.append(bound_field)
                else:
                    layout_object.bound_fields = [bound_field]
            context.update({'field': bound_field, 'labelclass': labelclass,
                'flat_attrs': flatatt(attrs if isinstance(attrs, dict) else
                {})})
            if show_labels is not None:
                context['form_show_labels'] = show_labels
            html = template.render(context)
        return force_text(html)


def flatatt(attrs):
    """
    Taken from django.core.utils
    Convert a dictionary of attributes to a single string.
    The returned string will contain a leading space followed by key="value",
    XML-style pairs.  It is assumed that the keys do not need to be XML-escaped.
    If the passed dictionary is empty, then return an empty string.
    """
    return u''.join([(u' %s="%s"' % (k.replace('_', '-'),
        conditional_escape(v))) for k, v in attrs.items()])


def render_crispy_form(form, helper=None, context=None):
    """
    Renders a form and returns its HTML output.

    This function wraps the template logic in a function easy to use in a Django view.
    """
    from crispy_forms.templatetags.crispy_forms_tags import CrispyFormNode
    if helper is not None:
        node = CrispyFormNode('form', 'helper')
    else:
        node = CrispyFormNode('form', None)
    node_context = Context(context)
    node_context.update({'form': form, 'helper': helper})
    return node.render(node_context)

<mask token>
TEMPLATE_PACK = getattr(settings, 'CRISPY_TEMPLATE_PACK', 'bootstrap')
FAIL_SILENTLY = getattr(settings, 'CRISPY_FAIL_SILENTLY', True)


class UnresolvedError(Exception):
    pass


def default_field_template(template_pack=TEMPLATE_PACK):
    return get_template('%s/field.html' % template_pack)


default_field_template = memoize(default_field_template, {}, 1)


def flatten_list(tuples):
    return list(t for f in tuples for t in (f if isinstance(f, (list, tuple
        )) else (f,)))


def resolve_value(context, lookup, silent=True):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        obj = context
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                obj = obj[name]
            except (TypeError, KeyError, IndexError):
                try:
                    obj = getattr(obj, name)
                except AttributeError:
                    raise UnresolvedError

        def _resolve_value(value):
            if isinstance(value, dict):
                return dict((rk, rv) for rk, rv in ((k, _resolve_value(v)) for
                    k, v in value.items() if k[0] != '_') if rv)
            if isinstance(value, (tuple, list)):
                return [rv for rv in (_resolve_value(v) for v in value) if rv]
            return value
        return _resolve_value(obj)
    except UnresolvedError:
        if not silent:
            if not FAIL_SILENTLY:
                raise Exception("Could not resolve value for '%s'." % lookup)
            else:
                logging.warning("Could not resolve value for '%s'." %
                    lookup, exc_info=sys.exc_info())


def get_bound_field(context, obj, lookup):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        bound_field = None
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                bound_field = obj[name]
                if hasattr(bound_field.field, 'form'):
                    obj = bound_field.field.widget
            except (TypeError, KeyError, IndexError):
                if i != 0:
                    raise UnresolvedError
                if context is None:
                    raise Exception(
                        'context should be given for fields with absolute names'
                        )
                obj = context[name]
        if bound_field is None:
            raise UnresolvedError
        return bound_field
    except UnresolvedError:
        if not FAIL_SILENTLY:
            raise Exception("Could not resolve form field '%s'." % lookup)
        else:
            logging.warning("Could not resolve form field '%s'." % lookup,
                exc_info=sys.exc_info())


def render_field(field, form, form_style, context, template=None,
    labelclass=None, show_labels=None, layout_object=None, attrs=None,
    template_pack=TEMPLATE_PACK):
    """
    Renders a django-crispy-forms field

    :param field: Can be a string or a Layout object like `Row`. If it's a layout
        object, we call its render method, otherwise we instantiate a BoundField
        and render it using default template 'CRISPY_TEMPLATE_PACK/field.html'
        The field is added to a list that the form holds called `rendered_fields`
        to avoid double rendering fields.

    :param form: The form/formset to which that field belongs to.

    :param form_style: A way to pass style name to the CSS framework used.

    :template: Template used for rendering the field.

    :layout_object: If passed, it points to the Layout object that is being rendered.
        We use it to store its bound fields in a list called `layout_object.bound_fields`

    :attrs: Attributes for the field's widget
    """
    if field is None:
        return ''
    with KeepContext(context):
        if hasattr(field, 'render'):
            return force_text(field.render(form, form_style, context,
                template_pack=template_pack))
        elif PY2:
            try:
                if isinstance(field, text_type):
                    field = field.encode('ascii').decode()
                else:
                    field = text_type(field)
            except (UnicodeEncodeError, UnicodeDecodeError):
                raise Exception(
                    "Field '%s' is using forbidden unicode characters" % field)
        bound_field = get_bound_field(context, form, field)
        if not bound_field:
            return ''
        field_instance = bound_field.field
        if attrs is not None:
            widgets = getattr(field_instance.widget, 'widgets', [
                field_instance.widget])
            list_attrs = attrs
            if isinstance(attrs, dict):
                list_attrs = [attrs] * len(widgets)
            for index, (widget, attr) in enumerate(zip(widgets, list_attrs)):
                if hasattr(field_instance.widget, 'widgets'):
                    if 'type' in attr and attr['type'] == 'hidden':
                        field_instance.widget.widgets[index].is_hidden = True
                        field_instance.widget.widgets[index
                            ] = field_instance.hidden_widget()
                    field_instance.widget.widgets[index].attrs.update(attr)
                else:
                    if 'type' in attr and attr['type'] == 'hidden':
                        field_instance.widget.is_hidden = True
                        field_instance.widget = field_instance.hidden_widget()
                    field_instance.widget.attrs.update(attr)
        if hasattr(form, 'rendered_fields'):
            if field not in form.rendered_fields:
                form.rendered_fields.add(field)
            elif not FAIL_SILENTLY:
                raise Exception('A field should only be rendered once: %s' %
                    field)
            else:
                logging.warning('A field should only be rendered once: %s' %
                    field, exc_info=sys.exc_info())
        if field_instance is None:
            html = ''
        else:
            if template is None:
                if form.crispy_field_template is None:
                    template = default_field_template(template_pack)
                else:
                    template = get_template(form.crispy_field_template)
            else:
                template = get_template(template)
            if layout_object is not None:
                if hasattr(layout_object, 'bound_fields') and isinstance(
                    layout_object.bound_fields, list):
                    layout_object.bound_fields.append(bound_field)
                else:
                    layout_object.bound_fields = [bound_field]
            context.update({'field': bound_field, 'labelclass': labelclass,
                'flat_attrs': flatatt(attrs if isinstance(attrs, dict) else
                {})})
            if show_labels is not None:
                context['form_show_labels'] = show_labels
            html = template.render(context)
        return force_text(html)


def flatatt(attrs):
    """
    Taken from django.core.utils
    Convert a dictionary of attributes to a single string.
    The returned string will contain a leading space followed by key="value",
    XML-style pairs.  It is assumed that the keys do not need to be XML-escaped.
    If the passed dictionary is empty, then return an empty string.
    """
    return u''.join([(u' %s="%s"' % (k.replace('_', '-'),
        conditional_escape(v))) for k, v in attrs.items()])


def render_crispy_form(form, helper=None, context=None):
    """
    Renders a form and returns its HTML output.

    This function wraps the template logic in a function easy to use in a Django view.
    """
    from crispy_forms.templatetags.crispy_forms_tags import CrispyFormNode
    if helper is not None:
        node = CrispyFormNode('form', 'helper')
    else:
        node = CrispyFormNode('form', None)
    node_context = Context(context)
    node_context.update({'form': form, 'helper': helper})
    return node.render(node_context)

from __future__ import with_statement
import logging
import sys
from django.conf import settings
from django.template import Context
from django.template.loader import get_template
from django.utils.html import conditional_escape
from django.utils.functional import memoize
from django.utils.encoding import force_text
from .base import KeepContext
from .compatibility import text_type, PY2
TEMPLATE_PACK = getattr(settings, 'CRISPY_TEMPLATE_PACK', 'bootstrap')
FAIL_SILENTLY = getattr(settings, 'CRISPY_FAIL_SILENTLY', True)


class UnresolvedError(Exception):
    pass


def default_field_template(template_pack=TEMPLATE_PACK):
    return get_template('%s/field.html' % template_pack)


default_field_template = memoize(default_field_template, {}, 1)


def flatten_list(tuples):
    return list(t for f in tuples for t in (f if isinstance(f, (list, tuple
        )) else (f,)))


def resolve_value(context, lookup, silent=True):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        obj = context
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                obj = obj[name]
            except (TypeError, KeyError, IndexError):
                try:
                    obj = getattr(obj, name)
                except AttributeError:
                    raise UnresolvedError

        def _resolve_value(value):
            if isinstance(value, dict):
                return dict((rk, rv) for rk, rv in ((k, _resolve_value(v)) for
                    k, v in value.items() if k[0] != '_') if rv)
            if isinstance(value, (tuple, list)):
                return [rv for rv in (_resolve_value(v) for v in value) if rv]
            return value
        return _resolve_value(obj)
    except UnresolvedError:
        if not silent:
            if not FAIL_SILENTLY:
                raise Exception("Could not resolve value for '%s'." % lookup)
            else:
                logging.warning("Could not resolve value for '%s'." %
                    lookup, exc_info=sys.exc_info())


def get_bound_field(context, obj, lookup):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError
        bound_field = None
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'
            if callable(obj):
                obj = obj()
            if obj is None:
                raise UnresolvedError
            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                bound_field = obj[name]
                if hasattr(bound_field.field, 'form'):
                    obj = bound_field.field.widget
            except (TypeError, KeyError, IndexError):
                if i != 0:
                    raise UnresolvedError
                if context is None:
                    raise Exception(
                        'context should be given for fields with absolute names'
                        )
                obj = context[name]
        if bound_field is None:
            raise UnresolvedError
        return bound_field
    except UnresolvedError:
        if not FAIL_SILENTLY:
            raise Exception("Could not resolve form field '%s'." % lookup)
        else:
            logging.warning("Could not resolve form field '%s'." % lookup,
                exc_info=sys.exc_info())


def render_field(field, form, form_style, context, template=None,
    labelclass=None, show_labels=None, layout_object=None, attrs=None,
    template_pack=TEMPLATE_PACK):
    """
    Renders a django-crispy-forms field

    :param field: Can be a string or a Layout object like `Row`. If it's a layout
        object, we call its render method, otherwise we instantiate a BoundField
        and render it using default template 'CRISPY_TEMPLATE_PACK/field.html'
        The field is added to a list that the form holds called `rendered_fields`
        to avoid double rendering fields.

    :param form: The form/formset to which that field belongs to.

    :param form_style: A way to pass style name to the CSS framework used.

    :template: Template used for rendering the field.

    :layout_object: If passed, it points to the Layout object that is being rendered.
        We use it to store its bound fields in a list called `layout_object.bound_fields`

    :attrs: Attributes for the field's widget
    """
    if field is None:
        return ''
    with KeepContext(context):
        if hasattr(field, 'render'):
            return force_text(field.render(form, form_style, context,
                template_pack=template_pack))
        elif PY2:
            try:
                if isinstance(field, text_type):
                    field = field.encode('ascii').decode()
                else:
                    field = text_type(field)
            except (UnicodeEncodeError, UnicodeDecodeError):
                raise Exception(
                    "Field '%s' is using forbidden unicode characters" % field)
        bound_field = get_bound_field(context, form, field)
        if not bound_field:
            return ''
        field_instance = bound_field.field
        if attrs is not None:
            widgets = getattr(field_instance.widget, 'widgets', [
                field_instance.widget])
            list_attrs = attrs
            if isinstance(attrs, dict):
                list_attrs = [attrs] * len(widgets)
            for index, (widget, attr) in enumerate(zip(widgets, list_attrs)):
                if hasattr(field_instance.widget, 'widgets'):
                    if 'type' in attr and attr['type'] == 'hidden':
                        field_instance.widget.widgets[index].is_hidden = True
                        field_instance.widget.widgets[index
                            ] = field_instance.hidden_widget()
                    field_instance.widget.widgets[index].attrs.update(attr)
                else:
                    if 'type' in attr and attr['type'] == 'hidden':
                        field_instance.widget.is_hidden = True
                        field_instance.widget = field_instance.hidden_widget()
                    field_instance.widget.attrs.update(attr)
        if hasattr(form, 'rendered_fields'):
            if field not in form.rendered_fields:
                form.rendered_fields.add(field)
            elif not FAIL_SILENTLY:
                raise Exception('A field should only be rendered once: %s' %
                    field)
            else:
                logging.warning('A field should only be rendered once: %s' %
                    field, exc_info=sys.exc_info())
        if field_instance is None:
            html = ''
        else:
            if template is None:
                if form.crispy_field_template is None:
                    template = default_field_template(template_pack)
                else:
                    template = get_template(form.crispy_field_template)
            else:
                template = get_template(template)
            if layout_object is not None:
                if hasattr(layout_object, 'bound_fields') and isinstance(
                    layout_object.bound_fields, list):
                    layout_object.bound_fields.append(bound_field)
                else:
                    layout_object.bound_fields = [bound_field]
            context.update({'field': bound_field, 'labelclass': labelclass,
                'flat_attrs': flatatt(attrs if isinstance(attrs, dict) else
                {})})
            if show_labels is not None:
                context['form_show_labels'] = show_labels
            html = template.render(context)
        return force_text(html)


def flatatt(attrs):
    """
    Taken from django.core.utils
    Convert a dictionary of attributes to a single string.
    The returned string will contain a leading space followed by key="value",
    XML-style pairs.  It is assumed that the keys do not need to be XML-escaped.
    If the passed dictionary is empty, then return an empty string.
    """
    return u''.join([(u' %s="%s"' % (k.replace('_', '-'),
        conditional_escape(v))) for k, v in attrs.items()])


def render_crispy_form(form, helper=None, context=None):
    """
    Renders a form and returns its HTML output.

    This function wraps the template logic in a function easy to use in a Django view.
    """
    from crispy_forms.templatetags.crispy_forms_tags import CrispyFormNode
    if helper is not None:
        node = CrispyFormNode('form', 'helper')
    else:
        node = CrispyFormNode('form', None)
    node_context = Context(context)
    node_context.update({'form': form, 'helper': helper})
    return node.render(node_context)

from __future__ import with_statement

import logging
import sys

from django.conf import settings
from django.template import Context
from django.template.loader import get_template
from django.utils.html import conditional_escape
from django.utils.functional import memoize
from django.utils.encoding import force_text

from .base import KeepContext
from .compatibility import text_type, PY2

# Global field template, default template used for rendering a field.

TEMPLATE_PACK = getattr(settings, 'CRISPY_TEMPLATE_PACK', 'bootstrap')
FAIL_SILENTLY = getattr(settings, 'CRISPY_FAIL_SILENTLY', True)


class UnresolvedError(Exception):
    pass


# By memoizeing we avoid loading the template every time render_field
# is called without a template
def default_field_template(template_pack=TEMPLATE_PACK):
    return get_template("%s/field.html" % template_pack)
default_field_template = memoize(default_field_template, {}, 1)


def flatten_list(tuples):
    return list(t for f in tuples for t in (f if isinstance(f, (list, tuple)) else (f,)))


def resolve_value(context, lookup, silent=True):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError

        obj = context
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'

            if callable(obj):
                obj = obj()

            if obj is None:
                raise UnresolvedError

            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                obj = obj[name]

            except (TypeError, KeyError, IndexError):
                try:
                    obj = getattr(obj, name)
                except AttributeError:
                    raise UnresolvedError

        def _resolve_value(value):
            if isinstance(value, dict):
                return dict((rk, rv) for rk, rv in ((k, _resolve_value(v)) for k, v in value.items() if k[0] != '_') if rv)

            if isinstance(value, (tuple, list)):
                return [rv for rv in (_resolve_value(v) for v in value) if rv]

            return value

        return _resolve_value(obj)

    except UnresolvedError:
        if not silent:
            if not FAIL_SILENTLY:
                raise Exception("Could not resolve value for '%s'." % lookup)
            else:
                logging.warning("Could not resolve value for '%s'." % lookup, exc_info=sys.exc_info())


def get_bound_field(context, obj, lookup):
    try:
        fields = lookup.split('.')
        if not fields:
            raise UnresolvedError

        bound_field = None
        for i, name in enumerate(fields):
            if i == 0:
                name = name or 'form'

            if callable(obj):
                obj = obj()

            if obj is None:
                raise UnresolvedError

            try:
                if name.isdigit():
                    obj = obj[int(name)]
                    continue
                bound_field = obj[name]
                if hasattr(bound_field.field, 'form'):
                    obj = bound_field.field.widget

            except (TypeError, KeyError, IndexError):
                if i != 0:
                    raise UnresolvedError
                # Fallback to find main object in the context:
                if context is None:
                    raise Exception("context should be given for fields with absolute names")
                obj = context[name]

        if bound_field is None:
            raise UnresolvedError

        return bound_field

    except UnresolvedError:
        if not FAIL_SILENTLY:
            raise Exception("Could not resolve form field '%s'." % lookup)
        else:
            logging.warning("Could not resolve form field '%s'." % lookup, exc_info=sys.exc_info())


def render_field(field, form, form_style, context, template=None, labelclass=None, show_labels=None, layout_object=None, attrs=None, template_pack=TEMPLATE_PACK):
    """
    Renders a django-crispy-forms field

    :param field: Can be a string or a Layout object like `Row`. If it's a layout
        object, we call its render method, otherwise we instantiate a BoundField
        and render it using default template 'CRISPY_TEMPLATE_PACK/field.html'
        The field is added to a list that the form holds called `rendered_fields`
        to avoid double rendering fields.

    :param form: The form/formset to which that field belongs to.

    :param form_style: A way to pass style name to the CSS framework used.

    :template: Template used for rendering the field.

    :layout_object: If passed, it points to the Layout object that is being rendered.
        We use it to store its bound fields in a list called `layout_object.bound_fields`

    :attrs: Attributes for the field's widget
    """
    if field is None:
        return ''
    with KeepContext(context):
        if hasattr(field, 'render'):
            return force_text(field.render(form, form_style, context, template_pack=template_pack))
        else:
            # In Python 2 form field names cannot contain unicode characters without ASCII mapping
            if PY2:
                # This allows fields to be unicode strings, always they don't use non ASCII
                try:
                    if isinstance(field, text_type):
                        field = field.encode('ascii').decode()
                    # If `field` is not unicode then we turn it into a unicode string, otherwise doing
                    # str(field) would give no error and the field would not be resolved, causing confusion
                    else:
                        field = text_type(field)

                except (UnicodeEncodeError, UnicodeDecodeError):
                    raise Exception("Field '%s' is using forbidden unicode characters" % field)

        # Injecting HTML attributes into field's widget, Django handles rendering these
        bound_field = get_bound_field(context, form, field)
        if not bound_field:
            return ''
        field_instance = bound_field.field
        if attrs is not None:
            widgets = getattr(field_instance.widget, 'widgets', [field_instance.widget])

            # We use attrs as a dictionary later, so here we make a copy
            list_attrs = attrs
            if isinstance(attrs, dict):
                list_attrs = [attrs] * len(widgets)

            for index, (widget, attr) in enumerate(zip(widgets, list_attrs)):
                if hasattr(field_instance.widget, 'widgets'):
                    if 'type' in attr and attr['type'] == "hidden":
                        field_instance.widget.widgets[index].is_hidden = True
                        field_instance.widget.widgets[index] = field_instance.hidden_widget()

                    field_instance.widget.widgets[index].attrs.update(attr)
                else:
                    if 'type' in attr and attr['type'] == "hidden":
                        field_instance.widget.is_hidden = True
                        field_instance.widget = field_instance.hidden_widget()

                    field_instance.widget.attrs.update(attr)

        if hasattr(form, 'rendered_fields'):
            if field not in form.rendered_fields:
                form.rendered_fields.add(field)
            else:
                if not FAIL_SILENTLY:
                    raise Exception("A field should only be rendered once: %s" % field)
                else:
                    logging.warning("A field should only be rendered once: %s" % field, exc_info=sys.exc_info())

        if field_instance is None:
            html = ''
        else:
            if template is None:
                if form.crispy_field_template is None:
                    template = default_field_template(template_pack)
                else:   # FormHelper.field_template set
                    template = get_template(form.crispy_field_template)
            else:
                template = get_template(template)

            # We save the Layout object's bound fields in the layout object's `bound_fields` list
            if layout_object is not None:
                if hasattr(layout_object, 'bound_fields') and isinstance(layout_object.bound_fields, list):
                    layout_object.bound_fields.append(bound_field)
                else:
                    layout_object.bound_fields = [bound_field]

            context.update({
                'field': bound_field,
                'labelclass': labelclass,
                'flat_attrs': flatatt(attrs if isinstance(attrs, dict) else {}),
            })
            if show_labels is not None:
                context['form_show_labels'] = show_labels
            html = template.render(context)

        return force_text(html)


def flatatt(attrs):
    """
    Taken from django.core.utils
    Convert a dictionary of attributes to a single string.
    The returned string will contain a leading space followed by key="value",
    XML-style pairs.  It is assumed that the keys do not need to be XML-escaped.
    If the passed dictionary is empty, then return an empty string.
    """
    return u''.join([u' %s="%s"' % (k.replace('_', '-'), conditional_escape(v)) for k, v in attrs.items()])


def render_crispy_form(form, helper=None, context=None):
    """
    Renders a form and returns its HTML output.

    This function wraps the template logic in a function easy to use in a Django view.
    """
    from crispy_forms.templatetags.crispy_forms_tags import CrispyFormNode

    if helper is not None:
        node = CrispyFormNode('form', 'helper')
    else:
        node = CrispyFormNode('form', None)

    node_context = Context(context)
    node_context.update({
        'form': form,
        'helper': helper
    })

    return node.render(node_context)
