hook.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import os
  2. import re
  3. import glob
  4. import git
  5. _INCLUDE_EXAMPLES_REGEX = re.compile(
  6. r"""(?P<_includer_indent>[^\S\r\n]*){\s*%\s*include-examples\s*"(?P<example_name>[^")]+)"\s*%\s*}\s*""",
  7. flags=re.VERBOSE | re.DOTALL,
  8. )
  9. _INCLUDE_EXAMPLE_REGEX = re.compile(
  10. r"""(?P<_includer_indent>[^\S\r\n]*){\s*%\s*include-example\s*"(?P<example_path>[^")]+)"\s*%\s*}\s*""",
  11. flags=re.VERBOSE | re.DOTALL,
  12. )
  13. _LINT_MAP = {
  14. ".py": "python",
  15. ".json": "json",
  16. ".yaml": "yaml",
  17. ".yml": "yaml",
  18. ".sh": "sh",
  19. ".md": "md",
  20. }
  21. _REPO_BASE = os.path.abspath(
  22. os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
  23. )
  24. _EXAMPLES_BASE = os.path.abspath(os.path.join(_REPO_BASE, "examples"))
  25. def sub_include_examples(match):
  26. example_name = match.group("example_name")
  27. indents_level0 = match.group("_includer_indent")
  28. lines = []
  29. lines.append(f"{indents_level0}???+ Example\n")
  30. lines.append(f"{indents_level0}\n")
  31. indents_level1 = indents_level0 + " "
  32. for example_type, pretty_name in [("pipeline", "Pipeline"), ("dsl/v2", "DSL")]:
  33. include_path = os.path.join(_EXAMPLES_BASE, example_type, example_name, "*.*")
  34. lines.append(f'{indents_level1}=== "{pretty_name}"\n\n')
  35. indents_level2 = f"{indents_level1} "
  36. for name in glob.glob(include_path):
  37. if name.endswith("README.md") or name.endswith("readme.md"):
  38. lines.append(f"{indents_level2}```markdown\n")
  39. with open(name) as f:
  40. for line in f.readlines():
  41. lines.append(f"{indents_level2}{line}")
  42. lines.append(f"{indents_level2}\n")
  43. lines.append(f"{indents_level2}```\n")
  44. lines.append(f"{indents_level2}\n")
  45. for file_name in glob.glob(include_path):
  46. if file_name.endswith("README.md") or file_name.endswith("readme.md"):
  47. continue
  48. _, file_extension = os.path.splitext(file_name)
  49. lint = _LINT_MAP.get(file_extension, "")
  50. lines.append(
  51. f'{indents_level2}??? Example "{os.path.basename(file_name)}"\n'
  52. )
  53. lines.append(f"{indents_level2} ```{lint}\n")
  54. head = True
  55. with open(file_name) as f:
  56. for line in f.readlines():
  57. # skip license
  58. if head:
  59. if line.strip() == "" or line.lstrip().startswith("#"):
  60. continue
  61. head = False
  62. lines.append(f"{indents_level2} {line}")
  63. lines.append(f"{indents_level2} \n")
  64. lines.append(f"{indents_level2} ```\n")
  65. lines.append(f"{indents_level2} \n")
  66. return "".join(lines)
  67. def sub_include_example(src_file_path):
  68. def sub(match):
  69. example_path = match.group("example_path")
  70. indents_level0 = match.group("_includer_indent")
  71. lines = []
  72. lines.append(f"{indents_level0}\n")
  73. lines.append(f'{indents_level0}??? Example "{example_path}"\n')
  74. lines.append(f"{indents_level0}\n")
  75. indents_level1 = indents_level0 + " "
  76. abs_file_path = os.path.abspath(
  77. os.path.join(src_file_path, os.pardir, example_path)
  78. )
  79. if os.path.exists(abs_file_path):
  80. with open(abs_file_path) as f:
  81. _, file_extension = os.path.splitext(abs_file_path)
  82. lint = _LINT_MAP.get(file_extension, "")
  83. lines.append(f"{indents_level1}```{lint}\n")
  84. head = True
  85. for line in f.readlines():
  86. # skip license
  87. if head:
  88. if line.strip() == "" or line.lstrip().startswith("#"):
  89. continue
  90. head = False
  91. lines.append(f"{indents_level1} {line}")
  92. lines.append(f"{indents_level1}\n")
  93. lines.append(f"{indents_level1}```\n")
  94. lines.append(f"{indents_level1}\n")
  95. return "".join(lines)
  96. return sub
  97. try:
  98. repo = git.Repo(search_parent_directories=True)
  99. sha = repo.head.object.hexsha
  100. url = repo.remote().url
  101. if url.endswith(".git"):
  102. url = url[:-4]
  103. GITHUB_REPO = f"{url}/tree/{sha}"
  104. except BaseException:
  105. GITHUB_REPO = "https://github.com/FederatedAI/FATE/tree/master"
  106. _DIR_URL_REGEX = re.compile(
  107. r"""(?P<text>\[\s*:file_folder:[^\(]*\])\((?P<url>[^\)]+)\)""",
  108. flags=re.VERBOSE | re.DOTALL,
  109. )
  110. def _fix_dir_url(src_path):
  111. def _replace(match):
  112. text = match.group("text")
  113. url = match.group("url")
  114. if not url.startswith("http"):
  115. url_rel_to_repo_base = os.path.relpath(
  116. os.path.abspath(os.path.join(src_path, os.path.pardir, url)), _REPO_BASE
  117. )
  118. url = f"{GITHUB_REPO}/{url_rel_to_repo_base}"
  119. return f"{text}({url})"
  120. return _replace
  121. _COMMENT_REGEX = re.compile(
  122. r"""[^\S\r\n]*<!--\s*mkdocs\s*\n(?P<_content>.*?)-->""",
  123. flags=re.VERBOSE | re.DOTALL,
  124. )
  125. def _remove_comment(match):
  126. content = match.group("_content")
  127. return content
  128. def on_page_markdown(markdown, page, **kwargs):
  129. markdown = re.sub(_DIR_URL_REGEX, _fix_dir_url(page.file.abs_src_path), markdown)
  130. # remove specific commnent
  131. markdown = re.sub(_COMMENT_REGEX, _remove_comment, markdown)
  132. markdown = re.sub(
  133. _INCLUDE_EXAMPLES_REGEX,
  134. sub_include_examples,
  135. markdown,
  136. )
  137. markdown = re.sub(
  138. _INCLUDE_EXAMPLE_REGEX,
  139. sub_include_example(page.file.abs_src_path),
  140. markdown,
  141. )
  142. return markdown