This repository has been archived by the owner on Apr 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
toolbox.py
193 lines (158 loc) · 7.29 KB
/
toolbox.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
"""Tools for the automatic source link generation for mkdocstrings."""
import importlib
import inspect
from abc import ABC, abstractstaticmethod
from pathlib import Path
from typing import Dict, Optional, Union
class BuilderUtilities(ABC):
"""BuilderUtilities is the Metaclass of Utilities.
The Utilities are essential for building the mkdocstrings and hyperlinks to the source code.
Args:
ABC (class): Helper class that provides a standard way to create an ABC using
inheritance.
"""
@abstractstaticmethod
def insert_in_file(markdown_text: str, file_path: Path) -> None:
"""Abstract staticmethod of `insert_in_file`."""
@abstractstaticmethod
def element_to_mkdocstrings(element: str, titles_size: str) -> str:
"""Abstract staticmethod of `element_to_mkdocstrings`."""
@abstractstaticmethod
def make_source_link(
cls: classmethod,
project_url: Union[str, Dict[str, str]],
source: str = "**source code**",
) -> str:
"""Abstract staticmethod of `make_title`."""
@abstractstaticmethod
def make_title(cls: classmethod, titles_size: str, underline_title: bool) -> str:
"""Abstract staticmethod of `import_object`."""
@abstractstaticmethod
def return_as_Path(path: str = None) -> Optional[Path]:
"""Abstract staticmethod of `return_as_Path`."""
class Utilities(BuilderUtilities):
"""The `Utilities` build the mkdocstrings and generate the hyperlinks to the source code.
Args:
AbstractUtilities (class): Builder class of the abstract staticmethods of `Utilities`.
"""
@staticmethod
def insert_in_file(markdown_text: str, file_path: Path) -> None:
"""Insert the markdown formatted text into a new or existing file.
Args:
markdown_text (str): Text as string, which follows the markdown format.
file_path (Path): Filename and path as Path object.
Raises:
RuntimeError: If {{autogenerated}} is not provided in a template file, it will cause a
a **RuntimeError**.
"""
if file_path.exists():
template = file_path.read_text(encoding="utf-8")
if "{{autogenerated}}" not in template:
raise RuntimeError(
f"Template found for {file_path} but missing "
f"{{autogenerated}} tag."
)
markdown_text = template.replace("{{autogenerated}}", markdown_text)
print(f"...inserting autogenerated content into template:{file_path}")
else:
print(f"...creating new page with autogenerated content:{file_path}")
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(markdown_text, encoding="utf-8")
@staticmethod
def element_to_mkdocstrings(element: str, titles_size: str) -> str:
"""Converts point separated string into the mkdocstrings format.
For converting the elements to mkdocstrings, the element will added **:::** in front of the
element string. In addition to that, the the new mkdocstrings will get subheadings.
Args:
element (str): String of they python class, function, or method, which has to be
converted to a string in the mkdocstrings format.
titles_size (str): Current title size in the style of '#', which defines the headings.
Returns:
str: String of they python class, function, or method, which is converted to a string
in the mkdocstrings format.
"""
return f"##{titles_size} :::{element}\n"
@staticmethod
def make_source_link(
cls: classmethod,
project_url: Union[str, Dict[str, str]],
source: str = "**source code**",
) -> str:
"""Make a source link to the code basis including the linestart.
Args:
cls (classmethod): Convert a function to be a class method.
project_url (Union[str, Dict[str, str]]): URL to the repository like GitHub
https://github.com/AI2Business/mkdocstrings-sourcelink/.
source (str, optional): Name or sticker name for rendering the link to the
source.
Returns:
str: Hyperlink in html format with link to the repository.
!!! tip "About *source*"
Instead of using a string for `source = "**source code**"`, icons can be used instead
or as combination of string + icon(s) like.
```python
source = ":material-github::material-source-branch: source-code"
```
In case of using material-icons, please check https://pictogrammers.github.io/@mdi/font/5.4.55/
and replace `mdl` by `material`.
"""
if isinstance(project_url, dict):
if isinstance(cls, property):
base_module = cls.fget.__module__.split(".")[0]
else:
base_module = cls.__module__.split(".")[0]
project_url = project_url[base_module]
if isinstance(cls, property):
path = cls.fget.__module__.replace(".", "/")
line = inspect.getsourcelines(cls.fget)[-1]
else:
path = cls.__module__.replace(".", "/")
line = inspect.getsourcelines(cls)[-1]
return (
f'<span style="float:right;">'
f"[{source}]({project_url}/{path}.py#L{line})"
f"</span>"
)
@staticmethod
def make_title(cls: classmethod, titles_size: str, underline_title: bool) -> str:
"""Make the title of the class, function, or method.
Args:
cls (classmethod): Convert a function to be a class method. In case of class properties
`fget` is used to read out the name of the module.
titles_size (str): Current title size in the style of '#', which defines the headings.
Returns:
str: The name of the class, function, or method in a markdown conformed title.
"""
title_underline = "\n---\n" if underline_title else "\n"
if isinstance(cls, property):
return f"#{titles_size} {cls.fget.__name__}{title_underline}"
return f"#{titles_size} {cls.__name__}{title_underline}"
@staticmethod
def import_object(element: str) -> object:
"""Import an object like class, function, or method from a string.
Args:
element (str): String of class, function, or method, which should be converted to an
object.
Returns:
object: Class, function, or method object for the giving element.
"""
last_object_got = None
seen_names = []
for name in element.split("."):
seen_names.append(name)
try:
last_object_got = importlib.import_module(".".join(seen_names))
except ModuleNotFoundError:
last_object_got = getattr(last_object_got, name)
return last_object_got
@staticmethod
def return_as_Path(path: str = None) -> Optional[Path]:
"""Converts strings to Path of pathlib.
Args:
path (str, optional): String of a filename.
Returns:
Optional[Path]: Path object of the initial filename.
"""
if path:
return Path(path)
return None