mkdocs-partial 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. mkdocs_partial/__init__.py +24 -0
  2. mkdocs_partial/argparse_types.py +14 -0
  3. mkdocs_partial/docs_package_plugin.py +224 -0
  4. mkdocs_partial/entry_point.py +199 -0
  5. mkdocs_partial/integrations/__init__.py +0 -0
  6. mkdocs_partial/integrations/macros_plugin_shim.py +36 -0
  7. mkdocs_partial/integrations/material_blog_integration.py +149 -0
  8. mkdocs_partial/integrations/redirect_plugin_shim.py +23 -0
  9. mkdocs_partial/integrations/spellcheck_plugin_shim.py +46 -0
  10. mkdocs_partial/mkdcos_helpers.py +97 -0
  11. mkdocs_partial/packages/__init__.py +0 -0
  12. mkdocs_partial/packages/packager.py +218 -0
  13. mkdocs_partial/packages/templates/docs-package/dist-info/METADATA.j2 +7 -0
  14. mkdocs_partial/packages/templates/docs-package/dist-info/WHEEL.j2 +4 -0
  15. mkdocs_partial/packages/templates/docs-package/dist-info/entry_points.txt.j2 +2 -0
  16. mkdocs_partial/packages/templates/docs-package/package/__init__.py.j2 +3 -0
  17. mkdocs_partial/packages/templates/docs-package/package/__pyinstaller/__init__.py.j2 +5 -0
  18. mkdocs_partial/packages/templates/docs-package/package/__pyinstaller/hook-{{module_name}}.py.j2 +31 -0
  19. mkdocs_partial/packages/templates/docs-package/package/plugin.py.j2 +5 -0
  20. mkdocs_partial/packages/templates/site-package/dist-info/METADATA.j2 +7 -0
  21. mkdocs_partial/packages/templates/site-package/dist-info/WHEEL.j2 +4 -0
  22. mkdocs_partial/packages/templates/site-package/dist-info/entry_points.txt.j2 +5 -0
  23. mkdocs_partial/packages/templates/site-package/package/__init__.py.j2 +3 -0
  24. mkdocs_partial/packages/templates/site-package/package/__main__.py.j2 +4 -0
  25. mkdocs_partial/packages/templates/site-package/package/__pyinstaller/__init__.py.j2 +5 -0
  26. mkdocs_partial/packages/templates/site-package/package/__pyinstaller/hook-{{module_name}}.py.j2 +30 -0
  27. mkdocs_partial/packages/templates/site-package/package/entry_point.py.j2 +11 -0
  28. mkdocs_partial/partial_docs_plugin.py +92 -0
  29. mkdocs_partial/site_entry_point.py +151 -0
  30. mkdocs_partial/templating/__init__.py +5 -0
  31. mkdocs_partial/templating/markdown_extension.py +38 -0
  32. mkdocs_partial/templating/templater.py +76 -0
  33. mkdocs_partial/templating/templater_extension.py +17 -0
  34. mkdocs_partial/templating/version.py +5 -0
  35. mkdocs_partial/version.py +1 -0
  36. mkdocs_partial-1.2.1.dist-info/LICENSE +19 -0
  37. mkdocs_partial-1.2.1.dist-info/METADATA +31 -0
  38. mkdocs_partial-1.2.1.dist-info/RECORD +41 -0
  39. mkdocs_partial-1.2.1.dist-info/WHEEL +5 -0
  40. mkdocs_partial-1.2.1.dist-info/entry_points.txt +6 -0
  41. mkdocs_partial-1.2.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,46 @@
1
+ # pylint: disable=unused-argument
2
+ import os
3
+ import re
4
+ from typing import Any
5
+
6
+ from mkdocs import plugins
7
+ from mkdocs.config.defaults import MkDocsConfig
8
+ from mkdocs.structure.files import Files
9
+ from mkdocs.structure.pages import Page
10
+ from mkdocs_spellcheck.plugin import SpellCheckPlugin # pylint: disable=import-error
11
+
12
+ import mkdocs_partial
13
+
14
+
15
+ class SpellCheckShim(SpellCheckPlugin):
16
+ SKIP_SPELLCHECK = re.compile("<!-- *spellcheck: +disable *-->.*?($|<!-- *spellcheck: +enable *-->)", re.DOTALL)
17
+
18
+ def on_page_content(self, html: str, page: Page, **kwargs: Any) -> None:
19
+ if not mkdocs_partial.SpellCheckShimActive:
20
+ super().on_page_content(html, page, **kwargs)
21
+ return
22
+
23
+ if page.meta.get("spellcheck", True):
24
+ html_to_spellcheck = self.SKIP_SPELLCHECK.sub("", html)
25
+ if page.file.generated_by is None:
26
+ super().on_page_content(html_to_spellcheck, page, **kwargs)
27
+ else:
28
+ original_path = page.file.src_path
29
+ try:
30
+ page.file.src_path = f"{page.file.generated_by}:{page.file.src_path}"
31
+ super().on_page_content(html_to_spellcheck, page, **kwargs)
32
+ finally:
33
+ page.file.src_path = original_path
34
+
35
+ @plugins.event_priority(-100)
36
+ def on_files(self, files: Files, /, *, config: MkDocsConfig) -> Files | None:
37
+ if not mkdocs_partial.SpellCheckShimActive:
38
+ return files if not hasattr(super(), "on_files") else super().on_files(files, config=config)
39
+
40
+ known_words_files = list(file for file in files if os.path.basename(file.src_path) == "known_words.txt")
41
+ # remove known_words.txt files to avoid exposing them wth other docs
42
+ for file in known_words_files:
43
+ self.known_words.update(file.content_string.splitlines())
44
+ files.remove(file)
45
+
46
+ return files
@@ -0,0 +1,97 @@
1
+ import glob
2
+ import os
3
+ from importlib.metadata import EntryPoint
4
+ from pathlib import Path
5
+
6
+ import watchdog
7
+ from mkdocs.config.defaults import MkDocsConfig
8
+ from mkdocs.livereload import LiveReloadServer
9
+ from mkdocs.plugins import BasePlugin
10
+ from watchdog.events import FileSystemEvent
11
+
12
+
13
+ def normalize_path(path: str) -> str:
14
+ return os.path.normpath(path).replace("\\", "/")
15
+
16
+
17
+ def get_mkdocs_plugin(name: str, entrypoint: str, config: MkDocsConfig) -> BasePlugin | None:
18
+ plugin_entrypoint: EntryPoint = MkDocsConfig.plugins.installed_plugins.get(name, None)
19
+ plugin = config.plugins.get(name, None)
20
+ if (
21
+ # macros entry point is registered by mkdocs_macros plugin
22
+ plugin_entrypoint is not None
23
+ and plugin_entrypoint.value == entrypoint
24
+ # macros_plugin plugin is active
25
+ and plugin is not None
26
+ ):
27
+ return plugin
28
+ return None
29
+
30
+
31
+ def get_mkdocs_plugin_name(plugin: BasePlugin, config: MkDocsConfig):
32
+ for name, instance in config.plugins.items():
33
+ if instance == plugin:
34
+ return name
35
+ return None
36
+
37
+
38
+ def replace_mkdocs_plugin_entrypoint(name, entrypoint, new_entrypoint):
39
+ found_entrypoint: EntryPoint = MkDocsConfig.plugins.installed_plugins.get(name, None)
40
+ if found_entrypoint is not None and found_entrypoint.value == entrypoint:
41
+ MkDocsConfig.plugins.installed_plugins[name] = EntryPoint(name, new_entrypoint, "mkdocs.plugins")
42
+ if hasattr(MkDocsConfig.plugins, "plugins"):
43
+ plugin = MkDocsConfig.plugins.plugins.get(name, None)
44
+ assert plugin is None
45
+ return True
46
+ return False
47
+
48
+
49
+ def mkdocs_watch_ignore_path(server: LiveReloadServer, config: MkDocsConfig, ignore_dir, watched_dir=None):
50
+ if watched_dir is None:
51
+ watched_dir = config.docs_dir
52
+
53
+ try:
54
+ # Unwatch the directory watched by mkdocs.
55
+ server.unwatch(watched_dir)
56
+ except KeyError:
57
+ # watched_dir is not watched
58
+ pass
59
+
60
+ def callback(event: FileSystemEvent):
61
+ # Ignore events for directories as they do not affect mkdocs livereload
62
+ if event.is_directory:
63
+ return
64
+
65
+ # Ignore events for files within `ignore_dir`
66
+ if Path(event.src_path).is_relative_to(ignore_dir):
67
+ return
68
+
69
+ # Unwatch deleted files
70
+ if event.event_type in [watchdog.events.EVENT_TYPE_DELETED, watchdog.events.EVENT_TYPE_MOVED]:
71
+ try:
72
+ server.unwatch(event.src_path)
73
+ except KeyError:
74
+ # src_path is not watched
75
+ pass
76
+
77
+ # Watch created files
78
+ if event.event_type in [watchdog.events.EVENT_TYPE_CREATED]:
79
+ server.watch(event.src_path)
80
+ if event.event_type in [watchdog.events.EVENT_TYPE_MOVED]:
81
+ server.watch(event.dest_path)
82
+
83
+ # Touch mkdocs config file which is always watched to trigger rebuild and handle created/deleted files
84
+ os.utime(config.config_file_path)
85
+ return
86
+
87
+ # Call mkdocs watch for files within in `watched_dir` tree except those in `ignore_dir`
88
+ for path in glob.glob(os.path.join(watched_dir, "**/*"), recursive=True):
89
+ if os.path.isfile(path) and not Path(path).is_relative_to(ignore_dir):
90
+ server.watch(path)
91
+
92
+ # Start watching `watched_dir` updating mkdocs watches for files that are not in `ignored_dir`
93
+ handler = watchdog.events.FileSystemEventHandler()
94
+ handler.on_moved = callback
95
+ handler.on_deleted = callback
96
+ handler.on_created = callback
97
+ server.observer.schedule(handler, watched_dir, recursive=True)
File without changes
@@ -0,0 +1,218 @@
1
+ import glob
2
+ import hashlib
3
+ import importlib
4
+ import logging
5
+ import os
6
+ import zipfile
7
+ from abc import ABC
8
+ from datetime import datetime
9
+ from importlib.metadata import entry_points
10
+ from itertools import chain
11
+ from pathlib import Path
12
+ from tempfile import NamedTemporaryFile
13
+ from typing import List
14
+
15
+ from packaging.requirements import Requirement
16
+
17
+ from mkdocs_partial import MODULE_NAME_RESTRICTED_CHARS, version
18
+ from mkdocs_partial.docs_package_plugin import DocsPackagePlugin
19
+ from mkdocs_partial.mkdcos_helpers import normalize_path
20
+ from mkdocs_partial.templating.markdown_extension import TemplaterMarkdownExtension
21
+ from mkdocs_partial.templating.templater import Templater
22
+
23
+
24
+ class Packager(ABC):
25
+ def __init__(self, templates_dir):
26
+ self.__templates_dir = templates_dir
27
+
28
+ def pack( # pylint: disable=too-many-positional-arguments
29
+ self,
30
+ package_name,
31
+ package_version,
32
+ package_description,
33
+ output_dir,
34
+ resources_src_dir,
35
+ excludes=None,
36
+ resources_package_dir=None,
37
+ add_self_dependency=True,
38
+ requirements_path=None,
39
+ freeze=False,
40
+ **kwargs,
41
+ ):
42
+ resources_src_dir = os.path.abspath(resources_src_dir)
43
+ resources_src_dir = normalize_path(resources_src_dir)
44
+
45
+ output_dir = normalize_path(output_dir)
46
+ if excludes is None:
47
+ excludes = []
48
+ start = datetime.now()
49
+ logging.info(f"Building package {package_name} v{package_version} form folder {resources_src_dir}.")
50
+ module_name = MODULE_NAME_RESTRICTED_CHARS.sub("_", package_name.lower())
51
+
52
+ wheel_filename = os.path.join(output_dir, f"{module_name}-{package_version}-py3-none-any.whl")
53
+ script_dir = os.path.dirname(os.path.realpath(__file__))
54
+ templates_dir = os.path.join(script_dir, os.path.join("templates", self.__templates_dir))
55
+ templater = Templater(templates_dir=templates_dir).extend(TemplaterMarkdownExtension())
56
+
57
+ requirements = []
58
+ if requirements_path is not None:
59
+ if not os.path.isfile(requirements_path) and not os.path.isabs(requirements_path):
60
+ requirements_path = os.path.join(resources_src_dir, requirements_path)
61
+ if os.path.isfile(requirements_path):
62
+ requirements = self.parse_requirements(requirements_path)
63
+
64
+ if add_self_dependency:
65
+ self_dependency = Requirement(f"mkdocs-partial >={version.__version__}")
66
+ requirements.append(self_dependency)
67
+
68
+ if freeze:
69
+ requirements = Packager.freeze_requirements(requirements)
70
+ args = {**kwargs}
71
+ args.update(
72
+ {
73
+ "package_name": package_name,
74
+ "module_name": module_name,
75
+ "package_version": package_version,
76
+ "requirements": list(requirements),
77
+ "package_description": package_description,
78
+ }
79
+ )
80
+
81
+ with zipfile.ZipFile(wheel_filename, "w") as zipf:
82
+ dist_info_dir = f"{module_name}-{package_version}.dist-info"
83
+
84
+ record_lines = []
85
+
86
+ for templates_subdir, wheel_subdir, record in [
87
+ ("dist-info", dist_info_dir, False),
88
+ ("package", module_name, True),
89
+ ]:
90
+ for file in glob.glob(os.path.join(templates_dir, templates_subdir, "**/*"), recursive=True):
91
+ if os.path.isfile(file):
92
+ path = os.path.relpath(os.path.normpath(file), os.path.join(templates_dir, templates_subdir))
93
+ path = os.path.join(wheel_subdir, path).replace("\\", "/")
94
+ path = templater.template_string(path, **args)
95
+ if path.lower().endswith(".j2"):
96
+ path = path[:-3]
97
+ content = templater.template(os.path.relpath(file, templates_dir).replace("\\", "/"), **args)
98
+ content.replace("\r\n", "\n")
99
+ file_data = bytes(content, "utf8")
100
+ record_line = self.write_file(path, file_data, zipf)
101
+ if record:
102
+ record_lines.append(record_line)
103
+
104
+ excluded = chain(
105
+ *[
106
+ glob.glob(normalize_path(os.path.join(resources_src_dir, exclude)), recursive=True)
107
+ for exclude in excludes
108
+ ]
109
+ )
110
+ excluded = [normalize_path(exclude) for exclude in excluded]
111
+ for exclude in excludes:
112
+ logging.info(f"Excluded glob {normalize_path(os.path.join(resources_src_dir, exclude))}")
113
+ for exclude in excluded:
114
+ logging.info(f"Excluding file {exclude}")
115
+ for file in glob.glob(os.path.join(resources_src_dir, "**/*"), recursive=True):
116
+ file = normalize_path(file)
117
+ if os.path.isfile(file) and file not in excluded:
118
+ logging.info(f"Packaging file {file}")
119
+ path = module_name
120
+ if resources_package_dir is not None and resources_package_dir != "":
121
+ path = os.path.join(path, resources_package_dir)
122
+ path = os.path.join(path, os.path.relpath(file, resources_src_dir))
123
+ path = normalize_path(path)
124
+ record_lines.append(self.write_file(path, Path(file).read_bytes(), zipf))
125
+
126
+ zipf.writestr(f"{dist_info_dir}/RECORD", "\n".join(record_lines) + "\n")
127
+
128
+ logging.info(f"Package is built within {(datetime.now() - start)}. File is written to {wheel_filename}")
129
+
130
+ @staticmethod
131
+ def write_file(arcname, file_data, zipf):
132
+ sha256_hash = hashlib.sha256(file_data).hexdigest()
133
+ file_size = len(file_data)
134
+ with NamedTemporaryFile("wb", delete_on_close=False) as file:
135
+ file.write(file_data)
136
+ file.close()
137
+ zipf.write(file.name, arcname)
138
+ return f"{arcname},sha256={sha256_hash},{file_size}"
139
+
140
+ @staticmethod
141
+ def parse_requirements(path):
142
+ with open(path) as f_requirements:
143
+ requirements = [
144
+ Requirement(dependency)
145
+ for dependency in f_requirements.readlines()
146
+ if not dependency.isspace() and dependency != "" and dependency[0] != "#"
147
+ ]
148
+ return requirements
149
+
150
+ @staticmethod
151
+ def freeze(path):
152
+ requirements = Packager.parse_requirements(path)
153
+
154
+ with open(path, "w") as f_requirements:
155
+ for requirement in Packager.freeze_requirements(requirements):
156
+ f_requirements.write(f"{requirement}\n")
157
+ return True, None
158
+
159
+ @staticmethod
160
+ def freeze_requirements(requirements: List[Requirement]):
161
+ plugin_requirements = {}
162
+ for mkdocs_plugin in entry_points(group="mkdocs.plugins"):
163
+ try:
164
+ plugin_class = mkdocs_plugin.load()
165
+ except ModuleNotFoundError:
166
+ continue
167
+
168
+ if issubclass(plugin_class, DocsPackagePlugin) and plugin_class != DocsPackagePlugin:
169
+ plugin_requirements[mkdocs_plugin.dist.name] = Requirement(
170
+ f"{mkdocs_plugin.dist.name}=={mkdocs_plugin.dist.version}"
171
+ )
172
+
173
+ for requirement in requirements:
174
+ yield plugin_requirements.get(requirement.name, requirement)
175
+
176
+ @staticmethod
177
+ def get_mudules_from_packages(*packages: str):
178
+ installed_packages = list(chain(*[importlib.metadata.distributions(name=package) for package in packages]))
179
+ module_names = set()
180
+ for package in installed_packages:
181
+ distribution = importlib.metadata.distribution(package.metadata["Name"])
182
+ for file in distribution.files:
183
+ if (
184
+ not file.name.endswith(".pyc") # pylint: disable=too-many-boolean-expressions
185
+ and "__pycache__" not in Path(file.name).parts
186
+ and ".dist-info" not in Path(file.name).parts
187
+ and not file.parts[0].endswith(".dist-info")
188
+ and not file.parts[0].endswith(".egg-info")
189
+ and ".." not in file.parts
190
+ ):
191
+ module_name = file.parts[0]
192
+ name, extension = os.path.splitext(module_name)
193
+ if extension == ".py":
194
+ module_name = name
195
+ extension = ""
196
+ if extension == "" and not name.startswith("_"):
197
+ module_names.add(module_name)
198
+
199
+ return module_names
200
+
201
+
202
+ if __name__ == "__main__":
203
+ modules = Packager.get_mudules_from_packages(
204
+ "mkdocs-material",
205
+ "mkdocs-glightbox",
206
+ "mkdocs-macros-plugin",
207
+ "mkdocs-spellcheck",
208
+ "documentation-mkdocs-landscape",
209
+ "documentation-mkdocs-plugins",
210
+ "docs-documentation-inceptum",
211
+ "docs-documentation",
212
+ "docs-cicd",
213
+ "docs-observability",
214
+ "docs-organisation",
215
+ "docs-infrastructure",
216
+ "mkdocs_partial",
217
+ )
218
+ print(modules)
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.1
2
+ Name: {{package_name}}
3
+ Version: {{package_version}}
4
+ Description: {{package_description}}
5
+ {% for requirement in requirements %}
6
+ Requires-Dist: {{requirement}}
7
+ {% endfor %}
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [mkdocs.plugins]
2
+ {{package_name}} = {{module_name}}.plugin:Plugin
@@ -0,0 +1,3 @@
1
+ """Initialization of {{package_name}} package."""
2
+
3
+ __version__ = "{{package_version}}"
@@ -0,0 +1,5 @@
1
+
2
+ import os
3
+
4
+ def get_hook_dirs():
5
+ return [os.path.dirname(__file__)]
@@ -0,0 +1,31 @@
1
+ import importlib.metadata
2
+ from PyInstaller.utils.hooks import collect_all, copy_metadata
3
+ from mkdocs_partial.packages.packager import Packager
4
+ from itertools import chain
5
+
6
+ not_hooked_packages=["mkdocs"]
7
+ required_distributions= not_hooked_packages+ [
8
+ "{{package_name}}",
9
+ {% for requirement in requirements %}
10
+ "{{requirement.name}}",
11
+ {% endfor %}
12
+ ]
13
+ required_modules = Packager.get_mudules_from_packages(*required_distributions)
14
+
15
+ datas=[]
16
+ binaries=[]
17
+ hiddenimports=[]
18
+
19
+ for module in required_modules:
20
+ module_datas, module_binaries, module_hiddenimports = collect_all(module)
21
+ datas+=module_datas
22
+ binaries+=module_binaries
23
+ hiddenimports+=module_hiddenimports
24
+
25
+ installed_dists = list(importlib.metadata.distributions())
26
+ for distribution in required_distributions:
27
+ if any(dist for dist in installed_dists if dist.name=="organisation-registry" ):
28
+ datas+=copy_metadata(distribution, recursive=True)
29
+
30
+
31
+
@@ -0,0 +1,5 @@
1
+ from mkdocs_partial.docs_package_plugin import DocsPackagePlugin
2
+
3
+ class Plugin(DocsPackagePlugin):
4
+ def __init__(self, directory={{directory}}, edit_url_template={{edit_url_template}}, title={{title}}, blog_categories={{blog_categories}}):
5
+ super().__init__(directory=directory, edit_url_template=edit_url_template, title=title, blog_categories={{blog_categories}})
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.1
2
+ Name: {{package_name}}
3
+ Version: {{package_version}}
4
+ Description: {{package_description}}
5
+ {% for requirement in requirements %}
6
+ Requires-Dist: {{requirement}}
7
+ {% endfor %}
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ {{package_name}} = {{module_name}}.entry_point:run
3
+
4
+ [pyinstaller40]
5
+ hook-dirs = {{module_name}}.__pyinstaller:get_hook_dirs
@@ -0,0 +1,3 @@
1
+ """Initialization of {{package_name}} package."""
2
+
3
+ __version__ = "{{package_version}}"
@@ -0,0 +1,4 @@
1
+ from {{module_name}} import entry_point
2
+
3
+ if __name__ == '__main__':
4
+ entry_point.run()
@@ -0,0 +1,5 @@
1
+
2
+ import os
3
+
4
+ def get_hook_dirs():
5
+ return [os.path.dirname(__file__)]
@@ -0,0 +1,30 @@
1
+ import importlib.metadata
2
+ from PyInstaller.utils.hooks import collect_all, copy_metadata
3
+ from mkdocs_partial.packages.packager import Packager
4
+ from itertools import chain
5
+
6
+ not_hooked_packages=["mkdocs","pymdown-extensions","organisation-registry","symspellpy"]
7
+ required_distributions= not_hooked_packages+ [
8
+ "{{package_name}}",
9
+ {% for requirement in requirements %}
10
+ "{{requirement.name}}",
11
+ {% endfor %}
12
+ ]
13
+ required_modules = Packager.get_mudules_from_packages(*required_distributions)
14
+
15
+ datas=[]
16
+ binaries=[]
17
+ hiddenimports=[]
18
+
19
+
20
+ for module in required_modules:
21
+ module_datas, module_binaries, module_hiddenimports = collect_all(module)
22
+ datas+=module_datas
23
+ binaries+=module_binaries
24
+ hiddenimports+=module_hiddenimports
25
+
26
+ installed_dists = list(importlib.metadata.distributions())
27
+ for distribution in required_distributions:
28
+ if any(dist for dist in installed_dists if dist.name=="organisation-registry" ):
29
+ datas+=copy_metadata(distribution, recursive=True)
30
+
@@ -0,0 +1,11 @@
1
+ import inspect
2
+ import os
3
+
4
+ import {{module_name}}
5
+ from {{module_name}} import __version__
6
+ from mkdocs_partial.site_entry_point import SiteEntryPoint
7
+
8
+ def run():
9
+ print({{module_name}})
10
+ script_dir = os.path.dirname(__file__)
11
+ SiteEntryPoint(__version__, os.path.join(script_dir, "site"),"{{package_name}}").run()
@@ -0,0 +1,92 @@
1
+ # pylint: disable=unused-argument
2
+ import traceback
3
+ from typing import Callable, Dict, List, cast
4
+
5
+ from mkdocs import plugins
6
+ from mkdocs.config import Config, config_options
7
+ from mkdocs.config.config_options import Plugins
8
+ from mkdocs.config.defaults import MkDocsConfig
9
+ from mkdocs.exceptions import PluginError
10
+ from mkdocs.plugins import BasePlugin, get_plugin_logger
11
+ from mkdocs.structure.nav import Navigation
12
+ from mkdocs.structure.pages import Page
13
+ from mkdocs.utils.templates import TemplateContext
14
+
15
+ from mkdocs_partial.docs_package_plugin import DocsPackagePlugin, DocsPackagePluginConfig
16
+
17
+ log = get_plugin_logger("partial_docs")
18
+
19
+
20
+ class PartialDocsPluginConfig(Config):
21
+ enabled = config_options.Type(bool, default=True)
22
+ packages = config_options.DictOfItems(config_options.SubConfig(DocsPackagePluginConfig), default={})
23
+
24
+
25
+ class PartialDocsPlugin(BasePlugin[PartialDocsPluginConfig]):
26
+ docs_path_overrides: Dict[str, str] = {}
27
+
28
+ def __init__(self):
29
+ self.is_serve = False
30
+ self.is_dirty = False
31
+
32
+ def on_startup(self, *, command, dirty):
33
+ if not self.config.enabled:
34
+ return
35
+ self.is_serve = command == "serve"
36
+ self.is_dirty = dirty
37
+
38
+ def on_shutdown(self) -> None:
39
+ pass
40
+
41
+ def on_page_context(
42
+ self, context: TemplateContext, /, *, page: Page, config: MkDocsConfig, nav: Navigation
43
+ ) -> TemplateContext | None:
44
+ return context
45
+
46
+ @plugins.event_priority(100)
47
+ def on_config(self, config):
48
+ if not self.config.enabled:
49
+ return
50
+
51
+ global_plugins: Plugins = cast(Plugins, dict(config._schema)["plugins"])
52
+ assert isinstance(global_plugins, Plugins)
53
+
54
+ self.docs_package_plugins: dict[str, BasePlugin] = {}
55
+ try:
56
+ for name, plugin in self._load(global_plugins):
57
+ if plugin.config.enabled:
58
+ src = ""
59
+ if plugin.config.docs_path is not None:
60
+ src = f" from source path '{plugin.config.docs_path}'"
61
+ log.info(f"Injecting doc package {name} to '{plugin.directory}' directory{src}.")
62
+ self.docs_package_plugins[name] = plugin
63
+ except Exception:
64
+ raise PluginError(traceback.format_exc()) # pylint: disable=raise-missing-from
65
+
66
+ # Invoke `on_startup`
67
+ command = "serve" if self.is_serve else "build"
68
+ for method in global_plugins.plugins.events["startup"]:
69
+ plugin = self._get_plugin(method)
70
+
71
+ if plugin and plugin in self.docs_package_plugins.values():
72
+ method(command=command, dirty=self.is_dirty)
73
+
74
+ # Load doc package plugins
75
+ def _load(self, option: Plugins) -> List[tuple[str, DocsPackagePlugin]]:
76
+ for entrypoint in option.installed_plugins.values():
77
+ try:
78
+ plugin_class = entrypoint.load()
79
+ except ModuleNotFoundError:
80
+ continue
81
+ if issubclass(plugin_class, DocsPackagePlugin) and plugin_class != DocsPackagePlugin:
82
+ plugin_config: DocsPackagePluginConfig = self.config.packages.setdefault(
83
+ entrypoint.name, DocsPackagePluginConfig()
84
+ )
85
+ if entrypoint.name in PartialDocsPlugin.docs_path_overrides:
86
+ plugin_config.docs_path = PartialDocsPlugin.docs_path_overrides[entrypoint.name]
87
+
88
+ name, plugin = option.load_plugin_with_namespace(entrypoint.name, plugin_config.data)
89
+ yield name, cast(DocsPackagePlugin, plugin)
90
+
91
+ def _get_plugin(self, method: Callable):
92
+ return getattr(method, "__self__", None)