Bug 2176132 - python-venusian fails to build with Python 3.12: AttributeError: 'zipimporter' object has no attribute 'find_module'.
Summary: python-venusian fails to build with Python 3.12: AttributeError: 'zipimporter...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: python-venusian
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Ben Beasley
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: PYTHON3.12
TreeView+ depends on / blocked
 
Reported: 2023-03-07 13:40 UTC by Tomáš Hrnčiar
Modified: 2023-03-08 15:13 UTC (History)
6 users (show)

Fixed In Version: python-venusian-3.0.0-12.fc39
Clone Of:
Environment:
Last Closed: 2023-03-08 15:13:40 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Tomáš Hrnčiar 2023-03-07 13:40:50 UTC
python-venusian fails to build with Python 3.12.0a5.

_______________________ TestScanner.test_package_in_zip ________________________

self = <tests.test_venusian.TestScanner testMethod=test_package_in_zip>

    def test_package_in_zip(self):
        with zip_file_in_sys_path():
            import packageinzip
        test = _Test()
        scanner = self._makeOne(test=test)
>       scanner.scan(packageinzip)

tests/test_venusian.py:107: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <venusian.Scanner object at 0x7f9628b9aae0>
package = <module 'packageinzip' from '/builddir/build/BUILD/venusian-3.0.0/tests/fixtures/zipped.zip/packageinzip/__init__.py'>
categories = None, onerror = None, ignore = []

    def scan(self, package, categories=None, onerror=None, ignore=None):
        """ Scan a Python package and any of its subpackages.  All
        top-level objects will be considered; those marked with
        venusian callback attributes related to ``category`` will be
        processed.
    
        The ``package`` argument should be a reference to a Python
        package or module object.
    
        The ``categories`` argument should be sequence of Venusian
        callback categories (each category usually a string) or the
        special value ``None`` which means all Venusian callback
        categories.  The default is ``None``.
    
        The ``onerror`` argument should either be ``None`` or a callback
        function which behaves the same way as the ``onerror`` callback
        function described in
        http://docs.python.org/library/pkgutil.html#pkgutil.walk_packages .
        By default, during a scan, Venusian will propagate all errors that
        happen during its code importing process, including
        :exc:`ImportError`.  If you use a custom ``onerror`` callback, you
        can change this behavior.
    
        Here's an example ``onerror`` callback that ignores
        :exc:`ImportError`::
    
            import sys
            def onerror(name):
                if not issubclass(sys.exc_info()[0], ImportError):
                    raise # reraise the last exception
    
        The ``name`` passed to ``onerror`` is the module or package dotted
        name that could not be imported due to an exception.
    
        .. versionadded:: 1.0
           the ``onerror`` callback
    
        The ``ignore`` argument allows you to ignore certain modules,
        packages, or global objects during a scan.  It should be a sequence
        containing strings and/or callables that will be used to match
        against the full dotted name of each object encountered during a
        scan.  The sequence can contain any of these three types of objects:
    
        - A string representing a full dotted name.  To name an object by
          dotted name, use a string representing the full dotted name.  For
          example, if you want to ignore the ``my.package`` package *and any
          of its subobjects or subpackages* during the scan, pass
          ``ignore=['my.package']``.
    
        - A string representing a relative dotted name.  To name an object
          relative to the ``package`` passed to this method, use a string
          beginning with a dot.  For example, if the ``package`` you've
          passed is imported as ``my.package``, and you pass
          ``ignore=['.mymodule']``, the ``my.package.mymodule`` mymodule *and
          any of its subobjects or subpackages* will be omitted during scan
          processing.
    
        - A callable that accepts a full dotted name string of an object as
          its single positional argument and returns ``True`` or ``False``.
          For example, if you want to skip all packages, modules, and global
          objects with a full dotted path that ends with the word "tests", you
          can use ``ignore=[re.compile('tests$').search]``.  If the callable
          returns ``True`` (or anything else truthy), the object is ignored,
          if it returns ``False`` (or anything else falsy) the object is not
          ignored.  *Note that unlike string matches, ignores that use a
          callable don't cause submodules and subobjects of a module or
          package represented by a dotted name to also be ignored, they match
          individual objects found during a scan, including packages,
          modules, and global objects*.
    
        You can mix and match the three types of strings in the list.  For
        example, if the package being scanned is ``my``,
        ``ignore=['my.package', '.someothermodule',
        re.compile('tests$').search]`` would cause ``my.package`` (and all
        its submodules and subobjects) to be ignored, ``my.someothermodule``
        to be ignored, and any modules, packages, or global objects found
        during the scan that have a full dotted name that ends with the word
        ``tests`` to be ignored.
    
        Note that packages and modules matched by any ignore in the list will
        not be imported, and their top-level code will not be run as a result.
    
        A string or callable alone can also be passed as ``ignore`` without a
        surrounding list.
    
        .. versionadded:: 1.0a3
           the ``ignore`` argument
        """
    
        pkg_name = package.__name__
    
        if ignore is not None and (
            isinstance(ignore, str) or not hasattr(ignore, "__iter__")
        ):
            ignore = [ignore]
        elif ignore is None:
            ignore = []
    
        # non-leading-dotted name absolute object name
        str_ignores = [ign for ign in ignore if isinstance(ign, str)]
        # leading dotted name relative to scanned package
        rel_ignores = [ign for ign in str_ignores if ign.startswith(".")]
        # non-leading dotted names
        abs_ignores = [ign for ign in str_ignores if not ign.startswith(".")]
        # functions, e.g. re.compile('pattern').search
        callable_ignores = [ign for ign in ignore if callable(ign)]
    
        def _ignore(fullname):
            for ign in rel_ignores:
                if fullname.startswith(pkg_name + ign):
                    return True
            for ign in abs_ignores:
                # non-leading-dotted name absolute object name
                if fullname.startswith(ign):
                    return True
            for ign in callable_ignores:
                if ign(fullname):
                    return True
            return False
    
        def invoke(mod_name, name, ob):
    
            fullname = mod_name + "." + name
    
            if _ignore(fullname):
                return
    
            category_keys = categories
            try:
                # Some metaclasses do insane things when asked for an
                # ``ATTACH_ATTR``, like not raising an AttributeError but
                # some other arbitary exception.  Some even shittier
                # introspected code lets us access ``ATTACH_ATTR`` far but
                # barfs on a second attribute access for ``attached_to``
                # (still not raising an AttributeError, but some other
                # arbitrary exception).  Finally, the shittiest code of all
                # allows the attribute access of the ``ATTACH_ATTR`` *and*
                # ``attached_to``, (say, both ``ob.__getattr__`` and
                # ``attached_categories.__getattr__`` returning a proxy for
                # any attribute access), which either a) isn't callable or b)
                # is callable, but, when called, shits its pants in an
                # potentially arbitrary way (although for b, only TypeError
                # has been seen in the wild, from PyMongo).  Thus the
                # catchall except: return here, which in any other case would
                # be high treason.
                attached_categories = getattr(ob, ATTACH_ATTR)
                if not attached_categories.attached_to(mod_name, name, ob):
                    return
            except:
                return
            if category_keys is None:
                category_keys = list(attached_categories.keys())
                try:
                    # When metaclasses return proxies for any attribute access
                    # the list may contain keys of different types which might
                    # not be sortable.  In that case we can just return,
                    # because we're not dealing with a proper venusian
                    # callback.
                    category_keys.sort()
                except TypeError:  # pragma: no cover
                    return
            for category in category_keys:
                callbacks = attached_categories.get(category, [])
                try:
                    # Metaclasses might trick us by reaching this far and then
                    # fail with too little values to unpack.
                    for callback, cb_mod_name, liftid, scope in callbacks:
                        if cb_mod_name != mod_name:
                            # avoid processing objects that were imported into
                            # this module but were not actually defined there
                            continue
                        callback(self, name, ob)
                except ValueError:  # pragma: nocover
                    continue
    
        for name, ob in getmembers(package):
            # whether it's a module or a package, we need to scan its
            # members; walk_packages only iterates over submodules and
            # subpackages
            invoke(pkg_name, name, ob)
    
        if hasattr(package, "__path__"):  # package, not module
            results = walk_packages(
                package.__path__,
                package.__name__ + ".",
                onerror=onerror,
                ignore=_ignore,
            )
    
            for importer, modname, ispkg in results:
>               loader = importer.find_module(modname)
E               AttributeError: 'zipimporter' object has no attribute 'find_module'. Did you mean: 'load_module'?

zipimport: Remove find_loader() and find_module() methods, deprecated in Python 3.10: use the find_spec() method instead. See PEP 451 for the rationale. (Contributed by Victor Stinner in gh-94379.)

https://github.com/python/cpython/issues/94379
https://docs.python.org/3.12/whatsnew/3.12.html

For the build logs, see:
https://copr-be.cloud.fedoraproject.org/results/@python/python3.12/fedora-rawhide-x86_64/05577380-python-venusian/

For all our attempts to build python-venusian with Python 3.12, see:
https://copr.fedorainfracloud.org/coprs/g/python/python3.12/package/python-venusian/

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.12:
https://copr.fedorainfracloud.org/coprs/g/python/python3.12/

Let us know here if you have any questions.

Python 3.12 is planned to be included in Fedora 39. To make that update smoother, we're building Fedora packages with all pre-releases of Python 3.12.
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 2 Fedora Update System 2023-03-08 15:11:01 UTC
FEDORA-2023-b762ac51d8 has been submitted as an update to Fedora 39. https://bodhi.fedoraproject.org/updates/FEDORA-2023-b762ac51d8

Comment 3 Fedora Update System 2023-03-08 15:13:40 UTC
FEDORA-2023-b762ac51d8 has been pushed to the Fedora 39 stable repository.
If problem still persists, please make note of it in this bug report.


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