@@ -27,7 +27,6 @@ def _has_attr_section(el: dc.Docstring | None):
27
27
return any ([isinstance (x , ds .DocstringSectionAttributes ) for x in el .parsed ])
28
28
29
29
30
-
31
30
class MdRenderer (Renderer ):
32
31
"""Render docstrings to markdown.
33
32
@@ -66,8 +65,7 @@ def __init__(
66
65
show_signature_annotations : bool = False ,
67
66
display_name : str = "relative" ,
68
67
hook_pre = None ,
69
- use_interlinks = False ,
70
-
68
+ use_interlinks = False ,
71
69
):
72
70
self .header_level = header_level
73
71
self .show_signature = show_signature
@@ -79,14 +77,13 @@ def __init__(
79
77
self .crnt_header_level = self .header_level
80
78
81
79
@contextmanager
82
- def _increment_header (self , n = 1 ):
80
+ def _increment_header (self , n = 1 ):
83
81
self .crnt_header_level += n
84
82
try :
85
83
yield
86
- finally :
84
+ finally :
87
85
self .crnt_header_level -= n
88
86
89
-
90
87
def _fetch_object_dispname (self , el : "dc.Alias | dc.Object" ):
91
88
# TODO: copied from Builder, should move into util function
92
89
if self .display_name == "name" :
@@ -101,13 +98,12 @@ def _fetch_object_dispname(self, el: "dc.Alias | dc.Object"):
101
98
return el .canonical_path
102
99
103
100
raise ValueError (f"Unsupported display_name: `{ self .display_name } `" )
104
-
101
+
105
102
def _render_table (self , rows , headers ):
106
103
table = tabulate (rows , headers = headers , tablefmt = "github" )
107
104
108
105
return table
109
106
110
-
111
107
# render_annotation method --------------------------------------------------------
112
108
113
109
@dispatch
@@ -119,11 +115,11 @@ def render_annotation(self, el: str) -> str:
119
115
An object representing a type annotation.
120
116
"""
121
117
return el
122
-
118
+
123
119
@dispatch
124
120
def render_annotation (self , el : None ) -> str :
125
121
return ""
126
-
122
+
127
123
@dispatch
128
124
def render_annotation (self , el : expr .Name ) -> str :
129
125
# TODO: maybe there is a way to get tabulate to handle this?
@@ -142,18 +138,21 @@ def signature(self, el: dc.Alias, source: Optional[dc.Alias] = None):
142
138
return self .signature (el .target , el )
143
139
144
140
@dispatch
145
- def signature (self , el : Union [dc .Class , dc .Function ], source : Optional [dc .Alias ] = None ):
141
+ def signature (
142
+ self , el : Union [dc .Class , dc .Function ], source : Optional [dc .Alias ] = None
143
+ ):
146
144
name = self ._fetch_object_dispname (source or el )
147
145
pars = self .render (el .parameters )
148
146
149
147
return f"`{ name } ({ pars } )`"
150
148
151
149
@dispatch
152
- def signature (self , el : Union [dc .Module , dc .Attribute ], source : Optional [dc .Alias ] = None ):
150
+ def signature (
151
+ self , el : Union [dc .Module , dc .Attribute ], source : Optional [dc .Alias ] = None
152
+ ):
153
153
name = self ._fetch_object_dispname (source or el )
154
154
return f"`{ name } `"
155
155
156
-
157
156
@dispatch
158
157
def render_header (self , el : layout .Doc ):
159
158
"""Render the header of a docstring, including any anchors."""
@@ -164,7 +163,6 @@ def render_header(self, el: layout.Doc):
164
163
_anchor = f"{{ #{ el .obj .path } }}"
165
164
return f"{ '#' * self .crnt_header_level } { _str_dispname } { _anchor } "
166
165
167
-
168
166
# render method -----------------------------------------------------------
169
167
170
168
@dispatch
@@ -199,7 +197,7 @@ def render(self, el: layout.Section):
199
197
body = list (map (self .render , el .contents ))
200
198
201
199
return "\n \n " .join ([section_top , * body ])
202
-
200
+
203
201
@dispatch
204
202
def render (self , el : layout .Interlaced ):
205
203
# render a sequence of objects with like-sections together.
@@ -221,7 +219,6 @@ def render(self, el: layout.Interlaced):
221
219
if first_doc .obj .docstring is None :
222
220
raise ValueError ("The first element of Interlaced must have a docstring." )
223
221
224
-
225
222
str_title = self .render_header (first_doc )
226
223
str_sig = "\n \n " .join (map (self .signature , objs ))
227
224
str_body = []
@@ -265,7 +262,6 @@ def render(self, el: Union[layout.DocClass, layout.DocModule]):
265
262
raw_meths = [x for x in el .members if x .obj .is_function ]
266
263
raw_classes = [x for x in el .members if x .obj .is_class ]
267
264
268
-
269
265
header = "| Name | Description |\n | --- | --- |"
270
266
271
267
# attribute summary table ----
@@ -274,16 +270,16 @@ def render(self, el: Union[layout.DocClass, layout.DocModule]):
274
270
# TODO: for now, we skip making an attribute table on classes, unless
275
271
# they contain an attributes section in the docstring
276
272
if (
277
- raw_attrs
278
- and not _has_attr_section (el .obj .docstring )
279
- # TODO: what should backwards compat be?
280
- # and not isinstance(el, layout.DocClass)
281
- ):
273
+ raw_attrs
274
+ and not _has_attr_section (el .obj .docstring )
275
+ # TODO: what should backwards compat be?
276
+ # and not isinstance(el, layout.DocClass)
277
+ ):
282
278
283
279
_attrs_table = "\n " .join (map (self .summarize , raw_attrs ))
284
280
attrs = f"{ sub_header } Attributes\n \n { header } \n { _attrs_table } "
285
281
attr_docs .append (attrs )
286
-
282
+
287
283
# classes summary table ----
288
284
if raw_classes :
289
285
_summary_table = "\n " .join (map (self .summarize , raw_classes ))
@@ -293,22 +289,29 @@ def render(self, el: Union[layout.DocClass, layout.DocModule]):
293
289
294
290
n_incr = 1 if el .flat else 2
295
291
with self ._increment_header (n_incr ):
296
- class_docs .extend ([self .render (x ) for x in raw_classes if isinstance (x , layout .Doc )])
292
+ class_docs .extend (
293
+ [
294
+ self .render (x )
295
+ for x in raw_classes
296
+ if isinstance (x , layout .Doc )
297
+ ]
298
+ )
297
299
298
300
# method summary table ----
299
301
if raw_meths :
300
302
_summary_table = "\n " .join (map (self .summarize , raw_meths ))
301
303
section_name = (
302
- "Methods" if isinstance (el , layout .DocClass )
303
- else "Functions"
304
+ "Methods" if isinstance (el , layout .DocClass ) else "Functions"
304
305
)
305
306
objs = f"{ sub_header } { section_name } \n \n { header } \n { _summary_table } "
306
307
meth_docs .append (objs )
307
308
308
309
# TODO use context manager, or context variable?
309
310
n_incr = 1 if el .flat else 2
310
311
with self ._increment_header (n_incr ):
311
- meth_docs .extend ([self .render (x ) for x in raw_meths if isinstance (x , layout .Doc )])
312
+ meth_docs .extend (
313
+ [self .render (x ) for x in raw_meths if isinstance (x , layout .Doc )]
314
+ )
312
315
313
316
body = self .render (el .obj )
314
317
return "\n \n " .join ([title , body , * attr_docs , * class_docs , * meth_docs ])
@@ -366,19 +369,24 @@ def render(self, el: dc.Parameters):
366
369
367
370
# index for final positionly only args (via /)
368
371
try :
369
- pos_only = max ([ii for ii , el in enumerate (el ) if el .kind == dc .ParameterKind .positional_only ])
372
+ pos_only = max (
373
+ [
374
+ ii
375
+ for ii , el in enumerate (el )
376
+ if el .kind == dc .ParameterKind .positional_only
377
+ ]
378
+ )
370
379
except ValueError :
371
380
pos_only = None
372
381
373
-
374
382
pars = list (map (self .render , el ))
375
383
376
384
# insert a single `*,` argument to represent the shift to kw only arguments,
377
385
# only if the shift to kw_only was not triggered by *args (var_positional)
378
386
if (
379
387
kw_only is not None
380
388
and kw_only > 0
381
- and el [kw_only - 1 ].kind != dc .ParameterKind .var_positional
389
+ and el [kw_only - 1 ].kind != dc .ParameterKind .var_positional
382
390
):
383
391
pars .insert (kw_only , sanitize ("*" ))
384
392
@@ -461,7 +469,7 @@ def render(self, el: ds.DocstringAttribute):
461
469
row = [
462
470
sanitize (el .name ),
463
471
self .render_annotation (el .annotation ),
464
- sanitize (el .description or "" , allow_markdown = True )
472
+ sanitize (el .description or "" , allow_markdown = True ),
465
473
]
466
474
return row
467
475
@@ -530,7 +538,6 @@ def render(self, el: Union[ds.DocstringReturn, ds.DocstringRaise]):
530
538
def render (self , el ):
531
539
raise NotImplementedError (f"{ type (el )} " )
532
540
533
-
534
541
# Summarize ===============================================================
535
542
# this method returns a summary description, such as a table summarizing a
536
543
# layout.Section, or a row in the table for layout.Page or layout.DocFunction.
@@ -569,14 +576,16 @@ def summarize(self, el: layout.Section):
569
576
570
577
str_func_table = "\n " .join ([thead , * rendered ])
571
578
return f"{ header } \n \n { str_func_table } "
572
-
579
+
573
580
return header
574
581
575
582
@dispatch
576
583
def summarize (self , el : layout .Page ):
577
584
if el .summary is not None :
578
585
# TODO: assumes that files end with .qmd
579
- return self ._summary_row (f"[{ el .summary .name } ]({ el .path } .qmd)" , el .summary .desc )
586
+ return self ._summary_row (
587
+ f"[{ el .summary .name } ]({ el .path } .qmd)" , el .summary .desc
588
+ )
580
589
581
590
if len (el .contents ) > 1 and not el .flatten :
582
591
raise ValueError (
@@ -591,16 +600,18 @@ def summarize(self, el: layout.Page):
591
600
@dispatch
592
601
def summarize (self , el : layout .MemberPage ):
593
602
# TODO: model should validate these only have a single entry
594
- return self .summarize (el .contents [0 ], el .path , shorten = True )
595
-
603
+ return self .summarize (el .contents [0 ], el .path , shorten = True )
604
+
596
605
@dispatch
597
606
def summarize (self , el : layout .Interlaced , * args , ** kwargs ):
598
607
rows = [self .summarize (doc , * args , ** kwargs ) for doc in el .contents ]
599
608
600
609
return "\n " .join (rows )
601
610
602
611
@dispatch
603
- def summarize (self , el : layout .Doc , path : Optional [str ] = None , shorten : bool = False ):
612
+ def summarize (
613
+ self , el : layout .Doc , path : Optional [str ] = None , shorten : bool = False
614
+ ):
604
615
if path is None :
605
616
link = f"[{ el .name } ](#{ el .anchor } )"
606
617
else :
@@ -612,8 +623,8 @@ def summarize(self, el: layout.Doc, path: Optional[str] = None, shorten: bool =
612
623
613
624
@dispatch
614
625
def summarize (self , el : layout .Link ):
615
- description = self .summarize (el .obj )
616
- return self ._summary_row (f"[](`{ el .name } `)" , description )
626
+ description = self .summarize (el .obj )
627
+ return self ._summary_row (f"[](`{ el .name } `)" , description )
617
628
618
629
@dispatch
619
630
def summarize (self , obj : Union [dc .Object , dc .Alias ]) -> str :
0 commit comments