# Path: mongonaut/forms/form_utils.py
# def has_digit(string_or_list, sep="_"):
# def make_key(*args, **kwargs):
# 
# Path: mongonaut/forms/form_utils.py
# def has_digit(string_or_list, sep="_"):
#     """
#     Given a string or a list will return true if the last word or
#     element is a digit.  sep is used when a string is given to know
#     what separates one word from another.
#     """
#     if isinstance(string_or_list, (tuple, list)):
#         list_length = len(string_or_list)
#         if list_length:
#             return six.text_type(string_or_list[-1]).isdigit()
#         else:
#             return False
#     else:
#         return has_digit(string_or_list.split(sep))
# 
# Path: mongonaut/forms/form_utils.py
# def make_key(*args, **kwargs):
#     """
#     Given any number of lists and strings will join them in order as one
#     string separated by the sep kwarg.  sep defaults to u"_".
# 
#     Add exclude_last_string=True as a kwarg to exclude the last item in a
#     given string after being split by sep.  Note if you only have one word
#     in your string you can end up getting an empty string.
# 
#     Example uses:
# 
#     >>> from mongonaut.forms.form_utils import make_key
#     >>> make_key('hi', 'my', 'firend')
#     >>> u'hi_my_firend'
# 
#     >>> make_key('hi', 'my', 'firend', sep='i')
#     >>> 'hiimyifirend'
# 
#     >>> make_key('hi', 'my', 'firend',['this', 'be', 'what'], sep='i')
#     >>> 'hiimyifirendithisibeiwhat'
# 
#     >>> make_key('hi', 'my', 'firend',['this', 'be', 'what'])
#     >>> u'hi_my_firend_this_be_what'
# 
#     """
#     sep = kwargs.get('sep', u"_")
#     exclude_last_string = kwargs.get('exclude_last_string', False)
#     string_array = []
# 
#     for arg in args:
#         if isinstance(arg, list):
#             string_array.append(six.text_type(sep.join(arg)))
#         else:
#             if exclude_last_string:
#                 new_key_array = arg.split(sep)[:-1]
#                 if len(new_key_array) > 0:
#                     string_array.append(make_key(new_key_array))
#             else:
#                 string_array.append(six.text_type(arg))
#     return sep.join(string_array)
# 
# Path: mongonaut/forms/widgets.py
# def get_form_field_class(model_field):
#     """Gets the default form field  for a mongoenigne field."""
# 
#     FIELD_MAPPING = {
#         IntField: forms.IntegerField,
#         StringField: forms.CharField,
#         FloatField: forms.FloatField,
#         BooleanField: forms.BooleanField,
#         DateTimeField: forms.DateTimeField,
#         DecimalField: forms.DecimalField,
#         URLField: forms.URLField,
#         EmailField: forms.EmailField
#     }
# 
#     return FIELD_MAPPING.get(model_field.__class__, forms.CharField)
# 
# Path: mongonaut/utils.py
# def trim_field_key(document, field_key):
#     """
#     Returns the smallest delimited version of field_key that
#     is an attribute on document.
# 
#     return (key, left_over_array)
#     """
#     trimming = True
#     left_over_key_values = []
#     current_key = field_key
#     while trimming and current_key:
#         if hasattr(document, current_key):
#             trimming = False
#         else:
#             key_array = current_key.split("_")
#             left_over_key_values.append(key_array.pop())
#             current_key = u"_".join(key_array)
# 
#     left_over_key_values.reverse()
#     return current_key, left_over_key_values


import six
from copy import deepcopy
from django import forms
from mongoengine.base import BaseList
from mongoengine.base import TopLevelDocumentMetaclass
from mongoengine.fields import Document
from mongoengine.fields import EmbeddedDocumentField
from mongoengine.fields import ListField
from mongoengine.fields import ReferenceField
from .form_utils import FieldTuple
from .form_utils import has_digit
from .form_utils import make_key
from .widgets import get_form_field_class
from mongonaut.utils import trim_field_key
    from collections import OrderedDict
            raise TypeError(u"The model supplied must be a mongoengine Document")

        if self.is_initialized and not isinstance(self.model_instance, self.model):
            raise TypeError(u"The provided instance must be an instance of the given model")

        if self.post_data_dict is not None and not isinstance(self.post_data_dict, dict):
            raise TypeError(u"You must pass in a dictionary for form_post_data")

    def get_form_field_dict(self, model_dict):
        """
        Takes a model dictionary representation and creates a dictionary
        keyed by form field.  Each value is a  keyed 4 tuple of:
        (widget, mode_field_instance, model_field_type, field_key)
        """
        return_dict = OrderedDict()
        # Workaround: mongoengine doesn't preserve form fields ordering from metaclass __new__
        if hasattr(self.model, 'Meta') and hasattr(self.model.Meta, 'form_fields_ordering'):
            field_order_list = tuple(form_field for form_field
                                     in self.model.Meta.form_fields_ordering
                                     if form_field in model_dict.iterkeys())
            order_dict = OrderedDict.fromkeys(field_order_list)
            return_dict = order_dict

        for field_key, field_dict in sorted(model_dict.items()):
            if not field_key.startswith("_"):
                widget = field_dict.get('_widget', None)
                if widget is None:
                    return_dict[field_key] = self.get_form_field_dict(field_dict)
                    return_dict[field_key].update({'_field_type': field_dict.get('_field_type', None)})
                else:

# Path: mongonaut/forms/form_utils.py
# def has_digit(string_or_list, sep="_"):
# def make_key(*args, **kwargs):
# 
# Path: mongonaut/forms/form_utils.py
# def has_digit(string_or_list, sep="_"):
#     """
#     Given a string or a list will return true if the last word or
#     element is a digit.  sep is used when a string is given to know
#     what separates one word from another.
#     """
#     if isinstance(string_or_list, (tuple, list)):
#         list_length = len(string_or_list)
#         if list_length:
#             return six.text_type(string_or_list[-1]).isdigit()
#         else:
#             return False
#     else:
#         return has_digit(string_or_list.split(sep))
# 
# Path: mongonaut/forms/form_utils.py
# def make_key(*args, **kwargs):
#     """
#     Given any number of lists and strings will join them in order as one
#     string separated by the sep kwarg.  sep defaults to u"_".
# 
#     Add exclude_last_string=True as a kwarg to exclude the last item in a
#     given string after being split by sep.  Note if you only have one word
#     in your string you can end up getting an empty string.
# 
#     Example uses:
# 
#     >>> from mongonaut.forms.form_utils import make_key
#     >>> make_key('hi', 'my', 'firend')
#     >>> u'hi_my_firend'
# 
#     >>> make_key('hi', 'my', 'firend', sep='i')
#     >>> 'hiimyifirend'
# 
#     >>> make_key('hi', 'my', 'firend',['this', 'be', 'what'], sep='i')
#     >>> 'hiimyifirendithisibeiwhat'
# 
#     >>> make_key('hi', 'my', 'firend',['this', 'be', 'what'])
#     >>> u'hi_my_firend_this_be_what'
# 
#     """
#     sep = kwargs.get('sep', u"_")
#     exclude_last_string = kwargs.get('exclude_last_string', False)
#     string_array = []
# 
#     for arg in args:
#         if isinstance(arg, list):
#             string_array.append(six.text_type(sep.join(arg)))
#         else:
#             if exclude_last_string:
#                 new_key_array = arg.split(sep)[:-1]
#                 if len(new_key_array) > 0:
#                     string_array.append(make_key(new_key_array))
#             else:
#                 string_array.append(six.text_type(arg))
#     return sep.join(string_array)
# 
# Path: mongonaut/forms/widgets.py
# def get_form_field_class(model_field):
#     """Gets the default form field  for a mongoenigne field."""
# 
#     FIELD_MAPPING = {
#         IntField: forms.IntegerField,
#         StringField: forms.CharField,
#         FloatField: forms.FloatField,
#         BooleanField: forms.BooleanField,
#         DateTimeField: forms.DateTimeField,
#         DecimalField: forms.DecimalField,
#         URLField: forms.URLField,
#         EmailField: forms.EmailField
#     }
# 
#     return FIELD_MAPPING.get(model_field.__class__, forms.CharField)
# 
# Path: mongonaut/utils.py
# def trim_field_key(document, field_key):
#     """
#     Returns the smallest delimited version of field_key that
#     is an attribute on document.
# 
#     return (key, left_over_array)
#     """
#     trimming = True
#     left_over_key_values = []
#     current_key = field_key
#     while trimming and current_key:
#         if hasattr(document, current_key):
#             trimming = False
#         else:
#             key_array = current_key.split("_")
#             left_over_key_values.append(key_array.pop())
#             current_key = u"_".join(key_array)
# 
#     left_over_key_values.reverse()
#     return current_key, left_over_key_values


# Path: mongonaut/forms/form_mixins.py
import six
from copy import deepcopy
from django import forms
from mongoengine.base import BaseList
from mongoengine.base import TopLevelDocumentMetaclass
from mongoengine.fields import Document
from mongoengine.fields import EmbeddedDocumentField
from mongoengine.fields import ListField
from mongoengine.fields import ReferenceField
from .form_utils import FieldTuple
from .form_utils import has_digit
from .form_utils import make_key
from .widgets import get_form_field_class
from mongonaut.utils import trim_field_key
    from collections import OrderedDict

            raise TypeError(u"The model supplied must be a mongoengine Document")

        if self.is_initialized and not isinstance(self.model_instance, self.model):
            raise TypeError(u"The provided instance must be an instance of the given model")

        if self.post_data_dict is not None and not isinstance(self.post_data_dict, dict):
            raise TypeError(u"You must pass in a dictionary for form_post_data")

    def get_form_field_dict(self, model_dict):
        """
        Takes a model dictionary representation and creates a dictionary
        keyed by form field.  Each value is a  keyed 4 tuple of:
        (widget, mode_field_instance, model_field_type, field_key)
        """
        return_dict = OrderedDict()
        # Workaround: mongoengine doesn't preserve form fields ordering from metaclass __new__
        if hasattr(self.model, 'Meta') and hasattr(self.model.Meta, 'form_fields_ordering'):
            field_order_list = tuple(form_field for form_field
                                     in self.model.Meta.form_fields_ordering
                                     if form_field in model_dict.iterkeys())
            order_dict = OrderedDict.fromkeys(field_order_list)
            return_dict = order_dict

        for field_key, field_dict in sorted(model_dict.items()):
            if not field_key.startswith("_"):
                widget = field_dict.get('_widget', None)
                if widget is None:
                    return_dict[field_key] = self.get_form_field_dict(field_dict)
                    return_dict[field_key].update({'_field_type': field_dict.get('_field_type', None)})
                else:

                    return_dict[field_key] = FieldTuple(widget,