Plone bug report from Santa

Ho-Ho-Ho,

With the EOL of Python 2.7 Plone becomes unusable for Santa. The distro of Santa drops 2.7 because upstream does. Santa does not have the resources to invest in migration to Python 3 soon. Santa has already the important job of delivering presents. Santa’s stuck on Plone legacy. Santa does not mind because 4.3.X is Santa's favorite version. Santa and the Reindeers need to maintain Plone legacy for a long time.

For this Santa investigate the use of Tauthon. Tauthon strive to be the "drop in" replacement for Python 2.7. The Plone installer, virtualenv and pip are not compatible with Tauthon because they hard-coded PY_VERSION. And there is an AttributeError that even @zopyx never had seen with Plone. Santa noticed that Tauthon is Python 3 made easy. Tauthon does promises and awakens expectations that are appealing, at least to Santa. A summary from Tauthon on Github:

Summary

Tauthon is a backwards-compatible fork of the Python 2.7.17 interpreter with new syntax, builtins, and libraries backed from Python 3.x. Python code and C-extensions targeting Python 2.7 or below are expected to run unmodified on Tauthon and produce the same output.

Santa did a test run with Plone 4.3.19 and thinks that the AttributeError is caused by RestrictedPython being restricted to PY_VERSION <= 2.7.X. Tauthon is version 2.8. Santa hopes there is someone with a clue how to fix this issue. Santa thinks it is "a real Plone issue" that Plone is not compatible with Tauthon. Santa also thinks that Tauthon is an opportunity par excellence for Plone. Think of the amazing legacy. Why use Python anyhow? Santa thinks that the print statement in Tauthon does not prove that there is need for Python 3 because with the __future__ module print can be also a function in Tauthon, and wishes the Plone Community a Merry Christmas and a Happy New Year. :christmas_tree:

Santa.

:christmas_tree: AttributeError

Summary
Traceback (innermost last):
  Module ZPublisher.Publish, line 138, in publish
  Module ZPublisher.mapply, line 77, in mapply
  Module ZPublisher.Publish, line 48, in call_object
  Module Products.CMFPlone.browser.admin, line 223, in __call__
  Module Products.CMFPlone.factory, line 97, in addPloneSite
  Module Products.GenericSetup.tool, line 388, in runAllImportStepsFromProfile
   - __traceback_info__: profile-Products.CMFPlone:plone-content
  Module Products.GenericSetup.tool, line 1469, in _runImportStepsFromContext
  Module Products.GenericSetup.tool, line 1281, in _doRunImportStep
   - __traceback_info__: plone-content
  Module Products.CMFPlone.setuphandlers, line 491, in importContent
  Module Products.CMFPlone.setuphandlers, line 361, in setupPortalContent
  Module Products.PythonScripts.PythonScript, line 78, in manage_addPythonScript
  Module Products.PythonScripts.PythonScript, line 123, in __init__
  Module Products.PythonScripts.PythonScript, line 293, in _makeFunction
  Module Products.PythonScripts.PythonScript, line 245, in _compile
  Module Products.PythonScripts.PythonScript, line 239, in _compiler
  Module RestrictedPython.RCompile, line 91, in compile_restricted_function
  Module RestrictedPython.RCompile, line 74, in compileAndTuplize
  Module RestrictedPython.RCompile, line 67, in compile
  Module RestrictedPython.RCompile, line 59, in _get_tree
  Module RestrictedPython.MutatingWalker, line 74, in walk
  Module RestrictedPython.MutatingWalker, line 71, in dispatchNode
  Module RestrictedPython.RestrictionMutator, line 364, in visitModule
  Module RestrictedPython.MutatingWalker, line 32, in defaultVisitNode
  Module RestrictedPython.MutatingWalker, line 57, in dispatchObject
  Module RestrictedPython.MutatingWalker, line 71, in dispatchNode
  Module RestrictedPython.MutatingWalker, line 32, in defaultVisitNode
  Module RestrictedPython.MutatingWalker, line 59, in dispatchObject
  Module RestrictedPython.MutatingWalker, line 42, in visitSequence
  Module RestrictedPython.MutatingWalker, line 57, in dispatchObject
  Module RestrictedPython.MutatingWalker, line 71, in dispatchNode
  Module RestrictedPython.RestrictionMutator, line 141, in visitFunction
AttributeError: Function instance has no attribute 'argnames'
2019-12-20 17:50:17 ERROR ZServerPublisher exception caught
Traceback (most recent call last):
  File "/usr/home/zope/Plone/buildout-cache/eggs/Zope2-2.13.29-py2.8.egg/ZServer/PubCore/ZServerPublisher.py", line 31, in __init__
    response=b)
  File "/usr/home/zope/Plone/buildout-cache/eggs/Zope2-2.13.29-py2.8.egg/ZPublisher/Publish.py", line 455, in publish_module
    environ, debug, request, response)
  File "/usr/home/zope/Plone/buildout-cache/eggs/Zope2-2.13.29-py2.8.egg/ZPublisher/Publish.py", line 276, in publish_module_standard
    if request is not None: request.close()
  File "/usr/home/zope/Plone/buildout-cache/eggs/Zope2-2.13.29-py2.8.egg/ZPublisher/BaseRequest.py", line 220, in close
    notify(EndRequestEvent(None, self))
  File "/usr/home/zope/Plone/buildout-cache/eggs/zope.event-3.5.2-py2.8.egg/zope/event/__init__.py", line 31, in notify
    subscriber(event)
  File "/usr/home/zope/Plone/buildout-cache/eggs/zope.component-3.9.5-py2.8.egg/zope/component/event.py", line 24, in dispatch
    zope.component.subscribers(event, None)
  File "/usr/home/zope/Plone/buildout-cache/eggs/zope.component-3.9.5-py2.8.egg/zope/component/_api.py", line 136, in subscribers
    return sitemanager.subscribers(objects, interface)
  File "/usr/home/zope/Plone/buildout-cache/eggs/zope.component-3.9.5-py2.8.egg/zope/component/registry.py", line 321, in subscribers
    return self.adapters.subscribers(objects, provided)
AttributeError: adapters

:christmas_tree: Test run

Summary
$ ./bin/test
Test-module import failures:

Module: RestrictedPython.tests.testRestrictions

Traceback (most recent call last):
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/tests/testRestrictions.py", line 566, in <module>
    create_rmodule()
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/tests/testRestrictions.py", line 71, in create_rmodule
    code = compile_restricted(source, fn, 'exec')
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RCompile.py", line 114, in compile_restricted
    gen.compile()
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RCompile.py", line 67, in compile
    tree = self._get_tree()
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RCompile.py", line 59, in _get_tree
    MutatingWalker.walk(tree, self.rm)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 74, in walk
    return MutatingWalker(visitor).dispatchNode(tree)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 71, in dispatchNode
    return meth(node, self)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RestrictionMutator.py", line 364, in visitModule
    node = walker.defaultVisitNode(node)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 32, in defaultVisitNode
    v = self.dispatchObject(child)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 57, in dispatchObject
    return self.dispatchNode(ob)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 71, in dispatchNode
    return meth(node, self)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 32, in defaultVisitNode
    v = self.dispatchObject(child)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 59, in dispatchObject
    return self.visitSequence(ob)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 42, in visitSequence
    v = self.dispatchObject(child)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 57, in dispatchObject
    return self.dispatchNode(ob)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 71, in dispatchNode
    return meth(node, self)
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RestrictionMutator.py", line 141, in visitFunction
    for argname in node.argnames:
AttributeError: Function instance has no attribute 'argnames'


Running zope.testing.testrunner.layer.UnitTests tests:
  Set up zope.testing.testrunner.layer.UnitTests in 0.000 seconds.


Failure in test /usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt
Traceback (most recent call last):
  File "/usr/local/lib/tauthon2.8/unittest/case.py", line 329, in run
    testMethod()
  File "/usr/local/lib/tauthon2.8/doctest.py", line 2224, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for README.txt
  File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt", line 0


File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt", line 15, in README.txt
Failed example:
    code = compile_restricted(src, '<string>', 'exec')
Exception raised:
    Traceback (most recent call last):
      File "/usr/local/lib/tauthon2.8/doctest.py", line 1315, in __run
        compileflags, 1) in test.globs
      File "<doctest README.txt[2]>", line 1, in <module>
        code = compile_restricted(src, '<string>', 'exec')
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RCompile.py", line 114, in compile_restricted
        gen.compile()
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RCompile.py", line 67, in compile
        tree = self._get_tree()
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RCompile.py", line 59, in _get_tree
        MutatingWalker.walk(tree, self.rm)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 74, in walk
        return MutatingWalker(visitor).dispatchNode(tree)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 71, in dispatchNode
        return meth(node, self)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RestrictionMutator.py", line 364, in visitModule
        node = walker.defaultVisitNode(node)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 32, in defaultVisitNode
        v = self.dispatchObject(child)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 57, in dispatchObject
        return self.dispatchNode(ob)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 71, in dispatchNode
        return meth(node, self)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 32, in defaultVisitNode
        v = self.dispatchObject(child)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 59, in dispatchObject
        return self.visitSequence(ob)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 42, in visitSequence
        v = self.dispatchObject(child)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 57, in dispatchObject
        return self.dispatchNode(ob)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/MutatingWalker.py", line 71, in dispatchNode
        return meth(node, self)
      File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/RestrictionMutator.py", line 141, in visitFunction
        for argname in node.argnames:
    AttributeError: Function instance has no attribute 'argnames'

File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt", line 19, in README.txt
Failed example:
    exec(code)
Exception raised:
    Traceback (most recent call last):
      File "/usr/local/lib/tauthon2.8/doctest.py", line 1315, in __run
        compileflags, 1) in test.globs
      File "<doctest README.txt[3]>", line 1, in <module>
        exec(code)
    NameError: name 'code' is not defined

File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt", line 24, in README.txt
Failed example:
    hello_world()
Exception raised:
    Traceback (most recent call last):
      File "/usr/local/lib/tauthon2.8/doctest.py", line 1315, in __run
        compileflags, 1) in test.globs
      File "<doctest README.txt[4]>", line 1, in <module>
        hello_world()
    NameError: name 'hello_world' is not defined

File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt", line 177, in README.txt
Failed example:
    exec(code)
Expected:
    Traceback (most recent call last):
      ...
    TypeError: attribute-less object (assign or del)
Got nothing

File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt", line 196, in README.txt
Failed example:
    fibonacci
Expected:
    [1, 1, 2, 3, 5]
Got:
    5

File "/usr/home/zope/Plone/buildout-cache/eggs/RestrictedPython-3.6.0-py2.8.egg/RestrictedPython/README.txt", line 198, in README.txt
Failed example:
    sorted(transl.keys())
Exception raised:
    Traceback (most recent call last):
      File "/usr/local/lib/tauthon2.8/doctest.py", line 1315, in __run
        compileflags, 1) in test.globs
      File "<doctest README.txt[37]>", line 1, in <module>
        sorted(transl.keys())
    NameError: name 'transl' is not defined


  Ran 26 tests with 1 failures and 0 errors in 0.088 seconds.
Tearing down left over layers:
  Tear down zope.testing.testrunner.layer.UnitTests in 0.000 seconds.

Test-modules with import problems:
 RestrictedPython.tests.testRestrictions
2 Likes

Please use RHEL (or something equivalent) if you want Python2.7: https://access.redhat.com/solutions/4455511
You'll then have until 2024 to upgrade to Python3.

2 Likes

Santa Claus is running on Python 3 since a decade.

1 Like

@zopyx That's not the real Santa.

First, RestrictedPython is a Zope thing and Plone uses it and it runs standalone in pure Python.
Second, RestrictedPython has an excellent test suite, make it run with Tauthon standalone first.
Third, expect it to be tricky.

But I like the analogy with Tauthon and Santa. As kids we believe in him, but as grown ups, well..... we use Python 3?

This Tauthon project is an interesting idea ~ it maybe saves some very old no-budget Plone sites from being shut off. Thanks Santa for sharing this! I'll keep an eye on this effort!

Other than that, I'm happy that Plone already made the switch to Python 3 and I'm happy to work with Plone 5.2 on Python 3.

Grown ups often think too much of themself and do not take care of the need of kids.

What do you mean with “make it run with Tauthon standalone first”?

Zope is running on Tauthon in a zeo setup with one client. The problem is installing Plone. Then the AttributeError appears.

Your trace back shows problems in RestrictedPython. Maybe its a side effect maybe not. Debugging will tell you. But if it's RestrictedPython make sure it work first. Setup all tests of Zope and Plone with Tauthon. It will probably work to some point, then hunt down problem by problem. Learn how to do it, read about Python 3 migration efforts and learn its methodology for Python migration. I think it's some work. Question is, if it's less work to make it work on Tauthon or to migrate upwards. Anyway, it FOSS, so just do it, it's possible if it's what you need/want.

That is indeed the question. With the difference that migration to Tauthon is inshallah once and forever, and upward migration is an endless repeating effort. I hope that more can be said about this when first the issues with RestrictedPython are solved. The advantage of Plone Legacy is that everyone can create competitive enterprise sites without needing to learn ore read about Python migration efforts and methodology for Python migration.

Nobody can answer this. You need to proof 100% compatiblity for all Zope and Plone and all other dependencies for Tauthon...means you take over the maintainership of dozens of packages...again: an absurd undertaking. I have zero trust that a small Tauthon team (or a one person show) can maintain and oversee a Python fork for the time being nor do I trust in your resources and capabilities for maintaining Plone 4.3 yourself in the future.

You are totally right. I'm not going to maintain Plone 4.3 myself in the future and Tauthon need to be more than a small team or an one man show before it can be used for production sites. I want it to be a FreeBSD port with security fixes etc before using it in production. Reading the promises of Tauthon in theory even Plone 5.3 can run on it. Maybe the whole Zope/Plone Community need to migrate to Tauthon. Why don't you join the Tauthon team? Than you can help Tauthon do what Plone needs.

Before we can decide that Tauthon is not compatible with Plone the issue with RestrictedPython must be fixed. It is still unsure what the nature of this problem is. Is sys.version_info or sys.prefix set wrong ore is Tauthon really failing? The problems with the installer, virtualenv and pip are because they are hard-coded PY_VERSION. So that are not real issues. Because Tauthon is a Py 2.7 fork I expect it to behave be the same as Py 2.7.

well Plone 4.3 still runs with RestrictedPython 3.6.0 which is pre rewrite, so not a full test-suite is avaliable.

you may run Plone 4.3.x with a RestrictedPython > 4.0 and < 6.0 and test if it still fails, from that point on you can debug.

1 Like

Thank you! Plone 4.3.19 can be installed and runs on Tauthon and products can be installed with these versions pined:
RestrictedPython = 5.1.dev0
zope.security = 4.0.0
zope.proxy = 4.1.0
zope.pagetemplate = 4.0.3

RestrictedPython warns though that it is only supported on CPython and that use on other Python implementations may create security issues.