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])
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
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
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])
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
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)
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
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
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
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
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()
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()
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()
def test_patchelf_unavailable(find_executable): find_executable.return_value = False with pytest.raises(ValueError): Patchelf()
def test_patchelf_version_check(check_output, version): check_output.return_value.decode.return_value = f"patchelf {version}" Patchelf()
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)
def test_patchelf_version_check(check_output, version): check_output.return_value.decode.return_value = "patchelf {}".format( version) Patchelf()