Skip to content

Commit 3dfe252

Browse files
committed
Update generate_graph_objects_docs.py
1 parent 4b3017b commit 3dfe252

File tree

1 file changed

+77
-35
lines changed

1 file changed

+77
-35
lines changed

scripts/generate_graph_objects_docs.py

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)