From a4fd54e84c471301d69c89b07e897cb8cc82bc74 Mon Sep 17 00:00:00 2001 From: Carlo van Driesten Date: Tue, 9 Jan 2024 15:36:38 +0100 Subject: [PATCH 1/3] Add .venv/ to .gitignore. Signed-off-by: Carlo van Driesten Signed-off-by: Pierre R. Mai --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 26cc62ce5..2076b7c5d 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,8 @@ compile_commands.json # Python-generated files __pycache__/ +.venv/ +venv/ *.py[cod] proto2cpp.log .clang-format From ad258d91c1698750ca0c4f0aaa24647f1004eeb7 Mon Sep 17 00:00:00 2001 From: "Pierre R. Mai" Date: Fri, 12 Jan 2024 14:12:32 +0100 Subject: [PATCH 2/3] Move python dependencies to requirements_develop.txt Signed-off-by: Pierre R. Mai --- .github/workflows/protobuf.yml | 4 +++- requirements_develop.txt | 3 +++ setup.py | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 requirements_develop.txt diff --git a/.github/workflows/protobuf.yml b/.github/workflows/protobuf.yml index b55078fb8..feed38c13 100644 --- a/.github/workflows/protobuf.yml +++ b/.github/workflows/protobuf.yml @@ -28,7 +28,9 @@ jobs: python-version: '3.8' - name: Install Python Dependencies - run: python -m pip install --upgrade pip setuptools wheel pyyaml + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements_develop.txt - name: Install Doxygen run: sudo apt-get install doxygen graphviz diff --git a/requirements_develop.txt b/requirements_develop.txt new file mode 100644 index 000000000..6548edd76 --- /dev/null +++ b/requirements_develop.txt @@ -0,0 +1,3 @@ +setuptools +wheel +pyyaml diff --git a/setup.py b/setup.py index 435207aeb..6dfbb7222 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ import re from distutils.spawn import find_executable +# setuptool is dependend on wheel package from setuptools import setup from setuptools.command.build_py import build_py From 493bd514055d7351e0264c84655489158d878b7b Mon Sep 17 00:00:00 2001 From: "Pierre R. Mai" Date: Fri, 12 Jan 2024 14:14:50 +0100 Subject: [PATCH 3/3] Apply black formatting and checking to python files Signed-off-by: Pierre R. Mai --- .github/workflows/protobuf.yml | 3 + format/OSITrace.py | 73 ++++++---- format/osi2read.py | 75 ++++++---- format/txt2osi.py | 83 ++++++----- requirements_develop.txt | 1 + setup.py | 140 +++++++++--------- tests/test_comment_type.py | 151 ++++++++++++++------ tests/test_doxygen_output.py | 35 +++-- tests/test_invalid_comment.py | 23 ++- tests/test_invalid_enum.py | 97 +++++++++---- tests/test_invalid_html.py | 134 +++++++++++------- tests/test_invalid_message.py | 227 ++++++++++++++++++++++-------- tests/test_invalid_punctuation.py | 11 +- tests/test_invalid_tabs.py | 9 +- tests/test_newline.py | 11 +- tests/test_non_ascii.py | 27 +++- tests/test_rules.py | 99 ++++++++++--- tests/test_units.py | 49 +++++-- 18 files changed, 852 insertions(+), 396 deletions(-) diff --git a/.github/workflows/protobuf.yml b/.github/workflows/protobuf.yml index feed38c13..da70a5db3 100644 --- a/.github/workflows/protobuf.yml +++ b/.github/workflows/protobuf.yml @@ -32,6 +32,9 @@ jobs: python -m pip install --upgrade pip python -m pip install -r requirements_develop.txt + - name: Check black format + run: black --check --diff . + - name: Install Doxygen run: sudo apt-get install doxygen graphviz diff --git a/format/OSITrace.py b/format/OSITrace.py index f6d3d39fe..d8d2c246a 100644 --- a/format/OSITrace.py +++ b/format/OSITrace.py @@ -10,9 +10,10 @@ from osi3.osi_groundtruth_pb2 import GroundTruth from osi3.osi_sensordata_pb2 import SensorData import warnings -warnings.simplefilter('default') -SEPARATOR = b'$$__$$' +warnings.simplefilter("default") + +SEPARATOR = b"$$__$$" SEPARATOR_LENGTH = len(SEPARATOR) BUFFER_SIZE = 1000000 @@ -31,7 +32,7 @@ def get_size_from_file_stream(file_object): MESSAGES_TYPE = { "SensorView": SensorView, "GroundTruth": GroundTruth, - "SensorData": SensorData + "SensorData": SensorData, } @@ -49,7 +50,7 @@ def __init__(self, path=None, type_name="SensorView"): def from_file(self, path, type_name="SensorView", max_index=-1, format_type=None): """Import a scenario from a file""" - if path.lower().endswith(('.lzma', '.xz')): + if path.lower().endswith((".lzma", ".xz")): self.scenario_file = lzma.open(path, "rb") else: self.scenario_file = open(path, "rb") @@ -57,7 +58,7 @@ def from_file(self, path, type_name="SensorView", max_index=-1, format_type=None self.type_name = type_name self.format_type = format_type - if self.format_type == 'separated': + if self.format_type == "separated": # warnings.warn("The separated trace files will be completely removed in the near future. Please convert them to *.osi files with the converter in the main OSI repository.", PendingDeprecationWarning) self.timestep_count = self.retrieve_message_offsets(max_index) else: @@ -73,7 +74,7 @@ def retrieve_message_offsets(self, max_index): scenario_size = get_size_from_file_stream(self.scenario_file) if max_index == -1: - max_index = float('inf') + max_index = float("inf") buffer_deque = deque(maxlen=2) @@ -100,7 +101,7 @@ def retrieve_message_offsets(self, max_index): self.scenario_file.seek(message_offset) while eof and found != -1: - buffer = buffer[found + SEPARATOR_LENGTH:] + buffer = buffer[found + SEPARATOR_LENGTH :] found = buffer.find(SEPARATOR) buffer_offset = scenario_size - len(buffer) @@ -126,7 +127,7 @@ def retrieve_message(self): self.message_offsets = [0] eof = False - # TODO Implement buffering for the scenarios + # TODO Implement buffering for the scenarios self.scenario_file.seek(0) serialized_message = self.scenario_file.read() INT_LENGTH = len(struct.pack(" 1000000000: # Throw a warning if trace file is bigger than 1GB - gb_size_input = round(message_length/1000000000, 2) - gb_size_output = round(3.307692308*message_length/1000000000, 2) - warnings.warn(f"The trace file you are trying to make readable has the size {gb_size_input}GB. This will generate a readable file with the size {gb_size_output}GB. Make sure you have enough disc space and memory to read the file with your text editor.", ResourceWarning) - - with open(name, 'a') as f: - + gb_size_input = round(message_length / 1000000000, 2) + gb_size_output = round(3.307692308 * message_length / 1000000000, 2) + warnings.warn( + f"The trace file you are trying to make readable has the size {gb_size_input}GB. This will generate a readable file with the size {gb_size_output}GB. Make sure you have enough disc space and memory to read the file with your text editor.", + ResourceWarning, + ) + + with open(name, "a") as f: if interval is None and index is None: for i in self.get_messages(): f.write(str(i)) - + if interval is not None and index is None: - if type(interval) == tuple and len(interval) == 2 and interval[0] 0: matchName = re.search(r"\b\w[\S]*\b\s*=", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end()-1] + checkName = statement[ + matchName.start() : matchName.end() - 1 + ] # Check field message type (remove field name) type = statement.replace(checkName, "") matchName = re.search(r"\b\w[\S\.]*\s*=", type) if matchName is not None: - checkType = " "+type[matchName.start():matchName.end()-1]+" " + checkType = ( + " " + + type[ + matchName.start() : matchName.end() - 1 + ] + + " " + ) # Test case 12: Check nested message type - matchNameConv = re.search(r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]",checkType) + matchNameConv = re.search( + r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]", + checkType, + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) if noMessage > 0 and matchClosingBrace is not None: noMessage -= 1 - # Test to check if '\\brief' is appended in comment section for short comments. if matchComment is not None: noComment += 1 @@ -210,16 +245,36 @@ def test_comment_existence(self): hasBrief = True elif len(saveStatement) == 0: - statement = statement.strip() - if re.search(r"\bmessage\b", statement) is not None or re.search(r"\bextend\b",statement) is not None or re.search(r"\benum\b", statement) is not None: - - self.assertNotEqual(noComment, 0, file + " in line " + str(i - 1) + ": comment is missing for: '" + statement + "'") + if ( + re.search(r"\bmessage\b", statement) is not None + or re.search(r"\bextend\b", statement) is not None + or re.search(r"\benum\b", statement) is not None + ): + self.assertNotEqual( + noComment, + 0, + file + + " in line " + + str(i - 1) + + ": comment is missing for: '" + + statement + + "'", + ) if noMessage > 0 or isEnum == True: if statement.find(";") != -1: - self.assertNotEqual(noComment, 0, file + " in line " + str(i) + ": comment is missing for: '" + statement + "'") + self.assertNotEqual( + noComment, + 0, + file + + " in line " + + str(i) + + ": comment is missing for: '" + + statement + + "'", + ) noComment = 0 hasBrief = False @@ -229,12 +284,20 @@ def test_comment_existence(self): if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: - # Test to ensure no special characters are in ENUM name. - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b", endOfLine[matchName.start():matchName.end()]) - enumName = self.convert(endOfLine[matchName.start():matchName.end()]) + "_" + # Test to ensure no special characters are in ENUM name. + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + enumName = ( + self.convert( + endOfLine[matchName.start() : matchName.end()] + ) + + "_" + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -243,5 +306,5 @@ def test_comment_existence(self): enumName = "" def convert(self, name): - s1 = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', name) - return re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s1).upper() \ No newline at end of file + s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name) + return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1).upper() diff --git a/tests/test_doxygen_output.py b/tests/test_doxygen_output.py index 902e72ab8..37b80b4f4 100644 --- a/tests/test_doxygen_output.py +++ b/tests/test_doxygen_output.py @@ -4,29 +4,46 @@ DOC_FILES = glob.glob("doc/html/*.htm*") + class TestDoxygenOutput(unittest.TestCase): - """ Test class for the doxygen output. """ + """Test class for the doxygen output.""" def test_hash(self): - ''' Test case is checking if there are illegal hash chars in the documentation. -> doxygen link not found. ''' + """Test case is checking if there are illegal hash chars in the documentation. -> doxygen link not found.""" for file in DOC_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - self.assertNotRegex(line, r"([\s>]|^)#\w(\S)*", file + " in line " + str(i) + ": not permitted hash found.") - + self.assertNotRegex( + line, + r"([\s>]|^)#\w(\S)*", + file + " in line " + str(i) + ": not permitted hash found.", + ) def test_slash_triplet(self): - ''' Test case is checking if there are slash triplets in the documentation. -> doxygen didn't interpret something properly. ''' + """Test case is checking if there are slash triplets in the documentation. -> doxygen didn't interpret something properly.""" for file in DOC_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - self.assertNotRegex(line, r"([\s>]|^)///\s*", file + " in line " + str(i) + ": not permitted slash triplet found.") - + self.assertNotRegex( + line, + r"([\s>]|^)///\s*", + file + + " in line " + + str(i) + + ": not permitted slash triplet found.", + ) def test_backslash_triplet(self): - ''' Test case is checking if there are backslash triplets in the documentation. -> doxygen didn't interpret something properly. ''' + """Test case is checking if there are backslash triplets in the documentation. -> doxygen didn't interpret something properly.""" for file in DOC_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - self.assertNotRegex(line, r"([\s>]|^)\\\\\\\s*", file + " in line " + str(i) + ": not permitted backslash triplet found.") + self.assertNotRegex( + line, + r"([\s>]|^)\\\\\\\s*", + file + + " in line " + + str(i) + + ": not permitted backslash triplet found.", + ) diff --git a/tests/test_invalid_comment.py b/tests/test_invalid_comment.py index 59c0f7163..39636e04b 100644 --- a/tests/test_invalid_comment.py +++ b/tests/test_invalid_comment.py @@ -3,20 +3,33 @@ PROTO_FILES = glob.glob("*.proto") + class TestInvalidCommentType(unittest.TestCase): """Test class for invalid comment types""" def test_triple_slash(self): - ''' Test to check if more than two forward slash('/') are present in comment section of proto file. ''' + """Test to check if more than two forward slash('/') are present in comment section of proto file.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - self.assertEqual(line.find("///"), -1, file + " in line " + str(i) + ": not permitted use of '///' ") + self.assertEqual( + line.find("///"), + -1, + file + " in line " + str(i) + ": not permitted use of '///' ", + ) def test_comments_invalid_syntax(self): - ''' Test to check if comments are given using invalid syntax '/*' or '*/' ''' + """Test to check if comments are given using invalid syntax '/*' or '*/'""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - self.assertEqual(line.find("/*"), -1, file + " in line " + str(i) + ": not permitted use of '/*' ") - self.assertEqual(line.find("*/"), -1, file + " in line " + str(i) + ": not permitted use of '*/' ") \ No newline at end of file + self.assertEqual( + line.find("/*"), + -1, + file + " in line " + str(i) + ": not permitted use of '/*' ", + ) + self.assertEqual( + line.find("*/"), + -1, + file + " in line " + str(i) + ": not permitted use of '*/' ", + ) diff --git a/tests/test_invalid_enum.py b/tests/test_invalid_enum.py index 0ecee0b40..01d9ff9e9 100644 --- a/tests/test_invalid_enum.py +++ b/tests/test_invalid_enum.py @@ -4,11 +4,12 @@ PROTO_FILES = glob.glob("*.proto") + class TestInvalidEnum(unittest.TestCase): - ''' Test class to check invalid enum ''' + """Test class to check invalid enum""" def test_correct_enum_name(self): - ''' Test if enum name is correct. ''' + """Test if enum name is correct.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): isEnum = False @@ -22,8 +23,8 @@ def test_correct_enum_name(self): matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -42,8 +43,8 @@ def test_correct_enum_name(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] # This section will check PascalCase for enums and check enum name? @@ -51,26 +52,53 @@ def test_correct_enum_name(self): matchName = re.search(r"\b\w[\S:]+\b", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end()] + checkName = statement[matchName.start() : matchName.end()] # Test to check correct ENUM name. - self.assertEqual(checkName.find(enumName), 0, file + " in line " + str(i) + ": enum type wrong. '" + checkName + "' should start with '" + enumName + "'") + self.assertEqual( + checkName.find(enumName), + 0, + file + + " in line " + + str(i) + + ": enum type wrong. '" + + checkName + + "' should start with '" + + enumName + + "'", + ) # Test to check ENUM type is in captial letters/upper case. - self.assertEqual(checkName, checkName.upper(), file + " in line " + str(i) + ": enum type wrong. '" + checkName + "' should use upper case") - + self.assertEqual( + checkName, + checkName.upper(), + file + + " in line " + + str(i) + + ": enum type wrong. '" + + checkName + + "' should use upper case", + ) # Search for "enum". matchEnum = re.search(r"\benum\b", statement) if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: - # Test to ensure no special characters are in ENUM name. - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b", endOfLine[matchName.start():matchName.end()]) - enumName = self.convert(endOfLine[matchName.start():matchName.end()]) + "_" + # Test to ensure no special characters are in ENUM name. + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + enumName = ( + self.convert( + endOfLine[matchName.start() : matchName.end()] + ) + + "_" + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -78,9 +106,8 @@ def test_correct_enum_name(self): isEnum = False enumName = "" - def test_invalid_enum(self): - ''' Test invalid enum definition. ''' + """Test invalid enum definition.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): isEnum = False @@ -94,8 +121,8 @@ def test_invalid_enum(self): matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -114,8 +141,8 @@ def test_invalid_enum(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] # This section will check PascalCase for enums and check enum name? @@ -123,20 +150,36 @@ def test_invalid_enum(self): matchName = re.search(r"\b\w[\S:]+\b", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end()] + checkName = statement[matchName.start() : matchName.end()] # Search for "enum". matchEnum = re.search(r"\benum\b", statement) if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: # Test to ensure no special characters are in ENUM name. - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b", endOfLine[matchName.start():matchName.end()]) - self.assertIsNotNone(matchNameConv, file + " in line " + str(i) + ": enum name wrong. '" + endOfLine[matchName.start():matchName.end()] + "'") - enumName = self.convert(endOfLine[matchName.start():matchName.end()]) + "_" + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + self.assertIsNotNone( + matchNameConv, + file + + " in line " + + str(i) + + ": enum name wrong. '" + + endOfLine[matchName.start() : matchName.end()] + + "'", + ) + enumName = ( + self.convert( + endOfLine[matchName.start() : matchName.end()] + ) + + "_" + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -145,5 +188,5 @@ def test_invalid_enum(self): enumName = "" def convert(self, name): - s1 = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', name) - return re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s1).upper() \ No newline at end of file + s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name) + return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1).upper() diff --git a/tests/test_invalid_html.py b/tests/test_invalid_html.py index 776b0b5a3..037ccd9bb 100644 --- a/tests/test_invalid_html.py +++ b/tests/test_invalid_html.py @@ -4,11 +4,12 @@ PROTO_FILES = glob.glob("*.proto") + class TestInvalidHtml(unittest.TestCase): - """ Test class for invalid html comment. """ + """Test class for invalid html comment.""" def test_invalid_slash(self): - ''' Test case to check invalid slash in htmlonly sections ''' + """Test case to check invalid slash in htmlonly sections""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): htmlblock = False @@ -18,8 +19,8 @@ def test_invalid_slash(self): # Search for comment ("//"). matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -38,8 +39,8 @@ def test_invalid_slash(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] # Test case is checking comment and html tags if matchComment is not None: @@ -48,9 +49,8 @@ def test_invalid_slash(self): if htmlblock is False: matchHTMLOnly = re.search(r"\\htmlonly", comment) if matchHTMLOnly is not None: - - htmlComment = comment[matchHTMLOnly.end():] - htmlFreeComment = comment[:matchHTMLOnly.start()] + htmlComment = comment[matchHTMLOnly.end() :] + htmlFreeComment = comment[: matchHTMLOnly.start()] htmlblock = True else: htmlComment = comment @@ -59,16 +59,27 @@ def test_invalid_slash(self): if htmlblock is True: matchEndHTMLOnly = re.search(r"\\endhtmlonly", htmlComment) if matchEndHTMLOnly is not None: - htmlFreeComment = htmlFreeComment + htmlComment[matchEndHTMLOnly.end():] - htmlComment = htmlComment[:matchEndHTMLOnly.start()] + htmlFreeComment = ( + htmlFreeComment + + htmlComment[matchEndHTMLOnly.end() :] + ) + htmlComment = htmlComment[: matchEndHTMLOnly.start()] htmlblock = False # Test case to check html tags only in htmlonly sections - self.assertEqual(htmlComment.find("\\"), -1, file + " in line " + str(i) + ": doxygen comment \\.. reference found: '" + htmlComment + "'") - + self.assertEqual( + htmlComment.find("\\"), + -1, + file + + " in line " + + str(i) + + ": doxygen comment \\.. reference found: '" + + htmlComment + + "'", + ) def test_invalid_hash(self): - ''' Test case to check invalid # in htmlonly sections ''' + """Test case to check invalid # in htmlonly sections""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): htmlblock = False @@ -78,8 +89,8 @@ def test_invalid_hash(self): # Search for comment ("//"). matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -98,8 +109,8 @@ def test_invalid_hash(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] # Test case is checking comment and html tags if matchComment is not None: @@ -108,9 +119,8 @@ def test_invalid_hash(self): if htmlblock is False: matchHTMLOnly = re.search(r"\\htmlonly", comment) if matchHTMLOnly is not None: - - htmlComment = comment[matchHTMLOnly.end():] - htmlFreeComment = comment[:matchHTMLOnly.start()] + htmlComment = comment[matchHTMLOnly.end() :] + htmlFreeComment = comment[: matchHTMLOnly.start()] htmlblock = True else: htmlComment = comment @@ -119,15 +129,26 @@ def test_invalid_hash(self): if htmlblock is True: matchEndHTMLOnly = re.search(r"\\endhtmlonly", htmlComment) if matchEndHTMLOnly is not None: - htmlFreeComment = htmlFreeComment + htmlComment[matchEndHTMLOnly.end():] - htmlComment = htmlComment[:matchEndHTMLOnly.start()] + htmlFreeComment = ( + htmlFreeComment + + htmlComment[matchEndHTMLOnly.end() :] + ) + htmlComment = htmlComment[: matchEndHTMLOnly.start()] htmlblock = False - self.assertEqual(htmlComment.find("#"), -1, file + " in line " + str(i) + ": doxygen comment #.. reference found: '" + htmlComment + "'") - + self.assertEqual( + htmlComment.find("#"), + -1, + file + + " in line " + + str(i) + + ": doxygen comment #.. reference found: '" + + htmlComment + + "'", + ) def test_invalid_at(self): - ''' Test case to check invalid @ in comments ''' + """Test case to check invalid @ in comments""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): htmlblock = False @@ -137,8 +158,8 @@ def test_invalid_at(self): # Search for comment ("//"). matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -157,8 +178,8 @@ def test_invalid_at(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] # Test case is checking comment and html tags if matchComment is not None: @@ -167,9 +188,8 @@ def test_invalid_at(self): if htmlblock is False: matchHTMLOnly = re.search(r"\\htmlonly", comment) if matchHTMLOnly is not None: - - htmlComment = comment[matchHTMLOnly.end():] - htmlFreeComment = comment[:matchHTMLOnly.start()] + htmlComment = comment[matchHTMLOnly.end() :] + htmlFreeComment = comment[: matchHTMLOnly.start()] htmlblock = True else: htmlComment = comment @@ -178,14 +198,26 @@ def test_invalid_at(self): if htmlblock is True: matchEndHTMLOnly = re.search(r"\\endhtmlonly", htmlComment) if matchEndHTMLOnly is not None: - htmlFreeComment = htmlFreeComment + htmlComment[matchEndHTMLOnly.end():] - htmlComment = htmlComment[:matchEndHTMLOnly.start()] + htmlFreeComment = ( + htmlFreeComment + + htmlComment[matchEndHTMLOnly.end() :] + ) + htmlComment = htmlComment[: matchEndHTMLOnly.start()] htmlblock = False - self.assertEqual(comment.find("@"), -1, file + " in line " + str(i) + ": @ tag found (please replace with \\): '" + htmlFreeComment + "'") + self.assertEqual( + comment.find("@"), + -1, + file + + " in line " + + str(i) + + ": @ tag found (please replace with \\): '" + + htmlFreeComment + + "'", + ) def test_no_endhtmlonly(self): - ''' Test case to check no \endhtmlonly in comments ''' + """Test case to check no \endhtmlonly in comments""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): htmlblock = False @@ -195,8 +227,8 @@ def test_no_endhtmlonly(self): # Search for comment ("//"). matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -215,8 +247,8 @@ def test_no_endhtmlonly(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] # Test case is checking comment and html tags if matchComment is not None: @@ -225,9 +257,8 @@ def test_no_endhtmlonly(self): if htmlblock is False: matchHTMLOnly = re.search(r"\\htmlonly", comment) if matchHTMLOnly is not None: - - htmlComment = comment[matchHTMLOnly.end():] - htmlFreeComment = comment[:matchHTMLOnly.start()] + htmlComment = comment[matchHTMLOnly.end() :] + htmlFreeComment = comment[: matchHTMLOnly.start()] htmlblock = True else: htmlComment = comment @@ -237,10 +268,19 @@ def test_no_endhtmlonly(self): matchEndHTMLOnly = re.search(r"\\endhtmlonly", htmlComment) if matchEndHTMLOnly is not None: - htmlFreeComment = htmlFreeComment + htmlComment[matchEndHTMLOnly.end():] - htmlComment = htmlComment[:matchEndHTMLOnly.start()] + htmlFreeComment = ( + htmlFreeComment + + htmlComment[matchEndHTMLOnly.end() :] + ) + htmlComment = htmlComment[: matchEndHTMLOnly.start()] htmlblock = False elif htmlblock: - self.assertFalse(htmlblock, file + " in line " + str(i - 1) + ": doxygen comment html section without endhtmlonly") + self.assertFalse( + htmlblock, + file + + " in line " + + str(i - 1) + + ": doxygen comment html section without endhtmlonly", + ) htmlblock = False diff --git a/tests/test_invalid_message.py b/tests/test_invalid_message.py index 8d2f8eaf5..04eafc8a4 100644 --- a/tests/test_invalid_message.py +++ b/tests/test_invalid_message.py @@ -4,11 +4,12 @@ PROTO_FILES = glob.glob("*.proto") + class TestInvalidMessage(unittest.TestCase): - """ Test class for invalid html comment. """ + """Test class for invalid html comment.""" def test_message_name(self): - ''' Test to check if message name have any special character. It should not have any special character. ''' + """Test to check if message name have any special character. It should not have any special character.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): @@ -26,8 +27,8 @@ def test_message_name(self): matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -46,8 +47,8 @@ def test_message_name(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] if isEnum is False: # Check if not inside an enum. @@ -57,25 +58,44 @@ def test_message_name(self): if matchMessage is not None: # a new message or a new nested message noMessage += 1 - endOfLine = statement[matchMessage.end():] + endOfLine = statement[matchMessage.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: # Test to check if message name have any special character. It should not have any special character. # Message should always start with special character. - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b",endOfLine[matchName.start():matchName.end()]) - self.assertIsNotNone(matchNameConv, file + " in line " + str(i - 1) + ": message name wrong. '" + endOfLine[matchName.start():matchName.end()] + "'") + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + self.assertIsNotNone( + matchNameConv, + file + + " in line " + + str(i - 1) + + ": message name wrong. '" + + endOfLine[matchName.start() : matchName.end()] + + "'", + ) # Search for "enum". matchEnum = re.search(r"\benum\b", statement) if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: # Test to check presence of invalid special characters - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b", endOfLine[matchName.start():matchName.end()]) - enumName = self.convert(endOfLine[matchName.start():matchName.end()]) + "_" + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + enumName = ( + self.convert( + endOfLine[matchName.start() : matchName.end()] + ) + + "_" + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -83,9 +103,8 @@ def test_message_name(self): isEnum = False enumName = "" - def test_field_name(self): - ''' Test to check if field names are in lower case. ''' + """Test to check if field names are in lower case.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): @@ -104,8 +123,8 @@ def test_field_name(self): matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -124,8 +143,8 @@ def test_field_name(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] if isEnum is False: # Check if not inside an enum. @@ -135,10 +154,13 @@ def test_field_name(self): if matchMessage is not None: # a new message or a new nested message noMessage += 1 - endOfLine = statement[matchMessage.end():] + endOfLine = statement[matchMessage.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b",endOfLine[matchName.start():matchName.end()]) + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) elif re.search(r"\bextend\b", statement) is not None: # treat extend as message @@ -149,15 +171,35 @@ def test_field_name(self): matchName = re.search(r"\b\w[\S]*\b\s*=", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end() - 1] - self.assertEqual(checkName, checkName.lower(), file + " in line " + str(i) + ": field name wrong. '" + checkName + "' should use lower case") + checkName = statement[ + matchName.start() : matchName.end() - 1 + ] + self.assertEqual( + checkName, + checkName.lower(), + file + + " in line " + + str(i) + + ": field name wrong. '" + + checkName + + "' should use lower case", + ) type = statement.replace(checkName, "") matchName = re.search(r"\b\w[\S\.]*\s*=", type) if matchName is not None: - checkType = " " + type[matchName.start():matchName.end() - 1] + " " + checkType = ( + " " + + type[ + matchName.start() : matchName.end() - 1 + ] + + " " + ) # Test to check nested message type - matchNameConv = re.search(r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]",checkType) + matchNameConv = re.search( + r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]", + checkType, + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -169,12 +211,20 @@ def test_field_name(self): if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: # Test to check presence of invalid special characters - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b", endOfLine[matchName.start():matchName.end()]) - enumName = self.convert(endOfLine[matchName.start():matchName.end()]) + "_" + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + enumName = ( + self.convert( + endOfLine[matchName.start() : matchName.end()] + ) + + "_" + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -183,7 +233,7 @@ def test_field_name(self): enumName = "" def test_field_type(self): - ''' Test to check nested message type. ''' + """Test to check nested message type.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): @@ -202,8 +252,8 @@ def test_field_type(self): matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -222,8 +272,8 @@ def test_field_type(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] if isEnum is False: # Check if not inside an enum. @@ -233,10 +283,13 @@ def test_field_type(self): if matchMessage is not None: # a new message or a new nested message noMessage += 1 - endOfLine = statement[matchMessage.end():] + endOfLine = statement[matchMessage.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b",endOfLine[matchName.start():matchName.end()]) + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) elif re.search(r"\bextend\b", statement) is not None: # treat extend as message @@ -246,18 +299,37 @@ def test_field_type(self): if noMessage > 0: matchName = re.search(r"\b\w[\S]*\b\s*=", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end() - 1] + checkName = statement[ + matchName.start() : matchName.end() - 1 + ] # Check field message type (remove field name) type = statement.replace(checkName, "") matchName = re.search(r"\b\w[\S\.]*\s*=", type) if matchName is not None: - checkType = " " + type[matchName.start():matchName.end() - 1] + " " + checkType = ( + " " + + type[ + matchName.start() : matchName.end() - 1 + ] + + " " + ) # Test to check nested message type - matchNameConv = re.search(r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]", checkType) + matchNameConv = re.search( + r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]", + checkType, + ) checkType = checkType.strip() - self.assertIsNotNone(matchNameConv, file + " in line " + str(i) + ": field message type wrong. Check: '" + checkType + "'") + self.assertIsNotNone( + matchNameConv, + file + + " in line " + + str(i) + + ": field message type wrong. Check: '" + + checkType + + "'", + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -269,12 +341,20 @@ def test_field_type(self): if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: # Test to check presence of invalid special characters - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b", endOfLine[matchName.start():matchName.end()]) - enumName = self.convert(endOfLine[matchName.start():matchName.end()]) + "_" + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + enumName = ( + self.convert( + endOfLine[matchName.start() : matchName.end()] + ) + + "_" + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -283,7 +363,7 @@ def test_field_type(self): enumName = "" def test_field_multiplicity(self): - ''' Test to check if every field has the multiplicity "repeated" or "optional". ''' + """Test to check if every field has the multiplicity "repeated" or "optional".""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): @@ -294,7 +374,6 @@ def test_field_multiplicity(self): saveStatement = "" for line in fin: - # Skipping test on multiplicity for protobuf 3.0.0 if '"proto3"' in line: break @@ -307,8 +386,8 @@ def test_field_multiplicity(self): matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -327,8 +406,8 @@ def test_field_multiplicity(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] if isEnum is False: # Check if not inside an enum. @@ -338,10 +417,13 @@ def test_field_multiplicity(self): if matchMessage is not None: # a new message or a new nested message noMessage += 1 - endOfLine = statement[matchMessage.end():] + endOfLine = statement[matchMessage.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b",endOfLine[matchName.start():matchName.end()]) + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) elif re.search(r"\bextend\b", statement) is not None: # treat extend as message @@ -352,18 +434,38 @@ def test_field_multiplicity(self): if noMessage > 0: matchName = re.search(r"\b\w[\S]*\b\s*=", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end() - 1] + checkName = statement[ + matchName.start() : matchName.end() - 1 + ] # Check field message type (remove field name) type = statement.replace(checkName, "") matchName = re.search(r"\b\w[\S\.]*\s*=", type) if matchName is not None: - checkType = " " + type[matchName.start():matchName.end() - 1] + " " + checkType = ( + " " + + type[ + matchName.start() : matchName.end() - 1 + ] + + " " + ) # Test to check nested message type - matchNameConv = re.search(r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]",checkType) + matchNameConv = re.search( + r"[ ][a-zA-Z][a-zA-Z0-9]*([\.][A-Z][a-zA-Z0-9]*)*[ ]", + checkType, + ) statement = statement.strip() - self.assertIsNotNone(re.search(r"\boptional\b", type) is None and re.search(r"\brepeated\b",type), file + " in line " + str(i) + ": field multiplicity (\"optional\" or \"repeated\") is missing. Check: '" + statement + "'") + self.assertIsNotNone( + re.search(r"\boptional\b", type) is None + and re.search(r"\brepeated\b", type), + file + + " in line " + + str(i) + + ': field multiplicity ("optional" or "repeated") is missing. Check: \'' + + statement + + "'", + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -375,12 +477,20 @@ def test_field_multiplicity(self): if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: # Test to check presence of invalid special characters - matchNameConv = re.search(r"\b[A-Z][a-zA-Z0-9]*\b", endOfLine[matchName.start():matchName.end()]) - enumName = self.convert(endOfLine[matchName.start():matchName.end()]) + "_" + matchNameConv = re.search( + r"\b[A-Z][a-zA-Z0-9]*\b", + endOfLine[matchName.start() : matchName.end()], + ) + enumName = ( + self.convert( + endOfLine[matchName.start() : matchName.end()] + ) + + "_" + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -389,6 +499,5 @@ def test_field_multiplicity(self): enumName = "" def convert(self, name): - s1 = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', name) - return re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s1).upper() - + s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name) + return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1).upper() diff --git a/tests/test_invalid_punctuation.py b/tests/test_invalid_punctuation.py index 224411322..e658d624d 100644 --- a/tests/test_invalid_punctuation.py +++ b/tests/test_invalid_punctuation.py @@ -3,12 +3,17 @@ PROTO_FILES = glob.glob("*.proto") + class TestInvalidPunctuation(unittest.TestCase): - ''' Test class to check invalid punctuation character '__' ''' + """Test class to check invalid punctuation character '__'""" def test_invalid_punctuation(self): - ''' Test to check invalid punctuation character '__' ''' + """Test to check invalid punctuation character '__'""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - self.assertEqual(line.find("__"), -1, file + " in line " + str(i) + ": not permitted use of '__' ") + self.assertEqual( + line.find("__"), + -1, + file + " in line " + str(i) + ": not permitted use of '__' ", + ) diff --git a/tests/test_invalid_tabs.py b/tests/test_invalid_tabs.py index 4b55f58f8..f6c61853f 100644 --- a/tests/test_invalid_tabs.py +++ b/tests/test_invalid_tabs.py @@ -3,12 +3,17 @@ PROTO_FILES = glob.glob("*.proto") + class TestInvalidTabs(unittest.TestCase): """Test class for invalid tabulators""" def test_invalid_tabs(self): - ''' Test to check if invalid tabs exist. ''' + """Test to check if invalid tabs exist.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - self.assertEqual(line.find("\t"), -1, file + " in line " + str(i) + ": not permitted tab found") + self.assertEqual( + line.find("\t"), + -1, + file + " in line " + str(i) + ": not permitted tab found", + ) diff --git a/tests/test_newline.py b/tests/test_newline.py index 1260659f7..fbc0a30e1 100644 --- a/tests/test_newline.py +++ b/tests/test_newline.py @@ -3,12 +3,17 @@ PROTO_FILES = glob.glob("*.proto") + class TestNewLine(unittest.TestCase): - ''' Test class for mandatory new line. ''' + """Test class for mandatory new line.""" def test_newline(self): - ''' Test to check last line of file must end with a new line. ''' + """Test to check last line of file must end with a new line.""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): lastCharacter = fin.read()[-1] - self.assertEqual(lastCharacter, "\n", file + " has no new line at the end of the file.") + self.assertEqual( + lastCharacter, + "\n", + file + " has no new line at the end of the file.", + ) diff --git a/tests/test_non_ascii.py b/tests/test_non_ascii.py index ccfc76acb..db6656fd0 100644 --- a/tests/test_non_ascii.py +++ b/tests/test_non_ascii.py @@ -5,15 +5,34 @@ PROTO_FILES = glob.glob("*.proto") + class TestNonAscii(unittest.TestCase): """Class is checking if there is an "Umlaut" or any non ASCII characters are present.""" def test_non_ascii(self): - ''' Test if there are any non ASCII characters present like an "Umlaut". ''' + """Test if there are any non ASCII characters present like an "Umlaut".""" for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - if (sys.version_info >= (3, 0)): - self.assertEqual(line, unicodedata.normalize('NFKD', line).encode('ASCII', 'ignore').decode(), file + " in line " + str(i) + ": a none ASCII char is present") + if sys.version_info >= (3, 0): + self.assertEqual( + line, + unicodedata.normalize("NFKD", line) + .encode("ASCII", "ignore") + .decode(), + file + + " in line " + + str(i) + + ": a none ASCII char is present", + ) else: - self.assertEqual(line, unicodedata.normalize('NFKD', unicode(line, 'ISO-8859-1')).encode('ASCII', 'ignore'), file + " in line " + str(i) + ": a none ASCII char is present") \ No newline at end of file + self.assertEqual( + line, + unicodedata.normalize( + "NFKD", unicode(line, "ISO-8859-1") + ).encode("ASCII", "ignore"), + file + + " in line " + + str(i) + + ": a none ASCII char is present", + ) diff --git a/tests/test_rules.py b/tests/test_rules.py index d20c96e29..8f8dac7bd 100644 --- a/tests/test_rules.py +++ b/tests/test_rules.py @@ -5,15 +5,16 @@ PROTO_FILES = glob.glob("*.proto") + class TestRules(unittest.TestCase): - """ Test class for units documentation. """ + """Test class for units documentation.""" def test_rules_compliance(self): - ''' Test rule compliance syntax of proto files. ''' + """Test rule compliance syntax of proto files.""" - with open(r'rules.yml') as rules_file: + with open(r"rules.yml") as rules_file: RULES_DICT = yaml.load(rules_file, Loader=yaml.BaseLoader) - + for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): line_number = 0 @@ -30,8 +31,8 @@ def test_rules_compliance(self): # Search for comment ("//"). matchComment = re.search("//", line) if matchComment is not None: - statement = line[:matchComment.start()] - comment = line[matchComment.end():] + statement = line[: matchComment.start()] + comment = line[matchComment.end() :] else: statement = line comment = "" @@ -50,18 +51,22 @@ def test_rules_compliance(self): saveStatement = statement statement = "" else: - saveStatement = statement[matchSep.end():] - statement = statement[:matchSep.end()] + saveStatement = statement[matchSep.end() :] + statement = statement[: matchSep.end()] # Search for "message". matchMessage = re.search(r"\bmessage\b", statement) if matchMessage is not None: # a new message or a new nested message numMessage += 1 - self.assertFalse(foundruleCount > 0 or lineruleCount > 0, file + f" in line {str(line_number-1)}: message should not have rules for '{statement.strip()}'") - endOfLine = statement[matchMessage.end():] + self.assertFalse( + foundruleCount > 0 or lineruleCount > 0, + file + + f" in line {str(line_number-1)}: message should not have rules for '{statement.strip()}'", + ) + endOfLine = statement[matchMessage.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) - + elif re.search(r"\bextend\b", statement) is not None: # treat extend as message numMessage += 1 @@ -70,7 +75,9 @@ def test_rules_compliance(self): if numMessage > 0: matchName = re.search(r"\b\w[\S]*\b\s*=", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end()-1] + checkName = statement[ + matchName.start() : matchName.end() - 1 + ] # Check field message type (remove field name) type = statement.replace(checkName, "") matchName = re.search(r"\b\w[\S\.]*\s*=", type) @@ -78,17 +85,25 @@ def test_rules_compliance(self): if isEnum: matchName = re.search(r"\b\w[\S:]+\b", statement) if matchName is not None: - checkName = statement[matchName.start():matchName.end()] - self.assertFalse(foundruleCount > 0 or lineruleCount > 0, file + f" in line {str(line_number-1)}: enum field should not have rules for '{statement.strip()}'") + checkName = statement[matchName.start() : matchName.end()] + self.assertFalse( + foundruleCount > 0 or lineruleCount > 0, + file + + f" in line {str(line_number-1)}: enum field should not have rules for '{statement.strip()}'", + ) # Search for "enum". matchEnum = re.search(r"\benum\b", statement) if matchEnum is not None: isEnum = True - endOfLine = statement[matchEnum.end():] + endOfLine = statement[matchEnum.end() :] matchName = re.search(r"\b\w[\S]*\b", endOfLine) if matchName is not None: - self.assertFalse(foundruleCount > 0 or lineruleCount > 0, file + f" in line {str(line_number-1)}: enum should not have rules for '{statement.strip()}'") + self.assertFalse( + foundruleCount > 0 or lineruleCount > 0, + file + + f" in line {str(line_number-1)}: enum should not have rules for '{statement.strip()}'", + ) # Search for a closing brace. matchClosingBrace = re.search("}", statement) @@ -106,7 +121,7 @@ def test_rules_compliance(self): lineruleCount = 0 foundruleCount = 0 - if not endRule and comment != '': + if not endRule and comment != "": for rulename, ruleregex in RULES_DICT.items(): if re.search(ruleregex, comment): foundruleCount += 1 @@ -115,10 +130,49 @@ def test_rules_compliance(self): if numMessage > 0: if statement.find(";") != -1: statement = statement.strip() - self.assertFalse(hasRule and lineruleCount != foundruleCount and endRule and lineruleCount-foundruleCount-1>0, file + " in line " + str(line_number) + ": "+str(lineruleCount-foundruleCount-1)+" defined rule(s) does not exists for: '"+statement+"'") - self.assertFalse(hasRule and not endRule, file + " in line " + str(line_number) + ": \\endrules statement does not exists for: '"+statement+"'. Check spacing and rule syntax.") - self.assertFalse(not hasRule and endRule, file + " in line " + str(line_number) + ": \\rules statement does not exists for: '"+statement+"'. Check spacing and rule syntax.") - self.assertFalse(not hasRule and not endRule and lineruleCount < foundruleCount, file + " in line " + str(line_number) + ": rules found but no statements (\\rules and \\endrules) around it for: '"+statement+"'") + self.assertFalse( + hasRule + and lineruleCount != foundruleCount + and endRule + and lineruleCount - foundruleCount - 1 > 0, + file + + " in line " + + str(line_number) + + ": " + + str(lineruleCount - foundruleCount - 1) + + " defined rule(s) does not exists for: '" + + statement + + "'", + ) + self.assertFalse( + hasRule and not endRule, + file + + " in line " + + str(line_number) + + ": \\endrules statement does not exists for: '" + + statement + + "'. Check spacing and rule syntax.", + ) + self.assertFalse( + not hasRule and endRule, + file + + " in line " + + str(line_number) + + ": \\rules statement does not exists for: '" + + statement + + "'. Check spacing and rule syntax.", + ) + self.assertFalse( + not hasRule + and not endRule + and lineruleCount < foundruleCount, + file + + " in line " + + str(line_number) + + ": rules found but no statements (\\rules and \\endrules) around it for: '" + + statement + + "'", + ) lineruleCount = 0 foundruleCount = 0 @@ -128,5 +182,6 @@ def test_rules_compliance(self): if hasRule and not endRule or not hasRule and endRule: lineruleCount += 1 -if __name__ == '__main__': + +if __name__ == "__main__": unittest.main() diff --git a/tests/test_units.py b/tests/test_units.py index 2bcd4ac9d..dea7ce784 100644 --- a/tests/test_units.py +++ b/tests/test_units.py @@ -4,25 +4,54 @@ PROTO_FILES = glob.glob("*.proto") + class TestUnits(unittest.TestCase): - """ Test class for units documentation. """ + """Test class for units documentation.""" def test_no_brackets(self): - ''' Test to check if units have the right syntax. ''' + """Test to check if units have the right syntax.""" + + NOT_VALID_BRACKETS = [r"\(", r"\)", r"\[", r"\]", r"\{", r"\}"] - NOT_VALID_BRACKETS = [r'\(', r'\)', r'\[', r'\]', r'\{', r'\}'] - for file in PROTO_FILES: with open(file, "rt") as fin, self.subTest(file=file): for i, line in enumerate(fin, start=1): - found = re.search('Unit:', line, re.IGNORECASE) + found = re.search("Unit:", line, re.IGNORECASE) if found: comment_list = line.split() - self.assertEqual(comment_list[0], '//', file + " in line " + str(i) + ": Unit must be on a separate line or have a space between //. (Example: '// Unit: m')") - self.assertEqual(comment_list[1], 'Unit:', file + " in line " + str(i) + f": '{comment_list[1]}' do not match 'Unit:'. (Example: '// Unit: m')") - self.assertGreaterEqual(len(comment_list), 3, file + " in line " + str(i) + ": No unit defined. (Example: '// Unit: m')") - + self.assertEqual( + comment_list[0], + "//", + file + + " in line " + + str(i) + + ": Unit must be on a separate line or have a space between //. (Example: '// Unit: m')", + ) + self.assertEqual( + comment_list[1], + "Unit:", + file + + " in line " + + str(i) + + f": '{comment_list[1]}' do not match 'Unit:'. (Example: '// Unit: m')", + ) + self.assertGreaterEqual( + len(comment_list), + 3, + file + + " in line " + + str(i) + + ": No unit defined. (Example: '// Unit: m')", + ) + for unit in comment_list: for brackets in NOT_VALID_BRACKETS: - self.assertNotRegex(unit, brackets, file + " in line " + str(i) + ": Invalid brackets around units.") + self.assertNotRegex( + unit, + brackets, + file + + " in line " + + str(i) + + ": Invalid brackets around units.", + )