Bug 2246330 - python-passlib fails to build with Python 3.13: passlib.exc.MissingBackendError: bcrypt: no backends available
Summary: python-passlib fails to build with Python 3.13: passlib.exc.MissingBackendErr...
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: python-passlib
Version: 40
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Joel Capitao
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: PYTHON3.13
TreeView+ depends on / blocked
 
Reported: 2023-10-26 10:07 UTC by Karolina Surma
Modified: 2024-02-26 15:59 UTC (History)
6 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2024-02-26 15:59:19 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Karolina Surma 2023-10-26 10:07:06 UTC
python-passlib fails to build with Python 3.13.

It seems it relies on bcrypt being in the environment and fails when it isn't present.
The build time dependency on bcrypt is not declared in the specfile: https://src.fedoraproject.org/rpms/python-passlib/blob/rawhide/f/python-passlib.spec

Also, there's a change in Python 3.13 regarding the crypt library:

PEP 594: Remove the crypt module and its private _crypt extension, deprecated in Python 3.11. The hashlib module is a potential replacement for certain use cases. Otherwise, the following PyPI projects can be used:

    bcrypt: Modern password hashing for your software and your servers.
    passlib: Comprehensive password hashing framework supporting over 30 schemes.
    argon2-cffi: The secure Argon2 password hashing algorithm.
    legacycrypt: Wrapper to the POSIX crypt library call and associated functionality.
(Contributed by Victor Stinner in gh-104773.)

See: https://docs.python.org/3.13/whatsnew/3.13.html for more information.


________________ bcrypt_sha256_os_crypt_test.test_using_version ________________

self = <passlib.tests.test_handlers_bcrypt.bcrypt_sha256_os_crypt_test testMethod=test_using_version>

    def setUp(self):
        # ensure builtin is enabled for duration of test.
        if TEST_MODE("full") and self.backend == "builtin":
            key = "PASSLIB_BUILTIN_BCRYPT"
            orig = os.environ.get(key)
            if orig:
                self.addCleanup(os.environ.__setitem__, key, orig)
            else:
                self.addCleanup(os.environ.__delitem__, key)
            os.environ[key] = "enabled"
>       super(_bcrypt_sha256_test, self).setUp()

passlib/tests/test_handlers_bcrypt.py:586: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
passlib/tests/utils.py:3212: in setUp
    self._patch_safe_crypt()
passlib/tests/utils.py:3246: in _patch_safe_crypt
    handler, alt_backend = self._get_safe_crypt_handler_backend()
passlib/tests/test_handlers_bcrypt.py:680: in _get_safe_crypt_handler_backend
    return bcrypt_os_crypt_test._get_safe_crypt_handler_backend()
passlib/tests/utils.py:3225: in _get_safe_crypt_handler_backend
    handler.get_backend()
passlib/utils/handlers.py:2088: in get_backend
    cls.set_backend()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'passlib.handlers.bcrypt.bcrypt'>, name = 'builtin', dryrun = False

    @classmethod
    def set_backend(cls, name="any", dryrun=False):
        """
        Load specified backend.
    
        :arg name:
            name of backend to load, can be any of the following:
    
            * ``"any"`` -- use current backend if one is loaded,
              otherwise load the first available backend.
    
            * ``"default"`` -- use the first available backend.
    
            * any string in :attr:`backends`, loads specified backend.
    
        :param dryrun:
            If True, this perform all setup actions *except* switching over to the new backend.
            (this flag is used to implement :meth:`has_backend`).
    
            .. versionadded:: 1.7
    
        :raises ValueError:
            If backend name is unknown.
    
        :raises passlib.exc.MissingBackendError:
            If specific backend is missing;
            or in the case of ``"any"`` / ``"default"``, if *no* backends are available.
    
        :raises passlib.exc.PasslibSecurityError:
    
            If ``"any"`` or ``"default"`` was specified,
            but the only backend available has a PasslibSecurityError.
        """
        # check if active backend is acceptable
        if (name == "any" and cls.__backend) or (name and name == cls.__backend):
            return cls.__backend
    
        # if this isn't the final subclass, whose bases we can modify,
        # find that class, and recursively call this method for the proper class.
        owner = cls._get_backend_owner()
        if owner is not cls:
            return owner.set_backend(name, dryrun=dryrun)
    
        # pick first available backend
        if name == "any" or name == "default":
            default_error = None
            for name in cls.backends:
                try:
                    return cls.set_backend(name, dryrun=dryrun)
                except exc.MissingBackendError:
                    continue
                except exc.PasslibSecurityError as err:
                    # backend is available, but refuses to load due to security issue.
                    if default_error is None:
                        default_error = err
                    continue
            if default_error is None:
                msg = "%s: no backends available" % cls.name
                if cls._no_backend_suggestion:
                    msg += cls._no_backend_suggestion
                default_error = exc.MissingBackendError(msg)
>           raise default_error
E           passlib.exc.MissingBackendError: bcrypt: no backends available -- recommend you install one (e.g. 'pip install bcrypt')

passlib/utils/handlers.py:2176: MissingBackendError

=========================== short test summary info ============================
FAILED passlib/tests/test_handlers.py::des_crypt_os_crypt_test::test_82_crypt_support
FAILED passlib/tests/test_handlers.py::md5_crypt_os_crypt_test::test_82_crypt_support
FAILED passlib/tests/test_handlers.py::sha256_crypt_os_crypt_test::test_82_crypt_support
FAILED passlib/tests/test_handlers.py::sha512_crypt_os_crypt_test::test_82_crypt_support
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_01_required_attributes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_02_config_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_02_using_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_03_hash_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_03_legacy_hash_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_04_hash_types
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_05_backends
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_10_optional_salt_attributes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_11_unique_salt
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_12_min_salt_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_13_max_salt_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_14_salt_chars
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_15_salt_type
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_20_optional_rounds_attributes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_21_min_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_21b_max_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_30_HasManyIdents
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_61_secret_case_sensitive
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_62_secret_border
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_63_large_secret
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_64_forbidden_chars
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_70_hashes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_70_parsehash
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_71_alternates
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_71_parsehash_results
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_72_configs
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_73_unidentified
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_74_malformed
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_75_foreign
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_76_hash_border
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_77_fuzz_input
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_78_fuzz_threading
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_80_faulty_crypt
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_81_crypt_fallback
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_82_crypt_support
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_90_bcrypt_padding
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_disable_and_enable
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_many_idents_using
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_replace_w_max_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_using_and_needs_update
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_using_harness
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_using_w_default_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_using_w_min_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_using_w_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_using_w_vary_rounds_generation
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_has_rounds_using_w_vary_rounds_parsing
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_needs_update_w_padding
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_secret_w_truncate_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_secret_wo_truncate_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_truncate_error_setting
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_os_crypt_test::test_using_salt_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_01_required_attributes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_02_config_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_02_using_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_03_hash_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_03_legacy_hash_workflow
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_04_hash_types
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_05_backends
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_10_optional_salt_attributes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_11_unique_salt
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_12_min_salt_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_13_max_salt_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_14_salt_chars
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_15_salt_type
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_20_optional_rounds_attributes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_21_min_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_21b_max_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_30_HasManyIdents
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_30_HasOneIdent
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_61_secret_case_sensitive
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_62_secret_border
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_63_large_secret
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_64_forbidden_chars
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_70_hashes
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_70_parsehash
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_71_alternates
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_71_parsehash_results
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_72_configs
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_73_unidentified
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_74_malformed
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_75_foreign
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_76_hash_border
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_77_fuzz_input
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_78_fuzz_threading
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_80_faulty_crypt
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_81_crypt_fallback
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_82_crypt_support
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_calc_digest_v2
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_disable_and_enable
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_many_idents_using
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_replace_w_max_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_using_and_needs_update
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_using_harness
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_using_w_default_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_using_w_min_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_using_w_rounds
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_using_w_vary_rounds_generation
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_has_rounds_using_w_vary_rounds_parsing
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_secret_w_truncate_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_secret_wo_truncate_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_truncate_error_setting
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_using_salt_size
FAILED passlib/tests/test_handlers_bcrypt.py::bcrypt_sha256_os_crypt_test::test_using_version
=== 107 failed, 1806 passed, 2357 skipped, 44 warnings in 110.34s (0:01:50) ====


For the build logs, see:
https://copr-be.cloud.fedoraproject.org/results/@python/python3.13/fedora-rawhide-x86_64/06546817-python-passlib/builder-live.log.gz

For all our attempts to build python-parso with Python 3.13, see:
https://copr.fedorainfracloud.org/coprs/g/python/python3.13/package/python-passlib/

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

Let us know here if you have any questions.

Python 3.13 is planned to be included in Fedora 41.
To make that update smoother, we're building Fedora packages with all
pre-releases of Python 3.13.
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 Aoife Moloney 2024-02-15 23:02:14 UTC
This bug appears to have been reported against 'rawhide' during the Fedora Linux 40 development cycle.
Changing version to 40.


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