1 from __future__ import print_function
7 from pprint import pprint
12 from bs4 import BeautifulSoup
14 raise ImportError('Error: '
15 'Install BeautifulSoup (bs4) for adding'
16 ' Python & Java signatures documentation')
18 def load_html_file(file_dir):
19 """ Uses BeautifulSoup to load an html """
20 with open(file_dir, 'rb') as fp:
22 if os.name == 'nt' or sys.version_info[0] == 3:
23 data = data.decode(encoding='utf-8', errors='strict')
24 data = re.sub(r'(\>)([ ]+)', lambda match: match.group(1) + ('!space!' * len(match.group(2))), data)
25 data = re.sub(r'([ ]+)(\<)', lambda match: ('!space!' * len(match.group(1))) + match.group(2), data)
26 if os.name == 'nt' or sys.version_info[0] == 3:
27 data = data.encode('utf-8', 'ignore')
28 soup = BeautifulSoup(data, 'html.parser')
31 def update_html(file, soup):
33 s = s.replace('!space!', ' ')
34 if os.name == 'nt' or sys.version_info[0] == 3:
35 s = s.encode('utf-8', 'ignore')
36 with open(file, 'wb') as f:
40 def insert_python_signatures(python_signatures, symbols_dict, filepath):
41 soup = load_html_file(filepath)
42 entries = soup.find_all(lambda tag: tag.name == "a" and tag.has_attr('id'))
45 if anchor in symbols_dict:
46 s = symbols_dict[anchor]
47 logging.info('Process: %r' % s)
48 if s.type == 'fn' or s.type == 'method':
49 process_fn(soup, e, python_signatures[s.cppname], s)
50 elif s.type == 'const':
51 process_const(soup, e, python_signatures[s.cppname], s)
53 logging.error('unsupported type: %s' % s);
55 update_html(filepath, soup)
58 def process_fn(soup, anchor, python_signature, symbol):
60 r = anchor.find_next_sibling(class_='memitem').find(class_='memproto').find('table')
61 insert_python_fn_signature(soup, r, python_signature, symbol)
63 logging.error("Can't process: %s" % symbol)
68 def process_const(soup, anchor, python_signature, symbol):
70 #pprint(anchor.parent)
71 description = append(soup.new_tag('div', **{'class' : ['python_language']}),
72 'Python: ' + python_signature[0]['name'])
73 old = anchor.find_next_sibling('div', class_='python_language')
75 anchor.parent.append(description)
77 old.replace_with(description)
78 #pprint(anchor.parent)
80 logging.error("Can't process: %s" % symbol)
85 def insert_python_fn_signature(soup, table, variants, symbol):
86 description = create_python_fn_description(soup, variants)
87 description['class'] = 'python_language'
88 soup = insert_or_replace(table, description, 'table', 'python_language')
92 def create_python_fn_description(soup, variants):
94 table = soup.new_tag('table')
95 heading_row = soup.new_tag('th')
97 append(soup.new_tag('tr'),
98 append(soup.new_tag('th', colspan=999, style="text-align:left"), language)))
101 add_signature_to_table(soup, table, v, language, type)
106 def add_signature_to_table(soup, table, signature, language, type):
107 """ Add a signature to an html table"""
108 row = soup.new_tag('tr')
109 row.append(soup.new_tag('td', style='width: 20px;'))
111 if 'ret' in signature:
112 row.append(append(soup.new_tag('td'), signature['ret']))
113 row.append(append(soup.new_tag('td'), '='))
115 row.append(soup.new_tag('td')) # return values
116 row.append(soup.new_tag('td')) # '='
118 row.append(append(soup.new_tag('td'), signature['name'] + '('))
119 row.append(append(soup.new_tag('td', **{'class': 'paramname'}), signature['arg']))
120 row.append(append(soup.new_tag('td'), ')'))
124 def append(target, obj):
129 def insert_or_replace(element_before, new_element, tag, tag_class):
130 old = element_before.find_next_sibling(tag, class_=tag_class)
132 element_before.insert_after(new_element)
134 old.replace_with(new_element)