diff --git a/python/selfie-lib/selfie_lib/SourceFile.py b/python/selfie-lib/selfie_lib/SourceFile.py index 208cb2bd..6ab05fc9 100644 --- a/python/selfie-lib/selfie_lib/SourceFile.py +++ b/python/selfie-lib/selfie_lib/SourceFile.py @@ -12,7 +12,7 @@ def __init__(self, filename: str, content: str) -> None: self.__content_slice: Slice = Slice(content.replace("\r\n", "\n")) self.__language: Language = Language.from_filename(filename) self.__escape_leading_whitespace = EscapeLeadingWhitespace.appropriate_for( - self.content_slice.__str__() + self.__content_slice.__str__() ) @property @@ -38,6 +38,12 @@ def __init__( self.__language = language self.__escape_leading_whitespace = escape_leading_whitespace + def _get_function_call_plus_arg(self): + return self.__function_call_plus_arg + + def _get_arg(self): + return self.__arg + def set_literal_and_get_newline_delta(self, literal_value: LiteralValue) -> int: encoded = literal_value.format.encode( literal_value.actual, self.__language, self.__escape_leading_whitespace @@ -57,7 +63,7 @@ def set_literal_and_get_newline_delta(self, literal_value: LiteralValue) -> int: ) existing_newlines = self.__function_call_plus_arg.count("\n") new_newlines = encoded.count("\n") - self.content_slice = self.__function_call_plus_arg.replaceSelfWith( + self.__content_slice = self.__function_call_plus_arg.replaceSelfWith( f"{self.__dot_fun_open_paren}{encoded})" ) return new_newlines - existing_newlines @@ -66,7 +72,7 @@ def parse_literal(self, literal_format: LiteralFormat) -> Any: return literal_format.parse(self.__arg.__str__(), self.__language) def find_on_line(self, to_find: str, line_one_indexed: int) -> Slice: - line_content = self.content_slice.unixLine(line_one_indexed) + line_content = self.__content_slice.unixLine(line_one_indexed) idx = line_content.indexOf(to_find) if idx == -1: raise AssertionError( @@ -80,12 +86,12 @@ def find_on_line(self, to_find: str, line_one_indexed: int) -> Slice: def replace_on_line(self, line_one_indexed: int, find: str, replace: str) -> None: assert "\n" not in find assert "\n" not in replace - line_content = self.content_slice.unixLine(line_one_indexed).__str__() + line_content = self.__content_slice.unixLine(line_one_indexed).__str__() new_content = line_content.replace(find, replace) - self.content_slice = Slice(self.content_slice.replaceSelfWith(new_content)) + self.__content_slice = Slice(self.__content_slice.replaceSelfWith(new_content)) def parse_to_be_like(self, line_one_indexed: int) -> ToBeLiteral: - line_content = self.content_slice.unixLine(line_one_indexed) + line_content = self.__content_slice.unixLine(line_one_indexed) dot_fun_open_paren = None for to_be_like in TO_BE_LIKES: @@ -102,14 +108,14 @@ def parse_to_be_like(self, line_one_indexed: int) -> ToBeLiteral: dot_function_call = dot_function_call_in_place + line_content.startIndex arg_start = dot_function_call + len(dot_fun_open_paren) - if self.content_slice.__len__() == arg_start: + if self.__content_slice.__len__() == arg_start: raise AssertionError( f"Appears to be an unclosed function call `{dot_fun_open_paren}` " f"on line {line_one_indexed}" ) - while self.content_slice[arg_start].isspace(): + while self.__content_slice[arg_start].isspace(): arg_start += 1 - if self.content_slice.__len__() == arg_start: + if self.__content_slice.__len__() == arg_start: raise AssertionError( f"Appears to be an unclosed function call `{dot_fun_open_paren}` " f"on line {line_one_indexed}" @@ -117,9 +123,9 @@ def parse_to_be_like(self, line_one_indexed: int) -> ToBeLiteral: end_arg = -1 end_paren = 0 - if self.content_slice[arg_start] == '"': - if self.content_slice[arg_start].startswith(self.TRIPLE_QUOTE): - end_arg = self.content_slice.indexOf( + if self.__content_slice[arg_start] == '"': + if self.__content_slice[arg_start].startswith(self.TRIPLE_QUOTE): + end_arg = self.__content_slice.indexOf( self.TRIPLE_QUOTE, arg_start + len(self.TRIPLE_QUOTE) ) if end_arg == -1: @@ -133,11 +139,11 @@ def parse_to_be_like(self, line_one_indexed: int) -> ToBeLiteral: else: end_arg = arg_start + 1 while ( - self.content_slice[end_arg] != '"' - or self.content_slice[end_arg - 1] == "\\" + self.__content_slice[end_arg] != '"' + or self.__content_slice[end_arg - 1] == "\\" ): end_arg += 1 - if end_arg == self.content_slice.__len__(): + if end_arg == self.__content_slice.__len__(): raise AssertionError( f'Appears to be an unclosed string literal `"` ' f"on line {line_one_indexed}" @@ -146,34 +152,34 @@ def parse_to_be_like(self, line_one_indexed: int) -> ToBeLiteral: end_paren = end_arg else: end_arg = arg_start - while not self.content_slice[end_arg].isspace(): - if self.content_slice[end_arg] == ")": + while not self.__content_slice[end_arg].isspace(): + if self.__content_slice[end_arg] == ")": break end_arg += 1 - if end_arg == self.content_slice.__len__(): + if end_arg == self.__content_slice.__len__(): raise AssertionError( f"Appears to be an unclosed numeric literal " f"on line {line_one_indexed}" ) end_paren = end_arg - while self.content_slice[end_paren] != ")": - if not self.content_slice[end_paren].isspace(): + while self.__content_slice[end_paren] != ")": + if not self.__content_slice[end_paren].isspace(): raise AssertionError( f"Non-primitive literal in `{dot_fun_open_paren}` starting at " f"line {line_one_indexed}: error for character " - f"`{self.content_slice[end_paren]}` on line " - f"{self.content_slice.baseLineAtOffset(end_paren)}" + f"`{self.__content_slice[end_paren]}` on line " + f"{self.__content_slice.baseLineAtOffset(end_paren)}" ) end_paren += 1 - if end_paren == self.content_slice.__len__(): + if end_paren == self.__content_slice.__len__(): raise AssertionError( f"Appears to be an unclosed function call `{dot_fun_open_paren}` " f"starting at line {line_one_indexed}" ) return self.ToBeLiteral( dot_fun_open_paren.replace("_TODO", ""), - self.content_slice.subSequence(dot_function_call, end_paren + 1), - self.content_slice.subSequence(arg_start, end_arg), + self.__content_slice.subSequence(dot_function_call, end_paren + 1), + self.__content_slice.subSequence(arg_start, end_arg), self.__language, self.__escape_leading_whitespace, ) diff --git a/python/selfie-lib/tests/SourceFile_test.py b/python/selfie-lib/tests/SourceFile_test.py index 23db7a5d..221f2718 100644 --- a/python/selfie-lib/tests/SourceFile_test.py +++ b/python/selfie-lib/tests/SourceFile_test.py @@ -1,175 +1,90 @@ from selfie_lib import SourceFile -def test_todo(): - source_file = SourceFile("UnderTest.py", ".toBe_TODO()") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe_TODO()" - assert str(source_file.parse_to_be_like(1).arg) == "" - - source_file = SourceFile("UnderTest.py", " .toBe_TODO() ") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe_TODO()" - assert str(source_file.parse_to_be_like(1).arg) == "" - - source_file = SourceFile("UnderTest.py", " .toBe_TODO( ) ") - assert ( - str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe_TODO( )" - ) - assert str(source_file.parse_to_be_like(1).arg) == "" - - source_file = SourceFile("UnderTest.py", " .toBe_TODO( \n ) ") - assert ( - str(source_file.parse_to_be_like(1).function_call_plus_arg) - == ".toBe_TODO( \n )" - ) - assert str(source_file.parse_to_be_like(1).arg) == "" - - -def test_numeric(): - source_file = SourceFile("UnderTest.py", ".toBe(7)") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe(7)" - assert str(source_file.parse_to_be_like(1).arg) == "7" - - source_file = SourceFile("UnderTest.py", " .toBe(7)") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe(7)" - assert str(source_file.parse_to_be_like(1).arg) == "7" - - source_file = SourceFile("UnderTest.py", ".toBe(7) ") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe(7)" - assert str(source_file.parse_to_be_like(1).arg) == "7" +def python_test(source_raw, function_call_plus_arg_raw, arg_raw=""): + source = source_raw.replace("'", '"') + function_call_plus_arg = function_call_plus_arg_raw.replace("'", '"') + arg = arg_raw.replace("'", '"') + parsed = SourceFile("UnderTest.py", source) + to_be_literal = parsed.parse_to_be_like(1) + assert to_be_literal._get_function_call_plus_arg() == function_call_plus_arg + assert to_be_literal._get_arg() == arg - source_file = SourceFile("UnderTest.py", " .toBe(7) ") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe(7)" - assert str(source_file.parse_to_be_like(1).arg) == "7" - source_file = SourceFile("UnderTest.py", " .toBe( 7 ) ") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe( 7 )" - assert str(source_file.parse_to_be_like(1).arg) == "7" - - source_file = SourceFile("UnderTest.py", " .toBe(\n7) ") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe(\n7)" - assert str(source_file.parse_to_be_like(1).arg) == "7" +def python_test_error(source_raw, error_msg): + try: + python_test(source_raw, "unusedArg") + except AssertionError as e: + assert str(e) == error_msg - source_file = SourceFile("UnderTest.py", " .toBe(7\n) ") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe(7\n)" - assert str(source_file.parse_to_be_like(1).arg) == "7" +def todo(): + python_test(".toBe_TODO()", ".toBe_TODO()", "") + python_test(" .toBe_TODO() ", ".toBe_TODO()", "") + python_test(" .toBe_TODO( ) ", ".toBe_TODO( )", "") + python_test(" .toBe_TODO( \n ) ", ".toBe_TODO( \n )", "") -def test_single_line_string(): - source_file = SourceFile("UnderTest.py", ".toBe('7')") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe('7')" - assert str(source_file.parse_to_be_like(1).arg) == "'7'" - source_file = SourceFile("UnderTest.py", ".toBe('')") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe('')" - assert str(source_file.parse_to_be_like(1).arg) == "''" +def numeric(): + python_test(".toBe(7)", ".toBe(7)", "7") + python_test(" .toBe(7)", ".toBe(7)", "7") + python_test(".toBe(7) ", ".toBe(7)", "7") + python_test(" .toBe(7) ", ".toBe(7)", "7") + python_test(" .toBe( 7 ) ", ".toBe( 7 )", "7") + python_test(" .toBe(\n7) ", ".toBe(\n7)", "7") + python_test(" .toBe(7\n) ", ".toBe(7\n)", "7") - source_file = SourceFile("UnderTest.py", ".toBe( '' )") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe( '' )" - assert str(source_file.parse_to_be_like(1).arg) == "''" - source_file = SourceFile("UnderTest.py", ".toBe( \n '' \n )") - assert ( - str(source_file.parse_to_be_like(1).function_call_plus_arg) - == ".toBe( \n '' \n )" - ) - assert str(source_file.parse_to_be_like(1).arg) == "''" +def single_line_string(): + python_test(".toBe('7')", "'7'") + python_test(".toBe('')", "''") + python_test(".toBe( '' )", "''") + python_test(".toBe( \n '' \n )", "''") + python_test(".toBe( \n '78' \n )", "'78'") + python_test(".toBe('\\'')", "'\\''") - source_file = SourceFile("UnderTest.py", ".toBe( \n '78' \n )") - assert ( - str(source_file.parse_to_be_like(1).function_call_plus_arg) - == ".toBe( \n '78' \n )" - ) - assert str(source_file.parse_to_be_like(1).arg) == "'78'" - source_file = SourceFile("UnderTest.py", ".toBe('\\'')") - assert str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe('\\'')" - assert str(source_file.parse_to_be_like(1).arg) == "'\\''" +def multi_line_string(): + python_test(".toBe('''7''')", "'''7'''") + python_test(".toBe(''' 7 ''')", "''' 7 '''") + python_test(".toBe('''\n7\n''')", "'''\n7\n'''") + python_test(".toBe(''' ' '' ' ''')", "''' ' '' ' '''") -def test_multi_line_string(): - source_file = SourceFile("UnderTest.py", ".toBe('''7''')") - assert ( - str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe('''7''')" +def error_unclosed(): + python_test_error( + ".toBe(", "Appears to be an unclosed function call `.toBe()` on line 1" ) - assert str(source_file.parse_to_be_like(1).arg) == "'''7'''" - - source_file = SourceFile("UnderTest.py", ".toBe('''7''')") - assert ( - str(source_file.parse_to_be_like(1).function_call_plus_arg) == ".toBe('''7''')" + python_test_error( + ".toBe( \n ", "Appears to be an unclosed function call `.toBe()` on line 1" ) - assert str(source_file.parse_to_be_like(1).arg) == "'''7'''" - - # source_file = SourceFile("UnderTest.py", ".toBe('''\n7\n''')") - # assert ( - # str(source_file.parse_to_be_like(1).function_call_plus_arg) - # == ".toBe('''\n7\n''')" - # ) - # assert str(source_file.parse_to_be_like(1).arg) == "'''\n7\n'''" - - # source_file = SourceFile("UnderTest.py", ".toBe(''' ' '' ' ''')") - # assert ( - # str(source_file.parse_to_be_like(1).function_call_plus_arg) - # == ".toBe(''' ' '' ' ''')" - # ) - # assert str(source_file.parse_to_be_like(1).arg) == "''' ' '' ' '''" - - -def test_error_unclosed(): - source_file = SourceFile("UnderTest.py", ".toBe(") - assert_raises_error( - source_file, "Appears to be an unclosed function call `.toBe(` on line 1" + python_test_error( + ".toBe_TODO(", + "Appears to be an unclosed function call `.toBe_TODO()` on line 1", ) - - source_file = SourceFile("UnderTest.py", ".toBe( \n ") - assert_raises_error( - source_file, "Appears to be an unclosed function call `.toBe(` on line 1" + python_test_error( + ".toBe_TODO( \n ", + "Appears to be an unclosed function call `.toBe_TODO()` on line 1", ) - - source_file = SourceFile("UnderTest.py", ".toBe_TODO(") - assert_raises_error( - source_file, "Appears to be an unclosed function call `.toBe_TODO(` on line 1" + python_test_error( + ".toBe_TODO(')", 'Appears to be an unclosed string literal `"` on line 1' ) - - source_file = SourceFile("UnderTest.py", ".toBe_TODO( \n ") - assert_raises_error( - source_file, "Appears to be an unclosed function call `.toBe_TODO(` on line 1" + python_test_error( + ".toBe_TODO(''')", + 'Appears to be an unclosed multiline string literal `"""` on line 1', ) - # source_file = SourceFile("UnderTest.py", ".toBe_TODO(')") - # assert_raises_error( - # source_file, 'Appears to be an unclosed string literal `"` on line 1' - # ) - # source_file = SourceFile("UnderTest.py", ".toBe_TODO(''')") - # assert_raises_error( - # source_file, - # 'Appears to be an unclosed multiline string literal `"""` on line 1', - # ) - - -def test_error_non_primitive(): - source_file = SourceFile("UnderTest.py", ".toBe(1 + 1)") - assert_raises_error( - source_file, - "Non-primitive literal in `.toBe(` starting at line 1: error for character `+` on line 1", +def error_non_primitive(): + python_test_error( + ".toBe(1 + 1)", + "Non-primitive literal in `.toBe()` starting at line 1: error for character `+` on line 1", ) - - source_file = SourceFile("UnderTest.py", ".toBe('1' + '1')") - assert_raises_error( - source_file, - "Non-primitive literal in `.toBe(` starting at line 1: error for character `+` on line 1", + python_test_error( + ".toBe('1' + '1')", + "Non-primitive literal in `.toBe()` starting at line 1: error for character `+` on line 1", ) - - source_file = SourceFile("UnderTest.py", ".toBe('''1''' + '''1''')") - assert_raises_error( - source_file, - "Non-primitive literal in `.toBe(` starting at line 1: error for character `+` on line 1", + python_test_error( + ".toBe('''1''' + '''1''')", + "Non-primitive literal in `.toBe()` starting at line 1: error for character `+` on line 1", ) - - -def assert_raises_error(source_file, error_msg): - try: - source_file.parse_to_be_like(1) - assert False, "Expected an AssertionError, but none was raised." - except AssertionError as e: - assert str(e) == error_msg