mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
doc: finalize Python signatures injection
This commit is contained in:
+105
-187
@@ -1,7 +1,10 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
|
||||
import logging
|
||||
import os
|
||||
from pprint import pprint
|
||||
import traceback
|
||||
|
||||
try:
|
||||
import bs4
|
||||
@@ -13,195 +16,110 @@ except ImportError:
|
||||
|
||||
def load_html_file(file_dir):
|
||||
""" Uses BeautifulSoup to load an html """
|
||||
with open(file_dir) as fp:
|
||||
with open(file_dir, 'rb') as fp:
|
||||
soup = BeautifulSoup(fp, 'html.parser')
|
||||
return soup
|
||||
|
||||
def add_item(soup, new_row, is_parameter, text):
|
||||
""" Adds a new html tag for the table with the signature """
|
||||
new_item = soup.new_tag('td')
|
||||
if is_parameter:
|
||||
new_item = soup.new_tag('td', **{'class': 'paramname'})
|
||||
new_item.append(text)
|
||||
new_row.append(new_item)
|
||||
return new_row, soup
|
||||
|
||||
def add_signature_to_table(soup, tmp_row, signature, language, type):
|
||||
""" Add a signature to an html table"""
|
||||
new_item = soup.new_tag('td', style="padding-left: 0.5cm;")
|
||||
|
||||
if str(signature.get('ret', None)) != "None":
|
||||
new_item.append(signature.get('ret') + ' =')
|
||||
tmp_row.append(new_item)
|
||||
|
||||
tmp_name = signature.get('name', None)
|
||||
if type is not "method":
|
||||
tmp_name = "cv2." + tmp_name
|
||||
else:
|
||||
tmp_name = "obj." + tmp_name
|
||||
tmp_row, soup = add_item(soup, tmp_row, False, tmp_name + '(')
|
||||
tmp_row, soup = add_item(soup, tmp_row, True, signature['arg'])
|
||||
tmp_row, soup = add_item(soup, tmp_row, False, ')')
|
||||
return tmp_row, soup
|
||||
|
||||
|
||||
def new_line(soup, tmp_table, new_row):
|
||||
""" Adds a new line to the html table """
|
||||
tmp_table.append(new_row)
|
||||
new_row = soup.new_tag('tr')
|
||||
return new_row, soup
|
||||
|
||||
|
||||
def add_bolded(soup, new_row, text):
|
||||
""" Adds bolded text to the table """
|
||||
new_item = soup.new_tag('th', style="text-align:left")
|
||||
new_item.append(text)
|
||||
new_row.append(new_item)
|
||||
return new_row, soup
|
||||
|
||||
|
||||
def create_description(soup, language, signatures, type):
|
||||
""" Insert the new Python / Java table after the current html c++ table """
|
||||
assert signatures
|
||||
tmp_table = soup.new_tag('table')
|
||||
new_row = soup.new_tag('tr')
|
||||
new_row, soup = add_bolded(soup, new_row, language)
|
||||
new_row, soup = new_line(soup, tmp_table, new_row)
|
||||
for s in signatures:
|
||||
new_row, soup = new_line(soup, tmp_table, new_row)
|
||||
new_row, soup = add_signature_to_table(soup, new_row, s, language, type)
|
||||
new_row, soup = new_line(soup, tmp_table, new_row)
|
||||
return tmp_table, soup
|
||||
|
||||
|
||||
def get_anchor_list(anchor, soup):
|
||||
a_list = []
|
||||
# go through all the links
|
||||
for a in soup.find_all('a', href=True):
|
||||
# find links with the same anchor
|
||||
last_part_of_link = a['href'].rsplit('#', 1)[-1]
|
||||
if last_part_of_link == anchor:
|
||||
a_list.append(a)
|
||||
return a_list
|
||||
|
||||
def is_static_method(element):
|
||||
if element.name == "table":
|
||||
tmp_element = element.find('td', {'class': 'memname'})
|
||||
if tmp_element is not None:
|
||||
if 'static' in tmp_element.text:
|
||||
return True
|
||||
else:
|
||||
if element['class'][0] == 'memItemRight':
|
||||
if "static" in element.previousSibling.text:
|
||||
return True
|
||||
return False
|
||||
|
||||
def append_python_signatures_to_table(soup, signatures, table, type):
|
||||
if type == "method":
|
||||
if is_static_method(table):
|
||||
type = "static" + type
|
||||
description, soup = create_description(soup, "Python:", signatures, type)
|
||||
description['class'] = 'python_language'
|
||||
soup = insert_or_replace(soup, table, description, "table", "python_language")
|
||||
return soup
|
||||
|
||||
def get_heading_text(a):
|
||||
str = ""
|
||||
element = a.parent
|
||||
if element is not None:
|
||||
childs = element.find_all('a')
|
||||
# the anchor should not be an argument of a function / method
|
||||
if childs.index(a) is not 0:
|
||||
return str
|
||||
element = element.parent
|
||||
if element is not None:
|
||||
if element.has_attr('class'):
|
||||
tmp_class = element["class"][0]
|
||||
if "memitem:" in tmp_class and "python" not in tmp_class:
|
||||
str = element.parent.find("tr").text
|
||||
return str
|
||||
|
||||
def insert_or_replace(soup, element, description, tag_name, tag_class):
|
||||
old = element.next_sibling
|
||||
if old is not None:
|
||||
if old.name != tag_name:
|
||||
old = None
|
||||
elif not tag_class in old.get('class', []):
|
||||
old = None
|
||||
# if already existed replace with the new
|
||||
if old is None:
|
||||
element.insert_after(description)
|
||||
else:
|
||||
old.replace_with(description)
|
||||
return soup
|
||||
|
||||
def new_heading_td(soup, s, href, type):
|
||||
if href is None:
|
||||
attrs = {'class': 'memItemLeft', 'valign': 'top', 'align': 'right'}
|
||||
new_td = soup.new_tag('td', **attrs)
|
||||
new_td.append(str(s.get('ret', None)))
|
||||
else:
|
||||
attrs = {'class': 'memItemRight', 'valign': 'bottom'}
|
||||
new_td = soup.new_tag('td', **attrs)
|
||||
|
||||
# make the function name linkable
|
||||
attrs_a = {'class': 'el', 'href': href}
|
||||
new_a = soup.new_tag('a', **attrs_a)
|
||||
tmp_name = str(s.get('name', None))
|
||||
if type is not "method":
|
||||
tmp_name = "cv2." + tmp_name
|
||||
else:
|
||||
tmp_name = "obj." + tmp_name
|
||||
new_a.append(tmp_name)
|
||||
new_td.append(new_a)
|
||||
|
||||
new_td.append("(" + s['arg'] +")")
|
||||
return soup, new_td
|
||||
|
||||
def append_python_signatures_to_heading(soup, signatures, element, href, type):
|
||||
if type == "method":
|
||||
if is_static_method(element):
|
||||
type = "static" + type
|
||||
for s in signatures:
|
||||
attrs = {'class': 'memitem:python'}
|
||||
new_tr = soup.new_tag('tr', **attrs)
|
||||
|
||||
soup, new_td_left = new_heading_td(soup, s, None, type)
|
||||
new_tr.append(new_td_left)
|
||||
|
||||
soup, new_td_right = new_heading_td(soup, s, href, type)
|
||||
new_tr.append(new_td_right)
|
||||
|
||||
soup = insert_or_replace(soup, element, new_tr, "tr", "memitem:python")
|
||||
return soup
|
||||
|
||||
def append_python_signature(function_variants, anchor_list, soup):
|
||||
type = anchor_list[0].type
|
||||
if type == "method" or type == "fn":
|
||||
if len(anchor_list) == 1:
|
||||
tmp_anchor = anchor_list[0].anchor
|
||||
a_list = get_anchor_list(tmp_anchor, soup)
|
||||
for a in a_list:
|
||||
if a['href'] == "#" + tmp_anchor:
|
||||
tmp_element = a.parent
|
||||
# ignore the More... link <td class = mdescRight>
|
||||
if tmp_element is None or tmp_element['class'][0] == 'mdescRight':
|
||||
continue
|
||||
# Function Documentation (tables)
|
||||
table = a.findNext('table')
|
||||
if table is not None:
|
||||
soup = append_python_signatures_to_table(soup, function_variants, table, type)
|
||||
else:
|
||||
str = get_heading_text(a)
|
||||
if "Functions" in str:
|
||||
soup = append_python_signatures_to_heading(soup, function_variants, a.parent, a['href'], type)
|
||||
return soup
|
||||
|
||||
def update_html(file, soup):
|
||||
tmp_str = str(soup)
|
||||
if os.name == 'nt': # if Windows
|
||||
with open(file, "wb") as tmp_file:
|
||||
tmp_file.write(tmp_str.encode("ascii","ignore"))
|
||||
s = str(soup)
|
||||
if os.name == 'nt' or sys.version_info[0] == 3: # if Windows
|
||||
s = s.encode('utf-8', 'ignore')
|
||||
with open(file, 'wb') as f:
|
||||
f.write(s)
|
||||
|
||||
|
||||
def insert_python_signatures(python_signatures, symbols_dict, filepath):
|
||||
soup = load_html_file(filepath)
|
||||
entries = soup.find_all(lambda tag: tag.name == "a" and tag.has_attr('id'))
|
||||
for e in entries:
|
||||
anchor = e['id']
|
||||
if anchor in symbols_dict:
|
||||
s = symbols_dict[anchor]
|
||||
logging.info('Process: %r' % s)
|
||||
if s.type == 'fn' or s.type == 'method':
|
||||
process_fn(soup, e, python_signatures[s.cppname], s)
|
||||
elif s.type == 'const':
|
||||
process_const(soup, e, python_signatures[s.cppname], s)
|
||||
else:
|
||||
logging.error('unsupported type: %s' % s);
|
||||
|
||||
update_html(filepath, soup)
|
||||
|
||||
|
||||
def process_fn(soup, anchor, python_signature, symbol):
|
||||
try:
|
||||
r = anchor.find_next_sibling(class_='memitem').find(class_='memproto').find('table')
|
||||
insert_python_fn_signature(soup, r, python_signature, symbol)
|
||||
except:
|
||||
logging.error("Can't process: %s" % symbol)
|
||||
traceback.print_exc()
|
||||
pprint(anchor)
|
||||
|
||||
|
||||
def process_const(soup, anchor, python_signature, symbol):
|
||||
try:
|
||||
#pprint(anchor.parent)
|
||||
description = append(soup.new_tag('div', **{'class' : ['python_language']}),
|
||||
'Python: ' + python_signature[0]['name'])
|
||||
old = anchor.find_next_sibling('div', class_='python_language')
|
||||
if old is None:
|
||||
anchor.parent.append(description)
|
||||
else:
|
||||
old.replace_with(description)
|
||||
#pprint(anchor.parent)
|
||||
except:
|
||||
logging.error("Can't process: %s" % symbol)
|
||||
traceback.print_exc()
|
||||
pprint(anchor)
|
||||
|
||||
|
||||
def insert_python_fn_signature(soup, table, variants, symbol):
|
||||
description = create_python_fn_description(soup, variants)
|
||||
description['class'] = 'python_language'
|
||||
soup = insert_or_replace(table, description, 'table', 'python_language')
|
||||
return soup
|
||||
|
||||
|
||||
def create_python_fn_description(soup, variants):
|
||||
language = 'Python:'
|
||||
table = soup.new_tag('table')
|
||||
heading_row = soup.new_tag('th')
|
||||
table.append(
|
||||
append(soup.new_tag('tr'),
|
||||
append(soup.new_tag('th', colspan=999, style="text-align:left"), language)))
|
||||
for v in variants:
|
||||
#logging.debug(v)
|
||||
add_signature_to_table(soup, table, v, language, type)
|
||||
#print(table)
|
||||
return table
|
||||
|
||||
|
||||
def add_signature_to_table(soup, table, signature, language, type):
|
||||
""" Add a signature to an html table"""
|
||||
row = soup.new_tag('tr')
|
||||
row.append(soup.new_tag('td', style='width: 20px;'))
|
||||
|
||||
if 'ret' in signature:
|
||||
row.append(append(soup.new_tag('td'), signature['ret']))
|
||||
row.append(append(soup.new_tag('td'), '='))
|
||||
else:
|
||||
with open(file, "w") as tmp_file:
|
||||
tmp_file.write(tmp_str)
|
||||
row.append(soup.new_tag('td')) # return values
|
||||
row.append(soup.new_tag('td')) # '='
|
||||
|
||||
row.append(append(soup.new_tag('td'), signature['name'] + '('))
|
||||
row.append(append(soup.new_tag('td', **{'class': 'paramname'}), signature['arg']))
|
||||
row.append(append(soup.new_tag('td'), ')'))
|
||||
table.append(row)
|
||||
|
||||
|
||||
def append(target, obj):
|
||||
target.append(obj)
|
||||
return target
|
||||
|
||||
|
||||
def insert_or_replace(element_before, new_element, tag, tag_class):
|
||||
old = element_before.find_next_sibling(tag, class_=tag_class)
|
||||
if old is None:
|
||||
element_before.insert_after(new_element)
|
||||
else:
|
||||
old.replace_with(new_element)
|
||||
|
||||
Reference in New Issue
Block a user