html_functions.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. from __future__ import print_function
  2. import sys
  3. import logging
  4. import os
  5. import re
  6. from pprint import pprint
  7. import traceback
  8. try:
  9. import bs4
  10. from bs4 import BeautifulSoup
  11. except ImportError:
  12. raise ImportError('Error: '
  13. 'Install BeautifulSoup (bs4) for adding'
  14. ' Python & Java signatures documentation')
  15. def load_html_file(file_dir):
  16. """ Uses BeautifulSoup to load an html """
  17. with open(file_dir, 'rb') as fp:
  18. data = fp.read()
  19. if os.name == 'nt' or sys.version_info[0] == 3:
  20. data = data.decode(encoding='utf-8', errors='strict')
  21. data = re.sub(r'(\>)([ ]+)', lambda match: match.group(1) + ('!space!' * len(match.group(2))), data)
  22. data = re.sub(r'([ ]+)(\<)', lambda match: ('!space!' * len(match.group(1))) + match.group(2), data)
  23. if os.name == 'nt' or sys.version_info[0] == 3:
  24. data = data.encode('utf-8', 'ignore')
  25. soup = BeautifulSoup(data, 'html.parser')
  26. return soup
  27. def update_html(file, soup):
  28. s = str(soup)
  29. s = s.replace('!space!', ' ')
  30. if os.name == 'nt' or sys.version_info[0] == 3:
  31. s = s.encode('utf-8', 'ignore')
  32. with open(file, 'wb') as f:
  33. f.write(s)
  34. def insert_python_signatures(python_signatures, symbols_dict, filepath):
  35. soup = load_html_file(filepath)
  36. entries = soup.find_all(lambda tag: tag.name == "a" and tag.has_attr('id'))
  37. for e in entries:
  38. anchor = e['id']
  39. if anchor in symbols_dict:
  40. s = symbols_dict[anchor]
  41. logging.info('Process: %r' % s)
  42. if s.type == 'fn' or s.type == 'method':
  43. process_fn(soup, e, python_signatures[s.cppname], s)
  44. elif s.type == 'const':
  45. process_const(soup, e, python_signatures[s.cppname], s)
  46. else:
  47. logging.error('unsupported type: %s' % s);
  48. update_html(filepath, soup)
  49. def process_fn(soup, anchor, python_signature, symbol):
  50. try:
  51. r = anchor.find_next_sibling(class_='memitem').find(class_='memproto').find('table')
  52. insert_python_fn_signature(soup, r, python_signature, symbol)
  53. except:
  54. logging.error("Can't process: %s" % symbol)
  55. traceback.print_exc()
  56. pprint(anchor)
  57. def process_const(soup, anchor, python_signature, symbol):
  58. try:
  59. #pprint(anchor.parent)
  60. description = append(soup.new_tag('div', **{'class' : ['python_language']}),
  61. 'Python: ' + python_signature[0]['name'])
  62. old = anchor.find_next_sibling('div', class_='python_language')
  63. if old is None:
  64. anchor.parent.append(description)
  65. else:
  66. old.replace_with(description)
  67. #pprint(anchor.parent)
  68. except:
  69. logging.error("Can't process: %s" % symbol)
  70. traceback.print_exc()
  71. pprint(anchor)
  72. def insert_python_fn_signature(soup, table, variants, symbol):
  73. description = create_python_fn_description(soup, variants)
  74. description['class'] = 'python_language'
  75. soup = insert_or_replace(table, description, 'table', 'python_language')
  76. return soup
  77. def create_python_fn_description(soup, variants):
  78. language = 'Python:'
  79. table = soup.new_tag('table')
  80. heading_row = soup.new_tag('th')
  81. table.append(
  82. append(soup.new_tag('tr'),
  83. append(soup.new_tag('th', colspan=999, style="text-align:left"), language)))
  84. for v in variants:
  85. #logging.debug(v)
  86. add_signature_to_table(soup, table, v, language, type)
  87. #print(table)
  88. return table
  89. def add_signature_to_table(soup, table, signature, language, type):
  90. """ Add a signature to an html table"""
  91. row = soup.new_tag('tr')
  92. row.append(soup.new_tag('td', style='width: 20px;'))
  93. row.append(append(soup.new_tag('td'), signature['name'] + '('))
  94. row.append(append(soup.new_tag('td', **{'class': 'paramname'}), signature['arg']))
  95. row.append(append(soup.new_tag('td'), ') -> '))
  96. row.append(append(soup.new_tag('td'), signature['ret']))
  97. table.append(row)
  98. def append(target, obj):
  99. target.append(obj)
  100. return target
  101. def insert_or_replace(element_before, new_element, tag, tag_class):
  102. old = element_before.find_next_sibling(tag, class_=tag_class)
  103. if old is None:
  104. element_before.insert_after(new_element)
  105. else:
  106. old.replace_with(new_element)