Plone 5.2.1 theming AttributeError: 'RequestContainer' object has no attribute 'PARENTS'

Hello all!

I'm running Plone 5.2.1 on Python 3.7.2 and working on theming my website. I have tried using both the Minimal Buildout and the Unified Installer. Once the site is launched to localhost, when I access the theming control panel and press the picture icon to preview or modify the theme and press the 'preview theme button' I receive the below stack trace. This occurs with the default Barceloneta theme as well as a theme that I import via a zip file.

Any information anyone can provide would be greatly appreciated!

Stacktrace:
AttributeError
Traceback (innermost last):
Module ZPublisher.WSGIPublisher, line 156, in transaction_pubevents
Module ZPublisher.WSGIPublisher, line 338, in publish_module
Module ZPublisher.WSGIPublisher, line 256, in publish
Module ZPublisher.mapply, line 85, in mapply
Module ZPublisher.WSGIPublisher, line 62, in call_object
Module plone.app.theming.browser.mapper, line 269, in getFrame
Module plone.app.theming.utils, line 193, in findContext
AttributeError: 'RequestContainer' object has no attribute 'PARENTS'

Version Overview

  • Plone 5.2.1 (5208)
  • CMF 2.4.2
  • Zope 4.1.3
  • Python 3.7.2 (default, Mar 24 2020, 13:50:54) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
  • PIL 6.2.1 (Pillow)
  • WSGI: On
  • Server: waitress 1.4.3

This seems to be an issue in the product plone.app.theming. I have the same problem with one of my new, local instances:

  • Plone 5.2.0 (5207)
  • CMF 2.4.0
  • Zope 4.1.1
  • Python 3.6.9 (default, Nov 7 2019, 10:44:02) [GCC 8.3.0]
  • PIL 6.1.0 (Pillow)
  • WSGI: An
  • Server: waitress 1.3.0

Just opened an issue on github: plone.app.theming #173

I agree, it is an issue with plone.app.theming. I was able to provide a work around solution by the following changes:

plone.app.theming.util.py
my new instance had no published content so the request.PARENTS[0] was null. I changed the def findContext(request) method to this:

def findContext(request):
    """Find the context from the request
    """
    published = request.get('PUBLISHED', None)
    context = getattr(published, '__parent__', None)
    if context is not None:
        return context

    #added this additional if check
    if not request:
        for parent in request.PARENTS:
            if IContentish.providedBy(parent) or ISiteRoot.providedBy(parent):
                return parent
        #and return with in the if block
        return request.PARENTS[0]

    #change the return type if the if fails
    return request

and then in plone.app.theming.browser.mapper.py in the def getFrame(self) method I changed the return type as bytes were being passed but strings were expected

result = ''.join(str(serializer))

Hope this helps anyone that is currently experiencing this issue

It makes no sense to me that a acquisition-wrapped previewed object is passed to utils.findContext by mapper.getFrame when a request is what findContext is expecting. I am guessing instead of calling findContext, getFrame should just use the previewed object or its parent as the context.

There's a PR; https://github.com/plone/plone.app.theming/pull/181

1 Like