Coverage for /usr/local/lib/python3.12/site-packages/prefect/utilities/render_swagger.py: 0%

63 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-12-05 10:48 +0000

1## 

2## THIS FILE WAS COPIED FROM https://github.com/bharel/mkdocs-render-swagger-plugin/blob/main/render_swagger.py 

3## TO ALLOW FOR CUSTOM MODIFICATION TO THE SWAGGERUIBUNDLE OBJECT 

4## 

5 

6import os 

7import re 

8import string 

9import urllib.parse 

10from pathlib import Path 

11from typing import Any, Optional, cast 

12from xml.sax.saxutils import escape 

13 

14import mkdocs.plugins 

15from mkdocs.config.defaults import MkDocsConfig 

16from mkdocs.structure.files import File, Files 

17from mkdocs.structure.pages import Page 

18 

19USAGE_MSG = ( 

20 "Usage: '!!swagger <filename>!!' or '!!swagger-http <url>!!'. " 

21 "File must either exist locally and be placed next to the .md that contains " 

22 "the swagger statement, or be an http(s) URL." 

23) 

24 

25TEMPLATE = string.Template( 

26 """ 

27 

28<link type="text/css" rel="stylesheet" href="$swagger_lib_css"> 

29<div id="swagger-ui"> 

30</div> 

31<script src="$swagger_lib_js" charset="UTF-8"></script> 

32<script> 

33 const ui = SwaggerUIBundle({ 

34 url: '$path', 

35 defaultModelsExpandDepth: -1, 

36 dom_id: '#swagger-ui', 

37 docExpansion: 'none', 

38 deepLinking: true, 

39 supportedSubmitMethods: [], 

40 }) 

41</script> 

42 

43""" 

44) 

45 

46ERROR_TEMPLATE = string.Template("!! SWAGGER ERROR: $error !!") 

47 

48# Used for JS. Runs locally on end-user. RFI / LFI not possible, no security risk. 

49# Restrict to local file. 

50TOKEN = re.compile(r"!!swagger(?: (?P<path>[^\\/\s><&:]+))?!!") 

51 

52# HTTP(S) variant 

53TOKEN_HTTP = re.compile(r"!!swagger-http(?: (?P<path>https?://[^\s]+))?!!") 

54 

55 

56def swagger_lib(config: MkDocsConfig) -> dict[str, Any]: 

57 """ 

58 Provides the actual swagger library used 

59 """ 

60 lib_swagger = { 

61 "css": "https://unpkg.com/swagger-ui-dist@3/swagger-ui.css", 

62 "js": "https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js", 

63 } 

64 

65 extra_javascript = config.extra_javascript 

66 extra_css = cast(list[str], config.extra_css) # pyright: ignore[reportUnknownMemberType] incomplete type hint 

67 for lib in extra_javascript: 

68 if ( 

69 os.path.basename(urllib.parse.urlparse(str(lib)).path) 

70 == "swagger-ui-bundle.js" 

71 ): 

72 lib_swagger["js"] = str(lib) 

73 break 

74 

75 for css in extra_css: 

76 if os.path.basename(urllib.parse.urlparse(css).path) == "swagger-ui.css": 

77 lib_swagger["css"] = css 

78 break 

79 return lib_swagger 

80 

81 

82class SwaggerPlugin(mkdocs.plugins.BasePlugin[Any]): 

83 def on_page_markdown( 

84 self, markdown: str, /, *, page: Page, config: MkDocsConfig, files: Files 

85 ) -> Optional[str]: 

86 is_http = False 

87 match = TOKEN.search(markdown) 

88 

89 if match is None: 

90 match = TOKEN_HTTP.search(markdown) 

91 is_http = True 

92 

93 if match is None: 

94 return markdown 

95 

96 pre_token = markdown[: match.start()] 

97 post_token = markdown[match.end() :] 

98 

99 def _error(message: str) -> str: 

100 return ( 

101 pre_token 

102 + escape(ERROR_TEMPLATE.substitute(error=message)) 

103 + post_token 

104 ) 

105 

106 path = match.group("path") 

107 

108 if path is None: 

109 return _error(USAGE_MSG) 

110 

111 if is_http: 

112 url = path 

113 else: 

114 base = page.file.abs_src_path 

115 assert base is not None 

116 try: 

117 api_file = Path(base).with_name(path) 

118 except ValueError as exc: 

119 return _error(f"Invalid path. {exc.args[0]}") 

120 

121 if not api_file.exists(): 

122 return _error(f"File {path} not found.") 

123 

124 src_dir = api_file.parent 

125 dest_dir = Path(page.file.abs_dest_path).parent 

126 

127 new_file = File(api_file.name, str(src_dir), str(dest_dir), False) 

128 files.append(new_file) 

129 url = Path(new_file.abs_dest_path).name 

130 

131 lib = swagger_lib(config) 

132 

133 markdown = ( 

134 pre_token 

135 + TEMPLATE.substitute( 

136 path=url, swagger_lib_js=lib["js"], swagger_lib_css=lib["css"] 

137 ) 

138 + post_token 

139 ) 

140 

141 # If multiple swaggers exist. 

142 return self.on_page_markdown(markdown, page=page, config=config, files=files)