<commit_before>from itertools import chain
from textwrap import dedent

import graphene
from django.core.exceptions import ImproperlyConfigured, ValidationError
from graphene.types.mutation import MutationOptions
from graphene_django.registry import get_global_registry
from graphql.error import GraphQLError
from graphql_jwt import ObtainJSONWebToken, Verify
from graphql_jwt.exceptions import JSONWebTokenError, PermissionDenied

from ...account import models
from ..account.types import User
from ..file_upload.types import Upload
from ..utils import get_nodes
from .types.common import Error
from .utils import snake_to_camel_case

registry = get_global_registry()


def get_model_name(model):
    """Return name of the model with first letter lowercase."""
    model_name = model.__name__
    return model_name[:1].lower() + model_name[1:]


def get_output_fields(model, return_field_name):
    """Return mutation output field for model instance."""
    model_type = registry.get_type_for_model(model)
    if not model_type:
        raise ImproperlyConfigured(
            'Unable to find type for model %s in graphene registry' % model.__name__)
    fields = {return_field_name: graphene.Field(model_type)}
    return fields


class ModelMutationOptions(MutationOptions):
    exclude = None
    model = None
    return_field_name = None


class BaseMutation(graphene.Mutation):
    errors = graphene.List(
        Error,
        description='List of errors that occurred executing the mutation.')

    class Meta:
        abstract = True

    @classmethod
    def __init_subclass_with_meta__(cls, description=None, **options):
        if not description:
            raise ImproperlyConfigured('No description provided in Meta')
        description = dedent(description)
        super().__init_subclass_with_meta__(description=description, **options)

    @classmethod
    def _update_mutation_arguments_and_fields(cls, arguments, fields):
        cls._meta.arguments.update(arguments)
        cls._meta.fields.update(fields)

    @classmethod
    def add_error(cls, errors, field, message):
        """Add a mutation user error.

        `errors` is the list of errors that happened during the execution of
        the mutation. `field` is the name of an input field the error is
        related to. `None` value is allowed and it indicates that the error
        is general and is not related to any of the input fields. `message`
        is the actual error message to be returned in the response.

        As a result of this method, the `errors` list is updated with an Error
        object to be returned as mutation result.
        """
        field = snake_to_camel_case(field)
        errors.append(Error(field=field, message=message))

    @classmethod
    def get_node_or_error(cls, info, global_id, errors, field, only_type=None):
        node = None
        try:
            node = graphene.Node.get_node_from_global_id(
                info, global_id, only_type)
        except (AssertionError, GraphQLError) as e:
            cls.add_error(errors, field, str(e))
        else:
            if node is None:
                message = "Couldn't resolve to a node: %s" % global_id
                cls.add_error(errors, field, message)
        return node

    @classmethod
    def get_nodes_or_error(cls, ids, errors, field, only_type=None):
        instances = None
        try:
            instances = get_nodes(ids, only_type)
        except GraphQLError as e:
            cls.add_error(field=field, message=str(e), errors=errors)
        return instances

    @classmethod
    def clean_instance(cls, instance, errors):
        """Clean the instance that was created using the input data.

        Once a instance is created, this method runs `full_clean()` to perform
        model fields' validation. Returns errors ready to be returned by
        the GraphQL response (if any occured).
        """
        try:
            instance.full_clean()
        except ValidationError as validation_errors:
            message_dict = validation_errors.message_dict
            for field in message_dict:
                if hasattr(cls._meta, 'exclude') and field in cls._meta.exclude:
                    continue
                for message in message_dict[field]:
                    field = snake_to_camel_case(field)
                    cls.add_error(errors, field, message)
        return errors


class ModelMutation(BaseMutation):
    class Meta:
        abstract = True

    @classmethod
    def __init_subclass_with_meta__(
            cls, arguments=None, model=None, exclude=None, _meta=None,
            **options):
        if not model:
            raise ImproperlyConfigured('model is required for ModelMutation')
        if not _meta:
            _meta = ModelMutationOptions(cls)

        if exclude is None:
            exclude = []

        return_field_name = get_model_name(model)
        if arguments is None:
            arguments = {}
        fields = get_output_fields(model, return_field_name)

        _meta.model = model
        _meta.return_field_name = return_field_name
        _meta.exclude = exclude
        super().__init_subclass_with_meta__(_meta=_meta, **options)
        cls._update_mutation_arguments_and_fields(
            arguments=arguments, fields=fields)

    @classmethod<commit_msg>Allow to customize return field name in ModelMutation<commit_after>from itertools import chain
from textwrap import dedent

import graphene
from django.core.exceptions import ImproperlyConfigured, ValidationError
from graphene.types.mutation import MutationOptions
from graphene_django.registry import get_global_registry
from graphql.error import GraphQLError
from graphql_jwt import ObtainJSONWebToken, Verify
from graphql_jwt.exceptions import JSONWebTokenError, PermissionDenied

from ...account import models
from ..account.types import User
from ..file_upload.types import Upload
from ..utils import get_nodes
from .types.common import Error
from .utils import snake_to_camel_case

registry = get_global_registry()


def get_model_name(model):
    """Return name of the model with first letter lowercase."""
    model_name = model.__name__
    return model_name[:1].lower() + model_name[1:]


def get_output_fields(model, return_field_name):
    """Return mutation output field for model instance."""
    model_type = registry.get_type_for_model(model)
    if not model_type:
        raise ImproperlyConfigured(
            'Unable to find type for model %s in graphene registry' % model.__name__)
    fields = {return_field_name: graphene.Field(model_type)}
    return fields


class ModelMutationOptions(MutationOptions):
    exclude = None
    model = None
    return_field_name = None


class BaseMutation(graphene.Mutation):
    errors = graphene.List(
        Error,
        description='List of errors that occurred executing the mutation.')

    class Meta:
        abstract = True

    @classmethod
    def __init_subclass_with_meta__(cls, description=None, **options):
        if not description:
            raise ImproperlyConfigured('No description provided in Meta')
        description = dedent(description)
        super().__init_subclass_with_meta__(description=description, **options)

    @classmethod
    def _update_mutation_arguments_and_fields(cls, arguments, fields):
        cls._meta.arguments.update(arguments)
        cls._meta.fields.update(fields)

    @classmethod
    def add_error(cls, errors, field, message):
        """Add a mutation user error.

        `errors` is the list of errors that happened during the execution of
        the mutation. `field` is the name of an input field the error is
        related to. `None` value is allowed and it indicates that the error
        is general and is not related to any of the input fields. `message`
        is the actual error message to be returned in the response.

        As a result of this method, the `errors` list is updated with an Error
        object to be returned as mutation result.
        """
        field = snake_to_camel_case(field)
        errors.append(Error(field=field, message=message))

    @classmethod
    def get_node_or_error(cls, info, global_id, errors, field, only_type=None):
        node = None
        try:
            node = graphene.Node.get_node_from_global_id(
                info, global_id, only_type)
        except (AssertionError, GraphQLError) as e:
            cls.add_error(errors, field, str(e))
        else:
            if node is None:
                message = "Couldn't resolve to a node: %s" % global_id
                cls.add_error(errors, field, message)
        return node

    @classmethod
    def get_nodes_or_error(cls, ids, errors, field, only_type=None):
        instances = None
        try:
            instances = get_nodes(ids, only_type)
        except GraphQLError as e:
            cls.add_error(field=field, message=str(e), errors=errors)
        return instances

    @classmethod
    def clean_instance(cls, instance, errors):
        """Clean the instance that was created using the input data.

        Once a instance is created, this method runs `full_clean()` to perform
        model fields' validation. Returns errors ready to be returned by
        the GraphQL response (if any occured).
        """
        try:
            instance.full_clean()
        except ValidationError as validation_errors:
            message_dict = validation_errors.message_dict
            for field in message_dict:
                if hasattr(cls._meta, 'exclude') and field in cls._meta.exclude:
                    continue
                for message in message_dict[field]:
                    field = snake_to_camel_case(field)
                    cls.add_error(errors, field, message)
        return errors


class ModelMutation(BaseMutation):
    class Meta:
        abstract = True

    @classmethod
    def __init_subclass_with_meta__(
            cls, arguments=None, model=None, exclude=None, return_field_name=None,
            _meta=None, **options):
        if not model:
            raise ImproperlyConfigured('model is required for ModelMutation')
        if not _meta:
            _meta = ModelMutationOptions(cls)

        if exclude is None:
            exclude = []

        if not return_field_name:
            return_field_name = get_model_name(model)
        if arguments is None:
            arguments = {}
        fields = get_output_fields(model, return_field_name)

        _meta.model = model
        _meta.return_field_name = return_field_name
        _meta.exclude = exclude
        super().__init_subclass_with_meta__(_meta=_meta, **options)
        cls._update_mutation_arguments_and_fields(
            arguments=arguments, fields=fields)

    @classmethod
{'fraction_non_alphanumeric': 0.06941612604263207, 'fraction_numerical': 0.0003707136237256719, 'mean_word_length': 2.7442748091603053, '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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1986171', 'n_tokens_mistral': 2957, 'n_tokens_neox': 2847, 'n_words': 914}