def test_base_fixed_continuation(log): ''' Tests that FortranReaderBase.get_source_item() logs the correct messages when there are quote mismatches across a continuation in fixed format. ''' code = ' character(4) :: cheese = "a & !\n & b' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(False, False) unit_under_test.set_format(mode) # Force sloppy fixed format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['error'] == [] assert log.messages['critical'] == [] expected = 'following character continuation: \'"\', expected None.' result = log.messages['warning'][0].split('<==')[1].lstrip() assert result == expected code = ' x=1 &\n +1 &\n -2' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(False, False) unit_under_test.set_format(mode) # Force sloppy fixed format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['error'] == [] assert log.messages['critical'] == [] expected = 'free format line continuation character `&\' detected ' \ + 'in fix format code\n 2: +1 &\n 3: -2' result = log.messages['warning'][0].split('<==')[1].lstrip() assert result == expected
def test_base_handle_multilines(log): ''' Tests that FortranReaderBase.get_source_item() logs the correct messages when there are quote discrepancies. ''' code = 'character(8) :: test = \'foo"""bar' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(True, True) unit_under_test.set_format(mode) # Force strict free format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['error'] == [] assert log.messages['critical'] == [] expected = 'multiline prefix contains odd number of "\'" characters' result = log.messages['warning'][0].split('<==')[1].lstrip() assert result == expected code = 'goo """boo\n doo""" soo \'foo' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(True, True) unit_under_test.set_format(mode) # Force strict free format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['error'] == [] assert log.messages['critical'] == [] expected = 'following character continuation: "\'", expected None.' result = log.messages['warning'][0].split('<==')[1].lstrip() assert result == expected
def test_fortranformat_equality(permutations, pretty): #pylint: disable=redefined-outer-name ''' Tests that the equality operator works as expected. ''' expected = (permutations[0] == pretty[0]) \ and (permutations[1] == pretty[1]) unit_under_test = FortranFormat(permutations[0], permutations[1]) candidate = FortranFormat(pretty[0], pretty[1]) assert (unit_under_test == candidate) == expected
def test_format_constructor_faults(): ''' Tests that the constructor correctly rejects attempts to create an object with "None" arguments. ''' with pytest.raises(Exception): _unit_under_test = FortranFormat(True, None) with pytest.raises(Exception): _unit_under_test = FortranFormat(None, True)
def test_base_fixed_nonlabel(log): ''' Tests that FortranReaderBase.get_source_item() logs the correct messages when there is an unexpected character in the initial 6 columns. ''' # Checks that a bad character in the first column causes an event to be # logged. code = 'w integer :: i' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(False, True) unit_under_test.set_format(mode) # Force fixed format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['error'] == [] assert log.messages['critical'] == [] result = log.messages['warning'][0].split('<==')[1].lstrip() expected = "non-space/digit char 'w' found in column 1 of fixed " \ + "Fortran code, interpreting line as comment line" assert result == expected # Checks a bad character in columns 2-6 for i in range(1, 5): code = ' ' * i + 'w' + ' ' * (5 - i) + 'integer :: i' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(False, True) unit_under_test.set_format(mode) # Force strict fixed format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['error'] == [] assert log.messages['critical'] == [] result = log.messages['warning'][0].split('<==')[1].lstrip() expected = "non-space/digit char 'w' found in column {col} " \ + "of fixed Fortran code" assert result == expected.format(col=i + 1) # Checks for a bad character, not in the first column, with "sloppy" mode # engaged. code = ' w integer :: i' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(False, False) unit_under_test.set_format(mode) # Force sloppy fixed format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['error'] == [] assert log.messages['critical'] == [] expected = "non-space/digit char 'w' found in column 2 " \ + "of fixed Fortran code, switching to free format mode" result = log.messages['warning'][0].split('<==')[1].lstrip() assert result == expected
def test_multi_stmt_line1(): '''Check that simple statements separated by ; on a single line are correctly split into multiple lines by FortranReaderBase ''' code = "do i=1,10;b=20 ; c=30" reader = FortranStringReader(code) mode = FortranFormat(True, False) reader.set_format(mode) line1 = reader.next() assert isinstance(line1, Line) assert line1.line == "do i=1,10" assert line1.span == (1, 1) assert line1.label is None assert line1.name is None assert line1.reader is reader line2 = reader.next() assert isinstance(line2, Line) assert line2.line == "b=20" assert line2.span is line1.span assert line2.label is None assert line2.name is None assert line2.reader is reader line3 = reader.next() assert isinstance(line3, Line) assert line3.line == "c=30" assert line3.span is line1.span assert line3.label is None assert line3.name is None assert line3.reader is reader
def __init__(self, parent, expr="UNSET", typeselect=False): ''' Construct a SelectionGen for creating a SELECT block :param parent: node to which to add this select block as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param str expr: the CASE expression :param bool typeselect: whether or not this is a SELECT TYPE rather than a SELECT CASE ''' self._typeselect = typeselect reader = FortranStringReader( "SELECT CASE (x)\nCASE (1)\nCASE DEFAULT\nEND SELECT") reader.set_format(FortranFormat(True, True)) # free form, strict select_line = reader.next() self._case_line = reader.next() self._case_default_line = reader.next() end_select_line = reader.next() if self._typeselect: select = SelectType(parent.root, select_line) else: select = SelectCase(parent.root, select_line) endselect = EndSelect(select, end_select_line) select.expr = expr select.content.append(endselect) BaseGen.__init__(self, parent, select)
def test_get_type_by_name(monkeypatch): ''' Tests for HasImplicitStmt.get_type_by_name(). ''' from fparser.common.utils import AnalyzeError from fparser.common.readfortran import FortranStringReader from fparser.common.sourceinfo import FortranFormat from fparser.one.typedecl_statements import Real, Integer from fparser.one.parsefortran import FortranParser # We can't just create a HasImplicitStmt object so we get the parser # to create a module object as that sub-classes HasImplicitStmt (amongst # other things). string = '''\ module some_block end module some_block ''' reader = FortranStringReader(string) reader.set_format(FortranFormat(True, False)) parser = FortranParser(reader) parser.parse() mod = parser.block.content[0] # Now we have a Module object, we can call get_type_by_name()... rtype = mod.get_type_by_name("a_real") assert isinstance(rtype, Real) itype = mod.get_type_by_name("i_int") assert isinstance(itype, Integer) # Check that we raise the correct error if we don't have any implicit # rules set monkeypatch.setattr(mod.a, "implicit_rules", None) with pytest.raises(AnalyzeError) as err: _ = mod.get_type_by_name("i_int") assert "Implicit rules mapping is null" in str(err)
def adduse(name, parent, only=False, funcnames=None): ''' Adds a use statement with the specified name to the supplied object. This routine is required when modifying an existing AST (e.g. when modifying a kernel). The classes are used when creating an AST from scratch (for the PSy layer). :param str name: name of module to USE :param parent: node in fparser1 AST to which to add this USE as a child :type parent: :py:class:`fparser.one.block_statements.*` :param bool only: whether this USE has an "ONLY" clause :param list funcnames: list of quantities to follow the "ONLY" clause :returns: an fparser1 Use object :rtype: :py:class:`fparser.one.block_statements.Use` ''' reader = FortranStringReader("use kern,only : func1_kern=>func1") reader.set_format(FortranFormat(True, True)) # free form, strict myline = reader.next() # find an appropriate place to add in our use statement while not (isinstance(parent, fparser1.block_statements.Program) or isinstance(parent, fparser1.block_statements.Module) or isinstance(parent, fparser1.block_statements.Subroutine)): parent = parent.parent use = fparser1.block_statements.Use(parent, myline) use.name = name use.isonly = only if funcnames is None: funcnames = [] use.isonly = False use.items = funcnames parent.content.insert(0, use) return use
def test_get_type_by_name_implicit(): ''' Tests for HasImplicitStmt.get_type_by_name() when the source code contains IMPLICIT statements. ''' from fparser.common.readfortran import FortranStringReader from fparser.common.sourceinfo import FortranFormat from fparser.one.typedecl_statements import Real, Integer from fparser.one.parsefortran import FortranParser # We can't just create a HasImplicitStmt object so we get the parser # to create a module object as that sub-classes HasImplicitStmt (amongst # other things). string = '''\ module some_block implicit real (a-e) implicit integer (f-z) end module some_block ''' reader = FortranStringReader(string) reader.set_format(FortranFormat(True, False)) parser = FortranParser(reader) parser.parse() # Get the module object mod = parser.block.content[0] # We have to run the analyze method on the Implicit objects # produced by the parser in order to populate the implicit_rules # of the module. mod.content[0].analyze() mod.content[1].analyze() # Now we can call get_type_by_name()... rtype = mod.get_type_by_name("a_real") assert isinstance(rtype, Real) itype = mod.get_type_by_name("f_int") assert isinstance(itype, Integer)
def __init__(self, parent, name="", args=None, implicitnone=False): ''' :param parent: node in AST to which to add Subroutine as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param str name: name of the Fortran subroutine :param list args: list of arguments accepted by the subroutine :param bool implicitnone: whether or not we should specify "implicit none" for the body of this subroutine ''' reader = FortranStringReader( "subroutine vanilla(vanilla_arg)\nend subroutine") reader.set_format(FortranFormat(True, True)) # free form, strict subline = reader.next() endsubline = reader.next() from fparser.one.block_statements import Subroutine, EndSubroutine self._sub = Subroutine(parent.root, subline) self._sub.name = name if args is None: args = [] self._sub.args = args endsub = EndSubroutine(self._sub, endsubline) self._sub.content.append(endsub) ProgUnitGen.__init__(self, parent, self._sub) if implicitnone: self.add(ImplicitNoneGen(self))
def test_implicit_topyf(monkeypatch): ''' Tests for the topyf() method of HasImplicitStmt. ''' from fparser.common.readfortran import FortranStringReader from fparser.common.sourceinfo import FortranFormat from fparser.one.parsefortran import FortranParser # We can't just create a HasImplicitStmt object so we get the parser # to create a module object as that sub-classes HasImplicitStmt (amongst # other things). string = '''\ module some_block implicit real (a-e) implicit integer (f-z) end module some_block ''' reader = FortranStringReader(string) reader.set_format(FortranFormat(True, False)) parser = FortranParser(reader) parser.parse() # Get the module object mod = parser.block.content[0] code = mod.topyf() assert "! default IMPLICIT rules apply" in code mod.content[0].analyze() mod.content[1].analyze() code = mod.topyf() assert "REAL (a, b, c, d, e)" in code assert "INTEGER (f, g, h" in code monkeypatch.setattr(mod.a, "implicit_rules", None) code = mod.topyf() assert "IMPLICIT NONE" in code
def test_fortranformat_invalid(): ''' Tests that the equality operator understands that it can't compare apples and oranges. ''' unit_under_test = FortranFormat(True, False) with pytest.raises(NotImplementedError): if unit_under_test == 'oranges': raise Exception("That shouldn't have happened")
def test_string_reader(): ''' Tests that Fortran source can be read from a string. ''' unit_under_test = FortranStringReader(FULL_FREE_SOURCE) expected = FortranFormat(True, False) assert unit_under_test.format == expected for expected in FULL_FREE_EXPECTED: assert unit_under_test.get_single_line(ignore_empty=True) == expected
def __init__(self, parent, datatype="", entity_decls=None, intent="", pointer=False, kind="", dimension="", allocatable=False): ''' :param parent: node to which to add this declaration as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param str datatype: the (intrinsic) type for this declaration :param list entity_decls: list of variable names to declare :param str intent: the INTENT attribute of this declaration :param bool pointer: whether or not this is a pointer declaration :param str kind: the KIND attribute to use for this declaration :param str dimension: the DIMENSION specifier (i.e. the xx in DIMENSION(xx)) :param bool allocatable: whether this declaration is for an ALLOCATABLE quantity :raises RuntimeError: if no variable names are specified :raises RuntimeError: if datatype is not one of "integer" or "real" ''' if entity_decls is None: raise RuntimeError( "Cannot create a variable declaration without specifying the " "name(s) of the variable(s)") fort_fmt = FortranFormat(True, False) # free form, strict if datatype.lower() == "integer": reader = FortranStringReader("integer :: vanilla") reader.set_format(fort_fmt) myline = reader.next() self._decl = fparser1.typedecl_statements.Integer(parent.root, myline) elif datatype.lower() == "real": reader = FortranStringReader("real :: vanilla") reader.set_format(fort_fmt) myline = reader.next() self._decl = fparser1.typedecl_statements.Real(parent.root, myline) else: raise RuntimeError( "f2pygen:DeclGen:init: Only integer and real are currently" " supported and you specified '{0}'".format(datatype)) # make a copy of entity_decls as we may modify it local_entity_decls = entity_decls[:] self._decl.entity_decls = local_entity_decls my_attrspec = [] if intent != "": my_attrspec.append("intent({0})".format(intent)) if pointer is not False: my_attrspec.append("pointer") if allocatable is not False: my_attrspec.append("allocatable") self._decl.attrspec = my_attrspec if dimension != "": my_attrspec.append("dimension({0})".format(dimension)) if kind is not "": self._decl.selector = ('', kind) BaseGen.__init__(self, parent, self._decl)
def test_nonblock_do_construct_tofortran_non_ascii(): ''' Check that the tofortran() method works when the non-block do-construct contains a character string with non-ascii characters. ''' from fparser.common.readfortran import FortranStringReader from fparser.common.sourceinfo import FortranFormat code = (u" DO 50\n" u" 50 WRITE(*,*) ' for e1=1\xb0'\n") reader = FortranStringReader(code) # Ensure reader in in 'fixed-format' mode reader.set_format(FortranFormat(False, True)) obj = Nonblock_Do_Construct(reader) out_str = str(obj) assert "for e1=1" in out_str
def __init__(self, parent, content): ''' :param parent: node in AST to which to add the Comment as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param str content: the content of the comment ''' reader = FortranStringReader("! content\n") reader.set_format(FortranFormat(True, True)) # free form, strict subline = reader.next() my_comment = Comment(parent.root, subline) my_comment.content = content BaseGen.__init__(self, parent, my_comment)
def test_fortranformat_constructor(pretty): #pylint: disable=redefined-outer-name ''' Tests the constructor correctly sets up the object. ''' unit_under_test = FortranFormat(pretty[0], pretty[1]) assert str(unit_under_test) == pretty[3] assert unit_under_test.is_free == pretty[0] assert unit_under_test.is_fixed == (not pretty[0]) assert unit_under_test.is_strict == pretty[1] assert unit_under_test.is_f77 == (not pretty[0] and pretty[1]) assert unit_under_test.is_fix == (not pretty[0] and not pretty[1]) assert unit_under_test.is_pyf == (pretty[0] and pretty[1]) assert unit_under_test.mode == pretty[2]
def test_fortranformat_from_mode(mode): #pylint: disable=redefined-outer-name ''' Tests that the object is correctly created by the from_mode function. ''' unit_under_test = FortranFormat.from_mode(mode[0]) assert unit_under_test.mode == mode[0] assert unit_under_test.is_free == mode[1] assert unit_under_test.is_fixed == (not mode[1]) assert unit_under_test.is_strict == mode[2] assert unit_under_test.is_f77 == (not mode[1] and mode[2]) assert unit_under_test.is_fix == (not mode[1] and not mode[2]) assert unit_under_test.is_pyf == (mode[1] and mode[2]) assert str(unit_under_test.mode) == mode[0]
def __init__(self, parent, clause): ''' :param parent: Node to which to add this IfThen as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param str clause: the condition, xx, to evaluate in the if(xx)then ''' reader = FortranStringReader("if (dummy) then\nend if") reader.set_format(FortranFormat(True, True)) # free form, strict ifthenline = reader.next() endifline = reader.next() my_if = fparser1.block_statements.IfThen(parent.root, ifthenline) my_if.expr = clause my_endif = fparser1.block_statements.EndIfThen(my_if, endifline) my_if.content.append(my_endif) BaseGen.__init__(self, parent, my_if)
def test_do(name, label, control_comma, terminal_expression, end_name, end_label): # pylint: disable=redefined-outer-name, too-many-arguments, too-many-locals ''' Checks that the "do" loop parser understands the "for-next" variant of the syntax. This is defined in BS ISO/IEC 1539-1:2010 with R814-R822. TODO: Only the terminal expression is tested. This is a short-cut and relies on expression handling being applied identically across all expressions. This was true at the time of writing the test. ''' name_snippet = name + ': ' if name else None label_snippet = label + ' ' if label else None comma_snippet = ', ' if control_comma else None # TODO: Although the Fortran standard allows for "continue" to be used in # place of "end do" fparser does not support it. end_snippet = 'continue' if end_name == 'continue' \ else get_end_do(end_name) do_code = '''{name}do {label}{comma}variable = 1, {term}, 1 write (6, '(I0)') variable {endlabel} {end} '''.format(name=name_snippet or '', label=label_snippet or '', comma=comma_snippet or '', term=terminal_expression, endlabel=end_label or '', end=end_snippet) do_expected = ''' {name}DO {label}variable = 1, {term}, 1 WRITE (6, '(I0)') variable {endlabel} {endstmt} '''.format(name=name_snippet or '', label=label_snippet or '', term=terminal_expression, endlabel=end_label or ' ', endstmt=get_end_do(end_name)) do_reader = FortranStringReader(do_code) do_reader.set_format(FortranFormat(True, False)) do_parser = FortranParser(do_reader) if (name != end_name) or (label and (label != end_label)): with pytest.raises(AnalyzeError): do_parser.parse() else: do_parser.parse() loop = do_parser.block.content[0] assert str(loop).splitlines() == do_expected.splitlines()
def test_base_free_continuation(log): ''' Tests that FortranReaderBase.get_source_item() logs the correct messages when there are quote mismatches across a continuation in free format. ''' code = 'character(4) :: "boo & que' log.reset() unit_under_test = FortranStringReader(code) mode = FortranFormat(True, False) unit_under_test.set_format(mode) # Force sloppy free format unit_under_test.get_source_item() assert log.messages['debug'] == [] assert log.messages['info'] == [] assert log.messages['warning'] == [] assert log.messages['critical'] == [] expected = 'following character continuation: \'"\', expected None.' result = log.messages['error'][0].split('<==')[1].lstrip() assert result == expected
def __init__(self, parent, name="", args=None): ''' :param parent: node in AST to which to add CallGen as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param str name: the name of the routine to call :param list args: list of arguments to pass to the call ''' reader = FortranStringReader("call vanilla(vanilla_arg)") reader.set_format(FortranFormat(True, True)) # free form, strict myline = reader.next() from fparser.one.block_statements import Call self._call = Call(parent.root, myline) self._call.designator = name if args is None: args = [] self._call.items = args BaseGen.__init__(self, parent, self._call)
def test_filename_reader(): ''' Tests that a Fortran source file can be read given its filename. ''' handle, filename = tempfile.mkstemp(suffix='.f90', text=True) os.close(handle) try: with io.open(filename, mode='w', encoding='UTF-8') as source_file: source_file.write(FULL_FREE_SOURCE) unit_under_test = FortranFileReader(filename) expected = FortranFormat(True, False) assert unit_under_test.format == expected for expected in FULL_FREE_EXPECTED: found = unit_under_test.get_single_line(ignore_empty=True) assert found == expected except Exception: os.unlink(filename) raise
def test_111fortranreaderbase(log, monkeypatch): ''' Tests the FortranReaderBase class. Currently only tests logging functionality. ''' class FailFile(object): ''' A "file-like" object which returns a line of Fortran source followed by raising a StopIteration exception. ''' _stuff = ['x=1'] def next(self): ''' Used by Python 2.7. ''' return self.__next__() def __next__(self): ''' Used by Python 3. ''' return self._stuff.pop() monkeypatch.setattr('fparser.common.readfortran.FortranReaderBase.id', lambda x: 'foo', raising=False) mode = FortranFormat(True, False) unit_under_test = FortranReaderBase(FailFile(), mode, True) assert str(unit_under_test.next()) == "line #1'x=1'" with pytest.raises(StopIteration): unit_under_test.next() assert log.messages['info'] == [] assert log.messages['warning'] == [] assert log.messages['error'] == [] result = log.messages['critical'][0].split('\n')[1] assert result == ' 1:x=1 <== while processing line' assert log.messages['critical'][1] == 'STOPPED READING' expected = 'Traceback\n' assert log.messages['debug'][0][:len(expected)] == expected
def __init__(self, parent): ''' :param parent: node in AST to which to add 'implicit none' as a child :type parent: :py:class:`psyclone.f2pygen.ModuleGen` or :py:class:`psyclone.f2pygen.SubroutineGen` :raises Exception: if `parent` is not a ModuleGen or SubroutineGen ''' if not isinstance(parent, ModuleGen) and not isinstance(parent, SubroutineGen): raise Exception( "The parent of ImplicitNoneGen must be a module or a " "subroutine, but found {0}".format(type(parent))) reader = FortranStringReader("IMPLICIT NONE\n") reader.set_format(FortranFormat(True, True)) # free form, strict subline = reader.next() from fparser.one.typedecl_statements import Implicit my_imp_none = Implicit(parent.root, subline) BaseGen.__init__(self, parent, my_imp_none)
def __init__(self, parent, variable_name, start, end, step=None): ''' :param parent: the node to which to add this do loop as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param str variable_name: the name of the loop variable :param str start: start value for Do loop :param str end: upper-limit of Do loop :param str step: increment to use in Do loop ''' reader = FortranStringReader("do i=1,n\nend do") reader.set_format(FortranFormat(True, True)) # free form, strict doline = reader.next() enddoline = reader.next() dogen = fparser1.block_statements.Do(parent.root, doline) dogen.loopcontrol = variable_name + "=" + start + "," + end if step is not None: dogen.loopcontrol = dogen.loopcontrol + "," + step enddo = fparser1.block_statements.EndDo(dogen, enddoline) dogen.content.append(enddo) BaseGen.__init__(self, parent, dogen)
def __init__(self, parent, content): ''' :param parent: node to which to add this DEALLOCATE as a child :type parent: :py:class:`psyclone.f2pygen.BaseGen` :param content: string or list of variables to deallocate :type content: list of strings or a single string :raises RuntimeError: if `content` is not of correct type ''' reader = FortranStringReader("deallocate(dummy)") reader.set_format(FortranFormat(True, False)) # free form, strict myline = reader.next() self._decl = fparser1.statements.Deallocate(parent.root, myline) if isinstance(content, str): self._decl.items = [content] elif isinstance(content, list): self._decl.items = content else: raise RuntimeError( "DeallocateGen expected the content argument to be a str" " or a list, but found {0}".format(type(content))) BaseGen.__init__(self, parent, self._decl)
def test_multi_stmt_line3(): '''Check that named do loops separated by ; on a single line are correctly split into multiple lines by FortranReaderBase ''' code = "name:do i=1,10;name2 : do j=1,10" reader = FortranStringReader(code) mode = FortranFormat(True, False) reader.set_format(mode) line1 = reader.next() assert isinstance(line1, Line) assert line1.line == "do i=1,10" assert line1.span == (1, 1) assert line1.label is None assert line1.name == "name" assert line1.reader is reader line2 = reader.next() assert line2.line == "do j=1,10" assert line2.span is line1.span assert line2.label is None assert line2.name == "name2" assert line2.reader is reader
def test_multi_stmt_line2(): '''Check that format statements separated by ; on a single line are correctly split into multiple lines by FortranReaderBase ''' code = "10 format(a); 20 format(b)" reader = FortranStringReader(code) mode = FortranFormat(True, False) reader.set_format(mode) line1 = reader.next() assert isinstance(line1, Line) assert line1.line == "format(a)" assert line1.span == (1, 1) assert line1.label == 10 assert line1.name is None assert line1.reader is reader line2 = reader.next() assert line2.line == "format(b)" assert line2.span is line1.span assert line2.label == 20 assert line2.name is None assert line2.reader is reader