# Reading content from migrator.py (2026-03-10 16:07Z) _**User**_ Read the first 100 lines of the file T:\Dynamic-Link-Manager\ops\migrator.py and return the actual content. Use Python to read the file. --- _**Agent (model accounts/fireworks/models/kimi-k2p5, mode Agent)**_ ---
Thought Process The user wants me to read the first 100 lines of a specific file using Python. Let me use the Shell tool to execute a Python command that reads the file.
---
Tool use: **run_terminal_command_v2** • Run command: python -c " with open(r'T:\Dynamic-Link-Manager\ops\migrator.py', 'r') as f: lines = f.readlines()[:100] print(''.join(lines)) " ```bash python -c " with open(r'T:\Dynamic-Link-Manager\ops\migrator.py', 'r') as f: lines = f.readlines()[:100] print(''.join(lines)) " ``` ``` # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. """Character migrator: migrate animation, constraints, relations from original to replacement armature.""" import bpy from ..utils import descendants, collection_containing_armature def get_pair_manual(context): """Return (orig_armature, rep_armature) from scene props, or (None, None).""" props = getattr(context.scene, "dynamic_link_manager", None) if not props: return None, None orig = getattr(props, "original_character", None) rep = getattr(props, "replacement_character", None) if orig and orig.type == "ARMATURE" and rep and rep.type == "ARMATURE": return orig, rep return None, None def get_pair_automatic(context): """Discover one pair by convention: Name_Rigify and Name_Rigify.001. Returns (orig, rep) or (None, None).""" pairs = [] for obj in bpy.data.objects: if obj.type != "ARMATURE": continue name = obj.name if name.endswith("_Rigify.001"): base = name[:-len("_Rigify.001")] orig = bpy.data.objects.get(f"{base}_Rigify") if orig and orig.type == "ARMATURE" and orig != obj: pairs.append((orig, obj)) return pairs[0] if pairs else (None, None) def run_copy_attr(orig, rep): """Copy armature object attributes: location, rotation, scale (CopyAttr).""" rep.location = orig.location.copy() if orig.rotation_mode == "QUATERNION": rep.rotation_quaternion = orig.rotation_quaternion.copy() else: rep.rotation_euler = orig.rotation_euler.copy() rep.scale = orig.scale.copy() def _has_als_anywhere(orig): """Return True if orig has Animation Layers (addon uses Object.als RNA PropertyGroup, obj.als.turn_on).""" # Animation Layers addon: bpy.types.Object.als (RNA), not id props if getattr(orig, "als", None) is not None: return True key = "als.turn_on" if key in orig: return True if getattr(orig, "data", None) and hasattr(orig.data, "keys") and key in orig.data: return True try: als = orig.get("als") if als is not None and callable(getattr(als, "keys", None)) and "turn_on" in als.keys(): return True except Exception: pass for pb in orig.pose.bones: if key in pb: return True try: als = pb.get("als") if als is not None and callable(getattr(als, "keys", None)) and "turn_on" in als.keys(): return True except Exception: pass return False def _debug_als_lookup(orig): """Print full debug for AnimLayers: RNA obj.als and every id_prop on orig.""" key = "als.turn_on" print("[DLM MigNLA] === AnimLayers debug ===") als_rna = getattr(orig, "als", None) print(f"[DLM MigNLA] orig.als (RNA): {als_rna!r}, turn_on={getattr(als_rna, 'turn_on', 'N/A') if als_rna else 'N/A'}") print(f"[DLM MigNLA] 'als.turn_on' in orig (object): {key in orig}") if getattr(orig, "data", None): has_data_keys = hasattr(orig.data, "keys") print(f"[DLM MigNLA] orig.data has keys(): {has_data_keys}") if has_data_keys: print(f"[DLM MigNLA] 'als.turn_on' in orig.data: {key in orig.data}") print(f"[DLM MigNLA] orig.data keys: {list(orig.data.keys())}") try: als = orig.get("als") has_als = als is not None and callable(getattr(als, "keys", None)) print(f"[DLM MigNLA] orig.get('als') is group: {has_als}") if has_als: print(f"[DLM MigNLA] orig['als'] keys: {list(als.keys())}") print(f"[DLM MigNLA] 'turn_on' in orig['als']: {'turn_on' in als.keys()}") except Exception as e: print(f"[DLM MigNLA] orig.get('als') error: {e}") print(f"[DLM MigNLA] orig (object) all keys: {list(orig.keys())}") ```
---
Thought Process The command executed successfully and returned the first 100 lines of the file. I should present this content to the user clearly.
--- Here are the first 100 lines of `T:\Dynamic-Link-Manager\ops\migrator.py`: ```python # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. """Character migrator: migrate animation, constraints, relations from original to replacement armature.""" import bpy from ..utils import descendants, collection_containing_armature def get_pair_manual(context): """Return (orig_armature, rep_armature) from scene props, or (None, None).""" props = getattr(context.scene, "dynamic_link_manager", None) if not props: return None, None orig = getattr(props, "original_character", None) rep = getattr(props, "replacement_character", None) if orig and orig.type == "ARMATURE" and rep and rep.type == "ARMATURE": return orig, rep return None, None def get_pair_automatic(context): """Discover one pair by convention: Name_Rigify and Name_Rigify.001. Returns (orig, rep) or (None, None).""" pairs = [] for obj in bpy.data.objects: if obj.type != "ARMATURE": continue name = obj.name if name.endswith("_Rigify.001"): base = name[:-len("_Rigify.001")] orig = bpy.data.objects.get(f"{base}_Rigify") if orig and orig.type == "ARMATURE" and orig != obj: pairs.append((orig, obj)) return pairs[0] if pairs else (None, None) def run_copy_attr(orig, rep): """Copy armature object attributes: location, rotation, scale (CopyAttr).""" rep.location = orig.location.copy() if orig.rotation_mode == "QUATERNION": rep.rotation_quaternion = orig.rotation_quaternion.copy() else: rep.rotation_euler = orig.rotation_euler.copy() rep.scale = orig.scale.copy() def _has_als_anywhere(orig): """Return True if orig has Animation Layers (addon uses Object.als RNA PropertyGroup, obj.als.turn_on).""" # Animation Layers addon: bpy.types.Object.als (RNA), not id props if getattr(orig, "als", None) is not None: return True key = "als.turn_on" if key in orig: return True if getattr(orig, "data", None) and hasattr(orig.data, "keys") and key in orig.data: return True try: als = orig.get("als") if als is not None and callable(getattr(als, "keys", None)) and "turn_on" in als.keys(): return True except Exception: pass for pb in orig.pose.bones: if key in pb: return True try: als = pb.get("als") if als is not None and callable(getattr(als, "keys", None)) and "turn_on" in als.keys(): return True except Exception: pass return False def _debug_als_lookup(orig): """Print full debug for AnimLayers: RNA obj.als and every id_prop on orig.""" key = "als.turn_on" print("[DLM MigNLA] === AnimLayers debug ===") als_rna = getattr(orig, "als", None) print(f"[DLM MigNLA] orig.als (RNA): {als_rna!r}, turn_on={getattr(als_rna, 'turn_on', 'N/A') if als_rna else 'N/A'}") print(f"[DLM MigNLA] 'als.turn_on' in orig (object): {key in orig}") if getattr(orig, "data", None): has_data_keys = hasattr(orig.data, "keys") print(f"[DLM MigNLA] orig.data has keys(): {has_data_keys}") if has_data_keys: print(f"[DLM MigNLA] 'als.turn_on' in orig.data: {key in orig.data}") print(f"[DLM MigNLA] orig.data keys: {list(orig.data.keys())}") try: als = orig.get("als") has_als = als is not None and callable(getattr(als, "keys", None)) print(f"[DLM MigNLA] orig.get('als') is group: {has_als}") if has_als: print(f"[DLM MigNLA] orig['als'] keys: {list(als.keys())}") print(f"[DLM MigNLA] 'turn_on' in orig['als']: {'turn_on' in als.keys()}") except Exception as e: print(f"[DLM MigNLA] orig.get('als') error: {e}") print(f"[DLM MigNLA] orig (object) all keys: {list(orig.keys())}") ``` ---