def setUp(self): self._engine = MagicMock() self._macros = MacroFactory(self._engine) self._symbols = SymbolTable.default() self._tokens = TokenFactory(self._symbols) self._factory = Factory(self._symbols) self._environment = Context(definitions=self._macros.all())
def _rewrite(self, text, source, symbol_table=None): character_table = symbol_table or self._character_table factory = Factory(character_table) macros = MacroFactory(self) parser = Parser(factory.as_tokens(text, source), factory, Context(definitions=macros.all())) return parser.process()
def setUp(self): self._engine = MagicMock() self._symbols = SymbolTable.default() self._tokens = TokenFactory(self._symbols) self._factory = Factory(self._symbols) self._environment = Context() self._lexer = None self._parser = None
class ClassificationTests(TestCase): def setUp(self): self._engine = MagicMock() self._macros = MacroFactory(self._engine) self._symbols = SymbolTable.default() self._tokens = TokenFactory(self._symbols) self._factory = Factory(self._symbols) self._environment = Context(definitions=self._macros.all()) def test_literal_macro(self): self._test((r"foo", "", r"{blablabla}"), r"\foo", False) def test_macro_with_input(self): self._test((r"foo", "#1", r"{\input{#1}}"), r"\foo{my-file}", True) def test_macro_with_include(self): self._test((r"foo", "#1", r"{\include{#1}}"), r"\foo{my-file}", True) def test_macro_with_masked_input(self): self._test((r"foo", "#1", r"{\def\input#1{blablab #1} \input{#1}}"), r"\foo{my-file}", False) def _test(self, macro, invocation, expected_category): self._define(*macro) self.assertEqual(expected_category, self._classify(invocation)) def _define(self, name, parameters, body): macro = self._macros.create_user_defined( name, self._factory.as_list(parameters), self._factory.as_list(body)) self._environment[name] = macro def _classify(self, expression): parser = Parser(self._factory.as_tokens(expression, "Unknown"), self._factory, self._environment) parser.process() return parser.shall_expand()
class ParserTests(TestCase): def setUp(self): self._engine = MagicMock() self._symbols = SymbolTable.default() self._tokens = TokenFactory(self._symbols) self._factory = Factory(self._symbols) self._environment = Context() self._lexer = None self._parser = None def test_parsing_a_regular_word(self): self._do_test_with("hello", "hello") def _do_test_with(self, input, output): parser = Parser(self._factory.as_tokens(input, "Unknown"), self._factory, self._engine, self._environment) tokens = parser.rewrite() self._verify_output_is(output, tokens) def _verify_output_is(self, expected_text, actual_tokens): output = "".join(str(t) for t in actual_tokens) self.assertEqual(expected_text, output) def test_rewriting_a_group(self): self._do_test_with("{bonjour}", "{bonjour}") def test_rewriting_a_command_that_shall_not_be_rewritten(self): self._do_test_with(r"\macro[option=23cm]{some text}", r"\macro[option=23cm]{some text}") def test_rewriting_a_command_within_a_group(self): self._do_test_with(r"{\macro[option=23cm]{some text} more text}", r"{\macro[option=23cm]{some text} more text}") def test_rewriting_a_command_in_a_verbatim_environment(self): self._do_test_with(r"\begin{verbatim}\foo{bar}\end{verbatim}", r"\begin{verbatim}\foo{bar}\end{verbatim}") def test_rewriting_a_input_in_a_verbatim_environment(self): self._engine.content_of.return_value = "blabla" self._do_test_with(r"\begin{verbatim}\input{bar}\end{verbatim}", r"\begin{verbatim}\input{bar}\end{verbatim}") self._engine.content_of.assert_not_called() def test_rewriting_a_unknown_environment(self): self._do_test_with(r"\begin{center}blabla\end{center}", r"\begin{center}blabla\end{center}") def test_parsing_a_macro_definition(self): self._do_test_with(r"\def\myMacro#1{my #1}", r"") def test_parsing_commented_out_input(self): self._do_test_with(r"% \input my-file", r"% \input my-file") self._engine.content_of.assert_not_called() def test_invoking_a_macro_with_one_parameter(self): self._define_macro(r"\foo", "(#1)", "{bar #1}") self._do_test_with(r"\foo(1)", "bar 1") def _define_macro(self, name, parameters, body): macro = self._macro(name, parameters, body) self._environment[name] = macro def _macro(self, name, parameters, body): return Macro(name, self._factory.as_list(parameters), self._factory.as_list(body)) def test_invoking_a_macro_where_one_argument_is_a_group(self): self._define_macro(r"\foo", "(#1)", "{Text: #1}") self._do_test_with(r"\foo({bar!})", r"Text: bar!") def test_invoking_a_macro_with_two_parameters(self): self._define_macro(r"\point", "(#1,#2)", "{X=#1 and Y=#2}") self._do_test_with(r"\point(12,{3 point 5})", "X=12 and Y=3 point 5") def test_defining_a_macro_without_parameter(self): self._do_test_with(r"\def\foo{X}", r"") self.assertEqual(self._macro(r"\foo", "", "{X}"), self._environment[r"\foo"]) def test_defining_internal_macro(self): self._symbols.CHARACTER += "@" self._do_test_with(r"\def\internal@foo{\internal@bar} \internal@foo", r" \internal@bar") self.assertEqual(self._macro(r"\internal@foo", "", r"{\internal@bar}"), self._environment[r"\internal@foo"]) def test_defining_a_macro_with_one_parameter(self): self._do_test_with(r"\def\foo#1{X}", r"") self.assertEqual(self._macro(r"\foo", "#1", "{X}"), self._environment[r"\foo"]) def test_defining_a_macro_with_multiple_parameters(self): self._do_test_with(r"\def\point(#1,#2,#3){X}", r"") self.assertEqual(self._macro(r"\point", "(#1,#2,#3)", "{X}"), self._environment[r"\point"]) def test_macro(self): self._do_test_with(r"\def\foo{X}\foo", r"X") def test_macro_with_one_parameter(self): self._do_test_with(r"\def\foo#1{x=#1}\foo{2}", r"x=2") def test_macro_with_inner_macro(self): self._do_test_with(r"\def\foo#1{\def\bar#1{X #1} \bar{#1}} \foo{Y}", r" X Y") def test_macro_with_parameter_scope(self): self._do_test_with(r"\def\foo(#1,#2){" r"\def\bar#1{Bar=#1}" r"\bar{#2} ; #1" r"}" r"\foo(2,3)", r"Bar=3 ; 2") def test_parsing_input(self): self._engine.content_of.return_value = "File content" self._do_test_with(r"\input{my-file}", r"File content") self._engine.content_of.assert_called_once_with("my-file", ANY) def test_macro_with_inner_redefinition_of_input(self): self._engine.content_of.return_value = "File content" self._do_test_with(r"\def\foo#1{\def\input#1{File: #1} \input{#1}} \foo{test.tex}", r" File: test.tex") def test_macro_with_inner_use_of_input(self): self._engine.content_of.return_value = "blabla" self._do_test_with(r"\def\foo#1{File: \input{#1}} \foo{test.tex}", r" File: blabla") def test_rewriting_multiline_commands(self): self._engine.update_link.return_value = "img_result" self._do_test_with("\\includegraphics % \n" + "[witdh=\\textwidth] % Blabla\n" + "{img/result.pdf}", "\\includegraphics % \n" + "[witdh=\\textwidth] % Blabla\n" + "{img_result}") self._engine.update_link.assert_called_once_with("img/result.pdf", ANY) def test_rewriting_includegraphics(self): self._engine.update_link.return_value = "img_result" self._do_test_with(r"\includegraphics{img/result.pdf}", r"\includegraphics{img_result}") self._engine.update_link.assert_called_once_with("img/result.pdf", ANY) def test_rewriting_includegraphics_with_parameters(self): self._engine.update_link.return_value = "img_result" self._do_test_with(r"\includegraphics[width=\linewidth]{img/result.pdf}", r"\includegraphics[width=\linewidth]{img_result}") self._engine.update_link.assert_called_once_with("img/result.pdf", ANY) def test_rewriting_graphicspath(self): self._do_test_with(r"\graphicspath{{img}}", r"\graphicspath{{img}}") self._engine.record_graphic_path.assert_called_once_with(["img"], ANY) def test_rewriting_include(self): self._engine.shall_include.return_value = True self._engine.content_of.return_value = "File content" self._do_test_with(r"\include{my-file}", r"File content\clearpage") self._engine.shall_include.assert_called_once_with("my-file") self._engine.content_of.assert_called_once_with("my-file", ANY) def test_rewriting_include_when_the_file_shall_not_be_included(self): self._engine.shall_include.return_value = False self._engine.content_of.return_value = "File content" self._do_test_with(r"\include{my-file}", r"") self._engine.shall_include.assert_called_once_with("my-file") self._engine.content_of.assert_not_called() def test_rewriting_includeonly(self): self._engine.shall_include.return_value = True self._do_test_with(r"\includeonly{my-file.tex}", r"") self._engine.include_only.assert_called_once_with(["my-file.tex"], ANY) def test_rewriting_subfile(self): self._engine.content_of.return_value \ = r"\documentclass[../main.tex]{subfiles}" \ r"" \ r"\begin{document}" \ r"File content" \ r"\end{document}" self._do_test_with(r"\subfile{my-file}", r"File content") self._engine.content_of.assert_called_once_with("my-file", ANY) def test_rewriting_document_class(self): self._do_test_with(r"\documentclass{article}" r"\begin{document}" r"Not much!" r"\end{document}", r"\documentclass{article}" r"\begin{document}" r"Not much!" r"\end{document}") self._engine.relocate_dependency.assert_called_once_with("article", ANY) def test_rewriting_usepackage(self): self._do_test_with(r"\usepackage{my-package}", r"\usepackage{my-package}") self._engine.relocate_dependency.assert_called_once_with("my-package", ANY) def test_rewriting_usepackage_with_options(self): self._do_test_with(r"\usepackage[length=3cm,width=2cm]{my-package}", r"\usepackage[length=3cm,width=2cm]{my-package}") self._engine.relocate_dependency.assert_called_once_with("my-package", ANY) def test_rewriting_usepackage_with_options(self): self._do_test_with(r"\RequirePackage[length=3cm,width=2cm]{my-package}", r"\RequirePackage[length=3cm,width=2cm]{my-package}") self._engine.relocate_dependency.assert_called_once_with("my-package", ANY) def test_rewriting_bibliography_style(self): self._engine.update_link_to_bibliography_style.return_value = "my-style" self._do_test_with(r"\bibliographystyle{my-style}", r"\bibliographystyle{my-style}") self._engine.update_link_to_bibliography_style.assert_called_once_with("my-style", ANY) def test_rewriting_make_index(self): self._engine.update_link_to_index_style.return_value = "my-style.ist" self._do_test_with("\\makeindex[columns=3, title=Alphabetical Index,\n options= -s my-style.ist]", "\\makeindex[columns=3, title=Alphabetical Index,\n options= -s my-style.ist]") self._engine.update_link_to_index_style.assert_called_once_with("my-style.ist", ANY)
class ClassificationTests(TestCase): def setUp(self): self._engine = MagicMock() self._macros = MacroFactory(self._engine) self._symbols = SymbolTable.default() self._tokens = TokenFactory(self._symbols) self._factory = Factory(self._symbols) self._environment = Context(definitions=self._macros.all()) def test_literal_macro(self): self._define(r"\foo", "", r"{blablabla}") self._verify_evaluation(r"\foo", "blablabla") def test_macro_that_uses_input(self): self._engine.content_of.return_value = "blabla" self._define(r"\foo", "#1", r"{File: \input{#1}}") self._verify_evaluation(r"\foo{my-file}", "File: blabla") def test_macro_that_redefines_input(self): self._define(r"\foo", "#1", r"{\def\input#1{File: #1}\input{#1}}") self._verify_evaluation(r"\foo{test.tex}", "File: test.tex") def test_macro_with_include(self): self._engine.content_of.return_value = "blabla" self._define(r"\foo", "#1", r"{\include{#1}}") self._verify_evaluation(r"\foo{my-file}", r"blabla\clearpage") def test_macro_with_masked_input(self): self._define(r"\foo", "#1", r"{\def\input#1{blabla #1}\input{#1}}") self._verify_evaluation(r"\foo{my-file}", "blabla my-file") def test_invoking_a_macro_with_a_group_as_argument(self): self._define(r"\foo", "(#1)", "{Text: #1}") self._verify_evaluation(r"\foo({bar!})", r"Text: bar!") def test_invoking_a_macro_with_two_parameters(self): self._define(r"\point", "(#1,#2)", "{X=#1 and Y=#2}") self._verify_evaluation(r"\point(12,{3 point 5})", "X=12 and Y=3 point 5") def test_macro_with_one_parameter(self): self._define(r"\foo", "#1", "{x=#1}") self._verify_evaluation(r"\foo{2}", r"x=2") def test_macro_with_parameter_scope(self): self._define(r"\foo", r"(#1,#2)", r"{\def\bar#1{Bar=#1}\bar#2 ; #1}") self._verify_evaluation(r"\foo(2,3)", r"Bar=3 ; 2") def test_defining_internal_macros(self): self._symbols.CHARACTER += "@" self._verify_evaluation(r"\def\internal@foo{\internal@bar}", "") self.assertEqual(self._macro(r"\internal@foo", "", r"{\internal@bar}"), self._environment[r"\internal@foo"]) def test_internal_macros(self): self._symbols.CHARACTER += "@" self._define(r"\internal@foo", "", r"{\internal@bar}") self._verify_evaluation(r"\internal@foo", "\internal@bar") def _verify_evaluation(self, invocation, expected_category): self.assertEqual(expected_category, self._evaluate(invocation)) def _define(self, name, parameters, body): self._environment[name] = self._macro(name, parameters, body) def _macro(self, name, parameters, body): return self._macros.create(name, self._factory.as_list(parameters), self._factory.as_list(body)) def _evaluate(self, expression): parser = Parser(self._factory.as_tokens(expression, "Unknown"), self._factory, self._environment) return "".join(map(str, parser.evaluate()))
class ParserTests(TestCase): def setUp(self): self._engine = MagicMock() self._macros = MacroFactory(self._engine) self._symbols = SymbolTable.default() self._tokens = TokenFactory(self._symbols) self._factory = Factory(self._symbols) self._environment = Context(definitions=self._macros.all()) self._lexer = None self._parser = None def test_parsing_a_regular_word(self): self._do_test_with("hello", "hello") def _do_test_with(self, collected, expected): parser = Parser(self._factory.as_tokens(collected, "Unknown"), self._factory, self._environment) tokens = parser.process() self._verify_output_is(expected, tokens) def _verify_output_is(self, expected_text, actual_tokens): output = "".join(str(t) for t in actual_tokens) self.assertEqual(expected_text, output) def test_rewriting_a_group(self): self._do_test_with("{bonjour}", "{bonjour}") def test_rewriting_a_command_that_shall_not_be_rewritten(self): self._do_test_with(r"\macro[option=23cm]{some text}", r"\macro[option=23cm]{some text}") def test_rewriting_a_command_within_a_group(self): self._do_test_with(r"{\macro[option=23cm]{some text} more text}", r"{\macro[option=23cm]{some text} more text}") def test_rewriting_a_command_in_a_verbatim_environment(self): self._do_test_with(r"\begin{verbatim}\foo{bar}\end{verbatim}", r"\begin{verbatim}\foo{bar}\end{verbatim}") def test_rewriting_a_input_in_a_verbatim_environment(self): self._engine.content_of.return_value = "blabla" self._do_test_with(r"\begin{verbatim}\input{bar}\end{verbatim}", r"\begin{verbatim}\input{bar}\end{verbatim}") self._engine.content_of.assert_not_called() def test_rewriting_a_unknown_environment(self): self._do_test_with(r"\begin{center}blabla\end{center}", r"\begin{center}blabla\end{center}") def test_rewriting_a_macro_definition(self): self._do_test_with(r"\def\myMacro#1{my #1}", r"\def\myMacro#1{my #1}") def test_rewriting_commented_out_input(self): self._do_test_with(r"% \input my-file", r"% \input my-file") self._engine.content_of.assert_not_called() def test_rewriting_invocation_with_one_parameter(self): self._define_macro(r"\foo", "(#1)", "{bar #1}") self._do_test_with(r"\foo(1)", r"\foo(1)") def _define_macro(self, name, parameters, body): macro = self._macro(name, parameters, body) self._environment[macro.name] = macro def _macro(self, name, parameters, body): return self._macros.create(name, self._factory.as_list(parameters), self._factory.as_list(body)) def test_defining_a_macro_without_parameter(self): self._do_test_with(r"\def\foo{X}", r"\def\foo{X}") self.assertEqual(self._macro(r"\foo", "", "{X}"), self._environment["foo"]) def test_defining_a_macro_with_one_parameter(self): self._do_test_with(r"\def\foo#1{X}", r"\def\foo#1{X}") self.assertEqual(self._macro(r"\foo", "#1", "{X}"), self._environment["foo"]) def test_defining_a_macro_with_multiple_parameters(self): self._do_test_with(r"\def\point(#1,#2,#3){X}", r"\def\point(#1,#2,#3){X}") self.assertEqual(self._macro(r"\point", "(#1,#2,#3)", "{X}"), self._environment["point"]) def test_rewriting_input(self): self._engine.content_of.return_value = "File content" self._do_test_with(r"\input{my-file}", r"File content") self._engine.content_of.assert_called_once_with("my-file", ANY) def test_rewriting_multiline_commands(self): self._engine.update_link_to_graphic.return_value = "img_result" self._do_test_with( "\\includegraphics % \n" + "[witdh=\\textwidth] % Blabla\n" + "{img/result.pdf}", "\\includegraphics % \n" + "[witdh=\\textwidth] % Blabla\n" + "{img_result}") self._engine.update_link_to_graphic\ .assert_called_once_with("img/result.pdf", ANY) def test_rewriting_includegraphics(self): self._engine.update_link_to_graphic.return_value = "img_result" self._do_test_with(r"\includegraphics{img/result.pdf}", r"\includegraphics{img_result}") self._engine.update_link_to_graphic\ .assert_called_once_with("img/result.pdf", ANY) def test_rewriting_includegraphics_with_parameters(self): self._engine.update_link_to_graphic.return_value = "img_result" self._do_test_with( r"\includegraphics[width=\linewidth]{img/result.pdf}", r"\includegraphics[width=\linewidth]{img_result}") self._engine.update_link_to_graphic\ .assert_called_once_with("img/result.pdf", ANY) def test_rewriting_graphicspath(self): self._do_test_with(r"\graphicspath{{img}}", r"\graphicspath{{img}}") self._engine.record_graphic_path\ .assert_called_once_with(["img"], ANY) def test_rewriting_include(self): self._engine.shall_include.return_value = True self._engine.content_of.return_value = "File content" self._do_test_with(r"\include{my-file}", r"File content\clearpage") self._engine.shall_include.assert_called_once_with("my-file") self._engine.content_of.assert_called_once_with("my-file", ANY) def test_rewriting_include_when_the_file_shall_not_be_included(self): self._engine.shall_include.return_value = False self._engine.content_of.return_value = "File content" self._do_test_with(r"\include{my-file}", r"") self._engine.shall_include.assert_called_once_with("my-file") self._engine.content_of.assert_not_called() def test_rewriting_includeonly(self): self._engine.shall_include.return_value = True self._do_test_with(r"\includeonly{my-file.tex}", r"") self._engine.include_only\ .assert_called_once_with(["my-file.tex"], ANY) def test_rewriting_subfile(self): self._engine.content_of.return_value \ = r"\documentclass[../main.tex]{subfiles}" \ r"" \ r"\begin{document}" \ r"File content" \ r"\end{document}" self._do_test_with(r"\subfile{my-file}", r"File content") self._engine.content_of.assert_called_once_with("my-file", ANY) def test_rewriting_document_class(self): self._do_test_with( r"\documentclass{article}" r"\begin{document}" r"Not much!" r"\end{document}", r"\documentclass{article}" r"\begin{document}" r"Not much!" r"\end{document}") self._engine.relocate_dependency.assert_called_once_with( "article", ANY) def test_rewriting_usepackage(self): self._engine.relocate_dependency.return_value = None self._do_test_with(r"\usepackage{my-package}", r"\usepackage{my-package}") self._engine.relocate_dependency.assert_called_once_with( "my-package", ANY) def test_rewriting_usepackage_that_exist_locally(self): self._engine.relocate_dependency.return_value = "style_my-package" self._do_test_with(r"\usepackage{style/my-package}", r"\usepackage{style_my-package}") self._engine.relocate_dependency.assert_called_once_with( "style/my-package", ANY) def test_rewriting_usepackage_with_options(self): self._engine.relocate_dependency.return_value = None self._do_test_with(r"\usepackage[length=3cm,width=2cm]{my-package}", r"\usepackage[length=3cm,width=2cm]{my-package}") self._engine.relocate_dependency.assert_called_once_with( "my-package", ANY) def test_rewriting_bibliography_style(self): self._engine.update_link_to_bibliography_style\ .return_value = "my-style" self._do_test_with(r"\bibliographystyle{my-style}", r"\bibliographystyle{my-style}") self._engine.update_link_to_bibliography_style.assert_called_once_with( "my-style", ANY) def test_rewriting_make_index(self): self._engine.update_link_to_index_style\ .return_value = "my-style.ist" self._do_test_with( "\\makeindex[columns=3, title=Alphabetical Index,\n" "options= -s my-style.ist]", "\\makeindex[columns=3, title=Alphabetical Index,\n" "options= -s my-style.ist]") self._engine.update_link_to_index_style.assert_called_once_with( "my-style.ist", ANY) def test_rewriting_endinput(self): self._do_test_with(r"foo \endinput bar", r"foo ") self._engine.end_of_input.assert_called_once_with("Unknown", ANY) def test_rewriting_overpic(self): self._engine.update_link_to_graphic.return_value = "img_result" self._do_test_with(r"\begin{overpic}{img/result}blabla\end{overpic}", r"\begin{overpic}{img_result}blabla\end{overpic}") self._engine.update_link_to_graphic\ .assert_called_once_with("img/result", ANY) def test_expanding_macros(self): self._engine.update_link_to_graphic.return_value = "images_logo" self._do_test_with( r"\def\logo{\includegraphics{images/logo}}" r"\logo", r"\def\logo{\includegraphics{images_logo}}" r"\logo")
# Flap is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Flap. If not, see <http://www.gnu.org/licenses/>. # from flap import logger from flap.latex.macros.commons import Macro, UserDefinedMacro from flap.latex.errors import UnknownSymbol from flap.latex.symbols import SymbolTable from flap.latex.parser import Factory factory = Factory(SymbolTable.default()) class CatCode(Macro): def __init__(self, flap): super().__init__(flap, "catcode", factory.as_list("#1=#2\n"), None) def _execute(self, parser, invocation): logger.debug("Invocation: " + invocation.as_text) character = "".join( str(each_token) for each_token in invocation.argument("#1")) if character[0] == "`": if character[1] == "\\": character = character[2] else:
def _rewrite(self, text, source, symbol_table=SymbolTable.default()): factory = Factory(symbol_table) parser = Parser(factory.as_tokens(text, source), factory, self, Context()) return parser.rewrite()
def _rewrite(self, text, source, symbol_table=SymbolTable.default()): factory = Factory(symbol_table) macros = MacroFactory(self) parser = Parser(factory.as_tokens(text, source), factory, Context(definitions=macros.all())) return parser.rewrite()