<commit_before># coding: utf-8

import copy

from django.conf import settings
from django.http import Http404
from django.db.models import Q

from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin.edit_handlers import FieldPanel,\
                                               MultiFieldPanel, FieldRowPanel
from wagtail.wagtailadmin.views.pages import get_page_edit_handler,\
                                             PAGE_EDIT_HANDLERS
from wagtail.wagtailsnippets.views.snippets import get_snippet_edit_handler,\
                                                   SNIPPET_EDIT_HANDLERS
from wagtail.wagtailcore.url_routing import RouteResult

from modeltranslation.translator import translator, NotRegistered


####################################
# TRANSLATION MIXIN
####################################
class TranslationMixin(object):
    _translation_options = None
    _wgform_class = None
    _translated = False

    def __init__(self, *args, **kwargs):
        super(TranslationMixin, self).__init__(*args, **kwargs)

        TranslationMixin._translation_options = translator.\
            get_options_for_model(
                self.__class__)

        if self.__class__._translated:
            return

        # CONSTRUCT TEMPORARY EDIT HANDLER
        if issubclass(self.__class__, Page):
            edit_handler_class = get_page_edit_handler(self.__class__)
        else:
            edit_handler_class = get_snippet_edit_handler(self.__class__)
        TranslationMixin._wgform_class = edit_handler_class.get_form_class(
            self.__class__)

        defined_tabs = TranslationMixin._fetch_defined_tabs(self.__class__)

        for tab_name, tab in defined_tabs:
            patched_tab = []

            for panel in tab:
                trtab = TranslationMixin._patch_panel(self, panel)

                if trtab:
                    for x in trtab:
                        patched_tab.append(x)

            setattr(self.__class__, tab_name, patched_tab)

        # DELETE TEMPORARY EDIT HANDLER IN ORDER TO LET WAGTAIL RECONSTRUCT
        # NEW EDIT HANDLER BASED ON NEW TRANSLATION PANELS
        if issubclass(self.__class__, Page):
            if self.__class__ in PAGE_EDIT_HANDLERS:
                del PAGE_EDIT_HANDLERS[self.__class__]
            edit_handler_class = get_page_edit_handler(self.__class__)
        else:
            if self.__class__ in SNIPPET_EDIT_HANDLERS:
                del SNIPPET_EDIT_HANDLERS[self.__class__]
            edit_handler_class = get_snippet_edit_handler(self.__class__)

        form = edit_handler_class.get_form_class(self.__class__)
        for fname, f in form.base_fields.items():
            if fname in TranslationMixin._translation_options.fields and TranslationMixin._is_orig_required(fname):
                f.required = False

        self.__class__._translated = True

    @staticmethod
    def _fetch_defined_tabs(defined_class):
        """
        Fetch tabs defined by user in models.py
        """
        tabs = ()

        # If user has defined panels dict on models.py
        if hasattr(defined_class, 'panels'):
            # TEST !!!
            tabs += (('panels',
                      copy.deepcopy(defined_class.panels)),)
        # Check for common tabs
        else:
            if hasattr(defined_class, 'content_panels'):
                tabs += (('content_panels',
                          copy.deepcopy(defined_class.content_panels)),)
            if hasattr(defined_class, 'promote_panels'):
                tabs += (('promote_panels',
                          copy.deepcopy(defined_class.promote_panels)),)
            if hasattr(defined_class, 'settings_panels'):
                tabs += (('settings_panels',
                          copy.deepcopy(defined_class.settings_panels)),)

        return tabs

    @staticmethod
    def _patch_panel(instance, panel, inline_tr_options=None):
        """
        Generic panel patching function
        """
        trpanels = None

        if panel.__class__.__name__ == 'FieldPanel':
            trpanels = TranslationMixin._patch_fieldpanel(
                panel, inline_tr_options)
        elif panel.__class__.__name__ == 'MultiFieldPanel':
            trpanels = [TranslationMixin._patch_multifieldpanel(
                panel, inline_tr_options)]
        elif panel.__class__.__name__ == 'InlinePanel':
            TranslationMixin._patch_inlinepanel(instance, panel)
            trpanels = [panel]
        else:
            trpanels = [panel]

        return trpanels

    @classmethod
    def _is_orig_required(cls, field_name, formset=None):
        """
        check if original field is required
        TODO:
        if formset is given, example for inline models.
        """
        required = False

        if not formset:
            for fname, f in cls._wgform_class.base_fields.items():
                if fname == field_name:
                    if f.required:
                        required = True
                    break

        return required

    @classmethod
    def _patch_fieldpanel(cls, fieldpanel, inline_tr_options=None):
        """
        Patch FieldPanels and return one per available language
        """
        tr_fields = []
        if inline_tr_options:
            tr_fields = inline_tr_options
        else:
            tr_fields = cls._translation_options.fields

        translated_fieldpanels = []
        if fieldpanel.field_name in tr_fields:
            # original field, HIDDEN
            # translated_fieldpanels.append(
            #     FieldPanel(
            #         fieldpanel.field_name,
            #         classname='visuallyhidden'))

            for lang in settings.LANGUAGES:
                classes = fieldpanel.classname

                if cls._is_orig_required(fieldpanel.field_name) and\
                   (lang[0] == settings.LANGUAGE_CODE):
                    classes += ' required'
                translated_field_name = "%s_%s" % (
                        fieldpanel.field_name, lang[0])
                translated_fieldpanels.append(
                    FieldPanel(
                        translated_field_name,
                        classname=classes))

            # delete original field from form
            if fieldpanel.field_name in cls._wgform_class._meta.fields:
                cls._wgform_class._meta.fields.remove(fieldpanel.field_name)
        else:
            return [fieldpanel]

        return translated_fieldpanels<commit_msg>fixed bug of required fields<commit_after># coding: utf-8

import copy

from django.conf import settings
from django.http import Http404
from django.db.models import Q

from wagtail.wagtailcore.models import Page
from wagtail.wagtailadmin.edit_handlers import FieldPanel,\
                                               MultiFieldPanel, FieldRowPanel
from wagtail.wagtailadmin.views.pages import get_page_edit_handler,\
                                             PAGE_EDIT_HANDLERS
from wagtail.wagtailsnippets.views.snippets import get_snippet_edit_handler,\
                                                   SNIPPET_EDIT_HANDLERS
from wagtail.wagtailcore.url_routing import RouteResult

from modeltranslation.translator import translator, NotRegistered


####################################
# TRANSLATION MIXIN
####################################
class TranslationMixin(object):
    _translation_options = None
    _wgform_class = None
    _translated = False
    _required_fields = []

    def __init__(self, *args, **kwargs):
        super(TranslationMixin, self).__init__(*args, **kwargs)

        TranslationMixin._translation_options = translator.\
            get_options_for_model(
                self.__class__)

        if self.__class__._translated:
            return

        # CONSTRUCT TEMPORARY EDIT HANDLER
        if issubclass(self.__class__, Page):
            edit_handler_class = get_page_edit_handler(self.__class__)
        else:
            edit_handler_class = get_snippet_edit_handler(self.__class__)
        TranslationMixin._wgform_class = edit_handler_class.get_form_class(
            self.__class__)

        defined_tabs = TranslationMixin._fetch_defined_tabs(self.__class__)

        for tab_name, tab in defined_tabs:
            patched_tab = []

            for panel in tab:
                trtab = TranslationMixin._patch_panel(self, panel)

                if trtab:
                    for x in trtab:
                        patched_tab.append(x)

            setattr(self.__class__, tab_name, patched_tab)

        # DELETE TEMPORARY EDIT HANDLER IN ORDER TO LET WAGTAIL RECONSTRUCT
        # NEW EDIT HANDLER BASED ON NEW TRANSLATION PANELS
        if issubclass(self.__class__, Page):
            if self.__class__ in PAGE_EDIT_HANDLERS:
                del PAGE_EDIT_HANDLERS[self.__class__]
            edit_handler_class = get_page_edit_handler(self.__class__)
        else:
            if self.__class__ in SNIPPET_EDIT_HANDLERS:
                del SNIPPET_EDIT_HANDLERS[self.__class__]
            edit_handler_class = get_snippet_edit_handler(self.__class__)

        form = edit_handler_class.get_form_class(self.__class__)
        for fname, f in form.base_fields.items():
            # set field required on formset level if original field is required as well
            if fname in self._required_fields:
                f.required = True

            if fname in TranslationMixin._translation_options.fields and TranslationMixin._is_orig_required(fname):
                f.required = False

        self.__class__._translated = True

    @staticmethod
    def _fetch_defined_tabs(defined_class):
        """
        Fetch tabs defined by user in models.py
        """
        tabs = ()

        # If user has defined panels dict on models.py
        if hasattr(defined_class, 'panels'):
            # TEST !!!
            tabs += (('panels',
                      copy.deepcopy(defined_class.panels)),)
        # Check for common tabs
        else:
            if hasattr(defined_class, 'content_panels'):
                tabs += (('content_panels',
                          copy.deepcopy(defined_class.content_panels)),)
            if hasattr(defined_class, 'promote_panels'):
                tabs += (('promote_panels',
                          copy.deepcopy(defined_class.promote_panels)),)
            if hasattr(defined_class, 'settings_panels'):
                tabs += (('settings_panels',
                          copy.deepcopy(defined_class.settings_panels)),)

        return tabs

    @staticmethod
    def _patch_panel(instance, panel, inline_tr_options=None):
        """
        Generic panel patching function
        """
        trpanels = None

        if panel.__class__.__name__ == 'FieldPanel':
            trpanels = TranslationMixin._patch_fieldpanel(
                panel, inline_tr_options)
        elif panel.__class__.__name__ == 'MultiFieldPanel':
            trpanels = [TranslationMixin._patch_multifieldpanel(
                panel, inline_tr_options)]
        elif panel.__class__.__name__ == 'InlinePanel':
            TranslationMixin._patch_inlinepanel(instance, panel)
            trpanels = [panel]
        else:
            trpanels = [panel]

        return trpanels

    @classmethod
    def _is_orig_required(cls, field_name, formset=None):
        """
        check if original field is required
        TODO:
        if formset is given, example for inline models.
        """
        required = False

        if not formset:
            for fname, f in cls._wgform_class.base_fields.items():
                if fname == field_name:
                    if f.required:
                        required = True
                    break

        return required

    @classmethod
    def _patch_fieldpanel(cls, fieldpanel, inline_tr_options=None):
        """
        Patch FieldPanels and return one per available language
        """
        tr_fields = []
        if inline_tr_options:
            tr_fields = inline_tr_options
        else:
            tr_fields = cls._translation_options.fields

        translated_fieldpanels = []
        if fieldpanel.field_name in tr_fields:
            for lang in settings.LANGUAGES:
                classes = fieldpanel.classname

                if cls._is_orig_required(fieldpanel.field_name) and\
                   (lang[0] == settings.LANGUAGE_CODE):
                    if ("%s_%s" % (fieldpanel.field_name, lang[0]) not in cls._required_fields):
                        cls._required_fields.append("%s_%s" % (
                                fieldpanel.field_name, lang[0]))

                translated_field_name = "%s_%s" % (
                        fieldpanel.field_name, lang[0])
                translated_fieldpanels.append(
                    FieldPanel(
                        translated_field_name,
                        classname=classes))

            # delete original field from form
            if fieldpanel.field_name in cls._wgform_class._meta.fields:
                cls._wgform_class._meta.fields.remove(fieldpanel.field_name)
        else:
            return [fieldpanel]

        return translated_fieldpanels
{'fraction_non_alphanumeric': 0.08055723803755299, 'fraction_numerical': 0.0010599636583888553, 'mean_word_length': 1.9353333333333333, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6700526', 'n_tokens_mistral': 3614, 'n_tokens_neox': 3411, 'n_words': 748}