[RESOLVED] Strange issue on upgrading to python3

Hi there.
After upgrading a project to python3.8 / Plone 5.2.6 I have this strange issue and I have no clue about where to look.
The project is running on a M1 and I'm using MySQL as a database.

After the migration of the codebase, the buildout goes well but when I try to start the zope instance I get:

Traceback (most recent call last):
  File "/Users/nicola/workspace/project/parts/instance/bin/interpreter", line 307, in <module>
    exec(compile(__file__f.read(), __file__, "exec"))
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/Startup/serve.py", line 255, in <module>
    sys.exit(main() or 0)
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/Startup/serve.py", line 251, in main
    return command.run()
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/Startup/serve.py", line 189, in run
    app = self.loadapp(app_spec, name=app_name, relative_to=base,
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/Startup/serve.py", line 220, in loadapp
    return loadapp(app_spec, name=name, relative_to=relative_to, **kw)
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/loadwsgi.py", line 253, in loadapp
    return loadobj(APP, uri, name=name, **kw)
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/loadwsgi.py", line 278, in loadobj
    return context.create()
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/loadwsgi.py", line 715, in create
    return self.object_type.invoke(self)
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/loadwsgi.py", line 209, in invoke
    app = context.app_context.create()
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/loadwsgi.py", line 715, in create
    return self.object_type.invoke(self)
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/loadwsgi.py", line 152, in invoke
    return fix_call(context.object, context.global_conf, **context.local_conf)
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/util.py", line 58, in fix_call
    reraise(*exc_info)
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/compat.py", line 32, in reraise
    raise e.with_traceback(tb)
  File "/opt/buildoutcache/egg-cache/cp38/PasteDeploy-2.1.1-py3.8.egg/paste/deploy/util.py", line 55, in fix_call
    val = callable(*args, **kw)
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/Startup/run.py", line 71, in make_wsgi_app
    starter.prepare()
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/Startup/starter.py", line 41, in prepare
    self.startZope()
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/Startup/starter.py", line 99, in startZope
    Zope2.startup_wsgi()
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/__init__.py", line 50, in startup_wsgi
    _startup()
  File "/opt/buildoutcache/egg-cache/cp38/Zope-4.6.3-py3.8.egg/Zope2/App/startup.py", line 162, in startup
    notify(DatabaseOpenedWithRoot(DB))
  File "/opt/buildoutcache/egg-cache/cp38/zope.event-4.5.0-py3.8.egg/zope/event/__init__.py", line 32, in notify
    subscriber(event)
  File "/opt/buildoutcache/egg-cache/cp38/zope.component-4.6.2-py3.8.egg/zope/component/event.py", line 27, in dispatch
    component_subscribers(event, None)
  File "/opt/buildoutcache/egg-cache/cp38/zope.component-4.6.2-py3.8.egg/zope/component/_api.py", line 134, in subscribers
    return sitemanager.subscribers(objects, interface)
  File "/opt/buildoutcache/egg-cache/cp38/zope.interface-5.4.0-py3.8-macosx-12-arm64.egg/zope/interface/registry.py", line 448, in subscribers
    return self.adapters.subscribers(objects, provided)
  File "/opt/buildoutcache/egg-cache/cp38/zope.interface-5.4.0-py3.8-macosx-12-arm64.egg/zope/interface/adapter.py", line 899, in subscribers
    subscription(*objects)
  File "/opt/buildoutcache/egg-cache/cp38/plone.app.theming-4.1.7-py3.8.egg/plone/app/theming/plugins/hooks.py", line 19, in onStartup
    plugin.onDiscovery(
  File "/opt/buildoutcache/egg-cache/cp38/plone.app.themingplugins-1.1-py3.8.egg/plone/app/themingplugins/views/plugin.py", line 101, in onDiscovery
    viewConfig.readfp(fp)
  File "/opt/homebrew/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/configparser.py", line 763, in readfp
    self.read_file(fp, source=filename)
  File "/opt/homebrew/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/configparser.py", line 718, in read_file
    self._read(f, source)
  File "/opt/homebrew/Cellar/python@3.8/3.8.12_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/configparser.py", line 1033, in _read
    if line.strip().startswith(prefix):
TypeError: startswith first arg must be bytes or a tuple of bytes, not str

Does somebody have any idea about this error? Have you seen something like this?

1 Like

Apparently, plone.app.themingplugins is not yet Python 3 compatible.

Yep, that was the cause, thank you!

    def openFile(self, path):
        filepath = self._resolveSubpath(path)
        return open(filepath, 'rb')

the file is opened as binary, while startswith want it as text. The real question is how it worked until now, maybe nobody used comments?

@dieter it should
https://pypi.org/project/plone.app.themingplugins/1.1/#changelog and it is used with Python3 projects. But maybe he didn't test config files with comments.

@nzambello quickfix: remove comments from the file, the problem is in comments in the config file.

            for prefix in self._comment_prefixes:
                if line.strip().startswith(prefix):
                    comment_start = 0

beware that plone depends on future (see @MrTango request) and future imports configparser, while you're using the one from python 3.8 directly. It is not a problem because the code is identical.

I doubt that it is correct to open configuration files in binary mode (under Python 3).