Skip to content

Commit d715bad

Browse files
committed
doc: update Python signatures generation
- drop dependency on 'import cv2', use pyopencv_signatures.json instead - try to make generator idempotent
1 parent 912de36 commit d715bad

File tree

3 files changed

+89
-79
lines changed

3 files changed

+89
-79
lines changed

doc/CMakeLists.txt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,27 +205,31 @@ if(BUILD_DOCS AND DOXYGEN_FOUND)
205205
list(APPEND js_tutorials_assets_deps "${f}" "${opencv_tutorial_html_dir}/${fname}")
206206
endforeach()
207207

208+
set(doxygen_result "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/index.html")
209+
208210
add_custom_target(doxygen_cpp
209211
COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
210212
DEPENDS ${doxyfile} ${rootfile} ${bibfile} ${deps} ${js_tutorials_assets_deps}
213+
COMMENT "Generate Doxygen documentation"
211214
)
215+
212216
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html
213217
DESTINATION "${OPENCV_DOC_INSTALL_PATH}"
214218
COMPONENT "docs" OPTIONAL
215219
)
216220

217221
if(BUILD_opencv_python2)
218222
add_custom_target(doxygen_python
219-
COMMAND ${PYTHON2_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/"
220-
DEPENDS doxygen_cpp opencv_python2
223+
COMMAND ${PYTHON2_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/" "${OPENCV_PYTHON2_SIGNATURES_FILE}"
224+
DEPENDS "${doxygen_result}" gen_opencv_python2
221225
)
222226
add_custom_target(doxygen
223227
DEPENDS doxygen_cpp doxygen_python
224228
)
225229
elseif(BUILD_opencv_python3)
226230
add_custom_target(doxygen_python
227-
COMMAND ${PYTHON3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/"
228-
DEPENDS doxygen_cpp opencv_python3
231+
COMMAND ${PYTHON3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/tools/python_signatures.py" "${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/" "${OPENCV_PYTHON3_SIGNATURES_FILE}"
232+
DEPENDS "${doxygen_result}" gen_opencv_python3
229233
)
230234
add_custom_target(doxygen
231235
DEPENDS doxygen_cpp doxygen_python

doc/tools/html_functions.py

Lines changed: 54 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
from __future__ import print_function
12
import logging
23
import os
34
import codecs
4-
import cv2
5-
5+
from pprint import pprint
66

77
try:
8+
import bs4
89
from bs4 import BeautifulSoup
910
except ImportError:
1011
raise ImportError('Error: '
@@ -63,14 +64,12 @@ def add_signature_to_table(tmp_soup, new_row, signature, function_name, language
6364
else:
6465
new_item = tmp_soup.new_tag('td')
6566

66-
if "-> None" in signature:
67-
pass
68-
elif "->" in signature:
69-
new_item.append(signature.split("->", 1)[1] + ' =')
67+
if str(signature.get('ret', None)) != "None":
68+
new_item.append(signature.get('ret') + ' =')
7069
new_row.append(new_item)
7170

7271
if "Python" in language:
73-
function_name = "cv2." + function_name
72+
pass # function_name = "cv2." + function_name
7473
elif "Java" in language:
7574
# get word before function_name (= output)
7675
str_before_bracket = signature.split('(', 1)[0]
@@ -79,8 +78,8 @@ def add_signature_to_table(tmp_soup, new_row, signature, function_name, language
7978
new_item.append(output + " ")
8079
new_row.append(new_item)
8180

82-
new_row = add_item(tmp_soup, new_row, False, function_name + '(')
83-
new_row = add_item(tmp_soup, new_row, True, get_text_between_substrings(signature, "(", ")"))
81+
new_row = add_item(tmp_soup, new_row, False, signature.get('name', function_name) + '(')
82+
new_row = add_item(tmp_soup, new_row, True, signature['arg'])
8483
new_row = add_item(tmp_soup, new_row, False, ')')
8584
return new_row
8685

@@ -100,98 +99,81 @@ def add_bolded(tmp_soup, new_row, text):
10099
return new_row
101100

102101

103-
def append_table_to(cpp_table, tmp_soup, language, signature, function_name):
102+
def create_description(tmp_soup, language, signatures, function_name):
104103
""" Insert the new Python / Java table after the current html c++ table """
105-
if signature != "":
106-
tmp_table = tmp_soup.new_tag('table')
107-
new_row = tmp_soup.new_tag('tr')
108-
new_row = add_bolded(tmp_soup, new_row, language)
109-
ident = False
110-
111-
if len(signature) > 120:
112-
new_row = new_line(tmp_soup, tmp_table, new_row)
113-
ident = True
114-
115-
if " or " in signature:
116-
ident = True
117-
for tmp_sig in signature.split(" or "):
118-
new_row = new_line(tmp_soup, tmp_table, new_row)
119-
new_row = add_signature_to_table(tmp_soup, new_row, tmp_sig, function_name, language, ident)
120-
new_row = new_line(tmp_soup, tmp_table, new_row)
121-
else:
122-
new_row = add_signature_to_table(tmp_soup, new_row, signature, function_name, language, ident)
123-
tmp_table.append(new_row)
104+
assert signatures
105+
tmp_table = tmp_soup.new_tag('table')
106+
new_row = tmp_soup.new_tag('tr')
107+
new_row = add_bolded(tmp_soup, new_row, language)
108+
ident = False
124109

125-
cpp_table.insert_after(tmp_table)
126-
return cpp_table
110+
new_row = new_line(tmp_soup, tmp_table, new_row)
111+
ident = True
127112

113+
for s in signatures:
114+
new_row = new_line(tmp_soup, tmp_table, new_row)
115+
new_row = add_signature_to_table(tmp_soup, new_row, s, function_name, language, ident)
116+
new_row = new_line(tmp_soup, tmp_table, new_row)
128117

129-
def add_signatures(tmp_soup, tmp_dir, ADD_JAVA, ADD_PYTHON, module_name):
118+
return tmp_table
119+
120+
121+
def add_signatures(tmp_soup, tmp_dir, module_name, config):
130122
""" Add signatures to the current soup and rewrite the html file"""
123+
131124
logging.debug(tmp_dir)
132125
sign_counter = 0
133126
python_sign_counter = 0
134127
java_sign_counter = 0
135128

136-
if ADD_JAVA:
129+
if config.ADD_JAVA:
137130
functions_file = "java_doc_txts/" + module_name + "/functions.txt"
138131
if os.path.exists(functions_file):
139132
with open(functions_file, 'r') as f:
140133
java_signatures = f.read().split("\n")
141134
else:
142-
ADD_JAVA = False # This C++ module (module_name) may not exist in Java
135+
config.ADD_JAVA = False # This C++ module (module_name) may not exist in Java
143136

144137
# the HTML tag & class being used to find functions
145138
for function in tmp_soup.findAll("h2", {"class": "memtitle"}):
146-
function_name = function.getText()
147-
if os.name == 'nt': # if Windows
148-
function_name = function_name.encode("ascii","ignore").decode()
149-
150-
# all functions have () in it's name
151-
if "()" not in function_name:
139+
function_name = None
140+
for c in function.contents:
141+
if isinstance(c, bs4.element.NavigableString):
142+
fn = str(c).encode("ascii","ignore").decode().strip()
143+
if not fn.endswith('()'): # all functions have () in it's name
144+
# enums, structures, etc
145+
continue
146+
function_name = fn[:-2]
147+
148+
if not function_name:
152149
continue
153150

154-
if "[" in function_name:
155-
if "[1/" in function_name:
156-
function_name = function_name.replace(' ', '')[:-7]
157-
else:
158-
continue
159-
else:
160-
function_name = function_name.replace(' ', '')[:-2]
161151
sign_counter += 1
162152

163-
# if not Windows computer
164-
if os.name != 'nt':
165-
function_name = function_name.replace(' ', '')[2:]
166-
167153
cpp_table = function.findNext('table')
168154

169-
if ADD_PYTHON:
170-
try:
155+
if config.ADD_PYTHON:
156+
signatures = config.python_signatures.get("cv::" + str(function_name), None)
157+
if signatures:
171158
print(function_name)
172-
method = getattr(cv2, str(function_name))
173-
description = str(method.__doc__).split("\n")
174-
signature = ""
175-
is_first_sig = True
176-
for line in description:
177-
if line.startswith(".") or line == "":
178-
continue
179-
else:
180-
if is_first_sig:
181-
signature += line
182-
is_first_sig = False
183-
else:
184-
signature += " or " + line
185-
186-
cpp_table = append_table_to(cpp_table, tmp_soup, "Python:", signature, function_name)
159+
160+
description = create_description(tmp_soup, "Python:", signatures, function_name)
161+
description['class'] = 'python_language'
162+
old = cpp_table.next_sibling
163+
if old.name != 'table':
164+
old = None
165+
elif not 'python_language' in old.get('class', []):
166+
old = None
167+
if old is None:
168+
cpp_table.insert_after(description)
169+
else:
170+
old.replace_with(description)
187171
python_sign_counter += 1
188-
except AttributeError:
189-
continue
190172

191-
if ADD_JAVA:
173+
if config.ADD_JAVA:
192174
for signature in java_signatures:
193175
if function_name in signature:
194-
append_table_to(cpp_table, tmp_soup, "Java:", signature, function_name)
176+
create_description(cpp_table, tmp_soup, "Java:", signature, function_name)
195177
java_sign_counter += 1
196178
break
197179

doc/tools/python_signatures.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,37 @@
88
* clarify special case:
99
http://docs.opencv.org/3.2.0/db/de0/group__core__utils.html#ga4910d7f86336cd4eff9dd05575667e41
1010
"""
11+
from __future__ import print_function
12+
import os
1113
import re
1214
import sys
13-
import html_functions
15+
import logging
16+
17+
loglevel=os.environ.get("LOGLEVEL", None)
18+
if loglevel:
19+
logging.basicConfig(level=loglevel)
1420

1521
ADD_JAVA = False
1622
ADD_PYTHON = True
1723
ROOT_DIR = sys.argv[1]
24+
PYTHON_SIGNATURES_FILE = sys.argv[2]
25+
26+
import json
27+
python_signatures = dict()
28+
with open(PYTHON_SIGNATURES_FILE, "rt") as f:
29+
python_signatures = json.load(f)
30+
print("Loaded Python signatures: %d" % len(python_signatures))
31+
32+
class Configuration():
33+
def __init__(self):
34+
self.ADD_PYTHON = ADD_PYTHON
35+
self.python_signatures = python_signatures
36+
self.ADD_JAVA = ADD_JAVA
37+
38+
config = Configuration()
39+
40+
41+
import html_functions
1842

1943
soup = html_functions.load_html_file(ROOT_DIR + "index.html")
2044
href_list = html_functions.get_links_list(soup, True)
@@ -24,11 +48,11 @@
2448
soup = html_functions.load_html_file(ROOT_DIR + link)
2549
sub_href_list = html_functions.get_links_list(soup, True)
2650
module_name = html_functions.get_text_between_substrings(link, "group__", ".html")
27-
html_functions.add_signatures(soup, ROOT_DIR + link, ADD_JAVA, ADD_PYTHON, module_name)
51+
html_functions.add_signatures(soup, ROOT_DIR + link, module_name, config)
2852

2953
# add python signatures to the sub-modules
3054
link = re.sub(r"group__.+html", "", link)
3155
for sub_link in sub_href_list:
3256
tmp_dir = ROOT_DIR + link + sub_link
3357
soup = html_functions.load_html_file(tmp_dir)
34-
html_functions.add_signatures(soup, tmp_dir, ADD_JAVA, ADD_PYTHON, module_name)
58+
html_functions.add_signatures(soup, tmp_dir, module_name, config)

0 commit comments

Comments
 (0)