# Path: crispy_forms/utils.py
# TEMPLATE_PACK = SimpleLazyObject(get_template_pack)
# 
# def flatatt(attrs):
#     """
#     Convert a dictionary of attributes to a single string.
# 
#     Passed attributes are redirected to `django.forms.utils.flatatt()`
#     with replaced "_" (underscores) by "-" (dashes) in their names.
#     """
#     return _flatatt({k.replace("_", "-"): v for k, v in attrs.items()})
# 
# def get_template_pack():
#     return getattr(settings, "CRISPY_TEMPLATE_PACK", "bootstrap4")
# 
# def render_field(  # noqa: C901
#     field,
#     form,
#     context,
#     template=None,
#     labelclass=None,
#     layout_object=None,
#     attrs=None,
#     template_pack=TEMPLATE_PACK,
#     extra_context=None,
#     **kwargs,
# ):
#     """
#     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.
#     :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
#     :template_pack: Name of the template pack to be used for rendering `field`
#     :extra_context: Dictionary to be added to context, added variables by the layout object
#     """
#     added_keys = [] if extra_context is None else extra_context.keys()
#     with KeepContext(context, added_keys):
#         if field is None:
#             return ""
# 
#         FAIL_SILENTLY = getattr(settings, "CRISPY_FAIL_SILENTLY", True)
# 
#         if hasattr(field, "render"):
#             return field.render(form, context, template_pack=template_pack)
# 
#         try:
#             # Injecting HTML attributes into field's widget, Django handles rendering these
#             bound_field = form[field]
#             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] = field_instance.hidden_widget(attr)
# 
#                         else:
#                             field_instance.widget.widgets[index].attrs.update(attr)
#                     else:
#                         if "type" in attr and attr["type"] == "hidden":
#                             field_instance.widget = field_instance.hidden_widget(attr)
# 
#                         else:
#                             field_instance.widget.attrs.update(attr)
# 
#         except KeyError:
#             if not FAIL_SILENTLY:
#                 raise Exception("Could not resolve form field '%s'." % field)
#             else:
#                 field_instance = None
#                 logging.warning("Could not resolve form field '%s'." % field, exc_info=sys.exc_info())
# 
#         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 extra_context is not None:
#                 context.update(extra_context)
# 
#             html = template.render(context.flatten())
# 
#         return html


from django.template import Template
from django.template.loader import render_to_string
from django.utils.html import conditional_escape
from django.utils.text import slugify
from crispy_forms.utils import TEMPLATE_PACK, flatatt, get_template_pack, render_field
    css_id : str, optional
        A custom DOM id for the layout object. If not provided the name
        argument is slugified and turned into the id for the submit button.
        By default None.
    css_class : str, optional
        Additional CSS classes to be applied to the ``<input>``. By default
        None.
    template : str, optional
        Overrides the default template, if provided. By default None.
    **kwargs : dict, optional
        Additional attributes are passed to `flatatt` and converted into
        key="value", pairs. These attributes are added to the ``<input>``.
    """

    template = "%s/layout/baseinput.html"

    def __init__(self, name, value, *, css_id=None, css_class=None, template=None, **kwargs):
        self.name = name
        self.value = value
        if css_id:
            self.id = css_id
        else:
            slug = slugify(self.name)
            self.id = f"{self.input_type}-id-{slug}"
        self.attrs = {}

        if css_class:
            self.field_classes += f" {css_class}"

        self.template = template or self.template

# Path: crispy_forms/utils.py
# TEMPLATE_PACK = SimpleLazyObject(get_template_pack)
# 
# def flatatt(attrs):
#     """
#     Convert a dictionary of attributes to a single string.
# 
#     Passed attributes are redirected to `django.forms.utils.flatatt()`
#     with replaced "_" (underscores) by "-" (dashes) in their names.
#     """
#     return _flatatt({k.replace("_", "-"): v for k, v in attrs.items()})
# 
# def get_template_pack():
#     return getattr(settings, "CRISPY_TEMPLATE_PACK", "bootstrap4")
# 
# def render_field(  # noqa: C901
#     field,
#     form,
#     context,
#     template=None,
#     labelclass=None,
#     layout_object=None,
#     attrs=None,
#     template_pack=TEMPLATE_PACK,
#     extra_context=None,
#     **kwargs,
# ):
#     """
#     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.
#     :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
#     :template_pack: Name of the template pack to be used for rendering `field`
#     :extra_context: Dictionary to be added to context, added variables by the layout object
#     """
#     added_keys = [] if extra_context is None else extra_context.keys()
#     with KeepContext(context, added_keys):
#         if field is None:
#             return ""
# 
#         FAIL_SILENTLY = getattr(settings, "CRISPY_FAIL_SILENTLY", True)
# 
#         if hasattr(field, "render"):
#             return field.render(form, context, template_pack=template_pack)
# 
#         try:
#             # Injecting HTML attributes into field's widget, Django handles rendering these
#             bound_field = form[field]
#             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] = field_instance.hidden_widget(attr)
# 
#                         else:
#                             field_instance.widget.widgets[index].attrs.update(attr)
#                     else:
#                         if "type" in attr and attr["type"] == "hidden":
#                             field_instance.widget = field_instance.hidden_widget(attr)
# 
#                         else:
#                             field_instance.widget.attrs.update(attr)
# 
#         except KeyError:
#             if not FAIL_SILENTLY:
#                 raise Exception("Could not resolve form field '%s'." % field)
#             else:
#                 field_instance = None
#                 logging.warning("Could not resolve form field '%s'." % field, exc_info=sys.exc_info())
# 
#         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 extra_context is not None:
#                 context.update(extra_context)
# 
#             html = template.render(context.flatten())
# 
#         return html


# Path: crispy_forms/layout.py
from django.template import Template
from django.template.loader import render_to_string
from django.utils.html import conditional_escape
from django.utils.text import slugify
from crispy_forms.utils import TEMPLATE_PACK, flatatt, get_template_pack, render_field

    css_id : str, optional
        A custom DOM id for the layout object. If not provided the name
        argument is slugified and turned into the id for the submit button.
        By default None.
    css_class : str, optional
        Additional CSS classes to be applied to the ``<input>``. By default
        None.
    template : str, optional
        Overrides the default template, if provided. By default None.
    **kwargs : dict, optional
        Additional attributes are passed to `flatatt` and converted into
        key="value", pairs. These attributes are added to the ``<input>``.
    """

    template = "%s/layout/baseinput.html"

    def __init__(self, name, value, *, css_id=None, css_class=None, template=None, **kwargs):
        self.name = name
        self.value = value
        if css_id:
            self.id = css_id
        else:
            slug = slugify(self.name)
            self.id = f"{self.input_type}-id-{slug}"
        self.attrs = {}

        if css_class:
            self.field_classes += f" {css_class}"

        self.template = template or self.template

        self.flat_attrs = flatatt(kwargs)