acrn-hypervisor/misc/config_tools/scenario_config/jsonschema/document.py
Weiyi Feng 696ba31be8 config_tools: refactor configurator for web page cache issue
refactor configurator for web page cache issue

Tracked-On: #7356
Signed-off-by: Weiyi Feng <weiyix.feng@intel.com>
2022-04-25 18:13:12 +08:00

152 lines
4.7 KiB
Python

#!/usr/bin/env python3
#
# Copyright (C) 2022 Intel Corporation.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# pyodide support status: Yes
"""
This program support run in pyodide env.
In js side you can pass params by add follow code before this script.
```js
params = "${Base64.encode(params)}"
```
"""
import re
import sys
from urllib.parse import urljoin
from subprocess import check_output
from typing import Optional
try:
import locale # module missing in Jython
locale.setlocale(locale.LC_ALL, '')
except locale.Error:
pass
from docutils.core import publish_string
from sphinx.ext.intersphinx import fetch_inventory
from bs4 import BeautifulSoup
class RSTNormalizer:
def __init__(self, url_base, objects_inv: [dict, str]):
self.url_base = url_base
if isinstance(objects_inv, dict):
# parsed data
self.data = objects_inv
elif isinstance(objects_inv, str):
self.data = self.__convert_inv(objects_inv)
else:
raise NotImplementedError
self.fake_roles = [
self.fake_role('option', 'std:cmdoption'),
self.fake_role('ref', 'std:label')
]
@staticmethod
def __convert_inv(url):
try:
inv_data = RSTNormalizer.__prase_inv_file(url)
except Exception as e:
print(e)
print('Download inv data failed, document link will link to search page.')
inv_data = None
return inv_data
@staticmethod
def __prase_inv_file(filename):
class MockConfig:
intersphinx_timeout: int = None
tls_verify = False
user_agent = None
class MockApp:
srcdir = ''
config = MockConfig()
def warn(self, msg: str) -> None:
print(msg, file=sys.stderr)
invdata = fetch_inventory(MockApp(), '', filename) # type: ignore
result = {}
for key in sorted(invdata or {}):
result[key] = {}
data = result[key]
for entry, einfo in sorted(invdata[key].items()):
data[entry] = {"title": einfo[3] if einfo[3] != '-' else '', "link": einfo[2]}
return result
def normalize(self, rest_text):
result = re.sub(r'\.\. option::[ \t]+(\S+)', lambda x: x.group(1) + f'\n{len(x.group(1)) * "-"}', rest_text)
for fake_role_handle in self.fake_roles:
result = fake_role_handle(result)
return result
def url(self, key, data):
title = data["title"] if data["title"] else key
url = urljoin(self.url_base, data['link'])
return f'`{title} <{url}>`_'
def fake_role(self, rest_key, json_key):
def handel_role(rest_text):
def re_sub(match):
key = match.group(1)
if self.data is None or json_key not in self.data or key not in self.data[json_key]:
return self.url(key, {'title': '', 'link': f'search.html?q={key}&check_keywords=yes&area=default'})
return self.url(key, self.data[json_key][key])
return re.sub(f':{rest_key}:' + r'`(.+?)`', re_sub, rest_text)
return handel_role
class ACRNDocumentStringConvertor:
def __init__(self, objects_inv: Optional[dict] = None):
self.version = self.get_acrn_document_version()
self.url_base = 'https://projectacrn.github.io/{}/'.format(self.version)
self.objects_inv = objects_inv
if self.objects_inv is None:
self.objects_inv = urljoin(self.url_base, 'objects.inv')
self.rst_normalizer = RSTNormalizer(self.url_base, self.objects_inv)
@staticmethod
def get_acrn_document_version(default_version='latest'):
version = default_version
try:
branch_name = check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode()
version = re.match(r"^release_(\d\.\d)$", branch_name).group(1)
except:
print("Can't detect current acrn-hypervisor version, document string will link to latest")
return version
def convert(self, docstring):
rst = self.rst_normalizer.normalize(docstring)
html = publish_string(rst, writer_name='html5').decode('utf-8')
soup = BeautifulSoup(html, 'lxml')
for link in soup.select('a'):
link['target'] = '_blank'
try:
fragment = soup.select_one('div.document').prettify()
except:
fragment = '\n'.join([str(x) for x in soup.select_one('main').children]).strip()
return fragment
def main():
params = {
"text": open('configdoc.txt').read(),
"objectsInv": None
}
doc_html = ACRNDocumentStringConvertor(params['objectsInv']).convert(params['text'])
return doc_html