<commit_before>import importlib

from django.utils.translation import ugettext as _
from django.db import models
from django.core.exceptions import ValidationError
from model_utils import Choices
from autoslug import AutoSlugField

from crispy_forms.helper import FormHelper
from crispy_forms import layout

import floppyforms as forms
import jsonfield

from formulator.conf import settings


def validate_non_empty_string(value):
    if len(value) <= 0:
        raise ValidationError(u'%s is an empty string.' % value)


class Form(models.Model):
    """
    Form class
    """

    ENCTYPES = Choices((0, 'urlencoded', 'application/x-www-form-urlencoded'),
                       (1, 'multipart', 'multipart/form-data'),
                       (2, 'plain', 'text/plain'))

    METHODS = Choices((0, 'get', 'GET'), (1, 'post', 'POST'))

    name = models.CharField(max_length=100, help_text='Name of the Form type', validators=[validate_non_empty_string])
    slug = AutoSlugField(unique=True, populate_from='name')  # will be used to autopopulate the ID

    # form attributes
    form_name = models.CharField(max_length=100, blank=True)
    form_action = models.CharField(max_length=250, blank=True)
    form_method = models.IntegerField(max_length=10, choices=METHODS, default=METHODS.get)

    form_accept_charset = models.CharField(max_length=100, blank=True)
    form_autocomplete = models.BooleanField(default=False)
    form_novalidate = models.BooleanField(default=False)
    form_enctype = models.IntegerField(choices=ENCTYPES, default=ENCTYPES.urlencoded)
    form_target = models.CharField(max_length=50, blank=True)

    # json field for global and event attributes, including class, id, etc...
    attrs = jsonfield.JSONField()

    def __unicode__(self):
        return u"formulator.Form instance: %s" % self.slug

    def save(self, *args, **kwargs):
        self.full_clean(exclude=['id'])
        super(Form, self).save(*args, **kwargs)


    @property
    def fieldsets(self):
        return self.fieldset_set.all()

    def form_class_factory(self, form_class=None):
        # again make sure that we have everything we need to create a class
        self.full_clean()

        if form_class is None:
            form_class = forms.BaseForm

        attrs = {}
        fields = {}
        fieldsets = []
        layouts = []

        for fieldset in self.fieldsets:
            fieldset_fields = fieldset.fields

            fieldset_layout = layout.Fieldset(fieldset.legend, *[f.name for f in fieldset_fields])
            layouts.append(fieldset_layout)

            for field in fieldset_fields:
                fields[field.name] = field.formfield_instance_factory()

        attrs['base_fields'] = fields

        helper = FormHelper()
        helper.layout = layout.Layout(*layouts)

        attrs['helper'] = helper

        return type(str(self.slug), (form_class,), attrs)


class FieldSet(models.Model):
    """
    """
    form = models.ForeignKey(Form)
    name = models.CharField(max_length=100)
    legend = models.CharField(max_length=100)

    @property
    def fields(self):
        return self.field_set.all()


class Field(models.Model):
    """

    """
    formset = models.ForeignKey(FieldSet)
    name = models.CharField(max_length=100, )
    slug = AutoSlugField(unique=True, populate_from='name')

    field = models.CharField(max_length=100, choices=settings.FORMULATOR_FIELDS)
    widget = models.CharField(max_length=100, choices=settings.FORMULATOR_WIDGETS, blank=True,
                              help_text="""A Widget class, or instance of a Widget class, that should
                                           be used for this Field when displaying it. Each Field has a
                                           default Widget that it'll use if you don't specify this. In
                                           most cases, the default widget is TextInput.""")

    required = models.BooleanField(help_text=_('Boolean that specifies whether the field is required.'))
    label = models.CharField(max_length=100, blank=True,
                             help_text=_("""A verbose name for this field, for use in displaying this
                                            field in a form. By default, Django will use a "pretty"
                                            version of the form field name, if the Field is part of a
                                            Form. """))

    initial = models.CharField(max_length=200, blank=True,
                               help_text=_("""A value to use in this Field's initial display. This value
                                              is *not* used as a fallback if data isn't given. """))

    hidden = models.BooleanField()
    help_text = models.TextField(blank=True,
                                 help_text=_("An optional string to use as 'help text' for this Field."))


    attrs = jsonfield.JSONField()

    def formfield_instance_factory(self, field_class=None, attrs=None):
        """Returns an instance of a form field"""

        if field_class is None:<commit_msg>adding positions to fieldsets and fields<commit_after>import importlib

from django.utils.translation import ugettext as _
from django.db import models
from django.core.exceptions import ValidationError
from model_utils import Choices
from autoslug import AutoSlugField
from positions import PositionField
from crispy_forms.helper import FormHelper
from crispy_forms import layout

import floppyforms as forms
import jsonfield

from formulator.conf import settings


def validate_non_empty_string(value):
    if len(value) <= 0:
        raise ValidationError(u'%s is an empty string.' % value)


class Form(models.Model):
    """
    Form class
    """

    ENCTYPES = Choices((0, 'urlencoded', 'application/x-www-form-urlencoded'),
                       (1, 'multipart', 'multipart/form-data'),
                       (2, 'plain', 'text/plain'))

    METHODS = Choices((0, 'get', 'GET'), (1, 'post', 'POST'))

    name = models.CharField(max_length=100, help_text='Name of the Form type')
    slug = AutoSlugField(unique=True, populate_from='name')  # will be used to autopopulate the ID

    # form attributes
    form_name = models.CharField(max_length=100, blank=True)
    form_action = models.CharField(max_length=250, blank=True)
    form_method = models.IntegerField(max_length=10, choices=METHODS, default=METHODS.get)

    form_accept_charset = models.CharField(max_length=100, blank=True)
    form_autocomplete = models.BooleanField(default=False)
    form_novalidate = models.BooleanField(default=False)
    form_enctype = models.IntegerField(choices=ENCTYPES, default=ENCTYPES.urlencoded)
    form_target = models.CharField(max_length=50, blank=True)

    # json field for global and event attributes, including class, id, etc...
    attrs = jsonfield.JSONField()

    def __unicode__(self):
        return u"formulator.Form instance: %s" % self.slug

    def save(self, *args, **kwargs):
        super(Form, self).save(*args, **kwargs)

    @property
    def fieldsets(self):
        return self.fieldset_set.all()

    def form_class_factory(self, form_class=None):
        # again make sure that we have everything we need to create a class
        self.full_clean()

        if form_class is None:
            form_class = forms.BaseForm

        attrs = {}
        fields = {}
        fieldsets = []
        layouts = []

        for fieldset in self.fieldsets:
            fieldset_fields = fieldset.fields

            fieldset_layout = layout.Fieldset(fieldset.legend, *[f.name for f in fieldset_fields])
            layouts.append(fieldset_layout)

            for field in fieldset_fields:
                fields[field.name] = field.formfield_instance_factory()

        attrs['base_fields'] = fields

        helper = FormHelper()
        helper.layout = layout.Layout(*layouts)

        attrs['helper'] = helper

        return type(str(self.slug), (form_class,), attrs)


class FieldSet(models.Model):
    """
    """
    form = models.ForeignKey(Form)
    position = PositionField(collection='form')
    name = models.CharField(max_length=100)
    legend = models.CharField(max_length=100)

    @property
    def fields(self):
        return self.field_set.all()


class Field(models.Model):
    """

    """
    formset = models.ForeignKey(FieldSet)
    name = models.CharField(max_length=100, )
    position = PositionField(collection='formset')
    slug = AutoSlugField(unique=True, populate_from='name')

    field = models.CharField(max_length=100, choices=settings.FORMULATOR_FIELDS)
    widget = models.CharField(max_length=100, choices=settings.FORMULATOR_WIDGETS, blank=True,
                              help_text="""A Widget class, or instance of a Widget class, that should
                                           be used for this Field when displaying it. Each Field has a
                                           default Widget that it'll use if you don't specify this. In
                                           most cases, the default widget is TextInput.""")

    required = models.BooleanField(help_text=_('Boolean that specifies whether the field is required.'))
    label = models.CharField(max_length=100, blank=True,
                             help_text=_("""A verbose name for this field, for use in displaying this
                                            field in a form. By default, Django will use a "pretty"
                                            version of the form field name, if the Field is part of a
                                            Form. """))

    initial = models.CharField(max_length=200, blank=True,
                               help_text=_("""A value to use in this Field's initial display. This value
                                              is *not* used as a fallback if data isn't given. """))

    hidden = models.BooleanField()
    help_text = models.TextField(blank=True,
                                 help_text=_("An optional string to use as 'help text' for this Field."))


    attrs = jsonfield.JSONField()

    def formfield_instance_factory(self, field_class=None, attrs=None):
        """Returns an instance of a form field"""

        if field_class is None:
{'fraction_non_alphanumeric': 0.0953492897450866, 'fraction_numerical': 0.008367386651099436, 'mean_word_length': 2.4998297582567246, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2807492', 'n_tokens_mistral': 2917, 'n_tokens_neox': 2768, 'n_words': 776}