# Path: mutant/compat.py
# def get_remote_field_model(field):
# def get_opts_label(opts):
# def many_to_many_set(instance, m2m, value):
# def get_remote_field_model(field):
# def get_opts_label(opts):
# def many_to_many_set(instance, m2m, value):


from collections import defaultdict
from contextlib import contextmanager
from copy import deepcopy
from itertools import chain, groupby
from operator import itemgetter
from django.apps import AppConfig, apps
from django.db import connections, models, router
from django.utils import six
from django.utils.encoding import force_text
from django.utils.functional import lazy
from .compat import get_remote_field, get_remote_field_model

def get_reverse_fields(opts):
    return opts._get_fields(forward=False, reverse=True, include_hidden=True)


def clear_opts_related_cache(model_class):
    opts = model_class._meta
    children = [
        related_object.related_model
        for related_object in opts.__dict__.get('related_objects', []) if related_object.parent_link
    ]
    opts._expire_cache()
    for child in children:
        clear_opts_related_cache(child)


def unreference_model(model):
    for field in get_foward_fields(model._meta):
        remote_field = get_remote_field(field)
        if field.model is model and remote_field:
            remote_field_model = get_remote_field_model(field)
            if isinstance(remote_field_model, models.base.ModelBase):
                clear_opts_related_cache(remote_field_model)
                rel_is_hidden = remote_field.is_hidden()
                # An accessor is added to related classes if they are not
                # hidden. However o2o fields *always* add an accessor
                # even if the relationship is hidden.
                o2o = isinstance(field, models.OneToOneField)
                if not rel_is_hidden or o2o:
                    try:

# Path: mutant/compat.py
# def get_remote_field_model(field):
# def get_opts_label(opts):
# def many_to_many_set(instance, m2m, value):
# def get_remote_field_model(field):
# def get_opts_label(opts):
# def many_to_many_set(instance, m2m, value):


# Path: mutant/utils.py
from collections import defaultdict
from contextlib import contextmanager
from copy import deepcopy
from itertools import chain, groupby
from operator import itemgetter
from django.apps import AppConfig, apps
from django.db import connections, models, router
from django.utils import six
from django.utils.encoding import force_text
from django.utils.functional import lazy
from .compat import get_remote_field, get_remote_field_model


def get_reverse_fields(opts):
    return opts._get_fields(forward=False, reverse=True, include_hidden=True)


def clear_opts_related_cache(model_class):
    opts = model_class._meta
    children = [
        related_object.related_model
        for related_object in opts.__dict__.get('related_objects', []) if related_object.parent_link
    ]
    opts._expire_cache()
    for child in children:
        clear_opts_related_cache(child)


def unreference_model(model):
    for field in get_foward_fields(model._meta):
        remote_field = get_remote_field(field)
        if field.model is model and remote_field:
            remote_field_model = get_remote_field_model(field)
            if isinstance(remote_field_model, models.base.ModelBase):
                clear_opts_related_cache(remote_field_model)
                rel_is_hidden = remote_field.is_hidden()
                # An accessor is added to related classes if they are not
                # hidden. However o2o fields *always* add an accessor
                # even if the relationship is hidden.
                o2o = isinstance(field, models.OneToOneField)
                if not rel_is_hidden or o2o:
                    try:

                        delattr(remote_field_model, get_remote_field(field).get_accessor_name())