Bug 1907442 - python-jinja2 fails to build with Python 3.10: Traceback did not match: ZeroDivisionError: division by zero
Summary: python-jinja2 fails to build with Python 3.10: Traceback did not match: ZeroD...
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: python-jinja2
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Thomas Moschny
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: PYTHON3.10
TreeView+ depends on / blocked
 
Reported: 2020-12-14 14:26 UTC by Tomáš Hrnčiar
Modified: 2021-02-06 17:39 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2021-02-06 13:07:21 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Tomáš Hrnčiar 2020-12-14 14:26:48 UTC
python-jinja2 fails to build with Python 3.10.0a3.


==================================== ERRORS ====================================
_______________ ERROR at setup of TestByteCodeCache.test_simple ________________

    @pytest.fixture
    def package_loader():
        """returns PackageLoader initialized from templates"""
>       return loaders.PackageLoader("res", "templates")

tests/conftest.py:32: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
src/jinja2/loaders.py:233: in __init__
    from pkg_resources import DefaultProvider
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    """
    Package resource API
    --------------------
    
    A resource is a logical file contained within a package, or a logical
    subdirectory thereof.  The package resource API expects resource names
    to have their path parts separated with ``/``, *not* whatever the local
    path separator is.  Do not use os.path operations to manipulate resource
    names being passed into the API.
    
    The package resource API is designed to work with normal filesystem packages,
    .egg files, and unpacked .egg files.  It can also work in a limited way with
    .zip files and with custom PEP 302 loaders that support the ``get_data()``
    method.
    """
    
    import sys
    import os
    import io
    import time
    import re
    import types
    import zipfile
    import zipimport
    import warnings
    import stat
    import functools
    import pkgutil
    import operator
    import platform
    import collections
    import plistlib
    import email.parser
    import errno
    import tempfile
    import textwrap
    import itertools
    import inspect
    import ntpath
    import posixpath
    from pkgutil import get_importer
    
    try:
        import _imp
    except ImportError:
        # Python 3.2 compatibility
        import imp as _imp
    
    try:
        FileExistsError
    except NameError:
        FileExistsError = OSError
    
    # capture these to bypass sandboxing
    from os import utime
    try:
        from os import mkdir, rename, unlink
        WRITE_SUPPORT = True
    except ImportError:
        # no write support, probably under GAE
        WRITE_SUPPORT = False
    
    from os import open as os_open
    from os.path import isdir, split
    
    try:
        import importlib.machinery as importlib_machinery
        # access attribute to force import under delayed import mechanisms.
        importlib_machinery.__name__
    except ImportError:
        importlib_machinery = None
    
>   from pkg_resources.extern import appdirs
E   ImportWarning: VendorImporter.exec_module() not found; falling back to load_module()

/usr/lib/python3.10/site-packages/pkg_resources/__init__.py:73: ImportWarning
______________ ERROR at setup of TestLoaders.test_package_loader _______________

    @pytest.fixture
    def package_loader():
        """returns PackageLoader initialized from templates"""
>       return loaders.PackageLoader("res", "templates")

tests/conftest.py:32: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
src/jinja2/loaders.py:233: in __init__
    from pkg_resources import DefaultProvider
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    """
    Package resource API
    --------------------
    
    A resource is a logical file contained within a package, or a logical
    subdirectory thereof.  The package resource API expects resource names
    to have their path parts separated with ``/``, *not* whatever the local
    path separator is.  Do not use os.path operations to manipulate resource
    names being passed into the API.
    
    The package resource API is designed to work with normal filesystem packages,
    .egg files, and unpacked .egg files.  It can also work in a limited way with
    .zip files and with custom PEP 302 loaders that support the ``get_data()``
    method.
    """
    
    import sys
    import os
    import io
    import time
    import re
    import types
    import zipfile
    import zipimport
    import warnings
    import stat
    import functools
    import pkgutil
    import operator
    import platform
    import collections
    import plistlib
    import email.parser
    import errno
    import tempfile
    import textwrap
    import itertools
    import inspect
    import ntpath
    import posixpath
    from pkgutil import get_importer
    
    try:
        import _imp
    except ImportError:
        # Python 3.2 compatibility
        import imp as _imp
    
    try:
        FileExistsError
    except NameError:
        FileExistsError = OSError
    
    # capture these to bypass sandboxing
    from os import utime
    try:
        from os import mkdir, rename, unlink
        WRITE_SUPPORT = True
    except ImportError:
        # no write support, probably under GAE
        WRITE_SUPPORT = False
    
    from os import open as os_open
    from os.path import isdir, split
    
    try:
        import importlib.machinery as importlib_machinery
        # access attribute to force import under delayed import mechanisms.
        importlib_machinery.__name__
    except ImportError:
        importlib_machinery = None
    
>   from pkg_resources.extern import appdirs
E   ImportWarning: VendorImporter.exec_module() not found; falling back to load_module()

/usr/lib/python3.10/site-packages/pkg_resources/__init__.py:73: ImportWarning
_______________ ERROR at setup of TestLoaders.test_choice_loader _______________

    @pytest.fixture
    def package_loader():
        """returns PackageLoader initialized from templates"""
>       return loaders.PackageLoader("res", "templates")

tests/conftest.py:32: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
src/jinja2/loaders.py:233: in __init__
    from pkg_resources import DefaultProvider
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    """
    Package resource API
    --------------------
    
    A resource is a logical file contained within a package, or a logical
    subdirectory thereof.  The package resource API expects resource names
    to have their path parts separated with ``/``, *not* whatever the local
    path separator is.  Do not use os.path operations to manipulate resource
    names being passed into the API.
    
    The package resource API is designed to work with normal filesystem packages,
    .egg files, and unpacked .egg files.  It can also work in a limited way with
    .zip files and with custom PEP 302 loaders that support the ``get_data()``
    method.
    """
    
    import sys
    import os
    import io
    import time
    import re
    import types
    import zipfile
    import zipimport
    import warnings
    import stat
    import functools
    import pkgutil
    import operator
    import platform
    import collections
    import plistlib
    import email.parser
    import errno
    import tempfile
    import textwrap
    import itertools
    import inspect
    import ntpath
    import posixpath
    from pkgutil import get_importer
    
    try:
        import _imp
    except ImportError:
        # Python 3.2 compatibility
        import imp as _imp
    
    try:
        FileExistsError
    except NameError:
        FileExistsError = OSError
    
    # capture these to bypass sandboxing
    from os import utime
    try:
        from os import mkdir, rename, unlink
        WRITE_SUPPORT = True
    except ImportError:
        # no write support, probably under GAE
        WRITE_SUPPORT = False
    
    from os import open as os_open
    from os.path import isdir, split
    
    try:
        import importlib.machinery as importlib_machinery
        # access attribute to force import under delayed import mechanisms.
        importlib_machinery.__name__
    except ImportError:
        importlib_machinery = None
    
>   from pkg_resources.extern import appdirs
E   ImportWarning: VendorImporter.exec_module() not found; falling back to load_module()

/usr/lib/python3.10/site-packages/pkg_resources/__init__.py:73: ImportWarning
=================================== FAILURES ===================================
_________________________ TestDebug.test_runtime_error _________________________

self = <test_debug.TestDebug object at 0x7f7b76651760>
fs_env = <jinja2.environment.Environment object at 0x7f7b76651970>

        def test_runtime_error(self, fs_env):
            def test():
                tmpl.render(fail=lambda: 1 / 0)
    
            tmpl = fs_env.get_template("broken.html")
>           self.assert_traceback_matches(
                test,
                r"""
      File ".*?broken.html", line 2, in (top-level template code|<module>)
        \{\{ fail\(\) \}\}
      File ".*debug?.pyc?", line \d+, in <lambda>
        tmpl\.render\(fail=lambda: 1 / 0\)
    ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
    """,
            )

tests/test_debug.py:37: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <test_debug.TestDebug object at 0x7f7b76651760>
callback = <function TestDebug.test_runtime_error.<locals>.test at 0x7f7b7677aca0>
expected_tb = '\n  File ".*?broken.html", line 2, in (top-level template code|<module>)\n    \\{\\{ fail\\(\\) \\}\\}\n  File ".*deb... <lambda>\n    tmpl\\.render\\(fail=lambda: 1 / 0\\)\nZeroDivisionError: (int(eger)? )?division (or modulo )?by zero\n'

    def assert_traceback_matches(self, callback, expected_tb):
        with pytest.raises(Exception) as exc_info:
            callback()
    
        tb = format_exception(exc_info.type, exc_info.value, exc_info.tb)
        m = re.search(expected_tb.strip(), "".join(tb))
>       assert m is not None, "Traceback did not match:\n\n%s\nexpected:\n%s" % (
            "".join(tb),
            expected_tb,
        )
E       AssertionError: Traceback did not match:
E         
E         Traceback (most recent call last):
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/test_debug.py", line 23, in assert_traceback_matches
E             callback()
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/test_debug.py", line 34, in test
E             tmpl.render(fail=lambda: 1 / 0)
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/asyncsupport.py", line 71, in render
E             return original_render(self, *args, **kwargs)
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/environment.py", line 1090, in render
E             self.environment.handle_exception()
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/environment.py", line 832, in handle_exception
E             reraise(*rewrite_traceback_stack(source=source))
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/_compat.py", line 28, in reraise
E             raise value.with_traceback(tb)
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/res/templates/broken.html", line 107, in top-level template code
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/test_debug.py", line 34, in <lambda>
E             tmpl.render(fail=lambda: 1 / 0)
E         ZeroDivisionError: division by zero
E         
E         expected:
E         
E           File ".*?broken.html", line 2, in (top-level template code|<module>)
E             \{\{ fail\(\) \}\}
E           File ".*debug?.pyc?", line \d+, in <lambda>
E             tmpl\.render\(fail=lambda: 1 / 0\)
E         ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
E         
E       assert None is not None

tests/test_debug.py:27: AssertionError
=========================== short test summary info ============================
FAILED tests/test_debug.py::TestDebug::test_runtime_error - AssertionError: T...
ERROR tests/test_bytecode_cache.py::TestByteCodeCache::test_simple - ImportWa...
ERROR tests/test_loader.py::TestLoaders::test_package_loader - ImportWarning:...
ERROR tests/test_loader.py::TestLoaders::test_choice_loader - ImportWarning: ...
============== 1 failed, 743 passed, 3 skipped, 3 errors in 3.66s ==============

For the build logs, see:
https://copr-be.cloud.fedoraproject.org/results/@python/python3.10/fedora-rawhide-x86_64/01826992-python-jinja2/

For all our attempts to build python-jinja2 with Python 3.10, see:
https://copr.fedorainfracloud.org/coprs/g/python/python3.10/package/python-jinja2/

Testing and mass rebuild of packages is happening in copr. You can follow these instructions to test locally in mock if your package builds with Python 3.10:
https://copr.fedorainfracloud.org/coprs/g/python/python3.10/

Let us know here if you have any questions.

Python 3.10 will be included in Fedora 35. To make that update smoother, we're building Fedora packages with early pre-releases of Python 3.10.
A build failure prevents us from testing all dependent packages (transitive [Build]Requires), so if this package is required a lot, it's important for us to get it fixed soon.
We'd appreciate help from the people who know this package best, but if you don't want to work on this now, let us know so we can try to work around it on our side.

Comment 1 Thomas Moschny 2020-12-27 12:07:34 UTC
Looks like an setuptools issue?

https://github.com/pypa/setuptools/issues/2481

Comment 2 Miro Hrončok 2021-01-04 13:04:03 UTC
Even with setuptools fixed, we still have:

=================================== FAILURES ===================================
_________________________ TestDebug.test_runtime_error _________________________

self = <test_debug.TestDebug object at 0x7fbdec31d4f0>
fs_env = <jinja2.environment.Environment object at 0x7fbdec31d4c0>

        def test_runtime_error(self, fs_env):
            def test():
                tmpl.render(fail=lambda: 1 / 0)
    
            tmpl = fs_env.get_template("broken.html")
>           self.assert_traceback_matches(
                test,
                r"""
      File ".*?broken.html", line 2, in (top-level template code|<module>)
        \{\{ fail\(\) \}\}
      File ".*debug?.pyc?", line \d+, in <lambda>
        tmpl\.render\(fail=lambda: 1 / 0\)
    ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
    """,
            )

tests/test_debug.py:37: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <test_debug.TestDebug object at 0x7fbdec31d4f0>
callback = <function TestDebug.test_runtime_error.<locals>.test at 0x7fbdec30b3a0>
expected_tb = '\n  File ".*?broken.html", line 2, in (top-level template code|<module>)\n    \\{\\{ fail\\(\\) \\}\\}\n  File ".*deb... <lambda>\n    tmpl\\.render\\(fail=lambda: 1 / 0\\)\nZeroDivisionError: (int(eger)? )?division (or modulo )?by zero\n'

    def assert_traceback_matches(self, callback, expected_tb):
        with pytest.raises(Exception) as exc_info:
            callback()
    
        tb = format_exception(exc_info.type, exc_info.value, exc_info.tb)
        m = re.search(expected_tb.strip(), "".join(tb))
>       assert m is not None, "Traceback did not match:\n\n%s\nexpected:\n%s" % (
            "".join(tb),
            expected_tb,
        )
E       AssertionError: Traceback did not match:
E         
E         Traceback (most recent call last):
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/test_debug.py", line 23, in assert_traceback_matches
E             callback()
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/test_debug.py", line 34, in test
E             tmpl.render(fail=lambda: 1 / 0)
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/asyncsupport.py", line 71, in render
E             return original_render(self, *args, **kwargs)
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/environment.py", line 1090, in render
E             self.environment.handle_exception()
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/environment.py", line 832, in handle_exception
E             reraise(*rewrite_traceback_stack(source=source))
E           File "/builddir/build/BUILD/Jinja2-2.11.2/src/jinja2/_compat.py", line 28, in reraise
E             raise value.with_traceback(tb)
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/res/templates/broken.html", line -62, in top-level template code
E           File "/builddir/build/BUILD/Jinja2-2.11.2/tests/test_debug.py", line 34, in <lambda>
E             tmpl.render(fail=lambda: 1 / 0)
E         ZeroDivisionError: division by zero
E         
E         expected:
E         
E           File ".*?broken.html", line 2, in (top-level template code|<module>)
E             \{\{ fail\(\) \}\}
E           File ".*debug?.pyc?", line \d+, in <lambda>
E             tmpl\.render\(fail=lambda: 1 / 0\)
E         ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
E         
E       assert None is not None

tests/test_debug.py:27: AssertionError

Comment 3 Thomas Moschny 2021-01-19 12:30:53 UTC
I have a patch for that problem, will open an upstream ticket.

However, there's another issue in tests/test_nativetypes.py, will have a look.

Comment 4 Thomas Moschny 2021-01-19 18:24:09 UTC
Partly fixed, see https://github.com/pallets/jinja/issues/1333.

Remaining failure:

================================================= FAILURES =================================================
_______________________________________ test_undefined_native_return _______________________________________

env = <jinja2.nativetypes.NativeEnvironment object at 0x7ff4469a0d00>

    def test_undefined_native_return(env):
        t = env.from_string("{{ missing }}")
>       assert isinstance(t.render(), Undefined)

tests/test_nativetypes.py:23:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/jinja2/nativetypes.py:92: in render
    return self.environment.handle_exception()
src/jinja2/environment.py:790: in handle_exception
    raise rewrite_traceback_stack(source=source)
src/jinja2/nativetypes.py:33: in native_concat
    return literal_eval(raw)
/usr/lib64/python3.10/ast.py:108: in literal_eval
    return _convert(node_or_string)
/usr/lib64/python3.10/ast.py:107: in _convert
    return _convert_signed_num(node)
/usr/lib64/python3.10/ast.py:81: in _convert_signed_num
    return _convert_num(node)
/usr/lib64/python3.10/ast.py:72: in _convert_num
    _raise_malformed_node(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

node = Undefined

    def _raise_malformed_node(node):
        msg = "malformed node or string"
>       if lno := getattr(node, 'lineno', None):
E       jinja2.exceptions.UndefinedError: 'missing' is undefined

/usr/lib64/python3.10/ast.py:67: UndefinedError

Comment 5 Thomas Moschny 2021-01-20 09:03:36 UTC
Reported upstream, with a proposal for a small patch: https://github.com/pallets/jinja/issues/1335

Comment 6 Thomas Moschny 2021-02-06 13:07:21 UTC
Fixed, see https://src.fedoraproject.org/rpms/python-jinja2/c/93898ae4

Comment 7 Miro Hrončok 2021-02-06 17:39:29 UTC
Awesome, thanks!


Note You need to log in before you can comment on or make changes to this bug.