<commit_before># -*- coding: UTF-8 -*-
# Copyright 2010-2018 Rumma & Ko Ltd
# License: BSD (see file COPYING for details)

from builtins import str
from builtins import object


from django.contrib.contenttypes.models import ContentType, models

from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.db.utils import DatabaseError
from django.db.models import FieldDoesNotExist

from lino.core.roles import SiteStaff
from lino.api import dd, rt
from etgen.html import E
from lino.utils import join_elems

from lino.core.utils import get_models


class ContentTypes(dd.Table):
    model = 'contenttypes.ContentType'

    required_roles = dd.login_required(SiteStaff)

    detail_layout = """
    id app_label model base_classes
    HelpTextsByModel
    BrokenGFKsByModel
    """

    @dd.displayfield(_("Base classes"))
    def base_classes(self, obj, ar):
        if obj is None:
            return ""
        chunks = []

        def add(cl):
            for b in cl.__bases__:
                add(b)
            # :
            if issubclass(cl, dd.Model) and cl is not dd.Model \
               and cl._meta.managed:
                if getattr(cl, '_meta', False) and not cl._meta.abstract:
                    #~ logger.info("20120205 adding(%r)",cl)
                    ct = ContentType.objects.get_for_model(cl)
                    chunks.append(
                        ar.obj2html(ct, str(cl._meta.verbose_name)))
        #~ add(obj.model_class())
        cl = obj.model_class()
        # e.g. if database is nor synchronized
        if cl is not None:
            for b in cl.__bases__:
                add(b)
        return E.p(*join_elems(chunks, sep=', '))



class HelpText(dd.Model):
    class Meta(object):
        app_label = 'gfks'
        verbose_name = _("Help Text")
        verbose_name_plural = _("Help Texts")

    content_type = dd.ForeignKey('contenttypes.ContentType',
                                 verbose_name=_("Model"))
    field = models.CharField(_("Field"), max_length=200)

    help_text = dd.RichTextField(_("HelpText"),
                                 blank=True, null=True, format='plain')

    def __str__(self):
        return self.content_type.app_label + '.' \
            + self.content_type.model + '.' + self.field

    @dd.chooser(simple_values=True)
    def field_choices(cls, content_type):
        l = []
        if content_type is not None:
            model = content_type.model_class()
            meta = model._meta
            for f in meta.fields:
                if not getattr(f, '_lino_babel_field', False):
                    l.append(f.name)
            for f in meta.many_to_many:
                l.append(f.name)
            for f in meta.virtual_fields:
                l.append(f.name)
            for a in model.get_default_table().get_actions():
                l.append(a.action.action_name)
            l.sort()
        return l

    #~ def get_field_display(cls,fld):
        #~ return fld

    @dd.virtualfield(models.CharField(_("Verbose name"), max_length=200))
    def verbose_name(self, request):
        m = self.content_type.model_class()
        de = m.get_default_table().get_data_elem(self.field)
        if isinstance(de, models.Field):
            return "%s (%s)" % (str(de.verbose_name),
                                str(_("database field")))
        if isinstance(de, dd.VirtualField):
            return str(de.return_type.verbose_name)
        if isinstance(de, dd.Action):
            return str(de.label)
        return str(de)


class HelpTexts(dd.Table):
    required_roles = dd.login_required(SiteStaff)
    model = 'gfks.HelpText'
    column_names = "field verbose_name help_text id content_type"


class HelpTextsByModel(HelpTexts):
    master_key = 'content_type'


class BrokenGFKs(dd.VirtualTable):
    label = _("Broken GFKs")
    required_roles = dd.login_required(SiteStaff)

    column_names = "database_model database_object message todo"

    @classmethod
    def get_data_rows(self, ar):
        f = settings.SITE.kernel.get_broken_generic_related
        for model in get_models(include_auto_created=True):
            for obj in f(model):
                yield obj
    
    @dd.displayfield(_("Database object"))
    def database_object(self, obj, ar):
        return ar.obj2html(obj)

    @dd.displayfield(_("Message"))
    def message(self, obj, ar):<commit_msg>keep ContentType.__str__() as it was in Django 2<commit_after># -*- coding: UTF-8 -*-
# Copyright 2010-2019 Rumma & Ko Ltd
# License: BSD (see file COPYING for details)

from builtins import str
from builtins import object

from django import VERSION
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.db.utils import DatabaseError
from django.db.models import FieldDoesNotExist
from django.contrib.contenttypes.models import ContentType, models

from lino.core.roles import SiteStaff
from lino.api import dd, rt
from etgen.html import E
from lino.utils import join_elems

from lino.core.utils import get_models


if VERSION[0] > 2:
    # restore Django 2 behaviour
    def old__ct_str(self):
        return self.name
    ContentType.__str__ = old__ct_str


class ContentTypes(dd.Table):
    model = 'contenttypes.ContentType'

    required_roles = dd.login_required(SiteStaff)

    detail_layout = """
    id app_label model base_classes
    HelpTextsByModel
    BrokenGFKsByModel
    """

    @dd.displayfield(_("Base classes"))
    def base_classes(self, obj, ar):
        if obj is None:
            return ""
        chunks = []

        def add(cl):
            for b in cl.__bases__:
                add(b)
            # :
            if issubclass(cl, dd.Model) and cl is not dd.Model \
               and cl._meta.managed:
                if getattr(cl, '_meta', False) and not cl._meta.abstract:
                    #~ logger.info("20120205 adding(%r)",cl)
                    ct = ContentType.objects.get_for_model(cl)
                    chunks.append(
                        ar.obj2html(ct, str(cl._meta.verbose_name)))
        #~ add(obj.model_class())
        cl = obj.model_class()
        # e.g. if database is nor synchronized
        if cl is not None:
            for b in cl.__bases__:
                add(b)
        return E.p(*join_elems(chunks, sep=', '))



class HelpText(dd.Model):
    class Meta(object):
        app_label = 'gfks'
        verbose_name = _("Help Text")
        verbose_name_plural = _("Help Texts")

    content_type = dd.ForeignKey('contenttypes.ContentType',
                                 verbose_name=_("Model"))
    field = models.CharField(_("Field"), max_length=200)

    help_text = dd.RichTextField(_("HelpText"),
                                 blank=True, null=True, format='plain')

    def __str__(self):
        return self.content_type.app_label + '.' \
            + self.content_type.model + '.' + self.field

    @dd.chooser(simple_values=True)
    def field_choices(cls, content_type):
        l = []
        if content_type is not None:
            model = content_type.model_class()
            meta = model._meta
            for f in meta.fields:
                if not getattr(f, '_lino_babel_field', False):
                    l.append(f.name)
            for f in meta.many_to_many:
                l.append(f.name)
            for f in meta.virtual_fields:
                l.append(f.name)
            for a in model.get_default_table().get_actions():
                l.append(a.action.action_name)
            l.sort()
        return l

    #~ def get_field_display(cls,fld):
        #~ return fld

    @dd.virtualfield(models.CharField(_("Verbose name"), max_length=200))
    def verbose_name(self, request):
        m = self.content_type.model_class()
        de = m.get_default_table().get_data_elem(self.field)
        if isinstance(de, models.Field):
            return "%s (%s)" % (str(de.verbose_name),
                                str(_("database field")))
        if isinstance(de, dd.VirtualField):
            return str(de.return_type.verbose_name)
        if isinstance(de, dd.Action):
            return str(de.label)
        return str(de)


class HelpTexts(dd.Table):
    required_roles = dd.login_required(SiteStaff)
    model = 'gfks.HelpText'
    column_names = "field verbose_name help_text id content_type"


class HelpTextsByModel(HelpTexts):
    master_key = 'content_type'


class BrokenGFKs(dd.VirtualTable):
    label = _("Broken GFKs")
    required_roles = dd.login_required(SiteStaff)

    column_names = "database_model database_object message todo"

    @classmethod
    def get_data_rows(self, ar):
        f = settings.SITE.kernel.get_broken_generic_related
        for model in get_models(include_auto_created=True):
            for obj in f(model):
                yield obj

    @dd.displayfield(_("Database object"))
    def database_object(self, obj, ar):
        return ar.obj2html(obj)

    @dd.displayfield(_("Message"))
    def message(self, obj, ar):
{'fraction_non_alphanumeric': 0.10327288810260947, 'fraction_numerical': 0.005970809376382132, 'mean_word_length': 2.233821952091527, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5365069', 'n_tokens_mistral': 2840, 'n_tokens_neox': 2687, 'n_words': 637}