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# -------------------------------------------------------------------------------------------------- 

2# Copyright (c) Lukas Vik. All rights reserved. 

3# 

4# This file is part of the tsfpga project. 

5# https://tsfpga.com 

6# https://gitlab.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9import re 

10 

11import pytest 

12 

13import tsfpga 

14from tsfpga.system_utils import create_file, read_file 

15from tsfpga.git_utils import find_git_files 

16 

17 

18class CopyrightHeader: 

19 

20 separator_line_length = 100 

21 

22 def __init__(self, file, copyright_holder, copyright_text_lines=None): 

23 self._file = file 

24 self.comment_character = self._get_comment_character() 

25 self.separator_line = f"{self.comment_character} " + "-" * ( 

26 self.separator_line_length - 1 - len(self.comment_character) 

27 ) 

28 self.expected_copyright_header = self._get_expected_copyright_header( 

29 copyright_holder, copyright_text_lines 

30 ) 

31 

32 def check_file(self): 

33 """ 

34 Copyright comments should be correct. It should be followed by a blank line or another 

35 comment. 

36 """ 

37 copyright_header_re = self.expected_copyright_header.replace("(", "\\(").replace(")", "\\)") 

38 regexp = re.compile(copyright_header_re + rf"($|\n|{self.comment_character})") 

39 data = read_file(self._file) 

40 return regexp.match(data) is not None 

41 

42 def fix_file(self): 

43 if self._is_suitable_for_insertion(): 

44 self._insert_copyright_header() 

45 else: 

46 raise ValueError(f"Can not fix copyright header in file {self._file}") 

47 

48 def _get_expected_copyright_header(self, copyright_holder, copyright_text_lines): 

49 header = f"{self.separator_line}\n" 

50 header += ( 

51 f"{self.comment_character} Copyright (c) {copyright_holder}. All rights reserved.\n" 

52 ) 

53 if copyright_text_lines: 

54 header += f"{self.comment_character}\n" 

55 for copyright_text_line in copyright_text_lines: 

56 header += f"{self.comment_character} {copyright_text_line}\n" 

57 header += f"{self.separator_line}\n" 

58 return header 

59 

60 def _get_comment_character(self): 

61 if self._file.name.endswith(".py"): 

62 return "#" 

63 if self._file.name.endswith(".vhd"): 

64 return "--" 

65 if self._file.name.endswith((".xdc", ".tcl")): 

66 return "#" 

67 if self._file.name.endswith((".c", ".cpp", ".h", ".v")): 

68 return "//" 

69 raise RuntimeError(f"Could not decide file ending of {self._file}") 

70 

71 def _is_suitable_for_insertion(self): 

72 """ 

73 If the file does not begin with a comment, we consired it suitable to insert a new copyright 

74 header comment. 

75 """ 

76 return not read_file(self._file).startswith(self.comment_character) 

77 

78 def _insert_copyright_header(self): 

79 data = read_file(self._file) 

80 data = f"{self.expected_copyright_header}\n{data}" 

81 create_file(self._file, data) 

82 

83 

84def files_to_check_for_copyright_header(): 

85 file_endings = (".py", ".vhd", ".tcl") 

86 exclude_directories = [tsfpga.TSFPGA_EXAMPLE_MODULES / "artyz7" / "tcl"] 

87 for file_ending in file_endings: 

88 for file in find_git_files( 

89 directory=tsfpga.REPO_ROOT, 

90 exclude_directories=exclude_directories, 

91 file_endings_include=file_ending, 

92 ): 

93 yield file 

94 

95 

96def test_copyright_header_of_all_checked_in_files(): 

97 test_ok = True 

98 for file in files_to_check_for_copyright_header(): 

99 copyright_lines = [ 

100 "This file is part of the tsfpga project.", 

101 "https://tsfpga.com", 

102 "https://gitlab.com/tsfpga/tsfpga", 

103 ] 

104 copyright_header_checker = CopyrightHeader(file, "Lukas Vik", copyright_lines) 

105 if not copyright_header_checker.check_file(): 

106 test_ok = False 

107 print( 

108 f"Fail for {file}\nExpected:\n{copyright_header_checker.expected_copyright_header}" 

109 ) 

110 assert test_ok 

111 

112 

113def test_check_file(tmp_path): 

114 header = "-- " + "-" * 97 + "\n" 

115 header += "-- Copyright (c) Apa. All rights reserved.\n" 

116 header += "-- " + "-" * 97 + "\n" 

117 

118 file = create_file(tmp_path / "header.vhd", header) 

119 copyright_header = CopyrightHeader(file, "Apa") 

120 assert copyright_header.check_file() 

121 

122 file = create_file(tmp_path / "non_comment.vhd", header + "non-comment on line after") 

123 copyright_header = CopyrightHeader(file, "Apa") 

124 assert not copyright_header.check_file() 

125 

126 file = create_file(tmp_path / "empty_line.vhd", header + "\nEmpty line and then non-comment") 

127 copyright_header = CopyrightHeader(file, "Apa") 

128 assert copyright_header.check_file() 

129 

130 file = create_file(tmp_path / "further_comment.vhd", header + "-- Further comment\n") 

131 copyright_header = CopyrightHeader(file, "Apa") 

132 assert copyright_header.check_file() 

133 

134 

135def test_check_file_with_copyright_text(tmp_path): 

136 header = "-- " + "-" * 97 + "\n" 

137 header += "-- Copyright (c) Apa. All rights reserved.\n" 

138 header += "--\n" 

139 header += "-- Some more\n" 

140 header += "-- text.\n" 

141 header += "-- " + "-" * 97 + "\n" 

142 

143 file = create_file(tmp_path / "header.vhd", header) 

144 copyright_header = CopyrightHeader(file, "Apa", ["Some more", "text."]) 

145 assert copyright_header.check_file() 

146 

147 

148def test_fix_file_comment_insertion(tmp_path): 

149 data = "Apa\n" 

150 file = create_file(tmp_path / "file_for_test.vhd", data) 

151 

152 copyright_header = CopyrightHeader(file, "Hest Hestsson") 

153 copyright_header.fix_file() 

154 

155 data = read_file(file).split("\n") 

156 assert data[0] == "-- " + "-" * 97 

157 assert data[1] == "-- Copyright (c) Hest Hestsson. All rights reserved." 

158 assert data[2] == "-- " + "-" * 97 

159 assert data[3] == "" 

160 assert data[4] == "Apa" 

161 

162 

163def test_fix_file_should_not_run_on_dirty_file(tmp_path): 

164 data = "-- Custom comment line\n\nApa\n" 

165 file = create_file(tmp_path / "file_for_test.vhd", data) 

166 copyright_header = CopyrightHeader(file, "A") 

167 

168 with pytest.raises(ValueError) as exception_info: 

169 copyright_header.fix_file() 

170 assert str(exception_info.value) == f"Can not fix copyright header in file {file}"