<commit_before># -*- coding: utf-8 -*-
import inspect

from aserializer.utils import py2to3
from aserializer.base import Serializer, SerializerBase
from aserializer import fields as serializer_fields
from aserializer.django.utils import get_related_model_from_field

try:
    from django.db import models as django_models
    model_field_mapping = {
        django_models.AutoField: serializer_fields.IntegerField,
        django_models.FloatField: serializer_fields.FloatField,
        django_models.PositiveIntegerField: serializer_fields.PositiveIntegerField,
        django_models.SmallIntegerField: serializer_fields.IntegerField,
        django_models.PositiveSmallIntegerField: serializer_fields.PositiveIntegerField,
        django_models.IntegerField: serializer_fields.IntegerField,
        django_models.DateTimeField: serializer_fields.DatetimeField,
        django_models.DateField: serializer_fields.DateField,
        django_models.TimeField: serializer_fields.TimeField,
        django_models.DecimalField: serializer_fields.DecimalField,
        django_models.EmailField: serializer_fields.EmailField,
        django_models.CharField: serializer_fields.StringField,
        django_models.URLField: serializer_fields.UrlField,
        django_models.SlugField: serializer_fields.StringField,
        django_models.TextField: serializer_fields.StringField,
        django_models.CommaSeparatedIntegerField: serializer_fields.StringField,
        django_models.BooleanField: serializer_fields.BooleanField,
        django_models.NullBooleanField: serializer_fields.BooleanField,
    }
except ImportError:
    django_models = None
    model_field_mapping = {}


class DjangoModelSerializerBase(SerializerBase):

    def __new__(cls, name, bases, attrs):
        new_class = super(DjangoModelSerializerBase, cls).__new__(cls, name, bases, attrs)
        cls.set_fields_from_model(new_class=new_class,
                                  fields=new_class._base_fields,
                                  model=new_class._meta.model)
        return new_class

    @staticmethod
    def get_all_fieldnames(fields):
        result = []
        for name, field in fields.items():
            result.append(name)
            if field.map_field:
                result.append(field.map_field)
        return list(set(result))

    @classmethod
    def set_fields_from_model(cls, new_class, fields, model):
        setattr(new_class, 'model_fields', [])
        if django_models is None or model is None:
            return
        opts = model._meta.concrete_model._meta

        all_field_names = cls.get_all_fieldnames(fields)
        for model_field in opts.fields:
            if model_field.name not in all_field_names:
                if cls.add_model_field(fields, model_field):
                    new_class.model_fields.append(model_field.name)
            else:
                new_class.model_fields.append(model_field.name)

    @staticmethod
    def get_field_class(model_field, mapping=None):
        if mapping is None:
            mapping = model_field_mapping
        for model in inspect.getmro(model_field.__class__):
            if model in mapping:
                return mapping[model]
        return None

    @staticmethod
    def get_nested_serializer_field(model_field):
        class NestedModelSerializer(NestedDjangoModelSerializer):
            class Meta:
                model = model_field

        kwargs = dict(serializer=NestedModelSerializer)
        return serializer_fields.SerializerField(**kwargs)

    @classmethod
    def get_field_from_modelfield(cls, model_field, **kwargs):
        field_class = cls.get_field_class(model_field)
        if model_field.primary_key:
            kwargs['identity'] = True
            kwargs['required'] = False
            kwargs['on_null'] = serializer_fields.HIDE_FIELD
        if model_field.null or model_field.blank:
            kwargs['required'] = False
        if model_field.has_default():
            kwargs['default'] = model_field.get_default()
        if model_field.flatchoices:
            kwargs['choices'] = model_field.flatchoices
            return serializer_fields.ChoiceField(**kwargs)

        if isinstance(model_field, django_models.CharField) and not isinstance(model_field, django_models.URLField):
            max_length = getattr(model_field, 'max_length', None)
            if max_length is not None:
                kwargs.update({'max_length': getattr(model_field, 'max_length')})
        elif isinstance(model_field, django_models.DecimalField):
            kwargs.update({'decimal_places': getattr(model_field, 'decimal_places')})
        if field_class is None:
            return cls.get_nested_serializer_field(get_related_model_from_field(model_field))
        return field_class(**kwargs)

    @classmethod
    def add_model_field(cls, fields, model_field, **kwargs):
        _field = cls.get_field_from_modelfield(model_field, **kwargs)<commit_msg>Added support for kwargs for get_nested_serializer_field<commit_after># -*- coding: utf-8 -*-
import inspect

from aserializer.utils import py2to3
from aserializer.base import Serializer, SerializerBase
from aserializer import fields as serializer_fields
from aserializer.django.utils import get_related_model_from_field, is_relation_field_relation

try:
    from django.db import models as django_models
    model_field_mapping = {
        django_models.AutoField: serializer_fields.IntegerField,
        django_models.FloatField: serializer_fields.FloatField,
        django_models.PositiveIntegerField: serializer_fields.PositiveIntegerField,
        django_models.SmallIntegerField: serializer_fields.IntegerField,
        django_models.PositiveSmallIntegerField: serializer_fields.PositiveIntegerField,
        django_models.IntegerField: serializer_fields.IntegerField,
        django_models.DateTimeField: serializer_fields.DatetimeField,
        django_models.DateField: serializer_fields.DateField,
        django_models.TimeField: serializer_fields.TimeField,
        django_models.DecimalField: serializer_fields.DecimalField,
        django_models.EmailField: serializer_fields.EmailField,
        django_models.CharField: serializer_fields.StringField,
        django_models.URLField: serializer_fields.UrlField,
        django_models.SlugField: serializer_fields.StringField,
        django_models.TextField: serializer_fields.StringField,
        django_models.CommaSeparatedIntegerField: serializer_fields.StringField,
        django_models.BooleanField: serializer_fields.BooleanField,
        django_models.NullBooleanField: serializer_fields.BooleanField,
    }
except ImportError:
    django_models = None
    model_field_mapping = {}


class DjangoModelSerializerBase(SerializerBase):

    def __new__(cls, name, bases, attrs):
        new_class = super(DjangoModelSerializerBase, cls).__new__(cls, name, bases, attrs)
        cls.set_fields_from_model(new_class=new_class,
                                  fields=new_class._base_fields,
                                  model=new_class._meta.model)
        return new_class

    @staticmethod
    def get_all_fieldnames(fields):
        result = []
        for name, field in fields.items():
            result.append(name)
            if field.map_field:
                result.append(field.map_field)
        return list(set(result))

    @classmethod
    def set_fields_from_model(cls, new_class, fields, model):
        setattr(new_class, 'model_fields', [])
        if django_models is None or model is None:
            return
        opts = model._meta.concrete_model._meta

        all_field_names = cls.get_all_fieldnames(fields)
        for model_field in opts.fields:
            if model_field.name not in all_field_names:
                if cls.add_model_field(fields, model_field):
                    new_class.model_fields.append(model_field.name)
            else:
                new_class.model_fields.append(model_field.name)

    @staticmethod
    def get_field_class(model_field, mapping=None):
        if mapping is None:
            mapping = model_field_mapping
        for model in inspect.getmro(model_field.__class__):
            if model in mapping:
                return mapping[model]
        return None

    @staticmethod
    def get_nested_serializer_field(model_field, **kwargs):
        class NestedModelSerializer(NestedDjangoModelSerializer):
            class Meta:
                model = model_field

        kwargs.update(dict(serializer=NestedModelSerializer))
        return serializer_fields.SerializerField(**kwargs)

    @classmethod
    def get_field_from_modelfield(cls, model_field, **kwargs):
        field_class = cls.get_field_class(model_field)
        if model_field.primary_key:
            kwargs['identity'] = True
            kwargs['required'] = False
            kwargs['on_null'] = serializer_fields.HIDE_FIELD
        if model_field.null:
            kwargs['required'] = False
        if model_field.has_default():
            kwargs['default'] = model_field.get_default()
        if model_field.flatchoices:
            kwargs['choices'] = model_field.flatchoices
            return serializer_fields.ChoiceField(**kwargs)

        if isinstance(model_field, django_models.CharField) and not isinstance(model_field, django_models.URLField):
            max_length = getattr(model_field, 'max_length', None)
            if max_length is not None:
                kwargs.update({'max_length': getattr(model_field, 'max_length')})
        elif isinstance(model_field, django_models.DecimalField):
            kwargs.update({'decimal_places': getattr(model_field, 'decimal_places')})
        if field_class is None:
            if is_relation_field_relation(model_field):
                return cls.get_nested_serializer_field(get_related_model_from_field(model_field), **kwargs)
            return None
        return field_class(**kwargs)

    @classmethod
    def add_model_field(cls, fields, model_field, **kwargs):
        _field = cls.get_field_from_modelfield(model_field, **kwargs)
{'fraction_non_alphanumeric': 0.0742172017439556, 'fraction_numerical': 0.0005945303210463733, 'mean_word_length': 3.068117694478033, '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': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2469998', 'n_tokens_mistral': 2795, 'n_tokens_neox': 2747, 'n_words': 508}