blob: d36752dd882d6b726a604f7e81611f0e25cf3555 [file] [log] [blame]
Paul Vinciguerra630ca992020-03-24 16:37:40 -04001#!/usr/bin/env python3
2# Copyright (c) 2020. Vinci Consulting Corp. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import glob
17import inspect
18import os.path
19import re
20
21
22class ContentRenderer:
23 name = ""
24 curr_path = os.path.abspath(inspect.getsourcefile(lambda: 0))
25 vpp_root = curr_path.rsplit("/", 2)[0]
26 output_dir = f"{vpp_root}/docs/dynamic_includes/"
27
28 def render(self):
29 raise NotImplementedError
30
31
32class PluginRenderer(ContentRenderer):
33 name = "plugin_list.inc"
34
35 plugin_dir = f"{ContentRenderer.vpp_root}/src/plugins"
36
37 pattern = r'VLIB_PLUGIN_REGISTER\s?\(\)\s*=\s*{.*\.description\s?=\s?"([^"]*)".*};' # noqa: 501
38 regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
39
40 def render(self):
41 with open(f"{self.__class__.output_dir}{self.__class__.name}",
42 "w") as output:
43 with os.scandir(self.__class__.plugin_dir) as pdir:
44 for entry in sorted(pdir, key=lambda entry: entry.name):
45 if not entry.name.startswith('.') and entry.is_dir():
46 description = "<no-description-found>"
47 # we use glob because a plugin can (ioam for now)
48 # define the plugin definition in
49 # a further subdirectory.
50 for f in glob.iglob(f'{self.__class__.plugin_dir}/'
51 f'{entry.name}/**',
52 recursive=True):
53 if f.endswith('.c'):
54 with open(f, "r", encoding="utf-8") \
55 as src:
56 for match in self.__class__.regex.finditer(
57 src.read()):
58 description = "%s" % (match.group(1))
59
60 output.write(f"* {entry.name} - {description}\n")
61
62
63# if this list grows substantially, we can move the classes to
64# a folder and import them.
65renderers = [PluginRenderer,
66 ]
67
68
69def main():
70 print("rendering dynamic includes...")
71 for renderer in renderers:
72 renderer().render()
73 print("done.")
74
75
76if __name__ == "__main__":
77 main()