Skip to content

Commit

Permalink
Bump minimum supported Python version to 3.8
Browse files Browse the repository at this point in the history
Python 3.7 wheels can still be repaired.

Refactor codebase to use assignment expressions.
  • Loading branch information
adang1345 committed Oct 8, 2024
1 parent c33542c commit 795ae74
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 137 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ jobs:
run: |
pip install setuptools
python run_tests.py -v
- name: set up Python 3.7
- name: set up Python 3.8
uses: actions/setup-python@v5
with:
python-version: '3.7'
- name: run tests with Python 3.7
python-version: '3.8'
- name: run tests with Python 3.8
working-directory: ${{ github.workspace }}\tests
run: |
pip install wheel
pip install $(Get-ChildItem ..\dist\delvewheel-*.whl)
python run_tests.py -v Python37TestCase
python run_tests.py -v Python38TestCase
- name: set up PyPy3.10
uses: actions/setup-python@v5
with:
Expand Down
3 changes: 1 addition & 2 deletions delvewheel/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ def main():
include = set(dll_name.lower() for dll_name in os.pathsep.join(args.include).split(os.pathsep) if dll_name)
exclude = set(dll_name.lower() for dll_name in os.pathsep.join(args.exclude).split(os.pathsep) if dll_name)

intersection = include & exclude
if intersection:
if intersection := include & exclude:
raise ValueError(f'Cannot force both inclusion and exclusion of {intersection}')

if add_paths:
Expand Down
63 changes: 22 additions & 41 deletions delvewheel/_dll_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ def get_interpreter_arch() -> MachineType:
kernel32.GetModuleFileNameW.restype = ctypes.wintypes.DWORD
kernel32.GetModuleFileNameW.argtypes = ctypes.wintypes.HMODULE, ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD

size = 256
while size <= 32768:
while (size := 256) <= 32768:
filename = ctypes.create_unicode_buffer(size)
if not kernel32.GetModuleFileNameW(None, filename, size):
raise OSError(ctypes.FormatError(ctypes.get_last_error())) from None
Expand Down Expand Up @@ -155,8 +154,7 @@ def null_translator(directory: str, arch: MachineType) -> str:

# determine architecture of interpreter and OS
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
interpreter_arch = get_interpreter_arch()
if not interpreter_arch:
if not (interpreter_arch := get_interpreter_arch()):
# file system redirection rules are unknown
return null_translator
if interpreter_arch is MachineType.ARM64:
Expand Down Expand Up @@ -277,40 +275,31 @@ def find_library(
except FileNotFoundError:
continue
for item in contents:
if name == item.lower():
path = os.path.join(wheel_dir, item)
if os.path.isfile(path) and get_arch(path) == arch:
return path, []
if name == item.lower() and os.path.isfile(path := os.path.join(wheel_dir, item)) and get_arch(path) == arch:
return path, []
for directory in os.environ['PATH'].split(os.pathsep):
directory = _translate_directory(directory, arch)
try:
contents = os.listdir(directory)
contents = os.listdir(directory := _translate_directory(directory, arch))
except FileNotFoundError:
continue
dll_path = None
for item in contents:
if name == item.lower():
path = os.path.join(directory, item)
if os.path.isfile(path) and get_arch(path) == arch:
dll_path = path
break
if name == item.lower() and os.path.isfile(path := os.path.join(directory, item)) and get_arch(path) == arch:
dll_path = path
break
associated_paths = []
if include_symbols:
symbol_name = os.path.splitext(name)[0] + '.pdb'
for item in contents:
if symbol_name == item.lower():
path = os.path.join(directory, item)
if os.path.isfile(path):
associated_paths.append(path)
break
if symbol_name == item.lower() and os.path.isfile(path := os.path.join(directory, item)):
associated_paths.append(path)
break
if include_imports:
imports_name = os.path.splitext(name)[0] + '.lib'
for item in contents:
if imports_name == item.lower():
path = os.path.join(directory, item)
if os.path.isfile(path):
associated_paths.append(path)
break
if imports_name == item.lower() and os.path.isfile(path := os.path.join(directory, item)):
associated_paths.append(path)
break
if dll_path:
return dll_path, associated_paths
return None
Expand Down Expand Up @@ -349,8 +338,7 @@ def get_direct_mangleable_needed(lib_path: str, exclude: set, no_mangles: set, v
if hasattr(pe, attr):
imports = itertools.chain(imports, getattr(pe, attr))
needed = []
lib_arch = MachineType.machine_field_to_type(pe.FILE_HEADER.Machine)
if not lib_arch:
if not (lib_arch := MachineType.machine_field_to_type(pe.FILE_HEADER.Machine)):
raise ValueError(f'{lib_path} has an unsupported CPU architecture')
ignore_names = _dll_list.ignore_names[lib_arch]
lib_name_lower = os.path.basename(lib_path).lower()
Expand Down Expand Up @@ -425,16 +413,14 @@ def get_all_needed(lib_path: str,
ignored = set()
not_found = set()
while stack:
lib_path = stack.pop()
if lib_path not in discovered:
if (lib_path := stack.pop()) not in discovered:
discovered.add(lib_path)
with PEContext(lib_path, None, True, verbose) as pe:
imports = []
for attr in ('DIRECTORY_ENTRY_IMPORT', 'DIRECTORY_ENTRY_DELAY_IMPORT'):
if hasattr(pe, attr):
imports = itertools.chain(imports, getattr(pe, attr))
lib_arch = MachineType.machine_field_to_type(pe.FILE_HEADER.Machine)
if not lib_arch:
if not (lib_arch := MachineType.machine_field_to_type(pe.FILE_HEADER.Machine)):
raise ValueError(f'{lib_path} has an unsupported CPU architecture')
ignore_names = _dll_list.ignore_names[lib_arch]
lib_name_lower = os.path.basename(lib_path).lower()
Expand All @@ -444,8 +430,7 @@ def get_all_needed(lib_path: str,
not any(r.fullmatch(dll_name) for r in _dll_list.ignore_regexes) and \
dll_name not in exclude and \
(lib_name_lower not in _dll_list.ignore_dependency or dll_name not in _dll_list.ignore_dependency[lib_name_lower]):
dll_info = find_library(dll_name, wheel_dirs, lib_arch, include_symbols, include_imports)
if dll_info:
if dll_info := find_library(dll_name, wheel_dirs, lib_arch, include_symbols, include_imports):
stack.append(dll_info[0])
associated.update(dll_info[1])
if re.fullmatch(_dll_list.vc_redist, dll_name):
Expand Down Expand Up @@ -691,13 +676,11 @@ def replace_needed(lib_path: str, old_deps: typing.List[str], name_map: typing.D
pe.OPTIONAL_HEADER.SizeOfImage = _round_to_next(pe.sections[-1].VirtualAddress + pe.sections[-1].Misc_VirtualSize, pe.OPTIONAL_HEADER.SectionAlignment)
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
old_dll = entry.dll.lower()
if old_dll in new_dlls_rva_mapping:
if (old_dll := entry.dll.lower()) in new_dlls_rva_mapping:
entry.struct.Name = new_dlls_rva_mapping[old_dll]
if hasattr(pe, 'DIRECTORY_ENTRY_DELAY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_DELAY_IMPORT:
old_dll = entry.dll.lower()
if old_dll in new_dlls_rva_mapping:
if (old_dll := entry.dll.lower()) in new_dlls_rva_mapping:
entry.struct.szName = new_dlls_rva_mapping[old_dll]
else: # not enough_padding
# generate data containing strings for new DLL names
Expand Down Expand Up @@ -734,13 +717,11 @@ def replace_needed(lib_path: str, old_deps: typing.List[str], name_map: typing.D
# update import tables
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
old_dll = entry.dll.lower()
if old_dll in new_section_offset_mapping:
if (old_dll := entry.dll.lower()) in new_section_offset_mapping:
entry.struct.Name = new_section_rva + new_section_offset_mapping[old_dll]
if hasattr(pe, 'DIRECTORY_ENTRY_DELAY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_DELAY_IMPORT:
old_dll = entry.dll.lower()
if old_dll in new_section_offset_mapping:
if (old_dll := entry.dll.lower()) in new_section_offset_mapping:
entry.struct.szName = new_section_rva + new_section_offset_mapping[old_dll]

# clear reference to attribute certificate table if it exists
Expand Down
Loading

0 comments on commit 795ae74

Please sign in to comment.