From fa427188d99f6760fd252b9eb2d6c1e8fe33b47d Mon Sep 17 00:00:00 2001 From: LemonNexus Date: Mon, 9 Feb 2026 19:25:56 +0000 Subject: [PATCH] fix: add error handling and validation to LoadoutConfig.from_dict - Added try/except with logging around from_dict - Added validation for armor_plates to handle non-dict values - Added error handling for Decimal/int conversions - Better error messages to diagnose loading issues --- ui/loadout_manager.py | 138 ++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 58 deletions(-) diff --git a/ui/loadout_manager.py b/ui/loadout_manager.py index 98b5922..f43f87e 100644 --- a/ui/loadout_manager.py +++ b/ui/loadout_manager.py @@ -314,75 +314,97 @@ class LoadoutConfig: @classmethod def from_dict(cls, data: dict) -> "LoadoutConfig": """Create LoadoutConfig from dictionary.""" - decimal_fields = [ - 'weapon_damage', 'weapon_decay_pec', 'weapon_ammo_pec', 'weapon_dpp', - 'armor_decay_pec', 'heal_cost_pec', 'heal_amount', 'protection_stab', - 'protection_cut', 'protection_impact', 'protection_penetration', - 'protection_shrapnel', 'protection_burn', 'protection_cold', - 'protection_acid', 'protection_electric' - ] + try: + decimal_fields = [ + 'weapon_damage', 'weapon_decay_pec', 'weapon_ammo_pec', 'weapon_dpp', + 'armor_decay_pec', 'heal_cost_pec', 'heal_amount', 'protection_stab', + 'protection_cut', 'protection_impact', 'protection_penetration', + 'protection_shrapnel', 'protection_burn', 'protection_cold', + 'protection_acid', 'protection_electric' + ] - for field in decimal_fields: - if field in data: - data[field] = Decimal(data[field]) + for field in decimal_fields: + if field in data: + try: + data[field] = Decimal(data[field]) + except Exception as e: + logger.warning(f"Could not convert {field} to Decimal: {e}") + data[field] = Decimal("0") - # Handle integer fields - int_fields = ['weapon_id', 'armor_id', 'shots_per_hour', 'hits_per_hour', 'heals_per_hour'] - for field in int_fields: - if field in data: - data[field] = int(data[field]) + # Handle integer fields + int_fields = ['weapon_id', 'armor_id', 'shots_per_hour', 'hits_per_hour', 'heals_per_hour'] + for field in int_fields: + if field in data: + try: + data[field] = int(data[field]) + except Exception as e: + logger.warning(f"Could not convert {field} to int: {e}") + data[field] = 0 - # Handle attachment configs - if 'weapon_amplifier' in data and data['weapon_amplifier']: - data['weapon_amplifier'] = AttachmentConfig.from_dict(data['weapon_amplifier']) - else: - data['weapon_amplifier'] = None + # Handle attachment configs + if 'weapon_amplifier' in data and data['weapon_amplifier']: + data['weapon_amplifier'] = AttachmentConfig.from_dict(data['weapon_amplifier']) + else: + data['weapon_amplifier'] = None - if 'weapon_scope' in data and data['weapon_scope']: - data['weapon_scope'] = AttachmentConfig.from_dict(data['weapon_scope']) - else: - data['weapon_scope'] = None + if 'weapon_scope' in data and data['weapon_scope']: + data['weapon_scope'] = AttachmentConfig.from_dict(data['weapon_scope']) + else: + data['weapon_scope'] = None - if 'weapon_absorber' in data and data['weapon_absorber']: - data['weapon_absorber'] = AttachmentConfig.from_dict(data['weapon_absorber']) - else: - data['weapon_absorber'] = None + if 'weapon_absorber' in data and data['weapon_absorber']: + data['weapon_absorber'] = AttachmentConfig.from_dict(data['weapon_absorber']) + else: + data['weapon_absorber'] = None - # Handle weapon enhancers - if 'weapon_enhancers' in data and data['weapon_enhancers']: - data['weapon_enhancers'] = [AttachmentConfig.from_dict(e) for e in data['weapon_enhancers']] - else: - data['weapon_enhancers'] = [] + # Handle weapon enhancers + if 'weapon_enhancers' in data and data['weapon_enhancers']: + data['weapon_enhancers'] = [AttachmentConfig.from_dict(e) for e in data['weapon_enhancers']] + else: + data['weapon_enhancers'] = [] - # Handle armor plates - if 'armor_plates' in data and data['armor_plates']: - data['armor_plates'] = {k: AttachmentConfig.from_dict(v) for k, v in data['armor_plates'].items()} - else: - data['armor_plates'] = {} + # Handle armor plates - with validation + if 'armor_plates' in data and data['armor_plates']: + plates = {} + for k, v in data['armor_plates'].items(): + try: + if isinstance(v, dict): + plates[k] = AttachmentConfig.from_dict(v) + else: + logger.warning(f"Invalid armor_plate value for {k}: {type(v)}") + except Exception as e: + logger.error(f"Error parsing armor_plate {k}: {e}") + data['armor_plates'] = plates + else: + data['armor_plates'] = {} - # Handle accessories - if 'clothing_items' not in data: - data['clothing_items'] = [] - if 'left_ring' not in data: - data['left_ring'] = None - if 'right_ring' not in data: - data['right_ring'] = None - if 'pet' not in data: - data['pet'] = None + # Handle accessories + if 'clothing_items' not in data: + data['clothing_items'] = [] + if 'left_ring' not in data: + data['left_ring'] = None + if 'right_ring' not in data: + data['right_ring'] = None + if 'pet' not in data: + data['pet'] = None - # Handle equipped armor - if 'equipped_armor' in data and data['equipped_armor']: - data['equipped_armor'] = EquippedArmor.from_dict(data['equipped_armor']) - else: - data['equipped_armor'] = None + # Handle equipped armor + if 'equipped_armor' in data and data['equipped_armor']: + data['equipped_armor'] = EquippedArmor.from_dict(data['equipped_armor']) + else: + data['equipped_armor'] = None - # Handle legacy configs - if 'heal_name' not in data: - data['heal_name'] = '-- Custom --' - if 'armor_set_name' not in data: - data['armor_set_name'] = '-- None --' + # Handle legacy configs + if 'heal_name' not in data: + data['heal_name'] = '-- Custom --' + if 'armor_set_name' not in data: + data['armor_set_name'] = '-- None --' - return cls(**data) + return cls(**data) + except Exception as e: + logger.error(f"Error in LoadoutConfig.from_dict: {e}") + logger.error(f"Data keys: {list(data.keys())}") + raise # ============================================================================