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.
- mkdocs_partial/__init__.py +24 -0
- mkdocs_partial/argparse_types.py +14 -0
- mkdocs_partial/docs_package_plugin.py +224 -0
- mkdocs_partial/entry_point.py +199 -0
- mkdocs_partial/integrations/__init__.py +0 -0
- mkdocs_partial/integrations/macros_plugin_shim.py +36 -0
- mkdocs_partial/integrations/material_blog_integration.py +149 -0
- mkdocs_partial/integrations/redirect_plugin_shim.py +23 -0
- mkdocs_partial/integrations/spellcheck_plugin_shim.py +46 -0
- mkdocs_partial/mkdcos_helpers.py +97 -0
- mkdocs_partial/packages/__init__.py +0 -0
- mkdocs_partial/packages/packager.py +218 -0
- mkdocs_partial/packages/templates/docs-package/dist-info/METADATA.j2 +7 -0
- mkdocs_partial/packages/templates/docs-package/dist-info/WHEEL.j2 +4 -0
- mkdocs_partial/packages/templates/docs-package/dist-info/entry_points.txt.j2 +2 -0
- mkdocs_partial/packages/templates/docs-package/package/__init__.py.j2 +3 -0
- mkdocs_partial/packages/templates/docs-package/package/__pyinstaller/__init__.py.j2 +5 -0
- mkdocs_partial/packages/templates/docs-package/package/__pyinstaller/hook-{{module_name}}.py.j2 +31 -0
- mkdocs_partial/packages/templates/docs-package/package/plugin.py.j2 +5 -0
- mkdocs_partial/packages/templates/site-package/dist-info/METADATA.j2 +7 -0
- mkdocs_partial/packages/templates/site-package/dist-info/WHEEL.j2 +4 -0
- mkdocs_partial/packages/templates/site-package/dist-info/entry_points.txt.j2 +5 -0
- mkdocs_partial/packages/templates/site-package/package/__init__.py.j2 +3 -0
- mkdocs_partial/packages/templates/site-package/package/__main__.py.j2 +4 -0
- mkdocs_partial/packages/templates/site-package/package/__pyinstaller/__init__.py.j2 +5 -0
- mkdocs_partial/packages/templates/site-package/package/__pyinstaller/hook-{{module_name}}.py.j2 +30 -0
- mkdocs_partial/packages/templates/site-package/package/entry_point.py.j2 +11 -0
- mkdocs_partial/partial_docs_plugin.py +92 -0
- mkdocs_partial/site_entry_point.py +151 -0
- mkdocs_partial/templating/__init__.py +5 -0
- mkdocs_partial/templating/markdown_extension.py +38 -0
- mkdocs_partial/templating/templater.py +76 -0
- mkdocs_partial/templating/templater_extension.py +17 -0
- mkdocs_partial/templating/version.py +5 -0
- mkdocs_partial/version.py +1 -0
- mkdocs_partial-1.2.1.dist-info/LICENSE +19 -0
- mkdocs_partial-1.2.1.dist-info/METADATA +31 -0
- mkdocs_partial-1.2.1.dist-info/RECORD +41 -0
- mkdocs_partial-1.2.1.dist-info/WHEEL +5 -0
- mkdocs_partial-1.2.1.dist-info/entry_points.txt +6 -0
- 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)
|
mkdocs_partial/packages/templates/docs-package/package/__pyinstaller/hook-{{module_name}}.py.j2
ADDED
|
@@ -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}})
|
mkdocs_partial/packages/templates/site-package/package/__pyinstaller/hook-{{module_name}}.py.j2
ADDED
|
@@ -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)
|