@@ -1266,7 +1266,7 @@ def _locate_app_functions(self, cur: Any) -> Tuple[Set[str], Set[str]]:
12661266
12671267 def _extract_sample_usage (self , docstring : str ) -> Optional [str ]:
12681268 """
1269- Extract sample usage from docstring that starts with ' SAMPLE:' .
1269+ Extract sample usage from NumPy-style docstring Examples section or legacy SAMPLE: prefix .
12701270
12711271 Parameters
12721272 ----------
@@ -1281,6 +1281,104 @@ def _extract_sample_usage(self, docstring: str) -> Optional[str]:
12811281 if not docstring :
12821282 return None
12831283
1284+ # Try to use numpydoc parser first
1285+ try :
1286+ import numpydoc .docscrape as nds
1287+ parsed = nds .FunctionDoc (None , doc = docstring )
1288+
1289+ # Extract Examples section
1290+ if hasattr (parsed , 'Examples' ) and parsed .Examples :
1291+ examples_lines = []
1292+ for example in parsed .Examples :
1293+ if hasattr (example , '__iter__' ) and not isinstance (example , str ):
1294+ examples_lines .extend (str (line ) for line in example )
1295+ else :
1296+ examples_lines .append (str (example ))
1297+
1298+ if examples_lines :
1299+ return '\n ' .join (examples_lines ).strip ()
1300+ except ImportError :
1301+ # numpydoc not available, fall back to manual parsing
1302+ pass
1303+ except Exception :
1304+ # If numpydoc parsing fails, fall back to manual parsing
1305+ pass
1306+
1307+ # Manual parsing for Examples section (NumPy-style)
1308+ examples_content = self ._manual_parse_examples_section (docstring )
1309+ if examples_content :
1310+ return examples_content
1311+
1312+ # Fallback to legacy SAMPLE: prefix parsing
1313+ return self ._legacy_sample_parsing (docstring )
1314+
1315+ def _manual_parse_examples_section (self , docstring : str ) -> Optional [str ]:
1316+ """
1317+ Manually parse Examples section from NumPy-style docstring.
1318+
1319+ Parameters
1320+ ----------
1321+ docstring : str
1322+ The function's docstring
1323+
1324+ Returns
1325+ -------
1326+ Optional[str]
1327+ The examples content if found, None otherwise
1328+ """
1329+ lines = docstring .strip ().split ('\n ' )
1330+ examples_lines = []
1331+ in_examples_section = False
1332+ examples_started = False
1333+
1334+ for i , line in enumerate (lines ):
1335+ stripped_line = line .strip ()
1336+
1337+ # Look for Examples section header
1338+ if stripped_line .lower () == 'examples' :
1339+ # Check if next line is underline (dashes)
1340+ if i + 1 < len (lines ) and lines [i + 1 ].strip ().startswith ('-' ):
1341+ in_examples_section = True
1342+ continue
1343+ elif in_examples_section :
1344+ # Check if we've hit another section (word followed by line of dashes)
1345+ if (stripped_line and
1346+ not stripped_line .startswith ('-' ) and
1347+ i + 1 < len (lines ) and
1348+ lines [i + 1 ].strip ().startswith ('-' )):
1349+ break
1350+
1351+ # Skip the underline
1352+ if stripped_line .startswith ('-' ) and not examples_started :
1353+ examples_started = True
1354+ continue
1355+
1356+ if examples_started :
1357+ # Collect all content in Examples section
1358+ examples_lines .append (line .rstrip ())
1359+
1360+ if examples_lines :
1361+ # Remove trailing empty lines
1362+ while examples_lines and not examples_lines [- 1 ].strip ():
1363+ examples_lines .pop ()
1364+ return '\n ' .join (examples_lines ) if examples_lines else None
1365+
1366+ return None
1367+
1368+ def _legacy_sample_parsing (self , docstring : str ) -> Optional [str ]:
1369+ """
1370+ Legacy parsing for SAMPLE: prefix format.
1371+
1372+ Parameters
1373+ ----------
1374+ docstring : str
1375+ The function's docstring
1376+
1377+ Returns
1378+ -------
1379+ Optional[str]
1380+ The sample usage string if found, None otherwise
1381+ """
12841382 lines = docstring .strip ().split ('\n ' )
12851383 sample_lines = []
12861384 in_sample_block = False
@@ -1293,14 +1391,16 @@ def _extract_sample_usage(self, docstring: str) -> Optional[str]:
12931391 if stripped_line .startswith (prefix ):
12941392 in_sample_block = True
12951393 # Extract the part after SAMPLE:
1296- sample_content = stripped_line [len (prefix )].strip () # Remove 'SAMPLE:' prefix
1394+ sample_content = stripped_line [len (prefix ): ].strip () # Remove 'SAMPLE:' prefix
12971395 if sample_content :
12981396 sample_lines .append (sample_content )
12991397 elif in_sample_block :
13001398 # Continue collecting lines until we hit an empty line or end
13011399 if not stripped_line :
13021400 break
13031401 sample_lines .append (stripped_line )
1402+
1403+ return '\n ' .join (sample_lines ) if sample_lines else None
13041404
13051405 def _get_function_implementation (self , func : Callable [..., Any ], func_name : str ) -> Dict [str , Any ]:
13061406 """
0 commit comments