# Path: djng/forms/fields.py
# class DefaultFieldMixin(object):
#     render_label = True
# 
#     def has_subwidgets(self):
#         return False
# 
#     def get_potential_errors(self):
#         return self.get_input_required_errors()
# 
#     def get_input_required_errors(self):
#         errors = []
#         if self.required:
#             self.widget.attrs['ng-required'] = 'true'
#             for key, msg in self.error_messages.items():
#                 if key == 'required':
#                     errors.append(('$error.required', msg))
#         return errors
# 
#     def get_min_max_length_errors(self):
#         errors = []
#         if getattr(self, 'min_length', None):
#             self.widget.attrs['ng-minlength'] = self.min_length
#         if getattr(self, 'max_length', None):
#             self.widget.attrs['ng-maxlength'] = self.max_length
#         for item in self.validators:
#             if getattr(item, 'code', None) == 'min_length':
#                 message = ungettext_lazy(
#                     'Ensure this value has at least %(limit_value)d character',
#                     'Ensure this value has at least %(limit_value)d characters',
#                     'limit_value')
#                 errors.append(('$error.minlength', message % {'limit_value': self.min_length}))
#             if getattr(item, 'code', None) == 'max_length':
#                 message = ungettext_lazy(
#                     'Ensure this value has at most %(limit_value)d character',
#                     'Ensure this value has at most %(limit_value)d characters',
#                     'limit_value')
#                 errors.append(('$error.maxlength', message % {'limit_value': self.max_length}))
#         return errors
# 
#     def get_min_max_value_errors(self):
#         errors = []
#         if isinstance(getattr(self, 'min_value', None), int):
#             self.widget.attrs['min'] = self.min_value
#         if isinstance(getattr(self, 'max_value', None), int):
#             self.widget.attrs['max'] = self.max_value
#         errkeys = []
#         for key, msg in self.error_messages.items():
#             if key == 'min_value':
#                 errors.append(('$error.min', msg))
#                 errkeys.append(key)
#             if key == 'max_value':
#                 errors.append(('$error.max', msg))
#                 errkeys.append(key)
#         for item in self.validators:
#             if getattr(item, 'code', None) == 'min_value' and 'min_value' not in errkeys:
#                 errors.append(('$error.min', item.message % {'limit_value': self.min_value}))
#                 errkeys.append('min_value')
#             if getattr(item, 'code', None) == 'max_value' and 'max_value' not in errkeys:
#                 errors.append(('$error.max', item.message % {'limit_value': self.max_value}))
#                 errkeys.append('max_value')
#         return errors
# 
#     def get_invalid_value_errors(self, ng_error_key):
#         errors = []
#         errkeys = []
#         for key, msg in self.error_messages.items():
#             if key == 'invalid':
#                 errors.append(('$error.{0}'.format(ng_error_key), msg))
#                 errkeys.append(key)
#         for item in self.validators:
#             if getattr(item, 'code', None) == 'invalid' and 'invalid' not in errkeys:
#                 errmsg = getattr(item, 'message', _("This input self does not contain valid data."))
#                 errors.append(('$error.{0}'.format(ng_error_key), errmsg))
#                 errkeys.append('invalid')
#         return errors
# 
#     def update_widget_attrs(self, bound_field, attrs):
#         """
#         Update the dictionary of attributes used  while rendering the input widget
#         """
#         bound_field.form.update_widget_attrs(bound_field, attrs)
#         widget_classes = self.widget.attrs.get('class', None)
#         if widget_classes:
#             if 'class' in attrs:
#                 attrs['class'] += ' ' + widget_classes
#             else:
#                 attrs.update({'class': widget_classes})
#         return attrs


from base64 import b64encode
from collections import UserList
from django.forms import forms
from django.forms.boundfield import BoundField
from django.http import QueryDict
from django.utils.html import format_html, format_html_join, escape, conditional_escape
from django.utils.encoding import force_text
from django.utils.module_loading import import_string
from django.utils.safestring import mark_safe, SafeText, SafeData
from django.core.exceptions import ValidationError, ImproperlyConfigured
from .fields import DefaultFieldMixin
import json
import warnings
    def __new__(cls, name, bases, attrs):
        attrs.update(formfield_callback=cls.formfield_callback)
        new_class = super(BaseFieldsModifierMetaclass, cls).__new__(cls, name, bases, attrs)
        cls.validate_formfields(new_class)
        return new_class

    @classmethod
    def formfield_callback(cls, modelfield, **kwargs):
        # first get the default formfield for this modelfield
        formfield = modelfield.formfield(**kwargs)

        if formfield:
            # use the same class name to load the corresponding inherited formfield
            try:
                formfield_class = import_string('djng.forms.fields.' + formfield.__class__.__name__)
            except ImportError: # form field not declared by Django
                formfield_class = type(str(formfield.__class__.__name__), (DefaultFieldMixin, formfield.__class__), {})

            # recreate the formfield using our customized field class
            if hasattr(formfield, 'choices'):
                kwargs.update(choices_form_class=formfield_class)
            kwargs.update(form_class=formfield_class)
            formfield = modelfield.formfield(**kwargs)
        return formfield

    @classmethod
    def validate_formfields(cls, new_class):
        msg = "Please use the corresponding form fields from 'djng.forms.fields' for field '{} = {}(...)' " \
              "in form '{}', which inherits from 'NgForm' or 'NgModelForm'."
        for name, field in new_class.base_fields.items():

# Path: djng/forms/fields.py
# class DefaultFieldMixin(object):
#     render_label = True
# 
#     def has_subwidgets(self):
#         return False
# 
#     def get_potential_errors(self):
#         return self.get_input_required_errors()
# 
#     def get_input_required_errors(self):
#         errors = []
#         if self.required:
#             self.widget.attrs['ng-required'] = 'true'
#             for key, msg in self.error_messages.items():
#                 if key == 'required':
#                     errors.append(('$error.required', msg))
#         return errors
# 
#     def get_min_max_length_errors(self):
#         errors = []
#         if getattr(self, 'min_length', None):
#             self.widget.attrs['ng-minlength'] = self.min_length
#         if getattr(self, 'max_length', None):
#             self.widget.attrs['ng-maxlength'] = self.max_length
#         for item in self.validators:
#             if getattr(item, 'code', None) == 'min_length':
#                 message = ungettext_lazy(
#                     'Ensure this value has at least %(limit_value)d character',
#                     'Ensure this value has at least %(limit_value)d characters',
#                     'limit_value')
#                 errors.append(('$error.minlength', message % {'limit_value': self.min_length}))
#             if getattr(item, 'code', None) == 'max_length':
#                 message = ungettext_lazy(
#                     'Ensure this value has at most %(limit_value)d character',
#                     'Ensure this value has at most %(limit_value)d characters',
#                     'limit_value')
#                 errors.append(('$error.maxlength', message % {'limit_value': self.max_length}))
#         return errors
# 
#     def get_min_max_value_errors(self):
#         errors = []
#         if isinstance(getattr(self, 'min_value', None), int):
#             self.widget.attrs['min'] = self.min_value
#         if isinstance(getattr(self, 'max_value', None), int):
#             self.widget.attrs['max'] = self.max_value
#         errkeys = []
#         for key, msg in self.error_messages.items():
#             if key == 'min_value':
#                 errors.append(('$error.min', msg))
#                 errkeys.append(key)
#             if key == 'max_value':
#                 errors.append(('$error.max', msg))
#                 errkeys.append(key)
#         for item in self.validators:
#             if getattr(item, 'code', None) == 'min_value' and 'min_value' not in errkeys:
#                 errors.append(('$error.min', item.message % {'limit_value': self.min_value}))
#                 errkeys.append('min_value')
#             if getattr(item, 'code', None) == 'max_value' and 'max_value' not in errkeys:
#                 errors.append(('$error.max', item.message % {'limit_value': self.max_value}))
#                 errkeys.append('max_value')
#         return errors
# 
#     def get_invalid_value_errors(self, ng_error_key):
#         errors = []
#         errkeys = []
#         for key, msg in self.error_messages.items():
#             if key == 'invalid':
#                 errors.append(('$error.{0}'.format(ng_error_key), msg))
#                 errkeys.append(key)
#         for item in self.validators:
#             if getattr(item, 'code', None) == 'invalid' and 'invalid' not in errkeys:
#                 errmsg = getattr(item, 'message', _("This input self does not contain valid data."))
#                 errors.append(('$error.{0}'.format(ng_error_key), errmsg))
#                 errkeys.append('invalid')
#         return errors
# 
#     def update_widget_attrs(self, bound_field, attrs):
#         """
#         Update the dictionary of attributes used  while rendering the input widget
#         """
#         bound_field.form.update_widget_attrs(bound_field, attrs)
#         widget_classes = self.widget.attrs.get('class', None)
#         if widget_classes:
#             if 'class' in attrs:
#                 attrs['class'] += ' ' + widget_classes
#             else:
#                 attrs.update({'class': widget_classes})
#         return attrs


# Path: djng/forms/angular_base.py
from base64 import b64encode
from collections import UserList
from django.forms import forms
from django.forms.boundfield import BoundField
from django.http import QueryDict
from django.utils.html import format_html, format_html_join, escape, conditional_escape
from django.utils.encoding import force_text
from django.utils.module_loading import import_string
from django.utils.safestring import mark_safe, SafeText, SafeData
from django.core.exceptions import ValidationError, ImproperlyConfigured
from .fields import DefaultFieldMixin
import json
import warnings

    def __new__(cls, name, bases, attrs):
        attrs.update(formfield_callback=cls.formfield_callback)
        new_class = super(BaseFieldsModifierMetaclass, cls).__new__(cls, name, bases, attrs)
        cls.validate_formfields(new_class)
        return new_class

    @classmethod
    def formfield_callback(cls, modelfield, **kwargs):
        # first get the default formfield for this modelfield
        formfield = modelfield.formfield(**kwargs)

        if formfield:
            # use the same class name to load the corresponding inherited formfield
            try:
                formfield_class = import_string('djng.forms.fields.' + formfield.__class__.__name__)
            except ImportError: # form field not declared by Django
                formfield_class = type(str(formfield.__class__.__name__), (DefaultFieldMixin, formfield.__class__), {})

            # recreate the formfield using our customized field class
            if hasattr(formfield, 'choices'):
                kwargs.update(choices_form_class=formfield_class)
            kwargs.update(form_class=formfield_class)
            formfield = modelfield.formfield(**kwargs)
        return formfield

    @classmethod
    def validate_formfields(cls, new_class):
        msg = "Please use the corresponding form fields from 'djng.forms.fields' for field '{} = {}(...)' " \
              "in form '{}', which inherits from 'NgForm' or 'NgModelForm'."
        for name, field in new_class.base_fields.items():

            if not isinstance(field, DefaultFieldMixin):