# Path: feincms3/regions.py
# class Regions:
#     """
#     ``Regions`` uses ``content_editor.contents.Contents`` and the
#     ``feincms3.renderer.TemplatePluginRenderer`` to convert a list of plugins
#     into a rendered representation, most often a HTML fragment.
# 
#     This class may also be instantiated directly but using the factory methods
#     (starting with ``from_``) below is probably more comfortable.
#     """
# 
#     @classmethod
#     def from_contents(cls, contents, *, renderer, **kwargs):
#         """
#         Create and return a regions instance using the bare minimum of a
#         contents instance and a renderer. Additional keyword arguments are
#         forwarded to the regions constructor.
#         """
#         return cls(contents=contents, renderer=renderer, **kwargs)
# 
#     @classmethod
#     def from_item(cls, item, *, renderer, inherit_from=None, timeout=None, **kwargs):
#         """
#         Create and return a regions instance for an item (for example a page,
#         an article or anything else managed by django-content-editor).
# 
#         The item's plugins are determined by what is registered with the
#         renderer. The plugin instances themselves are loaded lazily, and
#         loading every time can be avoided completely by specifying a
#         ``timeout``.
#         """
#         if timeout is not None and "cache_key" not in kwargs:
#             key = f"{item._meta.label_lower}-{item.pk}"
#             kwargs["cache_key"] = lambda region: f"{key}-{region}"
#         return cls.from_contents(
#             SimpleLazyObject(
#                 lambda: contents_for_item(
#                     item, renderer.plugins(), inherit_from=inherit_from
#                 )
#             ),
#             renderer=renderer,
#             timeout=timeout,
#             **kwargs,
#         )
# 
#     def __init__(self, *, contents, renderer, cache_key=None, timeout=None):
#         self.contents = contents
#         self.renderer = renderer
#         self.cache_key = cache_key
#         self.timeout = timeout
#         self.handlers = {
#             key[7:]: getattr(self, key)
#             for key in dir(self)
#             if key.startswith("handle_")
#         }
# 
#     @property
#     def regions(self):
#         return self.contents.regions
# 
#     @cached_render
#     def render(self, region, context=None):
#         """
#         Main function for rendering.
# 
#         Starts the generator and assembles all fragments into a safe HTML
#         string.
#         """
#         return mark_safe("".join(self.generate(self.contents[region], context)))
# 
#     def generate(self, items, context):
#         """
#         Inspects all items in the region for a  ``subregion`` attribute and
#         passes control to the subregions' respective rendering handler, named
#         ``handle_<subregion>``. If ``subregion`` is not set or is falsy
#         ``handle_default`` is invoked instead. This method raises a
#         ``KeyError`` exception if no matching handler exists.
# 
#         You probably want to call this method when overriding ``render``.
#         """
#         items = deque(items)
#         while items:
#             subregion = getattr(items[0], "subregion", None) or "default"
#             yield from self.handlers[subregion](items, context)
# 
#     def handle_default(self, items, context):
#         """
#         Renders items from the queue using the renderer instance as long as the
#         items either have no ``subregion`` attribute or whose ``subregion``
#         attribute is an empty string.
#         """
#         while True:
#             yield self.renderer.render_plugin_in_context(items.popleft(), context)
#             if not items or not matches(items[0], subregions={None, ""}):
#                 break
# 
# def matches(item, *, plugins=None, subregions=None):
#     """
#     Checks whether the item matches zero or more constraints.
# 
#     ``plugins`` should be a tuple of plugin classes or ``None`` if the type
#     shouldn't be checked.
# 
#     ``subregions`` should be set of allowed ``subregion`` attribute values or
#     ``None`` if the ``subregion`` attribute shouldn't be checked at all.
#     Include ``None`` in the set if you want ``matches`` to succeed also when
#     encountering an item without a ``subregion`` attribute.
#     """
#     if plugins is not None and not isinstance(item, plugins):
#         return False
#     if subregions is not None and getattr(item, "subregion", None) not in subregions:
#         return False
#     return True
# 
# Path: feincms3/renderer.py
# class TemplatePluginRenderer(RegionRenderer):
#     """
#     TemplatePluginRenderer is deprecated, use
#     :class:`~feincms3.renderer.RegionRenderer`.
#     """
# 
#     def __init__(self, *args, **kwargs):
#         warnings.warn(
#             "TemplatePluginRenderer is deprecated. Switch to the RegionRenderer now.",
#             DeprecationWarning,
#             stacklevel=2,
#         )
#         super().__init__(*args, **kwargs)


from types import SimpleNamespace
from django.test import TestCase
from feincms3.regions import Regions, matches
from feincms3.renderer import TemplatePluginRenderer
                    Command(subregion="faq"),
                    FAQ(text="Question"),
                    File(text="download2.pdf"),  # ...and inside the FAQ renderer
                    Text(text="Text 2"),  # Main renderer again.
                ]
            },
            renderer=renderer,
        )

        self.assertEqual(
            regions.render("main"),
            'Text 1download1.pdf<div class="faq">Questiondownload2.pdf</div>Text 2',
        )

    def test_restart_subregion(self):
        """Restarting the subregion we're already in works correctly"""

        class RestartRegions(Regions):
            def handle_restart(self, items, context):
                first = True
                yield '<div class="stuff">'
                while True:
                    yield self.renderer.render_plugin_in_context(
                        items.popleft(), context
                    )
                    # Item isn't the first and explicitly specifies
                    # subregion="restart", restart subregion
                    if (
                        not first
                        and items

# Path: feincms3/regions.py
# class Regions:
#     """
#     ``Regions`` uses ``content_editor.contents.Contents`` and the
#     ``feincms3.renderer.TemplatePluginRenderer`` to convert a list of plugins
#     into a rendered representation, most often a HTML fragment.
# 
#     This class may also be instantiated directly but using the factory methods
#     (starting with ``from_``) below is probably more comfortable.
#     """
# 
#     @classmethod
#     def from_contents(cls, contents, *, renderer, **kwargs):
#         """
#         Create and return a regions instance using the bare minimum of a
#         contents instance and a renderer. Additional keyword arguments are
#         forwarded to the regions constructor.
#         """
#         return cls(contents=contents, renderer=renderer, **kwargs)
# 
#     @classmethod
#     def from_item(cls, item, *, renderer, inherit_from=None, timeout=None, **kwargs):
#         """
#         Create and return a regions instance for an item (for example a page,
#         an article or anything else managed by django-content-editor).
# 
#         The item's plugins are determined by what is registered with the
#         renderer. The plugin instances themselves are loaded lazily, and
#         loading every time can be avoided completely by specifying a
#         ``timeout``.
#         """
#         if timeout is not None and "cache_key" not in kwargs:
#             key = f"{item._meta.label_lower}-{item.pk}"
#             kwargs["cache_key"] = lambda region: f"{key}-{region}"
#         return cls.from_contents(
#             SimpleLazyObject(
#                 lambda: contents_for_item(
#                     item, renderer.plugins(), inherit_from=inherit_from
#                 )
#             ),
#             renderer=renderer,
#             timeout=timeout,
#             **kwargs,
#         )
# 
#     def __init__(self, *, contents, renderer, cache_key=None, timeout=None):
#         self.contents = contents
#         self.renderer = renderer
#         self.cache_key = cache_key
#         self.timeout = timeout
#         self.handlers = {
#             key[7:]: getattr(self, key)
#             for key in dir(self)
#             if key.startswith("handle_")
#         }
# 
#     @property
#     def regions(self):
#         return self.contents.regions
# 
#     @cached_render
#     def render(self, region, context=None):
#         """
#         Main function for rendering.
# 
#         Starts the generator and assembles all fragments into a safe HTML
#         string.
#         """
#         return mark_safe("".join(self.generate(self.contents[region], context)))
# 
#     def generate(self, items, context):
#         """
#         Inspects all items in the region for a  ``subregion`` attribute and
#         passes control to the subregions' respective rendering handler, named
#         ``handle_<subregion>``. If ``subregion`` is not set or is falsy
#         ``handle_default`` is invoked instead. This method raises a
#         ``KeyError`` exception if no matching handler exists.
# 
#         You probably want to call this method when overriding ``render``.
#         """
#         items = deque(items)
#         while items:
#             subregion = getattr(items[0], "subregion", None) or "default"
#             yield from self.handlers[subregion](items, context)
# 
#     def handle_default(self, items, context):
#         """
#         Renders items from the queue using the renderer instance as long as the
#         items either have no ``subregion`` attribute or whose ``subregion``
#         attribute is an empty string.
#         """
#         while True:
#             yield self.renderer.render_plugin_in_context(items.popleft(), context)
#             if not items or not matches(items[0], subregions={None, ""}):
#                 break
# 
# def matches(item, *, plugins=None, subregions=None):
#     """
#     Checks whether the item matches zero or more constraints.
# 
#     ``plugins`` should be a tuple of plugin classes or ``None`` if the type
#     shouldn't be checked.
# 
#     ``subregions`` should be set of allowed ``subregion`` attribute values or
#     ``None`` if the ``subregion`` attribute shouldn't be checked at all.
#     Include ``None`` in the set if you want ``matches`` to succeed also when
#     encountering an item without a ``subregion`` attribute.
#     """
#     if plugins is not None and not isinstance(item, plugins):
#         return False
#     if subregions is not None and getattr(item, "subregion", None) not in subregions:
#         return False
#     return True
# 
# Path: feincms3/renderer.py
# class TemplatePluginRenderer(RegionRenderer):
#     """
#     TemplatePluginRenderer is deprecated, use
#     :class:`~feincms3.renderer.RegionRenderer`.
#     """
# 
#     def __init__(self, *args, **kwargs):
#         warnings.warn(
#             "TemplatePluginRenderer is deprecated. Switch to the RegionRenderer now.",
#             DeprecationWarning,
#             stacklevel=2,
#         )
#         super().__init__(*args, **kwargs)


# Path: tests/testapp/test_oldregions.py
from types import SimpleNamespace
from django.test import TestCase
from feincms3.regions import Regions, matches
from feincms3.renderer import TemplatePluginRenderer

                    Command(subregion="faq"),
                    FAQ(text="Question"),
                    File(text="download2.pdf"),  # ...and inside the FAQ renderer
                    Text(text="Text 2"),  # Main renderer again.
                ]
            },
            renderer=renderer,
        )

        self.assertEqual(
            regions.render("main"),
            'Text 1download1.pdf<div class="faq">Questiondownload2.pdf</div>Text 2',
        )

    def test_restart_subregion(self):
        """Restarting the subregion we're already in works correctly"""

        class RestartRegions(Regions):
            def handle_restart(self, items, context):
                first = True
                yield '<div class="stuff">'
                while True:
                    yield self.renderer.render_plugin_in_context(
                        items.popleft(), context
                    )
                    # Item isn't the first and explicitly specifies
                    # subregion="restart", restart subregion
                    if (
                        not first
                        and items

                        and matches(items[0], subregions={None, "restart"})