@@ -35,12 +35,21 @@ def __init__(self):
3535 self .packages : Dict [str , Any ] = {}
3636 self .module_paths : Dict [str , str ] = {}
3737
38+ # Hardcoded exclusions - classes/modules to skip during documentation generation
39+ self .excluded_classes = [
40+ # Exclude the deprecated lowercase version since we have the proper cased version
41+ "plotly.graph_objects.Histogram2dcontour" ,
42+ ]
43+ self .excluded_modules = [
44+ # Add any modules to exclude here if needed
45+ ]
46+
3847 def is_class (self , obj ) -> bool :
3948 """Check if an object is a class."""
4049 return inspect .isclass (obj ) and not obj .__name__ .startswith ('_' )
4150
42- def is_deprecated_class (self , full_class_name : str , class_obj : Any ) -> bool :
43- """Check if a class is deprecated by testing for deprecation warnings ."""
51+ def get_deprecation_info (self , full_class_name : str , class_obj : Any ) -> tuple [ bool , str ] :
52+ """Check if a class is deprecated and get the actual deprecation message ."""
4453 import warnings
4554
4655 try :
@@ -53,12 +62,17 @@ def is_deprecated_class(self, full_class_name: str, class_obj: Any) -> bool:
5362 # Check if any warnings contain "deprecat"
5463 for warning in w :
5564 if 'deprecat' in str (warning .message ).lower ():
56- return True
57- return False
65+ return True , str ( warning . message )
66+ return False , ""
5867 except Exception :
5968 # If we can't instantiate it, assume it's not deprecated
6069 # (it might just require parameters or have other issues)
61- return False
70+ return False , ""
71+
72+ def is_deprecated_class (self , full_class_name : str , class_obj : Any ) -> bool :
73+ """Check if a class is deprecated by testing for deprecation warnings."""
74+ is_deprecated , _ = self .get_deprecation_info (full_class_name , class_obj )
75+ return is_deprecated
6276
6377 def is_package (self , obj ) -> bool :
6478 """Check if an object is a package/module."""
@@ -97,6 +111,12 @@ def inspect_module(self, module, prefix: str = "") -> None:
97111 public_full_name = module_name .replace ("plotly.graph_objs" , "plotly.graph_objects" ) + f".{ attr_name } "
98112 else :
99113 public_full_name = f"{ module_name } .{ attr_name } "
114+
115+ # Skip excluded classes
116+ if public_full_name in self .excluded_classes :
117+ print (f" Skipping excluded class: { public_full_name } " )
118+ continue
119+
100120 self .classes [public_full_name ] = attr
101121 print (f" Found class: { public_full_name } " )
102122
@@ -107,6 +127,12 @@ def inspect_module(self, module, prefix: str = "") -> None:
107127 public_package_name = full_name
108128 if full_name .startswith ("plotly.graph_objs" ):
109129 public_package_name = full_name .replace ("plotly.graph_objs" , "plotly.graph_objects" )
130+
131+ # Skip excluded modules
132+ if public_package_name in self .excluded_modules :
133+ print (f" Skipping excluded module: { public_package_name } " )
134+ continue
135+
110136 self .packages [public_package_name ] = attr
111137 self .module_paths [public_package_name ] = self .get_module_path (attr )
112138 print (f" Found package: { public_package_name } " )
@@ -183,11 +209,15 @@ def generate_class_page(self, class_name: str, class_obj: Any) -> Path:
183209 content = f"# { class_name } \n \n "
184210
185211 # Check if this is a deprecated class
186- if self .inspector .is_deprecated_class (class_name , class_obj ):
187- content += f"**⚠️ DEPRECATED**: This class is deprecated and may not be available for import.\n \n "
188- content += f"Please refer to the specific implementation in the appropriate submodule.\n \n "
189- # Don't use ::: syntax for deprecated classes as they can't be imported
190- content += f"## Deprecated Class: { class_name } \n \n "
212+ is_deprecated , deprecation_message = self .inspector .get_deprecation_info (class_name , class_obj )
213+ if is_deprecated :
214+ content += f"!!! info \" Deprecated\" \n "
215+ # Use the actual deprecation message, properly indented
216+ for line in deprecation_message .split ('\n ' ):
217+ content += f" { line } \n "
218+ content += "\n "
219+ # Still generate the reference documentation for deprecated classes
220+ content += f"::: { class_name } \n "
191221 else :
192222 content += f"::: { class_name } \n "
193223
@@ -245,29 +275,31 @@ def generate_package_index(self, package_name: str, package_obj: Any) -> Path:
245275 if package_obj .__doc__ :
246276 content += f"{ package_obj .__doc__ } \n \n "
247277
248- # Add classes section
278+ # Add classes section with individual headings for TOC
249279 if package_classes :
250280 content += "## Classes\n \n "
251281 for class_name in sorted (package_classes ):
252282 class_display_name = class_name .split ('.' )[- 1 ]
253283 class_file_name = f"{ class_display_name } .md"
254- content += f"- [{ class_display_name } ]({ class_file_name } )\n "
284+ # Add individual class as H3 heading for TOC
285+ content += f"### [{ class_display_name } ]({ class_file_name } )\n \n "
255286 content += "\n "
256287
257- # Add subpackages section
288+ # Add submodules section
258289 if package_subpackages :
259- content += "## Packages \n \n "
290+ content += "## Submodules \n \n "
260291 for subpackage_name in sorted (package_subpackages ):
261292 subpackage_display_name = subpackage_name .split ('.' )[- 1 ]
262293 # Always link to local stub within the -package folder to avoid relative path issues
263294 subpackage_folder_name = f"{ subpackage_display_name } -package"
264295 link = f"{ subpackage_folder_name } /index.md"
265- content += f"- [{ subpackage_display_name } ]({ link } )\n "
296+ # Add individual submodule as H3 heading for TOC
297+ content += f"### [{ subpackage_display_name } ]({ link } )\n \n "
266298 content += "\n "
267299
268- # If no classes or packages , add a note
300+ # If no classes or submodules , add a note
269301 if not package_classes and not package_subpackages :
270- content += "This package contains no public classes or subpackages .\n "
302+ content += "This module contains no public classes or submodules .\n "
271303
272304 # Write file
273305 with open (file_path , 'w' ) as f :
@@ -307,32 +339,42 @@ def generate_main_index(self) -> Path:
307339 content = "# plotly.graph_objects\n \n "
308340 content += "The main package containing all Plotly graph objects, traces, and layout components.\n \n "
309341
310- if top_level_classes :
342+ # Separate classes into current and deprecated
343+ current_classes = []
344+ deprecated_classes = []
345+
346+ for short_name , full_name in top_level_classes :
347+ class_obj = self .inspector .classes [full_name ]
348+ if self .inspector .is_deprecated_class (full_name , class_obj ):
349+ deprecated_classes .append ((short_name , full_name ))
350+ else :
351+ current_classes .append ((short_name , full_name ))
352+
353+ # Add current classes section
354+ if current_classes :
311355 content += "## Classes\n \n "
312- for short_name , full_name in top_level_classes :
313- # Check if deprecated - get the class object
314- class_obj = self .inspector .classes [full_name ]
315- if self .inspector .is_deprecated_class (full_name , class_obj ):
316- content += f"- [{ short_name } ]({ short_name } .md) ⚠️ *Deprecated*\n "
317- else :
318- content += f"- [{ short_name } ]({ short_name } .md)\n "
356+ for short_name , full_name in current_classes :
357+ # Add individual class as H3 heading for TOC
358+ content += f"### [{ short_name } ]({ short_name } .md)\n \n "
319359 content += "\n "
320360
321361 if top_level_packages :
322- content += "## Packages \n \n "
362+ content += "## Modules \n \n "
323363 for short_name , full_name in top_level_packages :
324364 package_folder_name = f"{ short_name } -package"
325- content += f"- [{ short_name } ]({ package_folder_name } /index.md)\n "
365+ # Add individual module as H3 heading for TOC
366+ content += f"### [{ short_name } ]({ package_folder_name } /index.md)\n \n "
326367 content += "\n "
327368
328- # Check if any deprecated classes exist by testing a known deprecated class
329- try :
330- angular_axis_obj = self .inspector .classes .get ("plotly.graph_objects.AngularAxis" )
331- if angular_axis_obj and self .inspector .is_deprecated_class ("plotly.graph_objects.AngularAxis" , angular_axis_obj ):
332- content += "## Notes\n \n "
333- content += "⚠️ **Deprecated Classes**: Some classes marked as deprecated are legacy classes that have been replaced with more specific implementations in submodules. Please refer to the specific implementation in the appropriate submodule for current usage.\n "
334- except Exception :
335- pass # Skip notes section if we can't check deprecation
369+ # Add deprecated classes section at the end
370+ if deprecated_classes :
371+ content += "## Deprecated Classes\n \n "
372+ content += "!!! info \" Deprecated Classes\" \n "
373+ content += " These classes are deprecated and may not be available for import. Please refer to the specific implementation in the appropriate submodule for current usage.\n \n "
374+ for short_name , full_name in deprecated_classes :
375+ # Add individual deprecated class as H3 heading for TOC with clean (Deprecated) format
376+ content += f"### [{ short_name } ]({ short_name } .md) (Deprecated)\n \n "
377+ content += "\n "
336378
337379 # Write the file
338380 file_path .write_text (content )
0 commit comments