Refactor sorting methods in HostsFile to maintain fixed order for default entries while sorting non-default entries by IP and hostname.

This commit is contained in:
Philip Henning 2025-07-29 23:12:19 +02:00
parent 3084650c27
commit 3e892daf98

View file

@ -200,40 +200,87 @@ class HostsFile:
def sort_by_ip(self, ascending: bool = True) -> None: def sort_by_ip(self, ascending: bool = True) -> None:
""" """
Sort entries by IP address, keeping default entries on top. Sort entries by IP address, keeping default entries on top in fixed order.
Args: Args:
ascending: Sort in ascending order if True, descending if False ascending: Sort in ascending order if True, descending if False
""" """
def sort_key(entry): # Separate default and non-default entries
default_entries = [entry for entry in self.entries if entry.is_default_entry()]
non_default_entries = [entry for entry in self.entries if not entry.is_default_entry()]
def ip_sort_key(entry):
try: try:
ip_str = entry.ip_address.lstrip('# ') ip_str = entry.ip_address.lstrip('# ')
ip_obj = ipaddress.ip_address(ip_str) ip_obj = ipaddress.ip_address(ip_str)
# Default entries always come first (priority 0), others get priority 1 # Create a tuple for sorting: (version, ip_int)
priority = 0 if entry.is_default_entry() else 1 return (ip_obj.version, int(ip_obj))
# Create a tuple for sorting: (priority, version, ip_int)
return (priority, ip_obj.version, int(ip_obj))
except ValueError: except ValueError:
# If IP parsing fails, use string comparison with high sort priority # If IP parsing fails, use string comparison
priority = 0 if entry.is_default_entry() else 1 return (999, entry.ip_address)
return (priority, 999, entry.ip_address)
self.entries.sort(key=sort_key, reverse=not ascending) # Keep default entries in their natural fixed order (don't sort them)
# Define the fixed order for default entries
default_order = [
{"ip": "127.0.0.1", "hostname": "localhost"},
{"ip": "255.255.255.255", "hostname": "broadcasthost"},
{"ip": "::1", "hostname": "localhost"},
]
# Sort default entries according to their fixed order
def default_sort_key(entry):
for i, default in enumerate(default_order):
if (entry.ip_address == default["ip"] and
entry.hostnames and entry.hostnames[0] == default["hostname"]):
return i
return 999 # fallback for any unexpected default entries
default_entries.sort(key=default_sort_key)
# Sort non-default entries according to the specified direction
non_default_entries.sort(key=ip_sort_key, reverse=not ascending)
# Combine: default entries always first, then sorted non-default entries
self.entries = default_entries + non_default_entries
def sort_by_hostname(self, ascending: bool = True) -> None: def sort_by_hostname(self, ascending: bool = True) -> None:
""" """
Sort entries by first hostname, keeping default entries on top. Sort entries by first hostname, keeping default entries on top in fixed order.
Args: Args:
ascending: Sort in ascending order if True, descending if False ascending: Sort in ascending order if True, descending if False
""" """
def sort_key(entry): # Separate default and non-default entries
# Default entries always come first (priority 0), others get priority 1 default_entries = [entry for entry in self.entries if entry.is_default_entry()]
priority = 0 if entry.is_default_entry() else 1 non_default_entries = [entry for entry in self.entries if not entry.is_default_entry()]
hostname = (entry.hostnames[0] if entry.hostnames else "").lower()
return (priority, hostname)
self.entries.sort(key=sort_key, reverse=not ascending) def hostname_sort_key(entry):
hostname = (entry.hostnames[0] if entry.hostnames else "").lower()
return hostname
# Keep default entries in their natural fixed order (don't sort them)
# Define the fixed order for default entries
default_order = [
{"ip": "127.0.0.1", "hostname": "localhost"},
{"ip": "255.255.255.255", "hostname": "broadcasthost"},
{"ip": "::1", "hostname": "localhost"},
]
# Sort default entries according to their fixed order
def default_sort_key(entry):
for i, default in enumerate(default_order):
if (entry.ip_address == default["ip"] and
entry.hostnames and entry.hostnames[0] == default["hostname"]):
return i
return 999 # fallback for any unexpected default entries
default_entries.sort(key=default_sort_key)
# Sort non-default entries according to the specified direction
non_default_entries.sort(key=hostname_sort_key, reverse=not ascending)
# Combine: default entries always first, then sorted non-default entries
self.entries = default_entries + non_default_entries
def find_entries_by_hostname(self, hostname: str) -> List[int]: def find_entries_by_hostname(self, hostname: str) -> List[int]:
""" """