Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief Function to verify the files produced by Sphinx 

5""" 

6import os 

7import re 

8import warnings 

9from ..loghelper.flog import noLOG 

10from ..filehelper.synchelper import explore_folder_iterfile 

11 

12 

13class SphinxVerificationException(Exception): 

14 

15 """ 

16 to format the error message 

17 """ 

18 

19 def __init__(self, errors): 

20 """ 

21 @param errors errors met 

22 """ 

23 stack = [] 

24 for name, line, m in errors: 

25 message = '[sphinxerror]-4 {2}\n File "{0}", line {1}'.format( 

26 name, line + 1, m) 

27 stack.append(message) 

28 Exception.__init__(self, "\n" + "\n".join(stack)) 

29 

30 

31def verification_html_format(folder, fLOG=noLOG, raise_above=0.1): 

32 """ 

33 dig into folders abd subfolders to find HTML files 

34 produced by Sphinx, does some verification to detect errors, 

35 the function, the function raises an exception for all mistakes 

36 

37 @param folder folder to verifiy 

38 @param fLOG logging function 

39 @param raise_above raises an exception of the number of errors is above a given threshold 

40 or a relative threshold if it is a float 

41 @return list of errors 

42 """ 

43 nbfile = 0 

44 errors = [] 

45 for item in explore_folder_iterfile(folder, ".[.]html", fullname=True): 

46 fLOG("[verification_html_format]", item) 

47 if not os.path.exists(item): 

48 fLOG( 

49 "[verification_html_format] unable to find and check '{0}'".format(item)) 

50 continue 

51 err = verification_html_file(item, fLOG=fLOG) 

52 if len(err) > 0: 

53 fitem = os.path.abspath(item) 

54 if "html/coverage" in fitem.replace("\\", "/"): 

55 # we skip as it comes from coverage report. 

56 pass 

57 else: 

58 errors.extend((fitem, line, m) for line, m in err) 

59 nbfile += 1 

60 fLOG("[verification_html_format] checked:{0} errors:{1}".format( 

61 nbfile, len(errors))) 

62 if len(errors) > 0: 

63 e = SphinxVerificationException(errors) 

64 if isinstance(raise_above, int) and len(errors) >= raise_above: 

65 raise e 

66 if len(errors) * 1.0 / nbfile >= raise_above: 

67 raise e 

68 warnings.warn("Sphinx error {0}".format(e), UserWarning) 

69 return errors 

70 

71 

72def verification_html_file(item, fLOG=noLOG): 

73 """ 

74 Verifies a file produced by :epkg:`sphinx` and checks basic mistakes. 

75 

76 @param item filename 

77 @param fLOG logging function 

78 @return list of errors (line, message) 

79 

80 The first line is 0. 

81 """ 

82 with open(item, "r", encoding="utf8") as f: 

83 content = f.read() 

84 

85 content = content.replace("\r", "").replace("\n", "_#!#_LINES_#_") 

86 content = re.sub("<pre>(.*?)</pre>", "<pre></pre>", content) 

87 content = content.replace("_#!#_LINES_#_", "\n") 

88 lines = content.split("\n") 

89 reg = re.compile("([.][.] _[-a-z_A-Z0-9][:.])") 

90 

91 errors = [] 

92 for i, line in enumerate(lines): 

93 if "<h1>Source code for " in line or "<h1>Code source de " in line: 

94 # no need to go further 

95 # the source takes place after this substring 

96 break 

97 if ":ref:`" in line and ":ref:`{ref_name}`" not in line: 

98 errors.append((i, "wrong :ref:` in " + line.strip("\n\r "))) 

99 if ":func:`" in line: 

100 errors.append((i, "wrong :func:` in " + line.strip("\n\r "))) 

101 if ":class:`" in line: 

102 errors.append((i, "wrong :class:` in " + line.strip("\n\r "))) 

103 if ":meth:`" in line: 

104 errors.append((i, "wrong :meth:` in " + line.strip("\n\r "))) 

105 if ":method:`" in line: 

106 errors.append((i, "wrong :method:` in " + line.strip("\n\r "))) 

107 if ">`" in line and "`</span></a>-" not in line: 

108 errors.append((i, "wrong >`, missing _ in " + line.strip("\n\r "))) 

109 find = reg.findall(line) 

110 if len(find) > 0: 

111 errors.append( 

112 (i, "label or index remaining: " + str(find) + " in " + line.strip("\n\r "))) 

113 

114 return errors