From: Alexander Alekhin Date: Tue, 5 Sep 2017 15:55:01 +0000 (+0300) Subject: doc: update Python signatures generation X-Git-Tag: accepted/tizen/6.0/unified/20201030.111113~309^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d715badbde9c5a4fa739e48db484212c3d772fe6;p=platform%2Fupstream%2Fopencv.git doc: update Python signatures generation - drop dependency on 'import cv2', use pyopencv_signatures.json instead - try to make generator idempotent --- diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 7eaf62e..741c4a0 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -205,10 +205,14 @@ if(BUILD_DOCS AND DOXYGEN_FOUND) list(APPEND js_tutorials_assets_deps "${f}" "${opencv_tutorial_html_dir}/${fname}") endforeach() + set(doxygen_result "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/index.html") + add_custom_target(doxygen_cpp COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile} DEPENDS ${doxyfile} ${rootfile} ${bibfile} ${deps} ${js_tutorials_assets_deps} + COMMENT "Generate Doxygen documentation" ) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html DESTINATION "${OPENCV_DOC_INSTALL_PATH}" COMPONENT "docs" OPTIONAL @@ -216,16 +220,16 @@ if(BUILD_DOCS AND DOXYGEN_FOUND) if(BUILD_opencv_python2) add_custom_target(doxygen_python - COMMAND ${PYTHON2_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/" - DEPENDS doxygen_cpp opencv_python2 + COMMAND ${PYTHON2_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/" "${OPENCV_PYTHON2_SIGNATURES_FILE}" + DEPENDS "${doxygen_result}" gen_opencv_python2 ) add_custom_target(doxygen DEPENDS doxygen_cpp doxygen_python ) elseif(BUILD_opencv_python3) add_custom_target(doxygen_python - COMMAND ${PYTHON3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/" - DEPENDS doxygen_cpp opencv_python3 + COMMAND ${PYTHON3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/" "${OPENCV_PYTHON3_SIGNATURES_FILE}" + DEPENDS "${doxygen_result}" gen_opencv_python3 ) add_custom_target(doxygen DEPENDS doxygen_cpp doxygen_python diff --git a/doc/tools/html_functions.py b/doc/tools/html_functions.py index bf9577b..215a058 100644 --- a/doc/tools/html_functions.py +++ b/doc/tools/html_functions.py @@ -1,10 +1,11 @@ +from __future__ import print_function import logging import os import codecs -import cv2 - +from pprint import pprint try: + import bs4 from bs4 import BeautifulSoup except ImportError: raise ImportError('Error: ' @@ -63,14 +64,12 @@ def add_signature_to_table(tmp_soup, new_row, signature, function_name, language else: new_item = tmp_soup.new_tag('td') - if "-> None" in signature: - pass - elif "->" in signature: - new_item.append(signature.split("->", 1)[1] + ' =') + if str(signature.get('ret', None)) != "None": + new_item.append(signature.get('ret') + ' =') new_row.append(new_item) if "Python" in language: - function_name = "cv2." + function_name + pass # function_name = "cv2." + function_name elif "Java" in language: # get word before function_name (= output) str_before_bracket = signature.split('(', 1)[0] @@ -79,8 +78,8 @@ def add_signature_to_table(tmp_soup, new_row, signature, function_name, language new_item.append(output + " ") new_row.append(new_item) - new_row = add_item(tmp_soup, new_row, False, function_name + '(') - new_row = add_item(tmp_soup, new_row, True, get_text_between_substrings(signature, "(", ")")) + new_row = add_item(tmp_soup, new_row, False, signature.get('name', function_name) + '(') + new_row = add_item(tmp_soup, new_row, True, signature['arg']) new_row = add_item(tmp_soup, new_row, False, ')') return new_row @@ -100,98 +99,81 @@ def add_bolded(tmp_soup, new_row, text): return new_row -def append_table_to(cpp_table, tmp_soup, language, signature, function_name): +def create_description(tmp_soup, language, signatures, function_name): """ Insert the new Python / Java table after the current html c++ table """ - if signature != "": - tmp_table = tmp_soup.new_tag('table') - new_row = tmp_soup.new_tag('tr') - new_row = add_bolded(tmp_soup, new_row, language) - ident = False - - if len(signature) > 120: - new_row = new_line(tmp_soup, tmp_table, new_row) - ident = True - - if " or " in signature: - ident = True - for tmp_sig in signature.split(" or "): - new_row = new_line(tmp_soup, tmp_table, new_row) - new_row = add_signature_to_table(tmp_soup, new_row, tmp_sig, function_name, language, ident) - new_row = new_line(tmp_soup, tmp_table, new_row) - else: - new_row = add_signature_to_table(tmp_soup, new_row, signature, function_name, language, ident) - tmp_table.append(new_row) + assert signatures + tmp_table = tmp_soup.new_tag('table') + new_row = tmp_soup.new_tag('tr') + new_row = add_bolded(tmp_soup, new_row, language) + ident = False - cpp_table.insert_after(tmp_table) - return cpp_table + new_row = new_line(tmp_soup, tmp_table, new_row) + ident = True + for s in signatures: + new_row = new_line(tmp_soup, tmp_table, new_row) + new_row = add_signature_to_table(tmp_soup, new_row, s, function_name, language, ident) + new_row = new_line(tmp_soup, tmp_table, new_row) -def add_signatures(tmp_soup, tmp_dir, ADD_JAVA, ADD_PYTHON, module_name): + return tmp_table + + +def add_signatures(tmp_soup, tmp_dir, module_name, config): """ Add signatures to the current soup and rewrite the html file""" + logging.debug(tmp_dir) sign_counter = 0 python_sign_counter = 0 java_sign_counter = 0 - if ADD_JAVA: + if config.ADD_JAVA: functions_file = "java_doc_txts/" + module_name + "/functions.txt" if os.path.exists(functions_file): with open(functions_file, 'r') as f: java_signatures = f.read().split("\n") else: - ADD_JAVA = False # This C++ module (module_name) may not exist in Java + config.ADD_JAVA = False # This C++ module (module_name) may not exist in Java # the HTML tag & class being used to find functions for function in tmp_soup.findAll("h2", {"class": "memtitle"}): - function_name = function.getText() - if os.name == 'nt': # if Windows - function_name = function_name.encode("ascii","ignore").decode() - - # all functions have () in it's name - if "()" not in function_name: + function_name = None + for c in function.contents: + if isinstance(c, bs4.element.NavigableString): + fn = str(c).encode("ascii","ignore").decode().strip() + if not fn.endswith('()'): # all functions have () in it's name + # enums, structures, etc + continue + function_name = fn[:-2] + + if not function_name: continue - if "[" in function_name: - if "[1/" in function_name: - function_name = function_name.replace(' ', '')[:-7] - else: - continue - else: - function_name = function_name.replace(' ', '')[:-2] sign_counter += 1 - # if not Windows computer - if os.name != 'nt': - function_name = function_name.replace(' ', '')[2:] - cpp_table = function.findNext('table') - if ADD_PYTHON: - try: + if config.ADD_PYTHON: + signatures = config.python_signatures.get("cv::" + str(function_name), None) + if signatures: print(function_name) - method = getattr(cv2, str(function_name)) - description = str(method.__doc__).split("\n") - signature = "" - is_first_sig = True - for line in description: - if line.startswith(".") or line == "": - continue - else: - if is_first_sig: - signature += line - is_first_sig = False - else: - signature += " or " + line - - cpp_table = append_table_to(cpp_table, tmp_soup, "Python:", signature, function_name) + + description = create_description(tmp_soup, "Python:", signatures, function_name) + description['class'] = 'python_language' + old = cpp_table.next_sibling + if old.name != 'table': + old = None + elif not 'python_language' in old.get('class', []): + old = None + if old is None: + cpp_table.insert_after(description) + else: + old.replace_with(description) python_sign_counter += 1 - except AttributeError: - continue - if ADD_JAVA: + if config.ADD_JAVA: for signature in java_signatures: if function_name in signature: - append_table_to(cpp_table, tmp_soup, "Java:", signature, function_name) + create_description(cpp_table, tmp_soup, "Java:", signature, function_name) java_sign_counter += 1 break diff --git a/doc/tools/python_signatures.py b/doc/tools/python_signatures.py index 34ea322..6908de2 100644 --- a/doc/tools/python_signatures.py +++ b/doc/tools/python_signatures.py @@ -8,13 +8,37 @@ TODO: * clarify special case: http://docs.opencv.org/3.2.0/db/de0/group__core__utils.html#ga4910d7f86336cd4eff9dd05575667e41 """ +from __future__ import print_function +import os import re import sys -import html_functions +import logging + +loglevel=os.environ.get("LOGLEVEL", None) +if loglevel: + logging.basicConfig(level=loglevel) ADD_JAVA = False ADD_PYTHON = True ROOT_DIR = sys.argv[1] +PYTHON_SIGNATURES_FILE = sys.argv[2] + +import json +python_signatures = dict() +with open(PYTHON_SIGNATURES_FILE, "rt") as f: + python_signatures = json.load(f) + print("Loaded Python signatures: %d" % len(python_signatures)) + +class Configuration(): + def __init__(self): + self.ADD_PYTHON = ADD_PYTHON + self.python_signatures = python_signatures + self.ADD_JAVA = ADD_JAVA + +config = Configuration() + + +import html_functions soup = html_functions.load_html_file(ROOT_DIR + "index.html") href_list = html_functions.get_links_list(soup, True) @@ -24,11 +48,11 @@ for link in href_list: soup = html_functions.load_html_file(ROOT_DIR + link) sub_href_list = html_functions.get_links_list(soup, True) module_name = html_functions.get_text_between_substrings(link, "group__", ".html") - html_functions.add_signatures(soup, ROOT_DIR + link, ADD_JAVA, ADD_PYTHON, module_name) + html_functions.add_signatures(soup, ROOT_DIR + link, module_name, config) # add python signatures to the sub-modules link = re.sub(r"group__.+html", "", link) for sub_link in sub_href_list: tmp_dir = ROOT_DIR + link + sub_link soup = html_functions.load_html_file(tmp_dir) - html_functions.add_signatures(soup, tmp_dir, ADD_JAVA, ADD_PYTHON, module_name) + html_functions.add_signatures(soup, tmp_dir, module_name, config)