Example #1
0
 def test_set_soname(self, check_call, _0, _1):
     patcher = Patchelf()
     filename = "test.so"
     soname_new = "TEST_NEW"
     patcher.set_soname(filename, soname_new)
     check_call.assert_called_once_with(['patchelf', '--set-soname',
                                         soname_new, filename])
Example #2
0
    def test_append_rpath_reject_outside_wheel(self, check_call, check_output,
                                               _):
        patcher = Patchelf()
        # When a library has an existing RPATH entry outside wheel_dir
        existing_rpath = b"/outside/wheel/dir"
        check_output.return_value = existing_rpath
        wheel_dir = "/not/outside"
        lib_name = "test.so"
        full_lib_name = os.path.abspath(lib_name)
        append_rpath_within_wheel(lib_name, "$ORIGIN/.lib", wheel_dir, patcher)
        check_output_expected_args = [
            call(["patchelf", "--print-rpath", full_lib_name])
        ]
        # Then that entry is eliminated when updating the RPATH
        check_call_expected_args = [
            call(["patchelf", "--remove-rpath", full_lib_name]),
            call([
                "patchelf",
                "--force-rpath",
                "--set-rpath",
                "$ORIGIN/.lib",
                full_lib_name,
            ]),
        ]

        assert check_output.call_args_list == check_output_expected_args
        assert check_call.call_args_list == check_call_expected_args
Example #3
0
    def test_append_rpath(self, check_call, check_output, _):
        patcher = Patchelf()
        # When a library has an existing RPATH entry within wheel_dir
        existing_rpath = b"$ORIGIN/.existinglibdir"
        check_output.return_value = existing_rpath
        wheel_dir = "."
        lib_name = "test.so"
        full_lib_name = os.path.abspath(lib_name)
        append_rpath_within_wheel(lib_name, "$ORIGIN/.lib", wheel_dir, patcher)
        check_output_expected_args = [
            call(["patchelf", "--print-rpath", full_lib_name])
        ]
        # Then that entry is preserved when updating the RPATH
        check_call_expected_args = [
            call(["patchelf", "--remove-rpath", full_lib_name]),
            call([
                "patchelf",
                "--force-rpath",
                "--set-rpath",
                f"{existing_rpath.decode()}:$ORIGIN/.lib",
                full_lib_name,
            ]),
        ]

        assert check_output.call_args_list == check_output_expected_args
        assert check_call.call_args_list == check_call_expected_args
Example #4
0
 def test_replace_needed(self, check_call, _0, _1):
     patcher = Patchelf()
     filename = "test.so"
     soname_old = "TEST_OLD"
     soname_new = "TEST_NEW"
     patcher.replace_needed(filename, soname_old, soname_new)
     check_call.assert_called_once_with(['patchelf', '--replace-needed',
                                         soname_old, soname_new, filename])
Example #5
0
    def test_get_rpath(self, _0, check_output, _1):
        patcher = Patchelf()
        check_output.return_value = b"existing_rpath"
        result = patcher.get_rpath("test.so")
        check_output_expected_args = [call(["patchelf", "--print-rpath", "test.so"])]

        assert result == check_output.return_value.decode()
        assert check_output.call_args_list == check_output_expected_args
Example #6
0
def execute(args, p):
    import os
    from .repair import repair_wheel
    from .wheel_abi import analyze_wheel_abi, NonPlatformWheel

    if not isfile(args.WHEEL_FILE):
        p.error('cannot access %s. No such file' % args.WHEEL_FILE)

    logger.info('Repairing %s', basename(args.WHEEL_FILE))

    if not exists(args.WHEEL_DIR):
        os.makedirs(args.WHEEL_DIR)

    try:
        wheel_abi = analyze_wheel_abi(args.WHEEL_FILE)
    except NonPlatformWheel:
        logger.info('This does not look like a platform wheel')
        return 1

    reqd_tag = get_priority_by_name(args.PLAT)

    if reqd_tag > get_priority_by_name(wheel_abi.sym_tag):
        msg = ('cannot repair "%s" to "%s" ABI because of the presence '
               'of too-recent versioned symbols. You\'ll need to compile '
               'the wheel on an older toolchain.' %
               (args.WHEEL_FILE, args.PLAT))
        p.error(msg)

    if reqd_tag > get_priority_by_name(wheel_abi.ucs_tag):
        msg = ('cannot repair "%s" to "%s" ABI because it was compiled '
               'against a UCS2 build of Python. You\'ll need to compile '
               'the wheel against a wide-unicode build of Python.' %
               (args.WHEEL_FILE, args.PLAT))
        p.error(msg)

    patcher = Patchelf()
    out_wheel = repair_wheel(args.WHEEL_FILE,
                             abi=args.PLAT,
                             lib_sdir=args.LIB_SDIR,
                             out_dir=args.WHEEL_DIR,
                             update_tags=args.UPDATE_TAGS,
                             patcher=patcher)

    if out_wheel is not None:
        analyzed_tag = analyze_wheel_abi(out_wheel).overall_tag
        if reqd_tag < get_priority_by_name(analyzed_tag):
            logger.info(('Wheel is eligible for a higher priority tag. '
                         'You requested %s but I have found this wheel is '
                         'eligible for %s.'),
                        args.PLAT, analyzed_tag)
            out_wheel = repair_wheel(args.WHEEL_FILE,
                                     abi=analyzed_tag,
                                     lib_sdir=args.LIB_SDIR,
                                     out_dir=args.WHEEL_DIR,
                                     update_tags=args.UPDATE_TAGS,
                                     patcher=patcher)

        logger.info('\nFixed-up wheel written to %s', out_wheel)
Example #7
0
    def test_set_rpath(self, check_call, _0, _1):
        patcher = Patchelf()
        patcher.set_rpath("test.so", "$ORIGIN/.lib")
        check_call_expected_args = [call(['patchelf', '--remove-rpath',
                                          'test.so']),
                                    call(['patchelf', '--force-rpath',
                                          '--set-rpath', '$ORIGIN/.lib',
                                          'test.so'])]

        assert check_call.call_args_list == check_call_expected_args
Example #8
0
    def test_set_rpath(self, check_call, _0, _1):
        patcher = Patchelf()
        patcher.set_rpath("test.so", "$ORIGIN/.lib")
        check_call_expected_args = [
            call(["patchelf", "--remove-rpath", "test.so"]),
            call(
                ["patchelf", "--force-rpath", "--set-rpath", "$ORIGIN/.lib", "test.so"]
            ),
        ]

        assert check_call.call_args_list == check_call_expected_args
Example #9
0
    def test_append_rpath_ignore_duplicates(self, check_call, check_output, _):
        patcher = Patchelf()
        # When a library has an existing RPATH entry and we try and append it again
        existing_rpath = b"$ORIGIN"
        check_output.return_value = existing_rpath
        wheel_dir = '.'
        lib_name = "test.so"
        full_lib_name = os.path.abspath(lib_name)
        append_rpath_within_wheel(lib_name, "$ORIGIN", wheel_dir, patcher)
        check_output_expected_args = [call(['patchelf', '--print-rpath',
                                            full_lib_name])]
        # Then that entry is ignored when updating the RPATH
        check_call_expected_args = [call(['patchelf', '--remove-rpath',
                                          full_lib_name]),
                                    call(['patchelf', '--force-rpath',
                                          '--set-rpath',
                                          '$ORIGIN',
                                          full_lib_name])]

        assert check_output.call_args_list == check_output_expected_args
        assert check_call.call_args_list == check_call_expected_args
Example #10
0
    def test_append_rpath_ignore_relative(self, check_call, check_output, _):
        patcher = Patchelf()
        # When a library has an existing RPATH entry but it cannot be resolved
        # to an absolute path, it is eliminated
        existing_rpath = b"not/absolute"
        check_output.return_value = existing_rpath
        wheel_dir = '.'
        lib_name = "test.so"
        full_lib_name = os.path.abspath(lib_name)
        append_rpath_within_wheel(lib_name, "$ORIGIN", wheel_dir, patcher)
        check_output_expected_args = [call(['patchelf', '--print-rpath',
                                            full_lib_name])]
        # Then that entry is ignored when updating the RPATH
        check_call_expected_args = [call(['patchelf', '--remove-rpath',
                                          full_lib_name]),
                                    call(['patchelf', '--force-rpath',
                                          '--set-rpath',
                                          '$ORIGIN',
                                          full_lib_name])]

        assert check_output.call_args_list == check_output_expected_args
        assert check_call.call_args_list == check_call_expected_args
Example #11
0
def test_patchelf_version_check_fail(check_output, version):
    check_output.return_value.decode.return_value = f"patchelf {version}"
    with pytest.raises(ValueError, match=f"patchelf {version} found"):
        Patchelf()
Example #12
0
def test_patchelf_version_check_fail(check_output, version):
    check_output.return_value.decode.return_value = "patchelf {}".format(
        version)
    with pytest.raises(ValueError, match="patchelf {} found".format(version)):
        Patchelf()
Example #13
0
def test_patchelf_check_output_fail(check_output):
    check_output.side_effect = CalledProcessError(1, "patchelf --version")
    with pytest.raises(ValueError, match="Could not call"):
        Patchelf()
Example #14
0
def test_patchelf_unavailable(find_executable):
    find_executable.return_value = False
    with pytest.raises(ValueError):
        Patchelf()
Example #15
0
def test_patchelf_version_check(check_output, version):
    check_output.return_value.decode.return_value = f"patchelf {version}"
    Patchelf()
Example #16
0
def execute(args, p):
    import os

    from .repair import repair_wheel
    from .wheel_abi import NonPlatformWheel, analyze_wheel_abi

    if not isfile(args.WHEEL_FILE):
        p.error("cannot access %s. No such file" % args.WHEEL_FILE)

    logger.info("Repairing %s", basename(args.WHEEL_FILE))

    if not exists(args.WHEEL_DIR):
        os.makedirs(args.WHEEL_DIR)

    try:
        wheel_abi = analyze_wheel_abi(args.WHEEL_FILE)
    except NonPlatformWheel:
        logger.info("This does not look like a platform wheel")
        return 1

    policy = get_policy_by_name(args.PLAT)
    reqd_tag = policy["priority"]

    if reqd_tag > get_priority_by_name(wheel_abi.sym_tag):
        msg = (
            'cannot repair "%s" to "%s" ABI because of the presence '
            "of too-recent versioned symbols. You'll need to compile "
            "the wheel on an older toolchain." % (args.WHEEL_FILE, args.PLAT)
        )
        p.error(msg)

    if reqd_tag > get_priority_by_name(wheel_abi.ucs_tag):
        msg = (
            'cannot repair "%s" to "%s" ABI because it was compiled '
            "against a UCS2 build of Python. You'll need to compile "
            "the wheel against a wide-unicode build of Python."
            % (args.WHEEL_FILE, args.PLAT)
        )
        p.error(msg)

    if reqd_tag > get_priority_by_name(wheel_abi.blacklist_tag):
        msg = (
            'cannot repair "%s" to "%s" ABI because it depends on '
            "black-listed symbols." % (args.WHEEL_FILE, args.PLAT)
        )
        p.error(msg)

    abis = [policy["name"]] + policy["aliases"]
    if not args.ONLY_PLAT:
        if reqd_tag < get_priority_by_name(wheel_abi.overall_tag):
            logger.info(
                (
                    "Wheel is eligible for a higher priority tag. "
                    "You requested %s but I have found this wheel is "
                    "eligible for %s."
                ),
                args.PLAT,
                wheel_abi.overall_tag,
            )
            higher_policy = get_policy_by_name(wheel_abi.overall_tag)
            abis = [higher_policy["name"]] + higher_policy["aliases"] + abis

    patcher = Patchelf()
    out_wheel = repair_wheel(
        args.WHEEL_FILE,
        abis=abis,
        lib_sdir=args.LIB_SDIR,
        out_dir=args.WHEEL_DIR,
        update_tags=args.UPDATE_TAGS,
        patcher=patcher,
        strip=args.STRIP,
    )

    if out_wheel is not None:
        logger.info("\nFixed-up wheel written to %s", out_wheel)
Example #17
0
def test_patchelf_version_check(check_output, version):
    check_output.return_value.decode.return_value = "patchelf {}".format(
        version)
    Patchelf()