Skip to content

Commit 636525e

Browse files
authored
Render fields from dataclasses in API Reference (#1615)
Ensure that props/fields are correctly rendered in the autogenerated API reference.
1 parent cf5a556 commit 636525e

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

pcweb/pages/docs/apiref.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
rx.Base,
1010
rx.Component,
1111
rx.ComponentState,
12-
rx.Config,
12+
(rx.Config, rx.config.BaseConfig),
1313
rx.event.Event,
1414
rx.event.EventHandler,
1515
rx.event.EventSpec,
@@ -26,9 +26,17 @@
2626

2727
pages = []
2828
for module in modules:
29+
if isinstance(module, tuple):
30+
module, *extra_modules = module
31+
extra_fields = []
32+
for extra_module in extra_modules:
33+
s_extra = Source(module=extra_module)
34+
extra_fields.extend(s_extra.get_fields())
35+
else:
36+
extra_fields = None
2937
s = Source(module=module)
3038
name = module.__name__.lower()
31-
docs = generate_docs(name, s)
39+
docs = generate_docs(name, s, extra_fields=extra_fields)
3240
title = name.replace("_", " ").title()
3341
page_data = docpage(f"/docs/api-reference/{name}/", title)(docs)
3442
page_data.title = page_data.title.split("·")[0].strip()

pcweb/pages/docs/source.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import dataclasses
12
import inspect
23
import re
34

45
# Get the comment for a specific field.
5-
from typing import Callable, Type
6+
from typing import Callable, ClassVar, Type, get_origin, get_type_hints
67

78
import reflex as rx
89
from pcweb.templates.docpage import h1_comp, h2_comp
@@ -54,9 +55,11 @@ def get_class_fields(self) -> list[dict]:
5455
return out
5556

5657
def get_fields(self) -> list[dict]:
57-
if not issubclass(self.module, rx.Base):
58-
return []
59-
return self.get_annotations(self.module.__fields__)
58+
if dataclasses.is_dataclass(self.module):
59+
return self.get_annotations({f.name: f for f in dataclasses.fields(self.module)})
60+
elif isinstance(self.module, type) and issubclass(self.module, rx.Base):
61+
return self.get_annotations(self.module.__fields__)
62+
return []
6063

6164
def get_methods(self):
6265
return [
@@ -170,8 +173,16 @@ def get_annotations(self, props) -> list[dict]:
170173

171174

172175
def format_field(field):
173-
type_ = field["prop"].type_
176+
prop = field["prop"]
177+
try:
178+
type_ = prop.type_
179+
except AttributeError:
180+
type_ = prop.type
174181
default = field["prop"].default
182+
if default is dataclasses.MISSING:
183+
default = None
184+
else:
185+
default = repr(default)
175186
type_str = type_.__name__ if hasattr(type_, "__name__") else str(type_)
176187
if default:
177188
type_str += f" = {default}"
@@ -217,8 +228,10 @@ def format_fields(headers, fields):
217228
)
218229

219230

220-
def generate_docs(title: str, s: Source):
231+
def generate_docs(title: str, s: Source, extra_fields: list[dict] | None = None):
221232
fields = s.get_fields()
233+
if extra_fields:
234+
fields.extend(extra_fields)
222235
class_fields = s.get_class_fields()
223236
return rx.box(
224237
h1_comp(text=title.title()),

0 commit comments

Comments
 (0)