1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
from __future__ import print_function
import sys
import logging
import os
import re
from pprint import pprint
import traceback
try:
import bs4
from bs4 import BeautifulSoup
except ImportError:
raise ImportError('Error: '
'Install BeautifulSoup (bs4) for adding'
' Python & Java signatures documentation')
def load_html_file(file_dir):
""" Uses BeautifulSoup to load an html """
with open(file_dir, 'rb') as fp:
data = fp.read()
if os.name == 'nt' or sys.version_info[0] == 3:
data = data.decode(encoding='utf-8', errors='strict')
data = re.sub(r'(\>)([ ]+)', lambda match: match.group(1) + ('!space!' * len(match.group(2))), data)
data = re.sub(r'([ ]+)(\<)', lambda match: ('!space!' * len(match.group(1))) + match.group(2), data)
if os.name == 'nt' or sys.version_info[0] == 3:
data = data.encode('utf-8', 'ignore')
soup = BeautifulSoup(data, 'html.parser')
return soup
def update_html(file, soup):
s = str(soup)
s = s.replace('!space!', ' ')
if os.name == 'nt' or sys.version_info[0] == 3:
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:
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)
|