From 46ec6ed39b83f4d7f9293760e9f2fef18c060a5d Mon Sep 17 00:00:00 2001 From: "f.grunewald" Date: Mon, 7 Aug 2023 00:11:29 +0200 Subject: [PATCH 1/5] parse #error statements --- polyply/src/top_parser.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/polyply/src/top_parser.py b/polyply/src/top_parser.py index d95bf5e8..428eba1d 100644 --- a/polyply/src/top_parser.py +++ b/polyply/src/top_parser.py @@ -63,7 +63,8 @@ def __init__(self, topology, cwdir=None): } self.pragma_actions = { '#define': self.parse_define, - '#include': self.parse_include + '#include': self.parse_include, + '#error': self.parse_error, } def dispatch(self, line): @@ -391,10 +392,29 @@ def _molecule(self, line, lineno=0): Parses the lines of the [atoms] directive. """ self.current_itp.append(line) + def parse_error(self, line, lineno=0): + """ + Parse the #error statement. + """ + if self.current_meta: + # the #error is between ifdef + # however tag is not in defines we have + # read so the error is not triggered. + if self.current_meta["condition"] == "ifdef"\ + and self.current_meta["tag"] not in self.topology.defines: + return + # the current file is between ifndef + # so if tag is defined we ignore this file + elif self.current_meta["condition"] == "ifndef"\ + and self.current_meta["tag"] in self.topology.defines: + return + # we remove the #error + msg = line[7:] + raise NotImplementedError(msg) def parse_define(self, line): """ - Parse define statemetns + Parse define statements """ tokens = line.split() From ed65822aa504e64510183d74cc719a8d6af4ba8c Mon Sep 17 00:00:00 2001 From: "f.grunewald" Date: Mon, 7 Aug 2023 00:21:45 +0200 Subject: [PATCH 2/5] add tests for parsing #error statements --- polyply/tests/test_top_parser.py | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/polyply/tests/test_top_parser.py b/polyply/tests/test_top_parser.py index 56d6e3b2..bcff460b 100644 --- a/polyply/tests/test_top_parser.py +++ b/polyply/tests/test_top_parser.py @@ -384,6 +384,54 @@ def test_skip_directives(lines): "gen-pairs":'no', "fudgeLJ":1.0, "fudgeQQ":1.0} + @staticmethod + @pytest.mark.parametrize('lines', ( + """ + #define GMXERROR + #ifdef GMXERROR + #error "This will raise an error." + #endif + """, + """ + #error This will raise an error + """, + )) + def test_error_parsing(lines): + """ + Test that the #error pragma raises an error. + """ + new_lines = textwrap.dedent(lines) + new_lines = new_lines.splitlines() + force_field = vermouth.forcefield.ForceField(name='test_ff') + top = Topology(force_field, name="test") + with pytest.raises(NotImplementedError): + polyply.src.top_parser.read_topology(new_lines, top) + + @staticmethod + @pytest.mark.parametrize('lines', ( + """ + #define NOERROR + #ifdef GMXERROR + #error "This will raise an error." + #endif + """, + """ + #define NOERROR + #ifndef NOERROR + #error This will raise an error. + #endif + """, + )) + def test_error_skipped(lines): + """ + Test that the #error pragma is skipped when not defined. + """ + new_lines = textwrap.dedent(lines) + new_lines = new_lines.splitlines() + force_field = vermouth.forcefield.ForceField(name='test_ff') + top = Topology(force_field, name="test") + polyply.src.top_parser.read_topology(new_lines, top) + assert top.defines == {'NOERROR': True} def test_consistency(): """ From 4094ab77d4763a85ba2a7ca9f719079f00bd9623 Mon Sep 17 00:00:00 2001 From: "f.grunewald" Date: Fri, 11 Aug 2023 11:24:58 +0200 Subject: [PATCH 3/5] adjust error message --- polyply/tests/test_top_parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/polyply/tests/test_top_parser.py b/polyply/tests/test_top_parser.py index bcff460b..bf9a1bd4 100644 --- a/polyply/tests/test_top_parser.py +++ b/polyply/tests/test_top_parser.py @@ -393,7 +393,7 @@ def test_skip_directives(lines): #endif """, """ - #error This will raise an error + #error "This will raise an error." """, )) def test_error_parsing(lines): @@ -404,8 +404,9 @@ def test_error_parsing(lines): new_lines = new_lines.splitlines() force_field = vermouth.forcefield.ForceField(name='test_ff') top = Topology(force_field, name="test") - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as err_info: polyply.src.top_parser.read_topology(new_lines, top) + assert str(err_info.value) == "\"This will raise an error.\"" @staticmethod @pytest.mark.parametrize('lines', ( From e51c38bdba161140d49324e51eaddd9dde9965f8 Mon Sep 17 00:00:00 2001 From: "f.grunewald" Date: Fri, 11 Aug 2023 11:25:24 +0200 Subject: [PATCH 4/5] add white space --- polyply/src/top_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/polyply/src/top_parser.py b/polyply/src/top_parser.py index 428eba1d..d39e7b3a 100644 --- a/polyply/src/top_parser.py +++ b/polyply/src/top_parser.py @@ -392,6 +392,7 @@ def _molecule(self, line, lineno=0): Parses the lines of the [atoms] directive. """ self.current_itp.append(line) + def parse_error(self, line, lineno=0): """ Parse the #error statement. From 6fd599a03de9f8d7be8646b9a2c13871df6a2dd2 Mon Sep 17 00:00:00 2001 From: "f.grunewald" Date: Mon, 14 Aug 2023 19:17:20 +0200 Subject: [PATCH 5/5] fix comments --- polyply/src/top_parser.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/polyply/src/top_parser.py b/polyply/src/top_parser.py index d39e7b3a..01b0e7a0 100644 --- a/polyply/src/top_parser.py +++ b/polyply/src/top_parser.py @@ -398,14 +398,15 @@ def parse_error(self, line, lineno=0): Parse the #error statement. """ if self.current_meta: - # the #error is between ifdef - # however tag is not in defines we have - # read so the error is not triggered. + # In this case the #error is enclosed in an + # #ifdef statement. However tag of the #ifdef + # has not been defined previously. Thus the + # error is not triggered. if self.current_meta["condition"] == "ifdef"\ and self.current_meta["tag"] not in self.topology.defines: return - # the current file is between ifndef - # so if tag is defined we ignore this file + # the #error file is enlosed in an #ifndef + # so if tag is defined, we ignore this #error elif self.current_meta["condition"] == "ifndef"\ and self.current_meta["tag"] in self.topology.defines: return