<commit_before>from dimagi.ext.couchdbkit import (Document, StringProperty,
    BooleanProperty, SchemaListProperty, StringListProperty)
from dimagi.ext.jsonobject import JsonObject
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _

from .dbaccessors import get_by_domain_and_type


CUSTOM_DATA_FIELD_PREFIX = "data-field"
# If mobile-worker is demo, this will be set to value 'demo'
COMMCARE_USER_TYPE_KEY = 'user_type'
COMMCARE_USER_TYPE_DEMO = 'demo'
# This list is used to grandfather in existing data, any new fields should use
# the system prefix defined below
SYSTEM_FIELDS = ("commtrack-supply-point", 'name', 'type', 'owner_id', 'external_id', 'hq_user_id',
                 COMMCARE_USER_TYPE_KEY)
SYSTEM_PREFIX = "commcare"


def validate_reserved_words(slug):
    if slug in SYSTEM_FIELDS:
        raise ValidationError(_('You may not use "{}" as a field name').format(slug))
    for prefix in [SYSTEM_PREFIX, 'xml']:
        if slug and slug.startswith(prefix):
            raise ValidationError(_('Field names may not begin with "{}"').format(prefix))


def is_system_key(slug):
    try:
        validate_reserved_words(slug)
    except ValidationError:
        return True
    return False


class CustomDataField(JsonObject):
    slug = StringProperty()
    is_required = BooleanProperty()
    label = StringProperty()
    choices = StringListProperty()
    is_multiple_choice = BooleanProperty(default=False)


class CustomDataFieldsDefinition(Document):
    """
    Per-project user-defined fields such as custom user data.
    """
    field_type = StringProperty()
    base_doc = "CustomDataFieldsDefinition"
    domain = StringProperty()
    fields = SchemaListProperty(CustomDataField)

    def get_fields(self, required_only=False, include_system=True):
        def _is_match(field):
            if ((required_only and not field.is_required)
                    or (not include_system and is_system_key(field.slug))):
                return False
            return True
        return filter(_is_match, self.fields)

    @classmethod
    def get_or_create(cls, domain, field_type):
        # todo: this overrides get_or_create from DocumentBase but with a completely different signature.
        # This method should probably be renamed.
        existing = get_by_domain_and_type(domain, field_type)

        if existing:
            return existing
        else:
            new = cls(domain=domain, field_type=field_type)
            new.save()
            return new

    # TODO use this in the CustomDataEditor too?
    def get_validator(self, data_field_class):
        """
        Returns a validator to be used in bulk import<commit_msg>Replace if clause with return statement<commit_after>from dimagi.ext.couchdbkit import (Document, StringProperty,
    BooleanProperty, SchemaListProperty, StringListProperty)
from dimagi.ext.jsonobject import JsonObject
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _

from .dbaccessors import get_by_domain_and_type


CUSTOM_DATA_FIELD_PREFIX = "data-field"
# If mobile-worker is demo, this will be set to value 'demo'
COMMCARE_USER_TYPE_KEY = 'user_type'
COMMCARE_USER_TYPE_DEMO = 'demo'
# This list is used to grandfather in existing data, any new fields should use
# the system prefix defined below
SYSTEM_FIELDS = ("commtrack-supply-point", 'name', 'type', 'owner_id', 'external_id', 'hq_user_id',
                 COMMCARE_USER_TYPE_KEY)
SYSTEM_PREFIX = "commcare"


def validate_reserved_words(slug):
    if slug in SYSTEM_FIELDS:
        raise ValidationError(_('You may not use "{}" as a field name').format(slug))
    for prefix in [SYSTEM_PREFIX, 'xml']:
        if slug and slug.startswith(prefix):
            raise ValidationError(_('Field names may not begin with "{}"').format(prefix))


def is_system_key(slug):
    try:
        validate_reserved_words(slug)
    except ValidationError:
        return True
    return False


class CustomDataField(JsonObject):
    slug = StringProperty()
    is_required = BooleanProperty()
    label = StringProperty()
    choices = StringListProperty()
    is_multiple_choice = BooleanProperty(default=False)


class CustomDataFieldsDefinition(Document):
    """
    Per-project user-defined fields such as custom user data.
    """
    field_type = StringProperty()
    base_doc = "CustomDataFieldsDefinition"
    domain = StringProperty()
    fields = SchemaListProperty(CustomDataField)

    def get_fields(self, required_only=False, include_system=True):
        def _is_match(field):
            return not (
                (required_only and not field.is_required) or
                (not include_system and is_system_key(field.slug))
            )
        return filter(_is_match, self.fields)

    @classmethod
    def get_or_create(cls, domain, field_type):
        # todo: this overrides get_or_create from DocumentBase but with a completely different signature.
        # This method should probably be renamed.
        existing = get_by_domain_and_type(domain, field_type)

        if existing:
            return existing
        else:
            new = cls(domain=domain, field_type=field_type)
            new.save()
            return new

    # TODO use this in the CustomDataEditor too?
    def get_validator(self, data_field_class):
        """
        Returns a validator to be used in bulk import
{'fraction_non_alphanumeric': 0.07770022042615723, 'fraction_numerical': 0.0, 'mean_word_length': 3.3805309734513274, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7646324', 'n_tokens_mistral': 1544, 'n_tokens_neox': 1511, 'n_words': 445}