text: import logging
  
  import factory
  from django.utils.text import slugify
  from factory import errors, utils
  from factory.declarations import ParameteredAttribute
  from wagtail import VERSION as WAGTAIL_VERSION
  from wagtail.core.models import Collection, Page, Site
  from wagtail.images import get_image_model
  
  try:
      from factory.django import DjangoModelFactory
  except ImportError:
      from factory import DjangoModelFactory
  
  if WAGTAIL_VERSION >= (2, 8):
      from wagtail.documents import get_document_model
  else:
      from wagtail.documents.models import get_document_model
  
  __all__ = [
      "CollectionFactory",
      "ImageFactory",
      "PageFactory",
      "SiteFactory",
      "DocumentFactory",
  ]
  logger = logging.getLogger(__file__)
  
  
  class ParentNodeFactory(ParameteredAttribute):
  
      EXTEND_CONTAINERS = True
      FORCE_SEQUENCE = False
      UNROLL_CONTEXT_BEFORE_EVALUATION = False
  
      def generate(self, step, params):
          if not params:
              return None
  
          subfactory = step.builder.factory_meta.factory
          logger.debug(
              "ParentNodeFactory: Instantiating %s.%s(%s), create=%r",
              subfactory.__module__,
              subfactory.__name__,
              utils.log_pprint(kwargs=params),
              step,
          )
          force_sequence = step.sequence if self.FORCE_SEQUENCE else None
          return step.recurse(subfactory, params, force_sequence=force_sequence)
  
  
  class MP_NodeFactory(DjangoModelFactory):
  
      parent = ParentNodeFactory()
  
      @classmethod
      def _build(cls, model_class, *args, **kwargs):
          kwargs.pop("parent")
          return model_class(**kwargs)
  
      @classmethod
      def _create(cls, model_class, *args, **kwargs):
          parent = kwargs.pop("parent")
  
          if cls._meta.django_get_or_create:
              instance = cls._get_or_create(model_class, *args, parent=parent, **kwargs)
          else:
              instance = cls._create_instance(model_class, parent, kwargs)
              assert instance.pk
          return instance
  
      @classmethod
      def _create_instance(cls, model_class, parent, kwargs):
          instance = model_class(**kwargs)
          if parent:
              parent.add_child(instance=instance)
          else:
              model_class.add_root(instance=instance)
          return instance
  
      @classmethod
      def _get_or_create(cls, model_class, *args, **kwargs):
          """Create an instance of the model through objects.get_or_create."""
          manager = cls._get_manager(model_class)
          assert "defaults" not in cls._meta.django_get_or_create, (
              "'defaults' is a reserved keyword for get_or_create "
              "(in %s._meta.django_get_or_create=%r)"
              % (cls, cls._meta.django_get_or_create)
          )
  
          lookup_fields = {}
          for field in cls._meta.django_get_or_create:
              if field not in kwargs:
                  raise errors.FactoryError(
                      "django_get_or_create - "
                      "Unable to find initialization value for '%s' in factory %s"
                      % (field, cls.__name__)
                  )
              lookup_fields[field] = kwargs[field]
  
          parent = lookup_fields.pop("parent", None)
          kwargs.pop("parent", None)
  
          if parent:
              try:
                  return manager.child_of(parent).get(**lookup_fields)
              except model_class.DoesNotExist:
                  return cls._create_instance(model_class, parent, kwargs)
          else:
              return super()._get_or_create(model_class, *args, **kwargs)
  
  
  class CollectionFactory(MP_NodeFactory):
      name = "Test collection"
  
      class Meta:
          model = Collection
  
  
  class PageFactory(MP_NodeFactory):
      title = "Test page"
      slug = factory.LazyAttribute(lambda obj: slugify(obj.title))
  
      class Meta:
          model = Page
  
  
  class CollectionMemberFactory(DjangoModelFactory):
      collection = factory.SubFactory(CollectionFactory, parent=None)
  
  
  class ImageFactory(CollectionMemberFactory):
      class Meta:
          model = get_image_model()
  
      title = "An image"
      file = factory.django.ImageField()
  
  
  class SiteFactory(DjangoModelFactory):
      hostname = "localhost"
      port = factory.Sequence(lambda n: 81 + n)
      site_name = "Test site"
      root_page = factory.SubFactory(PageFactory, parent=None)
      is_default_site = False
  
      class Meta:
          model = Site
  
  
  class DocumentFactory(CollectionMemberFactory):
      class Meta:
          model = get_document_model()
  
      title = "An document"
      file = factory.django.FileField()
  