def test_mct_utf8(): '''Test that utf8 content can be read and written correctly in make_clean_tmpfile. ''' filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)), "utf.f90") _ = make_clean_tmpfile(filepath)
def test_mct_invalid_filename_arg(): '''Test that the expected exception occurs if an invalid input file is provided. ''' with pytest.raises(IOError) as excinfo: _ = make_clean_tmpfile("nonexistantfile") assert "No such file or directory" in str(excinfo.value)
def test_mct_invalid_encode_arg(tmpdir): '''Test that an appropriate exception is raised if the encode argument is invalid. ''' input_filepath = create_tmp_file("", tmpdir) with pytest.raises(InternalError) as excinfo: _ = make_clean_tmpfile(input_filepath, encoding="invalid") assert "unknown encoding: invalid'." in str(excinfo.value)
def test_mct_works(tmpdir): '''Test that if there are no errors in the input file then we get an exact copy of the input file in the temporary file.''' content = ("program valid\n" "end program valid\n") input_filepath = create_tmp_file(content, tmpdir) output_filepath = make_clean_tmpfile(input_filepath) with open(output_filepath, "r") as cfile: output = cfile.read() assert output == content
def test_mct_invalid_skip_arg(tmpdir): '''Test that the expected exception occurs if an invalid skip_bad_input argument is provided. ''' input_filepath = create_tmp_file("", tmpdir) with pytest.raises(InternalError) as excinfo: _ = make_clean_tmpfile(input_filepath, skip_bad_input="INVALID") assert ("skip_bad_input argument should be False or True but " "found 'INVALID'.") in str(excinfo.value)
def test_mct_parse_error(tmpdir): '''Test that an appropriate exception is raised if there is an invalid character in the input file and skip_bad_argument is set to False. ''' invalid_content = u"\xca" input_filepath = create_tmp_file(invalid_content, tmpdir) with pytest.raises(ParseError) as excinfo: _ = make_clean_tmpfile(input_filepath, skip_bad_input=False, encoding="ascii") assert ("Bad character in input file. Error returned was 'ascii' " "codec can't decode byte ") in str(excinfo.value) # Can't check the actual value as some versions of Python3 return # a different value to the one above. assert "in position 0: ordinal not in range(128)." in str(excinfo.value)
def test_mct_skip_error(tmpdir, caplog): '''Test that invalid characters are skipped in an input file by default and that logging messages are created. ''' content = "HELLO" invalid_content = u"\xca".join(content) input_filepath = create_tmp_file(invalid_content, tmpdir) output_filepath = make_clean_tmpfile(input_filepath, encoding="ascii") with open(output_filepath, "r") as cfile: output = cfile.read() assert output == content for record in caplog.records: assert record.levelname != 'CRITICAL' assert ("Skipped bad character in input file. Error returned was 'ascii' " "codec can't decode byte ") in caplog.text # Can't check the actual value as some versions of Python3 return # a different value to the one above. assert "in position 1: ordinal not in range(128)." in caplog.text
def get_source_info(file_candidate): ''' Determines the format of Fortran source held in a file. :param file_candidate: a filename or a file object :type file_candidate: str or (file (py2) or _io.TextIOWrapper (py3)) :returns: the Fortran format encoded as a string. :rtype: str ''' if hasattr(file_candidate, 'name') and hasattr(file_candidate, 'read'): filename = file_candidate.name # The behaviour of file.name when associated with a file without a # file name has changed between Python 2 and 3. # # Under Python 3 file.name holds an integer file handle. if isinstance(filename, int): filename = None # Under Python 2 file.name holds a string of the form "<..>". elif filename.startswith('<') and filename.endswith('>'): filename = None elif isinstance(file_candidate, six.string_types): # The preferred method for identifying strings changed between Python2 # and Python3. filename = file_candidate else: message = 'Argument must be a filename or file-like object.' raise ValueError(message) if filename: _, ext = os.path.splitext(filename) if ext == '.pyf': return FortranFormat(True, True) if hasattr(file_candidate, 'read'): # If the candidate object has a "read" method we assume it's a file # object. # # If it is a file object then it may be in the process of being read. # As such we need to take a note of the current state of the file # pointer so we can restore it when we've finished what we're doing. # pointer = file_candidate.tell() file_candidate.seek(0) source_info = get_source_info_str(file_candidate.read()) file_candidate.seek(pointer) return source_info else: # It isn't a file and it passed the type check above so it must be # a string. # # If it's a string we assume it is a filename. In which case we need # to open the named file so we can read it. # # It is closed on completion so as to return it to the state it was # found in. # from fparser.common.utils import make_clean_tmpfile tmpfile = make_clean_tmpfile(file_candidate) with io.open(tmpfile, 'r', encoding='utf8') as file_object: string = get_source_info_str(file_object.read()) os.remove(tmpfile) return string