Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/docs/source/_build/scripts/macro.py
6939 views
1
from collections import OrderedDict
2
import os
3
from typing import Any, List, Optional, Set
4
import yaml
5
import logging
6
7
8
from mkdocs_macros.plugin import MacrosPlugin
9
10
# Supported Languages and their metadata
11
LANGUAGES = OrderedDict(
12
python={
13
"extension": ".py",
14
"display_name": "Python",
15
"icon_name": "python",
16
"code_name": "python",
17
},
18
rust={
19
"extension": ".rs",
20
"display_name": "Rust",
21
"icon_name": "rust",
22
"code_name": "rust",
23
},
24
)
25
26
# Load all links to reference docs
27
with open("docs/source/_build/API_REFERENCE_LINKS.yml", "r") as f:
28
API_REFERENCE_LINKS = yaml.load(f, Loader=yaml.CLoader)
29
30
31
def create_feature_flag_link(feature_name: str) -> str:
32
"""Create a feature flag warning telling the user to activate a certain feature before running the code
33
34
Args:
35
feature_name (str): name of the feature
36
37
Returns:
38
str: Markdown formatted string with a link and the feature flag message
39
"""
40
return f'[:material-flag-plus: Available on feature {feature_name}](/user-guide/installation/#feature-flags "To use this functionality enable the feature flag {feature_name}"){{.feature-flag}}'
41
42
43
def create_feature_flag_links(language: str, api_functions: List[str]) -> List[str]:
44
"""Generate markdown feature flags for the code tabs based on the api_functions.
45
It checks for the key feature_flag in the configuration yaml for the function and if it exists print out markdown
46
47
Args:
48
language (str): programming languages
49
api_functions (List[str]): Api functions that are called
50
51
Returns:
52
List[str]: Per unique feature flag a markdown formatted string for the feature flag
53
"""
54
api_functions_info = [
55
info
56
for f in api_functions
57
if (info := API_REFERENCE_LINKS.get(language).get(f))
58
]
59
feature_flags: Set[str] = {
60
flag
61
for info in api_functions_info
62
if type(info) == dict and info.get("feature_flags")
63
for flag in info.get("feature_flags")
64
}
65
66
return [create_feature_flag_link(flag) for flag in feature_flags]
67
68
69
def create_api_function_link(language: str, function_key: str) -> Optional[str]:
70
"""Create an API link in markdown with an icon of the YAML file
71
72
Args:
73
language (str): programming language
74
function_key (str): Key to the specific function
75
76
Returns:
77
str: If the function is found than the link else None
78
"""
79
info = API_REFERENCE_LINKS.get(language, {}).get(function_key)
80
81
if info is None:
82
logging.warning(f"Could not find {function_key} for language {language}")
83
return None
84
else:
85
# Either be a direct link
86
if type(info) == str:
87
return f"[:material-api: `{function_key}`]({info})"
88
else:
89
function_name = info["name"]
90
link = info["link"]
91
return f"[:material-api: `{function_name}`]({link})"
92
93
94
def code_tab(
95
base_path: str,
96
section: Optional[str],
97
language_info: dict,
98
api_functions: List[str],
99
) -> str:
100
"""Generate a single tab for the code block corresponding to a specific language.
101
It gets the code at base_path and possible section and pretty prints markdown for it
102
103
Args:
104
base_path (str): path where the code is located
105
section (str, optional): section in the code that should be displayed
106
language_info (dict): Language specific information (icon name, display name, ...)
107
api_functions (List[str]): List of api functions which should be linked
108
109
Returns:
110
str: A markdown formatted string represented a single tab
111
"""
112
language = language_info["code_name"]
113
114
# Create feature flags
115
feature_flags_links = create_feature_flag_links(language, api_functions)
116
117
# Create API Links if they are defined in the YAML
118
api_functions = [
119
link for f in api_functions if (link := create_api_function_link(language, f))
120
]
121
language_headers = " ·".join(api_functions + feature_flags_links)
122
123
# Create path for Snippets extension
124
snippets_file_name = f"{base_path}:{section}" if section else f"{base_path}"
125
126
# See Content Tabs for details https://squidfunk.github.io/mkdocs-material/reference/content-tabs/
127
return f"""=== \":fontawesome-brands-{language_info['icon_name']}: {language_info['display_name']}\"
128
{language_headers}
129
```{language}
130
--8<-- \"{snippets_file_name}\"
131
```
132
"""
133
134
135
def define_env(env: MacrosPlugin) -> None:
136
@env.macro
137
def code_header(
138
language: str, section: str = [], api_functions: List[str] = []
139
) -> str:
140
language_info = LANGUAGES[language]
141
142
language = language_info["code_name"]
143
144
# Create feature flags
145
feature_flags_links = create_feature_flag_links(language, api_functions)
146
147
# Create API Links if they are defined in the YAML
148
api_functions = [
149
link
150
for f in api_functions
151
if (link := create_api_function_link(language, f))
152
]
153
language_headers = " ·".join(api_functions + feature_flags_links)
154
return f"""=== \":fontawesome-brands-{language_info['icon_name']}: {language_info['display_name']}\"
155
{language_headers}"""
156
157
@env.macro
158
def code_block(
159
path: str,
160
section: str = None,
161
api_functions: List[str] = None,
162
python_api_functions: List[str] = None,
163
rust_api_functions: List[str] = None,
164
) -> str:
165
"""Dynamically generate a code block for the code located under {language}/path
166
167
Args:
168
path (str): base_path for each language
169
section (str, optional): Optional segment within the code file. Defaults to None.
170
api_functions (List[str], optional): API functions that should be linked. Defaults to None.
171
Returns:
172
str: Markdown tabbed code block with possible links to api functions and feature flags
173
"""
174
result = []
175
176
for language, info in LANGUAGES.items():
177
base_path = f"{language}/{path}{info['extension']}"
178
full_path = "docs/source/src/" + base_path
179
if language == "python":
180
extras = python_api_functions or []
181
else:
182
extras = rust_api_functions or []
183
# Check if file exists for the language
184
if os.path.exists(full_path):
185
result.append(
186
code_tab(base_path, section, info, api_functions + extras)
187
)
188
189
return "\n".join(result)
190
191