3838
3939
4040def has_exempt_decorator (obj : Object ) -> bool :
41- """Check if object has any exempt decorator."""
41+ """Check if a Griffe object has any exempt decorator.
42+
43+ Args:
44+ obj: A Griffe Object to check for exempt decorators
45+
46+ Returns:
47+ bool: True if the object has any decorator matching EXEMPT_DECORATORS list
48+ """
4249 if not hasattr (obj , 'decorators' ):
4350 return False
4451 if not obj .decorators :
@@ -52,7 +59,19 @@ def has_exempt_decorator(obj: Object) -> bool:
5259
5360
5461def get_filtered_paths (package : Object , package_name : str ) -> set :
55- """Get all paths that should be filtered (have exempt decorators)."""
62+ """Recursively collect all object paths with exempt decorators from a package.
63+
64+ This function traverses the entire package tree and identifies objects that are
65+ decorated with any of the EXEMPT_DECORATORS, building a set of their full paths.
66+
67+ Args:
68+ package: The Griffe package object to traverse
69+ package_name: The full package name (e.g., "megatron.core") for path construction
70+
71+ Returns:
72+ set: A set of full object paths (e.g., "megatron.core.ModelParallelConfig")
73+ that should be filtered from compatibility checks
74+ """
5675 filtered = set ()
5776 visited = set ()
5877
@@ -92,7 +111,17 @@ def visit(obj, path, depth=0, is_root=False):
92111
93112
94113def strip_ansi_codes (text ):
95- """Remove ANSI escape codes from text."""
114+ """Remove ANSI escape codes (terminal formatting) from text.
115+
116+ Griffe includes ANSI codes for terminal formatting in some strings,
117+ which breaks string matching. This strips them out.
118+
119+ Args:
120+ text: String potentially containing ANSI escape codes
121+
122+ Returns:
123+ str: Clean text with ANSI codes removed
124+ """
96125 if not text :
97126 return text
98127 # Pattern to match ANSI escape codes
@@ -101,7 +130,20 @@ def strip_ansi_codes(text):
101130
102131
103132def get_object_path (change ) -> str :
104- """Extract the object path from a breaking change."""
133+ """Extract the full object path from a Griffe breaking change.
134+
135+ Tries multiple sources to get the object path:
136+ 1. Direct path attributes (new_path, old_path, path)
137+ 2. Path from new_value or old_value objects
138+ 3. Parse from the explanation string as last resort
139+
140+ Args:
141+ change: A Griffe breaking change object
142+
143+ Returns:
144+ str: The full object path (e.g., "megatron.core.ModelParallelConfig.__init__")
145+ or None if unable to extract
146+ """
105147 # Try different attributes
106148 path = (getattr (change , 'new_path' , None ) or
107149 getattr (change , 'old_path' , None ) or
@@ -154,7 +196,19 @@ def get_object_path(change) -> str:
154196
155197
156198def should_skip_change (change , filtered_paths : set ) -> bool :
157- """Check if a breaking change should be skipped based on filters."""
199+ """Determine if a breaking change should be skipped based on exempt decorators.
200+
201+ A change is skipped if:
202+ - The changed object itself is in filtered_paths (exact match)
203+ - The changed object is a child of an exempt object (prefix match)
204+
205+ Args:
206+ change: A Griffe breaking change object
207+ filtered_paths: Set of paths with exempt decorators
208+
209+ Returns:
210+ bool: True if the change should be skipped (filtered out)
211+ """
158212 path = get_object_path (change )
159213 if not path :
160214 return False
0 commit comments