3
3
import json
4
4
import tomllib
5
5
import yaml
6
+ import glob
6
7
7
8
import httpx
9
+ from dataclasses import dataclass
8
10
from git import Repo , GitCommandError
9
11
from mkdocs .config import Config , config_options
10
12
from mkdocs .config .defaults import MkDocsConfig
11
13
from mkdocs .exceptions import PluginError
12
- from mkdocs .plugins import event_priority , get_plugin_logger , BasePlugin
14
+ from mkdocs .plugins import get_plugin_logger , BasePlugin
13
15
from mkdocs .structure .files import File , Files
14
16
from mkdocs .structure .nav import Navigation , Section , Link
15
17
from mkdocs .structure .pages import Page
16
18
from mkdocs .utils .templates import TemplateContext
17
19
18
- from pulp_docs .context import ctx_blog , ctx_docstrings , ctx_draft
20
+ from pulp_docs .context import ctx_blog , ctx_docstrings , ctx_draft , ctx_path
19
21
20
22
log = get_plugin_logger (__name__ )
21
23
@@ -35,6 +37,42 @@ class ComponentOption(Config):
35
37
rest_api = config_options .Type (str , default = "" )
36
38
37
39
40
+ @dataclass (frozen = True )
41
+ class Component :
42
+ title : str
43
+ path : str
44
+ kind : str
45
+ git_url : str
46
+ rest_api : str
47
+
48
+ version : str
49
+ repository_dir : Path
50
+ component_dir : Path
51
+
52
+ @classmethod
53
+ def build (cls , find_path : list [str ], component_opt : ComponentOption ):
54
+ body = dict (component_opt )
55
+ repository_name = component_opt .path .split ("/" )[0 ]
56
+ for dir_spec in find_path :
57
+ repo_filter , _ , basedir = dir_spec .rpartition ("@" )
58
+ if repo_filter and repo_filter != repository_name :
59
+ continue
60
+ basedir = Path (basedir )
61
+ component_dir = basedir / component_opt .path
62
+ if component_dir .exists ():
63
+ version = "unknown"
64
+ try :
65
+ pyproject = component_dir / "pyproject.toml"
66
+ version = tomllib .loads (pyproject .read_text ())["project" ]["version" ]
67
+ except Exception :
68
+ pass
69
+ body ["version" ] = version
70
+ body ["repository_dir" ] = basedir / repository_name
71
+ body ["component_dir" ] = component_dir
72
+ return cls (** body )
73
+ return None
74
+
75
+
38
76
class PulpDocsPluginConfig (Config ):
39
77
components = config_options .ListOfItems (ComponentOption , default = [])
40
78
@@ -175,18 +213,12 @@ def _render_sitemap_item(nav_item: Page | Section) -> str:
175
213
176
214
177
215
def component_data (
178
- component : ComponentOption ,
179
- component_dir : Path ,
216
+ component : Component ,
180
217
) -> dict [str , str | list [str ]]:
181
218
"""Generate data for rendering md templates."""
219
+ component_dir = component .component_dir
182
220
path = component_dir .name
183
221
184
- version = "unknown"
185
- try :
186
- pyproject = component_dir / "pyproject.toml"
187
- version = tomllib .loads (pyproject .read_text ())["project" ]["version" ]
188
- except Exception :
189
- pass
190
222
github_org = "pulp"
191
223
try :
192
224
template_config = component_dir / "template_config.yml"
@@ -204,7 +236,7 @@ def component_data(
204
236
return {
205
237
"title" : f"[{ component .title } ](site:{ path } /)" ,
206
238
"kind" : component .kind ,
207
- "version" : version ,
239
+ "version" : component . version ,
208
240
"links" : links ,
209
241
}
210
242
@@ -225,34 +257,47 @@ def rss_items() -> list:
225
257
return rss_feed ["items" ][:20 ]
226
258
227
259
260
+ def load_components (find_path : list [str ], config : MkDocsConfig , draft : bool ):
261
+ loaded_components = []
262
+ for component_opt in config .components :
263
+ component = Component .build (find_path , component_opt )
264
+ if component :
265
+ loaded_components .append (component )
266
+ all_components = {o .path for o in config .components }
267
+ not_loaded_components = all_components .difference (
268
+ {o .path for o in loaded_components }
269
+ )
270
+ if not_loaded_components :
271
+ not_loaded_components = sorted (not_loaded_components )
272
+ if draft :
273
+ log .warning (f"Skip missing components { not_loaded_components } ." )
274
+ else :
275
+ raise PluginError (f"Components missing: { not_loaded_components } ." )
276
+ return loaded_components
277
+
278
+
228
279
class PulpDocsPlugin (BasePlugin [PulpDocsPluginConfig ]):
229
280
def on_config (self , config : MkDocsConfig ) -> MkDocsConfig | None :
230
- # Two directories up from docs is where we expect all the other repositories.
231
281
self .blog = ctx_blog .get ()
232
282
self .docstrings = ctx_docstrings .get ()
233
283
self .draft = ctx_draft .get ()
234
284
235
285
self .pulp_docs_dir = Path (config .docs_dir ).parent
236
- self .repositories_dir = self .pulp_docs_dir .parent
286
+ self .find_path = ctx_path .get () or [str (self .pulp_docs_dir .parent )]
287
+
288
+ loaded_components = load_components (self .find_path , self .config , self .draft )
289
+ self .config .components = loaded_components
290
+ loaded_component_dirnames = [str (c .component_dir ) for c in loaded_components ]
291
+ log .info (f"Using components={ loaded_component_dirnames } " )
237
292
238
293
mkdocstrings_config = config .plugins ["mkdocstrings" ].config
239
294
components_var = []
240
- new_components = []
241
295
for component in self .config .components :
242
- component_dir = self .repositories_dir / component .path
243
- if component_dir .exists ():
244
- components_var .append (component_data (component , component_dir ))
245
- config .watch .append (str (component_dir / "docs" ))
246
- mkdocstrings_config .handlers ["python" ]["paths" ].append (
247
- str (component_dir )
248
- )
249
- new_components .append (component )
250
- else :
251
- if self .draft :
252
- log .warning (f"Skip missing component '{ component .title } '." )
253
- else :
254
- raise PluginError (f"Component '{ component .title } ' missing." )
255
- self .config .components = new_components
296
+ components_var .append (component_data (component ))
297
+ config .watch .append (str (component .component_dir / "docs" ))
298
+ mkdocstrings_config .handlers ["python" ]["paths" ].append (
299
+ str (component .component_dir )
300
+ )
256
301
257
302
macros_plugin = config .plugins ["macros" ]
258
303
macros_plugin .register_macros ({"rss_items" : rss_items })
@@ -273,10 +318,10 @@ def on_files(self, files: Files, /, *, config: MkDocsConfig) -> Files | None:
273
318
user_nav : dict [str , t .Any ] = {}
274
319
dev_nav : dict [str , t .Any ] = {}
275
320
for component in self .config .components :
276
- component_dir = self . repositories_dir / component .path
321
+ component_dir = component .component_dir
277
322
278
323
log .info (f"Fetching docs from '{ component .title } '." )
279
- git_repository_dir = self . repositories_dir / Path ( component .path ). parts [ 0 ]
324
+ git_repository_dir = component .repository_dir
280
325
try :
281
326
git_branch = Repo (git_repository_dir ).active_branch .name
282
327
except TypeError :
0 commit comments