24
24
_RE_TYPED_ARGSTART = re .compile (r"([\w\[\]_]{1,}?)\s*?\((.*?)\):(.{2,})" , re .IGNORECASE )
25
25
_RE_ARGSTART = re .compile (r"(.{1,}?):(.{2,})" , re .IGNORECASE )
26
26
27
+ _IGNORE_GENERATION_INSTRUCTION = "lazydocs: ignore"
28
+
27
29
# String templates
28
30
29
31
_SOURCE_BADGE_TEMPLATE = """
@@ -179,7 +181,7 @@ def _order_by_line_nos(objs: Any, line_nos: List[int]) -> List[str]:
179
181
180
182
181
183
def to_md_file (
182
- string : str ,
184
+ markdown_str : str ,
183
185
filename : str ,
184
186
out_path : str = "." ,
185
187
watermark : bool = True ,
@@ -188,27 +190,31 @@ def to_md_file(
188
190
"""Creates an API docs file from a provided text.
189
191
190
192
Args:
191
- string (str): String with line breaks to write to file.
193
+ markdown_str (str): Markdown string with line breaks to write to file.
192
194
filename (str): Filename without the .md
193
195
watermark (bool): If `True`, add a watermark with a timestamp to bottom of the markdown files.
194
196
disable_markdownlint (bool): If `True`, an inline tag is added to disable markdownlint for this file.
195
197
out_path (str): The output directory
196
198
"""
199
+ if not markdown_str :
200
+ # Dont write empty files
201
+ return
202
+
197
203
md_file = filename
198
204
if not filename .endswith (".md" ):
199
205
md_file = filename + ".md"
200
206
201
207
if disable_markdownlint :
202
- string = "<!-- markdownlint-disable -->\n " + string
208
+ markdown_str = "<!-- markdownlint-disable -->\n " + markdown_str
203
209
204
210
if watermark :
205
- string += _WATERMARK_TEMPLATE .format (
211
+ markdown_str += _WATERMARK_TEMPLATE .format (
206
212
date = datetime .date .today ().strftime ("%d %b %Y" )
207
213
)
208
214
209
215
print ("Writing {}." .format (md_file ))
210
216
with open (os .path .join (out_path , md_file ), "w" ) as f :
211
- f .write (string )
217
+ f .write (markdown_str )
212
218
213
219
214
220
def _code_snippet (snippet : str ) -> str :
@@ -254,6 +260,20 @@ def _get_class_that_defined_method(meth: Any) -> Any:
254
260
return getattr (meth , "__objclass__" , None ) # handle special descriptor objects
255
261
256
262
263
+ def _get_docstring (obj : Any ) -> str :
264
+ return "" if obj .__doc__ is None else inspect .getdoc (obj ) or ""
265
+
266
+
267
+ def _is_object_ignored (obj : Any ) -> bool :
268
+ if (
269
+ _IGNORE_GENERATION_INSTRUCTION .replace (" " , "" ).lower ()
270
+ in _get_docstring (obj ).replace (" " , "" ).lower ()
271
+ ):
272
+ # Do not generate anything if docstring contains ignore instruction
273
+ return True
274
+ return False
275
+
276
+
257
277
def _get_src_root_path (obj : Any ) -> str :
258
278
"""Get the root path to a imported module.
259
279
@@ -271,9 +291,8 @@ def _get_src_root_path(obj: Any) -> str:
271
291
272
292
273
293
def _get_doc_summary (obj : Any ) -> str :
274
- doc = "" if obj .__doc__ is None else inspect .getdoc (obj ) or ""
275
294
# First line should contain the summary
276
- return doc .split ("\n " )[0 ]
295
+ return _get_docstring ( obj ) .split ("\n " )[0 ]
277
296
278
297
279
298
def _get_anchor_tag (header : str ) -> str :
@@ -299,7 +318,7 @@ def _doc2md(obj: Any) -> str:
299
318
# the documentation strings are now inherited if not overridden.
300
319
# For details see: https://docs.python.org/3.6/library/inspect.html#inspect.getdoc
301
320
# doc = getdoc(func) or ""
302
- doc = "" if obj . __doc__ is None else inspect . getdoc (obj ) or ""
321
+ doc = _get_docstring (obj )
303
322
304
323
blockindent = 0
305
324
argindent = 1
@@ -480,6 +499,10 @@ def func2md(self, func: Callable, clsname: str = "", depth: int = 3) -> str:
480
499
Returns:
481
500
str: Markdown documentation for selected function.
482
501
"""
502
+ if _is_object_ignored (func ):
503
+ # The function is ignored from generation
504
+ return ""
505
+
483
506
section = "#" * depth
484
507
funcname = func .__name__
485
508
modname = None
@@ -560,6 +583,10 @@ def class2md(self, cls: Any, depth: int = 2) -> str:
560
583
Returns:
561
584
str: Markdown documentation for selected class.
562
585
"""
586
+ if _is_object_ignored (cls ):
587
+ # The class is ignored from generation
588
+ return ""
589
+
563
590
section = "#" * depth
564
591
subsection = "#" * (depth + 2 )
565
592
clsname = cls .__name__
@@ -638,9 +665,9 @@ def class2md(self, cls: Any, depth: int = 2) -> str:
638
665
# object module should be the same as the calling module
639
666
and obj .__module__ == modname
640
667
):
641
- methods . append (
642
- _SEPARATOR + self . func2md ( obj , clsname = clsname , depth = depth + 1 )
643
- )
668
+ function_md = self . func2md ( obj , clsname = clsname , depth = depth + 1 )
669
+ if function_md :
670
+ methods . append ( _SEPARATOR + function_md )
644
671
645
672
markdown = _CLASS_TEMPLATE .format (
646
673
section = section ,
@@ -667,6 +694,10 @@ def module2md(self, module: types.ModuleType, depth: int = 1) -> str:
667
694
Returns:
668
695
str: Markdown documentation for selected module.
669
696
"""
697
+ if _is_object_ignored (module ):
698
+ # The module is ignored from generation
699
+ return ""
700
+
670
701
modname = module .__name__
671
702
doc = _doc2md (module )
672
703
summary = _get_doc_summary (module )
@@ -694,8 +725,10 @@ def module2md(self, module: types.ModuleType, depth: int = 1) -> str:
694
725
and hasattr (obj , "__module__" )
695
726
and obj .__module__ == modname
696
727
):
697
- classes .append (_SEPARATOR + self .class2md (obj , depth = depth + 1 ))
698
- line_nos .append (_get_line_no (obj ) or 0 )
728
+ class_markdown = self .class2md (obj , depth = depth + 1 )
729
+ if class_markdown :
730
+ classes .append (_SEPARATOR + class_markdown )
731
+ line_nos .append (_get_line_no (obj ) or 0 )
699
732
classes = _order_by_line_nos (classes , line_nos )
700
733
701
734
functions : List [str ] = []
@@ -708,8 +741,10 @@ def module2md(self, module: types.ModuleType, depth: int = 1) -> str:
708
741
and hasattr (obj , "__module__" )
709
742
and obj .__module__ == modname
710
743
):
711
- functions .append (_SEPARATOR + self .func2md (obj , depth = depth + 1 ))
712
- line_nos .append (_get_line_no (obj ) or 0 )
744
+ function_md = self .func2md (obj , depth = depth + 1 )
745
+ if function_md :
746
+ functions .append (_SEPARATOR + function_md )
747
+ line_nos .append (_get_line_no (obj ) or 0 )
713
748
functions = _order_by_line_nos (functions , line_nos )
714
749
715
750
variables : List [str ] = []
@@ -894,7 +929,7 @@ def generate_docs(
894
929
continue
895
930
896
931
try :
897
- mod = loader .find_module (module_name ).load_module (module_name )
932
+ mod = loader .find_module (module_name ).load_module (module_name ) # type: ignore
898
933
module_md = generator .module2md (mod )
899
934
if stdout_mode :
900
935
print (module_md )
@@ -963,7 +998,7 @@ def generate_docs(
963
998
if module_name .split ("." )[- 1 ].startswith ("_" ):
964
999
continue
965
1000
try :
966
- mod = loader .find_module (module_name ).load_module (
1001
+ mod = loader .find_module (module_name ).load_module ( # type: ignore
967
1002
module_name
968
1003
)
969
1004
module_md = generator .module2md (mod )
0 commit comments